diff options
author | Alexander Graf <agraf@suse.de> | 2012-08-13 01:04:19 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-10-05 23:38:45 +0200 |
commit | bd2be6836ee493d41fe42367a2b129aa771185c1 (patch) | |
tree | 6c3f609ad1d1b74c0e08eb616eec0715c6f7679b /arch/powerpc/kvm/powerpc.c | |
parent | KVM: PPC: Consistentify vcpu exit path (diff) | |
download | linux-bd2be6836ee493d41fe42367a2b129aa771185c1.tar.xz linux-bd2be6836ee493d41fe42367a2b129aa771185c1.zip |
KVM: PPC: Book3S: PR: Rework irq disabling
Today, we disable preemption while inside guest context, because we need
to expose to the world that we are not in a preemptible context. However,
during that time we already have interrupts disabled, which would indicate
that we are in a non-preemptible context.
The reason the checks for irqs_disabled() fail for us though is that we
manually control hard IRQs and ignore all the lazy EE framework. Let's
stop doing that. Instead, let's always use lazy EE to indicate when we
want to disable IRQs, but do a special final switch that gets us into
EE disabled, but soft enabled state. That way when we get back out of
guest state, we are immediately ready to process interrupts.
This simplifies the code drastically and reduces the time that we appear
as preempt disabled.
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/powerpc.c')
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 153a26abc915..266549979e9f 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -30,6 +30,7 @@ #include <asm/kvm_ppc.h> #include <asm/tlbflush.h> #include <asm/cputhreads.h> +#include <asm/irqflags.h> #include "timing.h" #include "../mm/mmu_decl.h" @@ -93,6 +94,19 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu) break; } +#ifdef CONFIG_PPC64 + /* lazy EE magic */ + hard_irq_disable(); + if (lazy_irq_pending()) { + /* Got an interrupt in between, try again */ + local_irq_enable(); + local_irq_disable(); + continue; + } + + trace_hardirqs_on(); +#endif + /* Going into guest context! Yay! */ vcpu->mode = IN_GUEST_MODE; smp_wmb(); |