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

[PATCH v4 34/42] xen/riscv: restore register state in the new IMSIC VS-file



Complete the migration of a vCPU's guest interrupt file: move the state
saved from the old IMSIC VS-file into the new one and make the vCPU use
the new VS-file.

The interrupt producers have already been retargeted to the new
VS-file, so MSIs may land in it before the saved state is restored.
Hence the saved eip/eie bits are ORed into the new VS-file rather than
written to it, so that such MSIs aren't lost. eithreshold and
eidelivery are restored last: the new VS-file was cleared when it was
acquired, so it doesn't deliver interrupts until its pending and enable
bits are complete.

As with reading the old VS-file, this has to be done on the pCPU owning
the new VS-file, with hstatus.VGEIN temporarily selecting it. That is
v->processor, the pCPU the vCPU runs on.

Finally, point hstatus.VGEIN in the registers restored when the vCPU
enters the guest at the new VS-file, so that it becomes the source of
the vCPU's VS-level external interrupts and the file the guest accesses
through its siselect/sireg. With that the migration is complete, so
drop the BUG_ON("unimplemented") placeholder from imsic_vsfile_move().

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
Changes in v4:
 - Drop imsic_eix_set(), following the removal of the switchcase
   expansion pyramid: imsic_eix_set64() uses imsic_vs_csr_set() directly.
 - Name imsic_eix_check() in the comment above imsic_eix_set64() rather
   than saying "above".
 - Use imsic_vsfile_select() and imsic_vsfile_deselect().
 - Make mrif in imsic_vsfile_local_update() a pointer to const.
 - Don't arm HGEIE for the new interrupt file: the file is now moved by
   the vCPU itself, which runs meanwhile, and imsic_ctxt_switch_from()
   arms it once the vCPU is switched out.
 - Restore the state in imsic_vsfile_move(), which now does the move for
   imsic_migrate_vcpu().
 - Restore the new file with a direct call rather than through
   imsic_call_on_cpu(), as it belongs to the pCPU the vCPU runs on. Give
   imsic_vsfile_local_update() a typed pointer and drop its cf_check.
 - Update the commit message accordingly.
 - Point hstatus.VGEIN at the new file with imsic_vsfile_set_vgein(),
   which replaces the open-coded update and its comment.
---
Changes in v3:
 - Reword the commit message: explain why the saved state is ORed into
   the new VS-file and why eithreshold and eidelivery are restored last,
   drop the note about explanatory comments.
 - Leave the trailing semicolon of the switchcase macros to their users.
 - Drop the redundant parentheses around the arguments of
   imsic_vs_csr_set() as they are passed to csr_*() as whole
   expressions.
 - Add missing break after ASSERT_UNREACHABLE() in the default case of
   imsic_eix_set().
 - Restore the state on v->processor and take the id of the new IMSIC
   VS-file from vsfile_data.hgei, as imsic_migrate_vcpu() no longer has
   separate local variables for the new VS-file.
 - Explain why hstatus and vsiselect are saved and restored with a short
   comment in imsic_vsfile_local_update().
 - Introduce imsic_eix_set64() to set bits of a whole 64-bit EIx group,
   which lets the #ifdef CONFIG_RISCV_32 in imsic_vsfile_local_update()
   go.
 - Move the MASK_INSR() conversion and the comment rewording in
   imsic_vsfile_local_read_clear() to the patch introducing that
   function.
---
Changes in v2:
 - New patch.
---
---
 xen/arch/riscv/imsic.c | 56 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c
index c705b287c7ff..adacac5c7268 100644
--- a/xen/arch/riscv/imsic.c
+++ b/xen/arch/riscv/imsic.c
@@ -115,6 +115,12 @@ do {                            \
     csr_swap(CSR_VSIREG, v);        \
 })
 
+#define imsic_vs_csr_set(c, v)      \
+do {                                \
+    csr_write(CSR_VSISELECT, c);    \
+    csr_set(CSR_VSIREG, v);         \
+} while (0)
+
 #define imsic_vs_csr_write(c, v)    \
 do {                                \
     csr_write(CSR_VSISELECT, c);    \
@@ -156,6 +162,15 @@ static uint64_t imsic_eix_swap64(unsigned int ireg, 
uint64_t val)
     return old;
 }
 
+/* Set bits of a whole 64-bit EIx group (see imsic_eix_check()). */
+static void imsic_eix_set64(unsigned int ireg, uint64_t val)
+{
+    imsic_eix_check(ireg);
+    imsic_vs_csr_set(ireg, val);
+    if ( IS_ENABLED(CONFIG_RISCV_32) )
+        imsic_vs_csr_set(ireg + 1, val >> 32);
+}
+
 unsigned int vcpu_guest_file_id(const struct vcpu *v)
 {
     return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id);
@@ -1087,6 +1102,42 @@ int __init vimsic_make_domu_dt_node(struct kernel_info 
*kinfo,
     return fdt_end_node(fdt);
 }
 
+static void imsic_vsfile_local_update(const struct imsic_vsfile_data *idata)
+{
+    unsigned int i;
+    const struct imsic_mrif *mrif = idata->mrif;
+    struct imsic_vsfile_ctx ctx;
+    unsigned long flags;
+
+    /* We can only update if we have a HW IMSIC context */
+    if ( !idata->hgei )
+        return;
+
+    /*
+     * No atomic accessors are needed to read the values out of the MRIF here,
+     * as this is always called with a pointer to a temporary MRIF on the
+     * stack.
+     */
+
+    /* Nothing on this pCPU is to run with the file selected meanwhile. */
+    local_irq_save(flags);
+
+    imsic_vsfile_select(idata->hgei, &ctx);
+
+    for ( i = 0; i < idata->nr_eix; i++ )
+    {
+        imsic_eix_set64(IMSIC_EIP0 + i * 2, mrif->eix[i].eip);
+        imsic_eix_set64(IMSIC_EIE0 + i * 2, mrif->eix[i].eie);
+    }
+
+    imsic_vs_csr_write(IMSIC_EITHRESHOLD, mrif->eithreshold);
+    imsic_vs_csr_write(IMSIC_EIDELIVERY, mrif->eidelivery);
+
+    imsic_vsfile_deselect(&ctx);
+
+    local_irq_restore(flags);
+}
+
 /*
  * Take a h/w guest interrupt file on the pCPU @v runs on and make it the
  * vCPU's one.
@@ -1270,7 +1321,10 @@ static void imsic_vsfile_move(struct vcpu *v)
     /* Free-up old IMSIC VS-file */
     vgein_release(v, old_vsfile_id, old_vsfile_cpu);
 
-    BUG_ON("unimplemented");
+    /* Restore register state in the new IMSIC VS-file */
+    imsic_vsfile_local_update(&vsfile_data);
+
+    imsic_vsfile_set_vgein(v, vsfile_data.hgei);
 }
 
 /*
-- 
2.56.1




 


Rackspace

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