[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 32/39] xen/riscv: remap interrupts to new IMSIC VS-file


  • To: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>
  • Date: Wed, 23 Sep 2026 17:25:10 +0200
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=vates.tech header.i="@vates.tech" header.h="From:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:In-Reply-To:References:Feedback-ID"
  • Autocrypt: addr=baptiste.le-duc@xxxxxxxxxx; keydata= xsBNBGoPSX8BCADSuTikqW3FD4mscQugY1thRaKlIhcJ2G9YCWYXAlp+xosvTlzfIftOZZim 750MLvyKtLPkQzB6TZtFZBiexSraaF/MdDKRTT5DcVa3r7ZnHgqMclWlPa4ioysS4yFcJanL cyNOT7HUFvIdirMMqiViedfYtS0GORPBBPVISD6ClMz3ecHIxqllfq9CHYQn4amKEfHmh6tm Rufo4Gjl6x8cUFZZlRQf+aCmUzdSPA0P5u3sueYH1uEz4w/jbD53MlKqzCvxUeOsfS2swTQA 6mS9jIgOjNadpUTOzKfDHMgFirtG+HFpm45Nwp6KQizxgDVOfTnOfVHm5Gwqm3ETl9y5ABEB AAHNPEJhcHRpc3RlIExlIER1YyAoVmF0ZXMgWXViaWtleSkgPGJhcHRpc3RlLmxlLWR1Y0B2 YXRlcy50ZWNoPsLAjgQTAQoAOBYhBGiSJ6HgW88MgT/gfu2Cu2XL9M6QBQJqD0l/AhsDBQsJ CAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEO2Cu2XL9M6QuMcH/ihiy/Nrxp919AmY0ENnc0NK r/2LDvW/hrX4FfbpxAmrGmQ7MU1aQTk0JDbfcsG8OYH6wO5sqnXb1gz50YrEdpfVSbHz5YTZ EhDIxE4g7NrvJZh3Qc0m0CAyjYTNHen7J6olVaCMjrOH7uRHUYZ7Pl3am9mZosfLmez/aWJO a6ihQxBXHI75brlk1teIURkep2kP7P0Flmfl4cA//saREoTF7GXCtjOSQk/xg8PP0Sswqp5G TdJptn3FQn6lAzfz0eFSYqkaoX2c2k1MDa7o+UX9cfGPL8ybMKnYkasLxck6eOWGJWf+YTrm ga/r0kBaftmqNDgt5nI2jNTDwZcT9g3OwE0Eag9JfwEIAM6IWbuBSvz+erv27oGDDpo8M6Fp dGUvft7v+WceHUfxiXpYFx9qgIU6XGy6y+3lJMAvNcltS8DuhioqMlfKRSYGKZlpliY65dNP 557IuM4ctVJ+I9CVclvv9eahARQKgF5auLJAAlvGSmU+ufNvlwTUmLIRcrPviTmB6X5jJYc+ fiNeyI0HcsgcN21C0r62tUCypuZ+vgEJXw2bx1V8mVGZKxdGJPh58QF6kRK+xmd4kEComLGV BeM6BcVOtEjDcGNC0tLhXb0p9g1Ys55iA8sd6s4WacyolW2J6rwmcOkjiWexWw1caYgIWAV1 004M3gwUaOz0dGq2i7HQ0AiVfVkAEQEAAcLAdgQYAQoAIBYhBGiSJ6HgW88MgT/gfu2Cu2XL 9M6QBQJqD0l/AhsMAAoJEO2Cu2XL9M6QovYH/RjstyL5o/V5K74ylBtz0j5t3pLX5JKbwApi 656rGgDdqElImyvvZppNMl/mgHNzvxmfFAhJXnSX9f1fqVEQKOGEhLUastnl/ssBiE5x7btM V0GAffxXbXJZbVv4b/DI+gVrOPc2YXlVwruapvTZNtD3hqPrkjrmq5WTtGR2loIVSe62hmh0 BGD2Fy79b/hYWyBqhayPBEjwGW75u4/yn+Yqy1PgG3hIcvg7GSuT3akhHZSB2Mbguzcoyf9Q DJl6t33JxPRkkNrEdkPPmRlQCTSiUkVjKqMDF3jlINWsJ5t4jKFsNF91ksdw7aQgiX+tQIpE ugMC1NuNi5dDGip66bw=
  • Cc: Romain Caritey <Romain.Caritey@xxxxxxxxxxxxx>, Zheng Zhang <zhangzheng@xxxxxxxxxxx>, Alistair Francis <alistair.francis@xxxxxxx>, Connor Davis <connojdavis@xxxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>
  • Delivery-date: Wed, 23 Sep 2026 15:25:30 +0000
  • Feedback-id: default:8631fc262581453bbf619ec5b2062170:Sweego
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

> xen/riscv: remap interrupts to new IMSIC VS-file

