Skip to content

Commit 961e2bf

Browse files
committed
KVM/arm64 updates for 6.9 - Infrastructure for building KVM's trap configuration based on the architectural features (or lack thereof) advertised in the VM's ID registers - Support for mapping vfio-pci BARs as Normal-NC (vaguely similar to x86's WC) at stage-2, improving the performance of interacting with assigned devices that can tolerate it - Conversion of KVM's representation of LPIs to an xarray, utilized to address serialization some of the serialization on the LPI injection path - Support for _architectural_ VHE-only systems, advertised through the absence of FEAT_E2H0 in the CPU's ID register - Miscellaneous cleanups, fixes, and spelling corrections to KVM and selftests
2 parents 233d0bc + 4a09ddb commit 961e2bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1409
-387
lines changed

arch/arm64/include/asm/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct cpuinfo_arm64 {
5656
u64 reg_id_aa64mmfr1;
5757
u64 reg_id_aa64mmfr2;
5858
u64 reg_id_aa64mmfr3;
59+
u64 reg_id_aa64mmfr4;
5960
u64 reg_id_aa64pfr0;
6061
u64 reg_id_aa64pfr1;
6162
u64 reg_id_aa64zfr0;

arch/arm64/include/asm/cpufeature.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ struct arm64_cpu_capabilities {
363363
u8 field_pos;
364364
u8 field_width;
365365
u8 min_field_value;
366+
u8 max_field_value;
366367
u8 hwcap_type;
367368
bool sign;
368369
unsigned long hwcap;

arch/arm64/include/asm/kvm_arm.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,7 @@
102102
#define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
103103
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
104104

105-
#define HCRX_GUEST_FLAGS \
106-
(HCRX_EL2_SMPME | HCRX_EL2_TCR2En | \
107-
(cpus_have_final_cap(ARM64_HAS_MOPS) ? (HCRX_EL2_MSCEn | HCRX_EL2_MCE2) : 0))
105+
#define HCRX_GUEST_FLAGS (HCRX_EL2_SMPME | HCRX_EL2_TCR2En)
108106
#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En)
109107

110108
/* TCR_EL2 Registers bits */

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ static inline bool vcpu_is_el2(const struct kvm_vcpu *vcpu)
209209

210210
static inline bool __vcpu_el2_e2h_is_set(const struct kvm_cpu_context *ctxt)
211211
{
212-
return ctxt_sys_reg(ctxt, HCR_EL2) & HCR_E2H;
212+
return (!cpus_have_final_cap(ARM64_HAS_HCR_NV1) ||
213+
(ctxt_sys_reg(ctxt, HCR_EL2) & HCR_E2H));
213214
}
214215

215216
static inline bool vcpu_el2_e2h_is_set(const struct kvm_vcpu *vcpu)

arch/arm64/include/asm/kvm_host.h

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,32 @@ static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
238238
return index;
239239
}
240240

241+
struct kvm_sysreg_masks;
242+
243+
enum fgt_group_id {
244+
__NO_FGT_GROUP__,
245+
HFGxTR_GROUP,
246+
HDFGRTR_GROUP,
247+
HDFGWTR_GROUP = HDFGRTR_GROUP,
248+
HFGITR_GROUP,
249+
HAFGRTR_GROUP,
250+
251+
/* Must be last */
252+
__NR_FGT_GROUP_IDS__
253+
};
254+
241255
struct kvm_arch {
242256
struct kvm_s2_mmu mmu;
243257

258+
/*
259+
* Fine-Grained UNDEF, mimicking the FGT layout defined by the
260+
* architecture. We track them globally, as we present the
261+
* same feature-set to all vcpus.
262+
*
263+
* Index 0 is currently spare.
264+
*/
265+
u64 fgu[__NR_FGT_GROUP_IDS__];
266+
244267
/* Interrupt controller */
245268
struct vgic_dist vgic;
246269

@@ -274,6 +297,8 @@ struct kvm_arch {
274297
#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 6
275298
/* Initial ID reg values loaded */
276299
#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 7
300+
/* Fine-Grained UNDEF initialised */
301+
#define KVM_ARCH_FLAG_FGU_INITIALIZED 8
277302
unsigned long flags;
278303

279304
/* VM-wide vCPU feature set */
@@ -294,6 +319,9 @@ struct kvm_arch {
294319
/* PMCR_EL0.N value for the guest */
295320
u8 pmcr_n;
296321

322+
/* Iterator for idreg debugfs */
323+
u8 idreg_debugfs_iter;
324+
297325
/* Hypercall features firmware registers' descriptor */
298326
struct kvm_smccc_features smccc_feat;
299327
struct maple_tree smccc_filter;
@@ -312,6 +340,9 @@ struct kvm_arch {
312340
#define KVM_ARM_ID_REG_NUM (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
313341
u64 id_regs[KVM_ARM_ID_REG_NUM];
314342

343+
/* Masks for VNCR-baked sysregs */
344+
struct kvm_sysreg_masks *sysreg_masks;
345+
315346
/*
316347
* For an untrusted host VM, 'pkvm.handle' is used to lookup
317348
* the associated pKVM instance in the hypervisor.
@@ -474,6 +505,13 @@ enum vcpu_sysreg {
474505
NR_SYS_REGS /* Nothing after this line! */
475506
};
476507

508+
struct kvm_sysreg_masks {
509+
struct {
510+
u64 res0;
511+
u64 res1;
512+
} mask[NR_SYS_REGS - __VNCR_START__];
513+
};
514+
477515
struct kvm_cpu_context {
478516
struct user_pt_regs regs; /* sp = sp_el0 */
479517

@@ -549,6 +587,7 @@ struct kvm_vcpu_arch {
549587

550588
/* Values of trap registers for the guest. */
551589
u64 hcr_el2;
590+
u64 hcrx_el2;
552591
u64 mdcr_el2;
553592
u64 cptr_el2;
554593

@@ -868,7 +907,15 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
868907

869908
#define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r))
870909

871-
#define __vcpu_sys_reg(v,r) (ctxt_sys_reg(&(v)->arch.ctxt, (r)))
910+
u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
911+
#define __vcpu_sys_reg(v,r) \
912+
(*({ \
913+
const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
914+
u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
915+
if (vcpu_has_nv((v)) && (r) >= __VNCR_START__) \
916+
*__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
917+
__r; \
918+
}))
872919

873920
u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg);
874921
void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg);
@@ -1055,14 +1102,20 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu);
10551102
int kvm_handle_sys_reg(struct kvm_vcpu *vcpu);
10561103
int kvm_handle_cp10_id(struct kvm_vcpu *vcpu);
10571104

1105+
void kvm_sys_regs_create_debugfs(struct kvm *kvm);
10581106
void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
10591107

10601108
int __init kvm_sys_reg_table_init(void);
1109+
struct sys_reg_desc;
1110+
int __init populate_sysreg_config(const struct sys_reg_desc *sr,
1111+
unsigned int idx);
10611112
int __init populate_nv_trap_config(void);
10621113

10631114
bool lock_all_vcpus(struct kvm *kvm);
10641115
void unlock_all_vcpus(struct kvm *kvm);
10651116

1117+
void kvm_init_sysreg(struct kvm_vcpu *);
1118+
10661119
/* MMIO helpers */
10671120
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
10681121
unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
@@ -1233,4 +1286,48 @@ static inline void kvm_hyp_reserve(void) { }
12331286
void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu);
12341287
bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu);
12351288

1289+
#define __expand_field_sign_unsigned(id, fld, val) \
1290+
((u64)SYS_FIELD_VALUE(id, fld, val))
1291+
1292+
#define __expand_field_sign_signed(id, fld, val) \
1293+
({ \
1294+
u64 __val = SYS_FIELD_VALUE(id, fld, val); \
1295+
sign_extend64(__val, id##_##fld##_WIDTH - 1); \
1296+
})
1297+
1298+
#define expand_field_sign(id, fld, val) \
1299+
(id##_##fld##_SIGNED ? \
1300+
__expand_field_sign_signed(id, fld, val) : \
1301+
__expand_field_sign_unsigned(id, fld, val))
1302+
1303+
#define get_idreg_field_unsigned(kvm, id, fld) \
1304+
({ \
1305+
u64 __val = IDREG((kvm), SYS_##id); \
1306+
FIELD_GET(id##_##fld##_MASK, __val); \
1307+
})
1308+
1309+
#define get_idreg_field_signed(kvm, id, fld) \
1310+
({ \
1311+
u64 __val = get_idreg_field_unsigned(kvm, id, fld); \
1312+
sign_extend64(__val, id##_##fld##_WIDTH - 1); \
1313+
})
1314+
1315+
#define get_idreg_field_enum(kvm, id, fld) \
1316+
get_idreg_field_unsigned(kvm, id, fld)
1317+
1318+
#define get_idreg_field(kvm, id, fld) \
1319+
(id##_##fld##_SIGNED ? \
1320+
get_idreg_field_signed(kvm, id, fld) : \
1321+
get_idreg_field_unsigned(kvm, id, fld))
1322+
1323+
#define kvm_has_feat(kvm, id, fld, limit) \
1324+
(get_idreg_field((kvm), id, fld) >= expand_field_sign(id, fld, limit))
1325+
1326+
#define kvm_has_feat_enum(kvm, id, fld, val) \
1327+
(get_idreg_field_unsigned((kvm), id, fld) == __expand_field_sign_unsigned(id, fld, val))
1328+
1329+
#define kvm_has_feat_range(kvm, id, fld, min, max) \
1330+
(get_idreg_field((kvm), id, fld) >= expand_field_sign(id, fld, min) && \
1331+
get_idreg_field((kvm), id, fld) <= expand_field_sign(id, fld, max))
1332+
12361333
#endif /* __ARM64_KVM_HOST_H__ */

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
7070
/*
7171
* Without an __arch_swab32(), we fall back to ___constant_swab32(), but the
7272
* static inline can allow the compiler to out-of-line this. KVM always wants
73-
* the macro version as its always inlined.
73+
* the macro version as it's always inlined.
7474
*/
7575
#define __kvm_swab32(x) ___constant_swab32(x)
7676

arch/arm64/include/asm/kvm_mmu.h

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,27 +53,6 @@
5353

5454
#include <asm/alternative.h>
5555

56-
/*
57-
* Convert a kernel VA into a HYP VA.
58-
* reg: VA to be converted.
59-
*
60-
* The actual code generation takes place in kvm_update_va_mask, and
61-
* the instructions below are only there to reserve the space and
62-
* perform the register allocation (kvm_update_va_mask uses the
63-
* specific registers encoded in the instructions).
64-
*/
65-
.macro kern_hyp_va reg
66-
#ifndef __KVM_VHE_HYPERVISOR__
67-
alternative_cb ARM64_ALWAYS_SYSTEM, kvm_update_va_mask
68-
and \reg, \reg, #1 /* mask with va_mask */
69-
ror \reg, \reg, #1 /* rotate to the first tag bit */
70-
add \reg, \reg, #0 /* insert the low 12 bits of the tag */
71-
add \reg, \reg, #0, lsl 12 /* insert the top 12 bits of the tag */
72-
ror \reg, \reg, #63 /* rotate back */
73-
alternative_cb_end
74-
#endif
75-
.endm
76-
7756
/*
7857
* Convert a hypervisor VA to a PA
7958
* reg: hypervisor address to be converted in place
@@ -127,14 +106,29 @@ void kvm_apply_hyp_relocations(void);
127106

128107
#define __hyp_pa(x) (((phys_addr_t)(x)) + hyp_physvirt_offset)
129108

109+
/*
110+
* Convert a kernel VA into a HYP VA.
111+
*
112+
* Can be called from hyp or non-hyp context.
113+
*
114+
* The actual code generation takes place in kvm_update_va_mask(), and
115+
* the instructions below are only there to reserve the space and
116+
* perform the register allocation (kvm_update_va_mask() uses the
117+
* specific registers encoded in the instructions).
118+
*/
130119
static __always_inline unsigned long __kern_hyp_va(unsigned long v)
131120
{
121+
/*
122+
* This #ifndef is an optimisation for when this is called from VHE hyp
123+
* context. When called from a VHE non-hyp context, kvm_update_va_mask() will
124+
* replace the instructions with `nop`s.
125+
*/
132126
#ifndef __KVM_VHE_HYPERVISOR__
133-
asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
134-
"ror %0, %0, #1\n"
135-
"add %0, %0, #0\n"
136-
"add %0, %0, #0, lsl 12\n"
137-
"ror %0, %0, #63\n",
127+
asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n" /* mask with va_mask */
128+
"ror %0, %0, #1\n" /* rotate to the first tag bit */
129+
"add %0, %0, #0\n" /* insert the low 12 bits of the tag */
130+
"add %0, %0, #0, lsl 12\n" /* insert the top 12 bits of the tag */
131+
"ror %0, %0, #63\n", /* rotate back */
138132
ARM64_ALWAYS_SYSTEM,
139133
kvm_update_va_mask)
140134
: "+r" (v));

arch/arm64/include/asm/kvm_nested.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ static inline u64 translate_ttbr0_el2_to_ttbr0_el1(u64 ttbr0)
6060
return ttbr0 & ~GENMASK_ULL(63, 48);
6161
}
6262

63-
extern bool __check_nv_sr_forward(struct kvm_vcpu *vcpu);
6463

6564
int kvm_init_nv_sysregs(struct kvm *kvm);
6665

arch/arm64/include/asm/kvm_pgtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ enum kvm_pgtable_stage2_flags {
197197
* @KVM_PGTABLE_PROT_W: Write permission.
198198
* @KVM_PGTABLE_PROT_R: Read permission.
199199
* @KVM_PGTABLE_PROT_DEVICE: Device attributes.
200+
* @KVM_PGTABLE_PROT_NORMAL_NC: Normal noncacheable attributes.
200201
* @KVM_PGTABLE_PROT_SW0: Software bit 0.
201202
* @KVM_PGTABLE_PROT_SW1: Software bit 1.
202203
* @KVM_PGTABLE_PROT_SW2: Software bit 2.
@@ -208,6 +209,7 @@ enum kvm_pgtable_prot {
208209
KVM_PGTABLE_PROT_R = BIT(2),
209210

210211
KVM_PGTABLE_PROT_DEVICE = BIT(3),
212+
KVM_PGTABLE_PROT_NORMAL_NC = BIT(4),
211213

212214
KVM_PGTABLE_PROT_SW0 = BIT(55),
213215
KVM_PGTABLE_PROT_SW1 = BIT(56),

arch/arm64/include/asm/memory.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,15 @@
173173
* Memory types for Stage-2 translation
174174
*/
175175
#define MT_S2_NORMAL 0xf
176+
#define MT_S2_NORMAL_NC 0x5
176177
#define MT_S2_DEVICE_nGnRE 0x1
177178

178179
/*
179180
* Memory types for Stage-2 translation when ID_AA64MMFR2_EL1.FWB is 0001
180181
* Stage-2 enforces Normal-WB and Device-nGnRE
181182
*/
182183
#define MT_S2_FWB_NORMAL 6
184+
#define MT_S2_FWB_NORMAL_NC 5
183185
#define MT_S2_FWB_DEVICE_nGnRE 1
184186

185187
#ifdef CONFIG_ARM64_4K_PAGES

0 commit comments

Comments
 (0)