On 04.10.2013, at 13:45, Paul Mackerras wrote:

> When an interrupt or exception happens in the guest that comes to the
> host, the CPU goes to hypervisor real mode (MMU off) to handle the
> exception but doesn't change the MMU context.  After saving a few
> registers, we then clear the "in guest" flag.  If, for any reason,
> we get an exception in the real-mode code, that then gets handled
> by the normal kernel exception handlers, which turn the MMU on.  This
> is disastrous if the MMU is still set to the guest context, since we
> end up executing instructions from random places in the guest kernel
> with hypervisor privilege.
> 
> In order to catch this situation, we define a new value for the "in guest"
> flag, KVM_GUEST_MODE_HOST_HV, to indicate that we are in hypervisor real
> mode with guest MMU context.  If the "in guest" flag is set to this value,
> we branch off to an emergency handler.  For the moment, this just does
> a branch to self to stop the CPU from doing anything further.

I don't understand how you get there. The only case I can imagine where you'd 
hit a normal Linux handler while in guest MMU context is a bug in the complex 
real mode handling code.

So basically what you're doing is you're changing the "guest mode" bit to 
HOST_NV while you're executing these.

The other change this patch does is it postpones the return to GUEST_MODE_NONE 
to after fast-path handling of interrupt exits.

What if you simply don't introduce a new mode but instead only postpone the 
GUEST_MODE_NONE switch to later? Worst case that can happen is that your bug 
spins the CPU into handling that exit in a tight loop - not much different from 
your explicit spin, no?


Alex

> 
> While we're here, we define another new flag value to indicate that we
> are in a HV guest, as distinct from a PR guest.  This will be useful
> when we have a kernel that can support both PR and HV guests concurrently.
> 
> Signed-off-by: Paul Mackerras <[email protected]>
> ---
> arch/powerpc/include/asm/kvm_asm.h      |  2 ++
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 31 +++++++++++++++++++++++++------
> 2 files changed, 27 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_asm.h 
> b/arch/powerpc/include/asm/kvm_asm.h
> index e2d4d46..1bd92fd 100644
> --- a/arch/powerpc/include/asm/kvm_asm.h
> +++ b/arch/powerpc/include/asm/kvm_asm.h
> @@ -138,6 +138,8 @@
> #define KVM_GUEST_MODE_NONE   0
> #define KVM_GUEST_MODE_GUEST  1
> #define KVM_GUEST_MODE_SKIP   2
> +#define KVM_GUEST_MODE_GUEST_HV      3
> +#define KVM_GUEST_MODE_HOST_HV       4
> 
> #define KVM_INST_FETCH_FAILED -1
> 
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S 
> b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index 8e0f28f..f1f1bf3 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -383,6 +383,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
>       mtspr   SPRN_DAR, r5
>       mtspr   SPRN_DSISR, r6
> 
> +     li      r6, KVM_GUEST_MODE_HOST_HV
> +     stb     r6, HSTATE_IN_GUEST(r13)
> +
> BEGIN_FTR_SECTION
>       /* Restore AMR and UAMOR, set AMOR to all 1s */
>       ld      r5,VCPU_AMR(r4)
> @@ -682,7 +685,7 @@ fast_guest_return:
>       mtspr   SPRN_HSRR1,r11
> 
>       /* Activate guest mode, so faults get handled by KVM */
> -     li      r9, KVM_GUEST_MODE_GUEST
> +     li      r9, KVM_GUEST_MODE_GUEST_HV
>       stb     r9, HSTATE_IN_GUEST(r13)
> 
>       /* Enter guest */
> @@ -742,6 +745,14 @@ kvmppc_interrupt:
>        */
>       /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
>       std     r9, HSTATE_HOST_R2(r13)
> +
> +     lbz     r9, HSTATE_IN_GUEST(r13)
> +     cmpwi   r9, KVM_GUEST_MODE_HOST_HV
> +     beq     kvmppc_bad_host_intr
> +     /* We're now back in the host but in guest MMU context */
> +     li      r9, KVM_GUEST_MODE_HOST_HV
> +     stb     r9, HSTATE_IN_GUEST(r13)
> +
>       ld      r9, HSTATE_KVM_VCPU(r13)
> 
>       /* Save registers */
> @@ -793,10 +804,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
>       std     r3, VCPU_GPR(R13)(r9)
>       std     r4, VCPU_LR(r9)
> 
> -     /* Unset guest mode */
> -     li      r0, KVM_GUEST_MODE_NONE
> -     stb     r0, HSTATE_IN_GUEST(r13)
> -
>       stw     r12,VCPU_TRAP(r9)
> 
>       /* Save HEIR (HV emulation assist reg) in last_inst
> @@ -1186,6 +1193,10 @@ BEGIN_FTR_SECTION
>       mtspr   SPRN_AMR,r6
> END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
> 
> +     /* Unset guest mode */
> +     li      r0, KVM_GUEST_MODE_NONE
> +     stb     r0, HSTATE_IN_GUEST(r13)
> +
>       /* Switch DSCR back to host value */
> BEGIN_FTR_SECTION
>       mfspr   r8, SPRN_DSCR
> @@ -1388,7 +1399,7 @@ fast_interrupt_c_return:
>       stw     r8, VCPU_LAST_INST(r9)
> 
>       /* Unset guest mode. */
> -     li      r0, KVM_GUEST_MODE_NONE
> +     li      r0, KVM_GUEST_MODE_HOST_HV
>       stb     r0, HSTATE_IN_GUEST(r13)
>       b       guest_exit_cont
> 
> @@ -1937,3 +1948,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
>       lwz     r7,VCPU_VRSAVE(r4)
>       mtspr   SPRN_VRSAVE,r7
>       blr
> +
> +/*
> + * We come here if we get any exception or interrupt while we are
> + * executing host real mode code while in guest MMU context.
> + * For now just spin, but we should do something better.
> + */
> +kvmppc_bad_host_intr:
> +     b       .
> -- 
> 1.8.4.rc3
> 

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to