ARM: KVM: perform save/restore of PAR
authorMarc Zyngier <marc.zyngier@arm.com>
Fri, 21 Jun 2013 12:08:46 +0000 (13:08 +0100)
committerChristoffer Dall <christoffer.dall@linaro.org>
Wed, 26 Jun 2013 17:50:04 +0000 (10:50 -0700)
Not saving PAR is an unfortunate oversight. If the guest performs
an AT* operation and gets scheduled out before reading the result
of the translation from PAR, it could become corrupted by another
guest or the host.

Saving this register is made slightly more complicated as KVM also
uses it on the permission fault handling path, leading to an ugly
"stash and restore" sequence. Fortunately, this is already a slow
path so we don't really care. Also, Linux doesn't do any AT*
operation, so Linux guests are not impacted by this bug.

  [ Slightly tweaked to use an even register as first operand to ldrd
    and strd operations in interrupts_head.S - Christoffer ]

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
arch/arm/include/asm/kvm_asm.h
arch/arm/kvm/coproc.c
arch/arm/kvm/interrupts.S
arch/arm/kvm/interrupts_head.S

index 6ae3d2a..a2f43dd 100644 (file)
 #define c5_AIFSR       15      /* Auxilary Instrunction Fault Status R */
 #define c6_DFAR                16      /* Data Fault Address Register */
 #define c6_IFAR                17      /* Instruction Fault Address Register */
-#define c9_L2CTLR      18      /* Cortex A15 L2 Control Register */
-#define c10_PRRR       19      /* Primary Region Remap Register */
-#define c10_NMRR       20      /* Normal Memory Remap Register */
-#define c12_VBAR       21      /* Vector Base Address Register */
-#define c13_CID                22      /* Context ID Register */
-#define c13_TID_URW    23      /* Thread ID, User R/W */
-#define c13_TID_URO    24      /* Thread ID, User R/O */
-#define c13_TID_PRIV   25      /* Thread ID, Privileged */
-#define c14_CNTKCTL    26      /* Timer Control Register (PL1) */
-#define NR_CP15_REGS   27      /* Number of regs (incl. invalid) */
+#define c7_PAR         18      /* Physical Address Register */
+#define c7_PAR_high    19      /* PAR top 32 bits */
+#define c9_L2CTLR      20      /* Cortex A15 L2 Control Register */
+#define c10_PRRR       21      /* Primary Region Remap Register */
+#define c10_NMRR       22      /* Normal Memory Remap Register */
+#define c12_VBAR       23      /* Vector Base Address Register */
+#define c13_CID                24      /* Context ID Register */
+#define c13_TID_URW    25      /* Thread ID, User R/W */
+#define c13_TID_URO    26      /* Thread ID, User R/O */
+#define c13_TID_PRIV   27      /* Thread ID, Privileged */
+#define c14_CNTKCTL    28      /* Timer Control Register (PL1) */
+#define NR_CP15_REGS   29      /* Number of regs (incl. invalid) */
 
 #define ARM_EXCEPTION_RESET      0
 #define ARM_EXCEPTION_UNDEFINED   1
index 8eea97b..4a51990 100644 (file)
@@ -180,6 +180,10 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c6_DFAR },
        { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32,
                        NULL, reset_unknown, c6_IFAR },
+
+       /* PAR swapped by interrupt.S */
+       { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
+
        /*
         * DC{C,I,CI}SW operations:
         */
index f7793df..d0a8fa3 100644 (file)
@@ -414,6 +414,10 @@ guest_trap:
        mrcne   p15, 4, r2, c6, c0, 4   @ HPFAR
        bne     3f
 
+       /* Preserve PAR */
+       mrrc    p15, 0, r0, r1, c7      @ PAR
+       push    {r0, r1}
+
        /* Resolve IPA using the xFAR */
        mcr     p15, 0, r2, c7, c8, 0   @ ATS1CPR
        isb
@@ -424,13 +428,19 @@ guest_trap:
        lsl     r2, r2, #4
        orr     r2, r2, r1, lsl #24
 
+       /* Restore PAR */
+       pop     {r0, r1}
+       mcrr    p15, 0, r0, r1, c7      @ PAR
+
 3:     load_vcpu                       @ Load VCPU pointer to r0
        str     r2, [r0, #VCPU_HPFAR]
 
 1:     mov     r1, #ARM_EXCEPTION_HVC
        b       __kvm_vcpu_return
 
-4:     pop     {r0, r1, r2}            @ Failed translation, return to guest
+4:     pop     {r0, r1}                @ Failed translation, return to guest
+       mcrr    p15, 0, r0, r1, c7      @ PAR
+       pop     {r0, r1, r2}
        eret
 
 /*
index 3c8f2f0..2b44b95 100644 (file)
@@ -302,11 +302,14 @@ vcpu      .req    r0              @ vcpu pointer always in r0
        .endif
 
        mrc     p15, 0, r2, c14, c1, 0  @ CNTKCTL
+       mrrc    p15, 0, r4, r5, c7      @ PAR
 
        .if \store_to_vcpu == 0
-       push    {r2}
+       push    {r2,r4-r5}
        .else
        str     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
+       add     r12, vcpu, #CP15_OFFSET(c7_PAR)
+       strd    r4, r5, [r12]
        .endif
 .endm
 
@@ -319,12 +322,15 @@ vcpu      .req    r0              @ vcpu pointer always in r0
  */
 .macro write_cp15_state read_from_vcpu
        .if \read_from_vcpu == 0
-       pop     {r2}
+       pop     {r2,r4-r5}
        .else
        ldr     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
+       add     r12, vcpu, #CP15_OFFSET(c7_PAR)
+       ldrd    r4, r5, [r12]
        .endif
 
        mcr     p15, 0, r2, c14, c1, 0  @ CNTKCTL
+       mcrr    p15, 0, r4, r5, c7      @ PAR
 
        .if \read_from_vcpu == 0
        pop     {r2-r12}