Nit: The next patch uses "restore" in its title, we might want to use
"save" terminology here for symmetry? e.g.:
    "xen/riscv: save old interrupt file state to memory"


On 8/27/26 5:22 PM, Oleksii Kurochko wrote:
After new IMSIC VS-file is zeroed-out it is necessary to do G-stage remaping
fo new IMSIC VS-file. Also, if any interrupts at an APLIC are forwarded by
MSIs to the old interrupt file, reconfigure the APLIC to send them to the
new interrupt file.

Generally it is needed also to modify the relevant translation tables at
all IOMMUs so that MSIs for this virtual interrupt file are now sent to
the new physical interrupt file but it is skipped for now there is no IOMMU
support for RISC-V.

Synchronize with APLIC to ensure that no straggler MSIs will arrive at
the old interrupt file by using of aplic_genmsi_barrier().

Technically there is no need for read_lock_irqsave() and
read_unlock_irqrestore() around reading of ->guest_file_id, as a write
cannot happen in parallel: any update to ->guest_file_id for a vCPU
will happen either in imsic_migrate_vcpu() itself or before the vCPU
first gains control (in continue_new_vcpu()), so there is no concurrent
access to it in imsic_migrate_vcpu(). The lock is added here for
potential future cases.

Keep BUG_ON("unimplemented") placeholder in imsic_migrate_vcpu() to guard
against silent incorrect behaviour or unexpected panics in guest VMs until
the function is fully implemented.

imsic_map_guest_file() and imsic_update_state() are stubs for now and will
be introduced later in a separate patch.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
Changes in v2:
  - New patch.
---
---
  xen/arch/riscv/imsic.c             | 103 +++++++++++++++++++++++++++++
  xen/arch/riscv/include/asm/imsic.h |   3 +
  2 files changed, 106 insertions(+)

diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c
index 5de45949610d..5e9f6995e443 100644
--- a/xen/arch/riscv/imsic.c
+++ b/xen/arch/riscv/imsic.c
@@ -27,6 +27,7 @@
  #include <xen/xvmalloc.h>
#include <asm/aia.h>
+#include <asm/aplic.h>
  #include <asm/imsic.h>
#define IMSIC_HART_SIZE(guest_bits) (BIT(guest_bits, U) * IMSIC_MMIO_PAGE_SZ)
@@ -60,6 +61,12 @@ static unsigned int __ro_after_init guest_num_msis;
  #define IMSIC_DISABLE_EITHRESHOLD   1
  #define IMSIC_ENABLE_EITHRESHOLD    0
+#define imsic_csr_read(c) \
+({                                  \
+    csr_write(CSR_SISELECT, (c));   \
+    csr_read(CSR_SIREG);            \
+})
+
  #define imsic_csr_write(c, v)   \
  do {                            \
      csr_write(CSR_SISELECT, c); \
@@ -141,6 +148,11 @@ unsigned int vcpu_guest_file_id(const struct vcpu *v)
      return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id);
  }
+void imsic_update_state(struct vcpu *v, unsigned int guest_file_id)
+{
+    BUG_ON("unimplemented\n");
+}
+
  void __init imsic_ids_local_delivery(bool enable)
  {
      if ( enable )
@@ -242,6 +254,15 @@ void imsic_irq_disable(unsigned int irq)
      spin_unlock(&imsic_cfg.lock);
  }
+static bool imsic_local_is_pending(unsigned int id)
+{
+    unsigned long isel =
+        (id / BITS_PER_LONG) * (BITS_PER_LONG / IMSIC_EIPx_BITS) + IMSIC_EIP0;
+    unsigned long bit = BIT(id % BITS_PER_LONG, UL);
+
+    return !!(imsic_csr_read(isel) & bit);
+}
+
  /* Callers aren't intended to changed imsic_cfg so return const. */
  const struct imsic_config *imsic_get_config(void)
  {
@@ -436,6 +457,11 @@ void cf_check imsic_ctxt_switch_to(struct vcpu *v)
      /* Nothing to do */
  }
