|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |