Skip to content

Commit 14d4802

Browse files
author
Marc Zyngier
committed
KVM: arm64: Allow use of S1 PTW for non-NV vcpus
As we are about to use the S1 PTW in non-NV contexts, we must make sure that we don't evaluate the EL2 state when dealing with the EL1&0 translation regime. Reviewed-by: Oliver Upton <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent dabf9f7 commit 14d4802

File tree

1 file changed

+28
-30
lines changed

1 file changed

+28
-30
lines changed

arch/arm64/kvm/at.c

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,26 @@ static enum trans_regime compute_translation_regime(struct kvm_vcpu *vcpu, u32 o
9898
}
9999
}
100100

101+
static u64 effective_tcr2(struct kvm_vcpu *vcpu, enum trans_regime regime)
102+
{
103+
if (regime == TR_EL10) {
104+
if (vcpu_has_nv(vcpu) &&
105+
!(__vcpu_sys_reg(vcpu, HCRX_EL2) & HCRX_EL2_TCR2En))
106+
return 0;
107+
108+
return __vcpu_sys_reg(vcpu, TCR2_EL1);
109+
}
110+
111+
return vcpu_read_sys_reg(vcpu, TCR2_EL2);
112+
}
113+
101114
static bool s1pie_enabled(struct kvm_vcpu *vcpu, enum trans_regime regime)
102115
{
103116
if (!kvm_has_s1pie(vcpu->kvm))
104117
return false;
105118

106-
switch (regime) {
107-
case TR_EL2:
108-
case TR_EL20:
109-
return vcpu_read_sys_reg(vcpu, TCR2_EL2) & TCR2_EL2_PIE;
110-
case TR_EL10:
111-
return (__vcpu_sys_reg(vcpu, HCRX_EL2) & HCRX_EL2_TCR2En) &&
112-
(__vcpu_sys_reg(vcpu, TCR2_EL1) & TCR2_EL1_PIE);
113-
default:
114-
BUG();
115-
}
119+
/* Abuse TCR2_EL1_PIE and use it for EL2 as well */
120+
return effective_tcr2(vcpu, regime) & TCR2_EL1_PIE;
116121
}
117122

118123
static void compute_s1poe(struct kvm_vcpu *vcpu, struct s1_walk_info *wi)
@@ -124,23 +129,11 @@ static void compute_s1poe(struct kvm_vcpu *vcpu, struct s1_walk_info *wi)
124129
return;
125130
}
126131

127-
switch (wi->regime) {
128-
case TR_EL2:
129-
case TR_EL20:
130-
val = vcpu_read_sys_reg(vcpu, TCR2_EL2);
131-
wi->poe = val & TCR2_EL2_POE;
132-
wi->e0poe = (wi->regime == TR_EL20) && (val & TCR2_EL2_E0POE);
133-
break;
134-
case TR_EL10:
135-
if (__vcpu_sys_reg(vcpu, HCRX_EL2) & HCRX_EL2_TCR2En) {
136-
wi->poe = wi->e0poe = false;
137-
return;
138-
}
132+
val = effective_tcr2(vcpu, wi->regime);
139133

140-
val = __vcpu_sys_reg(vcpu, TCR2_EL1);
141-
wi->poe = val & TCR2_EL1_POE;
142-
wi->e0poe = val & TCR2_EL1_E0POE;
143-
}
134+
/* Abuse TCR2_EL1_* for EL2 */
135+
wi->poe = val & TCR2_EL1_POE;
136+
wi->e0poe = (wi->regime != TR_EL2) && (val & TCR2_EL1_E0POE);
144137
}
145138

146139
static int setup_s1_walk(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
@@ -150,11 +143,16 @@ static int setup_s1_walk(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
150143
unsigned int stride, x;
151144
bool va55, tbi, lva;
152145

153-
hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
154-
155146
va55 = va & BIT(55);
156147

157-
wi->s2 = wi->regime == TR_EL10 && (hcr & (HCR_VM | HCR_DC));
148+
if (vcpu_has_nv(vcpu)) {
149+
hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
150+
wi->s2 = wi->regime == TR_EL10 && (hcr & (HCR_VM | HCR_DC));
151+
} else {
152+
WARN_ON_ONCE(wi->regime != TR_EL10);
153+
wi->s2 = false;
154+
hcr = 0;
155+
}
158156

159157
switch (wi->regime) {
160158
case TR_EL10:
@@ -851,7 +849,7 @@ static u64 compute_par_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
851849
par = SYS_PAR_EL1_NSE;
852850
par |= wr->pa & SYS_PAR_EL1_PA;
853851

854-
if (wi->regime == TR_EL10 &&
852+
if (wi->regime == TR_EL10 && vcpu_has_nv(vcpu) &&
855853
(__vcpu_sys_reg(vcpu, HCR_EL2) & HCR_DC)) {
856854
par |= FIELD_PREP(SYS_PAR_EL1_ATTR,
857855
MEMATTR(WbRaWa, WbRaWa));

0 commit comments

Comments
 (0)