Messages in this thread | | | Date | Thu, 20 Jan 2022 17:15:51 +0000 | From | Mark Rutland <> | Subject | Re: [PATCH v2 4/7] kvm/mips: rework guest entry logic |
| |
On Thu, Jan 20, 2022 at 05:57:05PM +0100, Paolo Bonzini wrote: > On 1/20/22 17:44, Mark Rutland wrote: > > On Wed, Jan 19, 2022 at 10:58:51AM +0000, Mark Rutland wrote: > > > In kvm_arch_vcpu_ioctl_run() we use guest_enter_irqoff() and > > > guest_exit_irqoff() directly, with interrupts masked between these. As > > > we don't handle any timer ticks during this window, we will not account > > > time spent within the guest as guest time, which is unfortunate. > > > > > > Additionally, we do not inform lockdep or tracing that interrupts will > > > be enabled during guest execution, which caan lead to misleading traces > > > and warnings that interrupts have been enabled for overly-long periods. > > > > > > This patch fixes these issues by using the new timing and context > > > entry/exit helpers to ensure that interrupts are handled during guest > > > vtime but with RCU watching, with a sequence: > > > > > > guest_timing_enter_irqoff(); > > > > > > guest_state_enter_irqoff(); > > > < run the vcpu > > > > guest_state_exit_irqoff(); > > > > > > < take any pending IRQs > > > > > > > guest_timing_exit_irqoff(); > > > > Looking again, this patch isn't sufficient. > > > > On MIPS a guest exit will be handled by kvm_mips_handle_exit() *before* > > returning into the "< run the vcpu >" step above, so we won't call > > guest_state_exit_irqoff() before using RCU, etc. > > Indeed. kvm_mips_handle_exit has a weird mutual recursion through runtime-assembled code, but then this is MIPS... > > This should do it: > > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c > index e59cb6246f76..6f2291f017f5 100644 > --- a/arch/mips/kvm/mips.c > +++ b/arch/mips/kvm/mips.c > @@ -1192,6 +1192,7 @@ int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) > kvm_mips_set_c0_status(); > local_irq_enable(); > + guest_timing_exit_irqoff(); > kvm_debug("kvm_mips_handle_exit: cause: %#x, PC: %p, kvm_run: %p, kvm_vcpu: %p\n", > cause, opc, run, vcpu); > @@ -1325,6 +1326,7 @@ int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) > } > if (ret == RESUME_GUEST) { > + guest_timing_enter_irqoff(); > trace_kvm_reenter(vcpu); > /*
As above, we'll also need the guest_state_{enter,exit}() calls surrounding this (e.g. before that local_irq_enable() at the start of kvm_mips_handle_exit(), and that needs to happen in noinstr code, etc.
It looks like the simplest thing to do is to rename kvm_mips_handle_exit() to __kvm_mips_handle_exit() and add a kvm_mips_handle_exit() wrapper that handles that (with the return path conditional on whether __kvm_mips_handle_exit() returns RESUME_GUEST).
I'll have a go at that tomorrow when I regain the capability to think.
Longer-term MIPS should move to a loop like everyone else has:
for (;;) { status = kvm_mips_enter_exit_vcpu();
if (handle_exit(status)) break; ... }
... which is far easier to manage.
Thanks, Mark.
| |