Skip to content

Commit 765bdb4

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM fixes from Paolo Bonzini: "KVM-ARM fixes, mostly coming from the PMU work" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: arm64: KVM: Fix guest dead loop when register accessor returns false arm64: KVM: Fix comments of the CP handler arm64: KVM: Fix wrong use of the CPSR MODE mask for 32bit guests arm64: KVM: Obey RES0/1 reserved bits when setting CPTR_EL2 arm64: KVM: Fix AArch64 guest userspace exception injection
2 parents 92e6edd + afc6074 commit 765bdb4

File tree

5 files changed

+52
-12
lines changed

5 files changed

+52
-12
lines changed

arch/arm64/include/asm/kvm_arm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
#define CPTR_EL2_TCPAC (1 << 31)
183183
#define CPTR_EL2_TTA (1 << 20)
184184
#define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT)
185+
#define CPTR_EL2_DEFAULT 0x000033ff
185186

186187
/* Hyp Debug Configuration Register bits */
187188
#define MDCR_EL2_TDRA (1 << 11)

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,14 @@ static inline unsigned long *vcpu_spsr(const struct kvm_vcpu *vcpu)
127127

128128
static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
129129
{
130-
u32 mode = *vcpu_cpsr(vcpu) & PSR_MODE_MASK;
130+
u32 mode;
131131

132-
if (vcpu_mode_is_32bit(vcpu))
132+
if (vcpu_mode_is_32bit(vcpu)) {
133+
mode = *vcpu_cpsr(vcpu) & COMPAT_PSR_MODE_MASK;
133134
return mode > COMPAT_PSR_MODE_USR;
135+
}
136+
137+
mode = *vcpu_cpsr(vcpu) & PSR_MODE_MASK;
134138

135139
return mode != PSR_MODE_EL0t;
136140
}

arch/arm64/kvm/hyp/switch.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
3636
write_sysreg(val, hcr_el2);
3737
/* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
3838
write_sysreg(1 << 15, hstr_el2);
39-
write_sysreg(CPTR_EL2_TTA | CPTR_EL2_TFP, cptr_el2);
39+
40+
val = CPTR_EL2_DEFAULT;
41+
val |= CPTR_EL2_TTA | CPTR_EL2_TFP;
42+
write_sysreg(val, cptr_el2);
43+
4044
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
4145
}
4246

@@ -45,7 +49,7 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
4549
write_sysreg(HCR_RW, hcr_el2);
4650
write_sysreg(0, hstr_el2);
4751
write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2);
48-
write_sysreg(0, cptr_el2);
52+
write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
4953
}
5054

5155
static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)

arch/arm64/kvm/inject_fault.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727

2828
#define PSTATE_FAULT_BITS_64 (PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | \
2929
PSR_I_BIT | PSR_D_BIT)
30-
#define EL1_EXCEPT_SYNC_OFFSET 0x200
30+
31+
#define CURRENT_EL_SP_EL0_VECTOR 0x0
32+
#define CURRENT_EL_SP_ELx_VECTOR 0x200
33+
#define LOWER_EL_AArch64_VECTOR 0x400
34+
#define LOWER_EL_AArch32_VECTOR 0x600
3135

3236
static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
3337
{
@@ -97,6 +101,34 @@ static void inject_abt32(struct kvm_vcpu *vcpu, bool is_pabt,
97101
*fsr = 0x14;
98102
}
99103

104+
enum exception_type {
105+
except_type_sync = 0,
106+
except_type_irq = 0x80,
107+
except_type_fiq = 0x100,
108+
except_type_serror = 0x180,
109+
};
110+
111+
static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
112+
{
113+
u64 exc_offset;
114+
115+
switch (*vcpu_cpsr(vcpu) & (PSR_MODE_MASK | PSR_MODE32_BIT)) {
116+
case PSR_MODE_EL1t:
117+
exc_offset = CURRENT_EL_SP_EL0_VECTOR;
118+
break;
119+
case PSR_MODE_EL1h:
120+
exc_offset = CURRENT_EL_SP_ELx_VECTOR;
121+
break;
122+
case PSR_MODE_EL0t:
123+
exc_offset = LOWER_EL_AArch64_VECTOR;
124+
break;
125+
default:
126+
exc_offset = LOWER_EL_AArch32_VECTOR;
127+
}
128+
129+
return vcpu_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
130+
}
131+
100132
static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
101133
{
102134
unsigned long cpsr = *vcpu_cpsr(vcpu);
@@ -108,8 +140,8 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
108140
*vcpu_spsr(vcpu) = cpsr;
109141
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
110142

143+
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
111144
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
112-
*vcpu_pc(vcpu) = vcpu_sys_reg(vcpu, VBAR_EL1) + EL1_EXCEPT_SYNC_OFFSET;
113145

114146
vcpu_sys_reg(vcpu, FAR_EL1) = addr;
115147

@@ -143,8 +175,8 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
143175
*vcpu_spsr(vcpu) = cpsr;
144176
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
145177

178+
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
146179
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
147-
*vcpu_pc(vcpu) = vcpu_sys_reg(vcpu, VBAR_EL1) + EL1_EXCEPT_SYNC_OFFSET;
148180

149181
/*
150182
* Build an unknown exception, depending on the instruction

arch/arm64/kvm/sys_regs.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,10 +1007,9 @@ static int emulate_cp(struct kvm_vcpu *vcpu,
10071007
if (likely(r->access(vcpu, params, r))) {
10081008
/* Skip instruction, since it was emulated */
10091009
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
1010+
/* Handled */
1011+
return 0;
10101012
}
1011-
1012-
/* Handled */
1013-
return 0;
10141013
}
10151014

10161015
/* Not handled */
@@ -1043,7 +1042,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
10431042
}
10441043

10451044
/**
1046-
* kvm_handle_cp_64 -- handles a mrrc/mcrr trap on a guest CP15 access
1045+
* kvm_handle_cp_64 -- handles a mrrc/mcrr trap on a guest CP14/CP15 access
10471046
* @vcpu: The VCPU pointer
10481047
* @run: The kvm_run struct
10491048
*/
@@ -1095,7 +1094,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
10951094
}
10961095

10971096
/**
1098-
* kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
1097+
* kvm_handle_cp_32 -- handles a mrc/mcr trap on a guest CP14/CP15 access
10991098
* @vcpu: The VCPU pointer
11001099
* @run: The kvm_run struct
11011100
*/

0 commit comments

Comments
 (0)