+int imsic_map_guest_file(struct vcpu *v, unsigned int vsfile_id)
+{
+    return -EOPNOTSUPP;
+}
+
  int cf_check vcpu_imsic_init(struct vcpu *v)
  {
      struct vimsic_state *imsic_state;
@@ -497,6 +523,27 @@ static void imsic_call_on_cpu(unsigned int cpu, void 
(*func)(void *),
          on_selected_cpus(cpumask_of(cpu), func, data, 1);
  }
+/*
+ * Ensure that all the MSIs the APLIC has already generated for the hart this
+ * runs on have really reached the hart's IMSIC.
+ *
+ * The barrier is the one described by the AIA specification in
+ * "Synchronizing interactions between a hart and the APLIC": ask the APLIC to
+ * send an MSI to the hart itself and wait until it shows up as pending in the
+ * hart's own interrupt file. As it says nothing about MSIs on their way to
+ * any other hart, it has to be executed by the pCPU owning the interrupt file
+ * the MSIs were being sent to.
+ */
+static void cf_check imsic_aplic_sync(void *data)
+{
+    imsic_local_eix_update(imsic_cfg.sync_id, 1, true, false);
+
+    aplic_genmsi_barrier();
+
+    while ( !imsic_local_is_pending(imsic_cfg.sync_id) )
+        cpu_relax();
+}
+
  static void cf_check imsic_vsfile_local_clear(void *data)
  {
      unsigned int i;
@@ -837,6 +884,10 @@ void imsic_migrate_vcpu(struct vcpu *v)
      struct imsic_vsfile_data vsfile_data = {
          .nr_eix = nr_hw_eix,
      };
+    struct vimsic_state *imsic_state = v->arch.vimsic_state;
+    unsigned long flags;
+    unsigned int old_vsfile_id;
+    unsigned int old_vsfile_cpu;
/*
       * The scheduler can mark a freshly created vCPU's unit as migrated and
@@ -848,8 +899,22 @@ void imsic_migrate_vcpu(struct vcpu *v)
      if ( v->arch.last_cpu == NR_CPUS )
          return;
+ read_lock_irqsave(&imsic_state->vsfile_lock, flags);
+    old_vsfile_id = imsic_state->guest_file_id;
+    old_vsfile_cpu = imsic_state->vsfile_cpu;
+    read_unlock_irqrestore(&imsic_state->vsfile_lock, flags);
+
+    /*
+     * We don't support SW interrupt files at the moment. Bail out before
+     * anything is touched, as the old file has no owning pCPU in that case
+     * and there is nothing to retarget the producers away from.
+     */
+    if ( old_vsfile_cpu == NR_CPUS )
+        panic("IMSIC SW-file isn't supported\n");
+
      /*
       * At this point, all interrupt producers are still using the old IMSIC
+     * VS-file so we first move all interrupt producers to the new IMSIC
       * VS-file.
       */
@@ -870,5 +935,43 @@ void imsic_migrate_vcpu(struct vcpu *v)
      /* Zero-out new IMSIC VS-file */
      imsic_call_on_cpu(new_vsfile_cpu, imsic_vsfile_local_clear, &vsfile_data);
+ /* Update G-stage mapping for the new IMSIC VS-file */
+    if ( imsic_map_guest_file(v, new_vsfile_hgei) )
+    {
+        domain_crash(v->domain, "Migration to hw interrupt file failed\n");
+
+        return;
+    }
+
+    imsic_update_state(v, new_vsfile_hgei);
+
+    /*
+     * TODO: Modify the relevant translation tables at all IOMMUs so that MSIs
+     *       for this virtual interrupt file are now sent to the new physical
+     *       interrupt file.
+     */
+    if ( iommu_enabled )
+        printk_once("IMSIC: IOMMU MSI retargeting is not implemented\n");
+
+    /*
+     * If any interrupts at an APLIC are forwarded by MSIs to the old interrupt
+     * file, reconfigure the APLIC to send them to the new interrupt file.
+     */
+    aplic_reconfigure_target(v, old_vsfile_id, old_vsfile_cpu);
+
+    /*
+     * Synchronizing interactions between a hart and the APLIC.
+     *
+     * The MSIs to be flushed are the ones still on their way to the old
+     * interrupt file, so the barrier has to be done by the pCPU which owns
+     * that file.
+     */
+    imsic_call_on_cpu(old_vsfile_cpu, imsic_aplic_sync, NULL);
+
+    /*
+     * At this point, all interrupt producers have been moved
+     * to the new IMSIC VS-file.
+     */
+
      BUG_ON("unimplemented");
  }
diff --git a/xen/arch/riscv/include/asm/imsic.h 
b/xen/arch/riscv/include/asm/imsic.h
index 6ea2e4b8ca12..6395b539c52d 100644
--- a/xen/arch/riscv/include/asm/imsic.h
+++ b/xen/arch/riscv/include/asm/imsic.h
@@ -114,12 +114,15 @@ void imsic_ids_local_delivery(bool enable);
  int vcpu_imsic_init(struct vcpu *v);
  void vcpu_imsic_deinit(struct vcpu *v);
  unsigned int vcpu_guest_file_id(const struct vcpu *v);
+void imsic_update_state(struct vcpu *v, unsigned int guest_file_id);
int vimsic_make_domu_dt_node(struct kernel_info *kinfo, unsigned int *phandle); void imsic_ctxt_switch_from(struct vcpu *v);
  void imsic_ctxt_switch_to(struct vcpu *v);
+int imsic_map_guest_file(struct vcpu *v, unsigned int vsfile_id);
+
  void imsic_migrate_vcpu(struct vcpu *v);
#endif /* ASM_RISCV_IMSIC_H */




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.