|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 06/16] xen/riscv: introduce tracking of pending vCPU interrupts, part 2
This patch is based on Linux kernel 6.16.0.
Add the consumer side (vcpu_flush_interrupts()) of the lockless pending
interrupt tracking introduced in part 1 (for producers). According, to the
design only one consumer is possible, and it is vCPU itself.
vcpu_flush_interrupts() is expected to be ran (as guests aren't ran now due
to the lack of functionality) before the hypervisor returns control to the
guest.
Producers may set bits in irqs_pending_mask without a lock. Clearing bits in
irqs_pending_mask is performed only by the consumer via xchg() (with aquire
semantics). The consumer must not write to irqs_pending and must not act on
bits that are not set in the mask. Otherwise, extra synchronization should
be provided.
The worst thing which could happen with such approach is that a new pending
bit will be set to irqs_pending bitmap during update of hvip variable in
vcpu_flush_interrupt() but it isn't problem as the new pending bit won't
be lost and just be proceded during the next flush.
As AIA specs introduced hviph register which would want to be updated when
guest related AIA code vcpu_update_hvip() is introduced instead of just
open-code it in vcpu_flush_interrupts().
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
Changes in v4:
- Move defintion of hvip local variable to narrower space in
vcpu_flush_interrupts().
- Use initializers for mask and val variables.
- Use local variable c as an argument of vcpu_flush_interrupts() in
check_for_pcpu_work().
---
Changes in v3:
- Update the error message in case of RV32 from "hviph" to v->arch.hviph.
- Make const argument of vcpu_update_hvip.
- Move local variables mask and val inside if() in vcpu_flush_interrupts().
- Call vcpu_flush_interrupts() in check_pcpu_work().
- Move vcpu_update_hvip() inside if() in vcpu_flush_interrupts().
---
Changes in v2:
- New patch.
---
xen/arch/riscv/domain.c | 31 +++++++++++++++++++++++++++++
xen/arch/riscv/include/asm/domain.h | 1 +
xen/arch/riscv/traps.c | 2 ++
3 files changed, 34 insertions(+)
diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c
index edbac39a0b18..35d8d5db02d0 100644
--- a/xen/arch/riscv/domain.c
+++ b/xen/arch/riscv/domain.c
@@ -198,3 +198,34 @@ void vcpu_sync_interrupts(struct vcpu *v)
# error "Update v->arch.vsieh"
#endif
}
+
+static void vcpu_update_hvip(const struct vcpu *v)
+{
+ csr_write(CSR_HVIP, v->arch.hvip);
+}
+
+void vcpu_flush_interrupts(struct vcpu *v)
+{
+ if ( ACCESS_ONCE(v->arch.irqs_pending_mask[0]) )
+ {
+ register_t *hvip = &v->arch.hvip;
+
+ unsigned long mask = xchg(&v->arch.irqs_pending_mask[0], 0UL);
+ unsigned long val = ACCESS_ONCE(v->arch.irqs_pending[0]) & mask;
+
+ *hvip &= ~mask;
+ *hvip |= val;
+
+ vcpu_update_hvip(v);
+ }
+
+/*
+ * Flush AIA high interrupts.
+ *
+ * It is necessary to do only for CONFIG_RISCV_32 which isn't
+ * supported now.
+ */
+#ifdef CONFIG_RISCV_32
+# error "Update v->arch.hviph"
+#endif
+}
diff --git a/xen/arch/riscv/include/asm/domain.h
b/xen/arch/riscv/include/asm/domain.h
index 2793f694d36f..5d25a884eea6 100644
--- a/xen/arch/riscv/include/asm/domain.h
+++ b/xen/arch/riscv/include/asm/domain.h
@@ -115,6 +115,7 @@ int vcpu_set_interrupt(struct vcpu *v, unsigned int irq);
int vcpu_unset_interrupt(struct vcpu *v, unsigned int irq);
void vcpu_sync_interrupts(struct vcpu *v);
+void vcpu_flush_interrupts(struct vcpu *v);
#endif /* ASM__RISCV__DOMAIN_H */
diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
index 366c3ff23e76..77738a01c8b5 100644
--- a/xen/arch/riscv/traps.c
+++ b/xen/arch/riscv/traps.c
@@ -174,6 +174,8 @@ static void check_for_pcpu_work(void)
struct vcpu *c = current;
vcpu_sync_interrupts(c);
+
+ vcpu_flush_interrupts(c);
}
void do_trap(struct cpu_user_regs *cpu_regs)
--
2.52.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |