aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2013-06-07 06:02:34 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2013-08-09 08:19:28 -0400
commit1bbd80549810637b7381ab0649ba7c7d62f1342a (patch)
treebaeef747d13eeb37203e62e9516256ae248a0831
parentc095ba7224d8edc71dcef0d655911399a8bd4a3f (diff)
arm64: KVM: perform save/restore of PAR_EL1
Not saving PAR_EL1 is an unfortunate oversight. If the guest performs an AT* operation and gets scheduled out before reading the result of the translation from PAREL1, 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. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--arch/arm64/include/asm/kvm_asm.h17
-rw-r--r--arch/arm64/kvm/hyp.S10
-rw-r--r--arch/arm64/kvm/sys_regs.c3
3 files changed, 23 insertions, 7 deletions
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index c92de4163eba..b25763bc0ec4 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -42,14 +42,15 @@
42#define TPIDR_EL1 18 /* Thread ID, Privileged */ 42#define TPIDR_EL1 18 /* Thread ID, Privileged */
43#define AMAIR_EL1 19 /* Aux Memory Attribute Indirection Register */ 43#define AMAIR_EL1 19 /* Aux Memory Attribute Indirection Register */
44#define CNTKCTL_EL1 20 /* Timer Control Register (EL1) */ 44#define CNTKCTL_EL1 20 /* Timer Control Register (EL1) */
45#define PAR_EL1 21 /* Physical Address Register */
45/* 32bit specific registers. Keep them at the end of the range */ 46/* 32bit specific registers. Keep them at the end of the range */
46#define DACR32_EL2 21 /* Domain Access Control Register */ 47#define DACR32_EL2 22 /* Domain Access Control Register */
47#define IFSR32_EL2 22 /* Instruction Fault Status Register */ 48#define IFSR32_EL2 23 /* Instruction Fault Status Register */
48#define FPEXC32_EL2 23 /* Floating-Point Exception Control Register */ 49#define FPEXC32_EL2 24 /* Floating-Point Exception Control Register */
49#define DBGVCR32_EL2 24 /* Debug Vector Catch Register */ 50#define DBGVCR32_EL2 25 /* Debug Vector Catch Register */
50#define TEECR32_EL1 25 /* ThumbEE Configuration Register */ 51#define TEECR32_EL1 26 /* ThumbEE Configuration Register */
51#define TEEHBR32_EL1 26 /* ThumbEE Handler Base Register */ 52#define TEEHBR32_EL1 27 /* ThumbEE Handler Base Register */
52#define NR_SYS_REGS 27 53#define NR_SYS_REGS 28
53 54
54/* 32bit mapping */ 55/* 32bit mapping */
55#define c0_MPIDR (MPIDR_EL1 * 2) /* MultiProcessor ID Register */ 56#define c0_MPIDR (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
@@ -69,6 +70,8 @@
69#define c5_AIFSR (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */ 70#define c5_AIFSR (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */
70#define c6_DFAR (FAR_EL1 * 2) /* Data Fault Address Register */ 71#define c6_DFAR (FAR_EL1 * 2) /* Data Fault Address Register */
71#define c6_IFAR (c6_DFAR + 1) /* Instruction Fault Address Register */ 72#define c6_IFAR (c6_DFAR + 1) /* Instruction Fault Address Register */
73#define c7_PAR (PAR_EL1 * 2) /* Physical Address Register */
74#define c7_PAR_high (c7_PAR + 1) /* PAR top 32 bits */
72#define c10_PRRR (MAIR_EL1 * 2) /* Primary Region Remap Register */ 75#define c10_PRRR (MAIR_EL1 * 2) /* Primary Region Remap Register */
73#define c10_NMRR (c10_PRRR + 1) /* Normal Memory Remap Register */ 76#define c10_NMRR (c10_PRRR + 1) /* Normal Memory Remap Register */
74#define c12_VBAR (VBAR_EL1 * 2) /* Vector Base Address Register */ 77#define c12_VBAR (VBAR_EL1 * 2) /* Vector Base Address Register */
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index ff985e3d8b72..218802f68b20 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -214,6 +214,7 @@ __kvm_hyp_code_start:
214 mrs x21, tpidr_el1 214 mrs x21, tpidr_el1
215 mrs x22, amair_el1 215 mrs x22, amair_el1
216 mrs x23, cntkctl_el1 216 mrs x23, cntkctl_el1
217 mrs x24, par_el1
217 218
218 stp x4, x5, [x3] 219 stp x4, x5, [x3]
219 stp x6, x7, [x3, #16] 220 stp x6, x7, [x3, #16]
@@ -225,6 +226,7 @@ __kvm_hyp_code_start:
225 stp x18, x19, [x3, #112] 226 stp x18, x19, [x3, #112]
226 stp x20, x21, [x3, #128] 227 stp x20, x21, [x3, #128]
227 stp x22, x23, [x3, #144] 228 stp x22, x23, [x3, #144]
229 str x24, [x3, #160]
228.endm 230.endm
229 231
230.macro restore_sysregs 232.macro restore_sysregs
@@ -243,6 +245,7 @@ __kvm_hyp_code_start:
243 ldp x18, x19, [x3, #112] 245 ldp x18, x19, [x3, #112]
244 ldp x20, x21, [x3, #128] 246 ldp x20, x21, [x3, #128]
245 ldp x22, x23, [x3, #144] 247 ldp x22, x23, [x3, #144]
248 ldr x24, [x3, #160]
246 249
247 msr vmpidr_el2, x4 250 msr vmpidr_el2, x4
248 msr csselr_el1, x5 251 msr csselr_el1, x5
@@ -264,6 +267,7 @@ __kvm_hyp_code_start:
264 msr tpidr_el1, x21 267 msr tpidr_el1, x21
265 msr amair_el1, x22 268 msr amair_el1, x22
266 msr cntkctl_el1, x23 269 msr cntkctl_el1, x23
270 msr par_el1, x24
267.endm 271.endm
268 272
269.macro skip_32bit_state tmp, target 273.macro skip_32bit_state tmp, target
@@ -753,6 +757,10 @@ el1_trap:
753 */ 757 */
754 tbnz x1, #7, 1f // S1PTW is set 758 tbnz x1, #7, 1f // S1PTW is set
755 759
760 /* Preserve PAR_EL1 */
761 mrs x3, par_el1
762 push x3, xzr
763
756 /* 764 /*
757 * Permission fault, HPFAR_EL2 is invalid. 765 * Permission fault, HPFAR_EL2 is invalid.
758 * Resolve the IPA the hard way using the guest VA. 766 * Resolve the IPA the hard way using the guest VA.
@@ -766,6 +774,8 @@ el1_trap:
766 774
767 /* Read result */ 775 /* Read result */
768 mrs x3, par_el1 776 mrs x3, par_el1
777 pop x0, xzr // Restore PAR_EL1 from the stack
778 msr par_el1, x0
769 tbnz x3, #0, 3f // Bail out if we failed the translation 779 tbnz x3, #0, 3f // Bail out if we failed the translation
770 ubfx x3, x3, #12, #36 // Extract IPA 780 ubfx x3, x3, #12, #36 // Extract IPA
771 lsl x3, x3, #4 // and present it like HPFAR 781 lsl x3, x3, #4 // and present it like HPFAR
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 94923609753b..02e9d09e1d80 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -211,6 +211,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
211 /* FAR_EL1 */ 211 /* FAR_EL1 */
212 { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000), 212 { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
213 NULL, reset_unknown, FAR_EL1 }, 213 NULL, reset_unknown, FAR_EL1 },
214 /* PAR_EL1 */
215 { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000),
216 NULL, reset_unknown, PAR_EL1 },
214 217
215 /* PMINTENSET_EL1 */ 218 /* PMINTENSET_EL1 */
216 { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001), 219 { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),