Skip to content

Commit 45b890f

Browse files
committed
Merge tag 'kvmarm-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 updates for 6.7 - Generalized infrastructure for 'writable' ID registers, effectively allowing userspace to opt-out of certain vCPU features for its guest - Optimization for vSGI injection, opportunistically compressing MPIDR to vCPU mapping into a table - Improvements to KVM's PMU emulation, allowing userspace to select the number of PMCs available to a VM - Guest support for memory operation instructions (FEAT_MOPS) - Cleanups to handling feature flags in KVM_ARM_VCPU_INIT, squashing bugs and getting rid of useless code - Changes to the way the SMCCC filter is constructed, avoiding wasted memory allocations when not in use - Load the stage-2 MMU context at vcpu_load() for VHE systems, reducing the overhead of errata mitigations - Miscellaneous kernel and selftest fixes
2 parents be47941 + 123f42f commit 45b890f

Some content is hidden

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

64 files changed

+3019
-1177
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3422,6 +3422,8 @@ return indicates the attribute is implemented. It does not necessarily
34223422
indicate that the attribute can be read or written in the device's
34233423
current state. "addr" is ignored.
34243424

3425+
.. _KVM_ARM_VCPU_INIT:
3426+
34253427
4.82 KVM_ARM_VCPU_INIT
34263428
----------------------
34273429

@@ -6140,6 +6142,56 @@ writes to the CNTVCT_EL0 and CNTPCT_EL0 registers using the SET_ONE_REG
61406142
interface. No error will be returned, but the resulting offset will not be
61416143
applied.
61426144

6145+
.. _KVM_ARM_GET_REG_WRITABLE_MASKS:
6146+
6147+
4.139 KVM_ARM_GET_REG_WRITABLE_MASKS
6148+
-------------------------------------------
6149+
6150+
:Capability: KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES
6151+
:Architectures: arm64
6152+
:Type: vm ioctl
6153+
:Parameters: struct reg_mask_range (in/out)
6154+
:Returns: 0 on success, < 0 on error
6155+
6156+
6157+
::
6158+
6159+
#define KVM_ARM_FEATURE_ID_RANGE 0
6160+
#define KVM_ARM_FEATURE_ID_RANGE_SIZE (3 * 8 * 8)
6161+
6162+
struct reg_mask_range {
6163+
__u64 addr; /* Pointer to mask array */
6164+
__u32 range; /* Requested range */
6165+
__u32 reserved[13];
6166+
};
6167+
6168+
This ioctl copies the writable masks for a selected range of registers to
6169+
userspace.
6170+
6171+
The ``addr`` field is a pointer to the destination array where KVM copies
6172+
the writable masks.
6173+
6174+
The ``range`` field indicates the requested range of registers.
6175+
``KVM_CHECK_EXTENSION`` for the ``KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES``
6176+
capability returns the supported ranges, expressed as a set of flags. Each
6177+
flag's bit index represents a possible value for the ``range`` field.
6178+
All other values are reserved for future use and KVM may return an error.
6179+
6180+
The ``reserved[13]`` array is reserved for future use and should be 0, or
6181+
KVM may return an error.
6182+
6183+
KVM_ARM_FEATURE_ID_RANGE (0)
6184+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6185+
6186+
The Feature ID range is defined as the AArch64 System register space with
6187+
op0==3, op1=={0, 1, 3}, CRn==0, CRm=={0-7}, op2=={0-7}.
6188+
6189+
The mask returned array pointed to by ``addr`` is indexed by the macro
6190+
``ARM64_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2)``, allowing userspace
6191+
to know what fields can be changed for the system register described by
6192+
``op0, op1, crn, crm, op2``. KVM rejects ID register values that describe a
6193+
superset of the features supported by the system.
6194+
61436195
5. The kvm_run structure
61446196
========================
61456197

Documentation/virt/kvm/arm/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ ARM
1111
hypercalls
1212
pvtime
1313
ptp_kvm
14+
vcpu-features
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
===============================
4+
vCPU feature selection on arm64
5+
===============================
6+
7+
KVM/arm64 provides two mechanisms that allow userspace to configure
8+
the CPU features presented to the guest.
9+
10+
KVM_ARM_VCPU_INIT
11+
=================
12+
13+
The ``KVM_ARM_VCPU_INIT`` ioctl accepts a bitmap of feature flags
14+
(``struct kvm_vcpu_init::features``). Features enabled by this interface are
15+
*opt-in* and may change/extend UAPI. See :ref:`KVM_ARM_VCPU_INIT` for complete
16+
documentation of the features controlled by the ioctl.
17+
18+
Otherwise, all CPU features supported by KVM are described by the architected
19+
ID registers.
20+
21+
The ID Registers
22+
================
23+
24+
The Arm architecture specifies a range of *ID Registers* that describe the set
25+
of architectural features supported by the CPU implementation. KVM initializes
26+
the guest's ID registers to the maximum set of CPU features supported by the
27+
system. The ID register values may be VM-scoped in KVM, meaning that the
28+
values could be shared for all vCPUs in a VM.
29+
30+
KVM allows userspace to *opt-out* of certain CPU features described by the ID
31+
registers by writing values to them via the ``KVM_SET_ONE_REG`` ioctl. The ID
32+
registers are mutable until the VM has started, i.e. userspace has called
33+
``KVM_RUN`` on at least one vCPU in the VM. Userspace can discover what fields
34+
are mutable in the ID registers using the ``KVM_ARM_GET_REG_WRITABLE_MASKS``.
35+
See the :ref:`ioctl documentation <KVM_ARM_GET_REG_WRITABLE_MASKS>` for more
36+
details.
37+
38+
Userspace is allowed to *limit* or *mask* CPU features according to the rules
39+
outlined by the architecture in DDI0487J.a D19.1.3 'Principles of the ID
40+
scheme for fields in ID register'. KVM does not allow ID register values that
41+
exceed the capabilities of the system.
42+
43+
.. warning::
44+
It is **strongly recommended** that userspace modify the ID register values
45+
before accessing the rest of the vCPU's CPU register state. KVM may use the
46+
ID register values to control feature emulation. Interleaving ID register
47+
modification with other system register accesses may lead to unpredictable
48+
behavior.

Documentation/virt/kvm/devices/arm-vgic-v3.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ Groups:
5959
It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
6060
KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
6161

62+
Note that to obtain reproducible results (the same VCPU being associated
63+
with the same redistributor across a save/restore operation), VCPU creation
64+
order, redistributor region creation order as well as the respective
65+
interleaves of VCPU and region creation MUST be preserved. Any change in
66+
either ordering may result in a different vcpu_id/redistributor association,
67+
resulting in a VM that will fail to run at restore time.
68+
6269
Errors:
6370

6471
======= =============================================================

arch/arm64/include/asm/kvm_arm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@
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 (HCRX_EL2_SMPME | HCRX_EL2_TCR2En)
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))
106108
#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En)
107109

108110
/* TCR_EL2 Registers bits */

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu);
5454
int kvm_inject_nested_sync(struct kvm_vcpu *vcpu, u64 esr_el2);
5555
int kvm_inject_nested_irq(struct kvm_vcpu *vcpu);
5656

57+
static inline bool vcpu_has_feature(const struct kvm_vcpu *vcpu, int feature)
58+
{
59+
return test_bit(feature, vcpu->kvm->arch.vcpu_features);
60+
}
61+
5762
#if defined(__KVM_VHE_HYPERVISOR__) || defined(__KVM_NVHE_HYPERVISOR__)
5863
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
5964
{
@@ -62,7 +67,7 @@ static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
6267
#else
6368
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
6469
{
65-
return test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features);
70+
return vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
6671
}
6772
#endif
6873

@@ -465,7 +470,7 @@ static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
465470

466471
static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
467472
{
468-
return vcpu_read_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
473+
return __vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
469474
}
470475

471476
static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
@@ -565,12 +570,6 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
565570
vcpu_set_flag((v), e); \
566571
} while (0)
567572

568-
569-
static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature)
570-
{
571-
return test_bit(feature, vcpu->arch.features);
572-
}
573-
574573
static __always_inline void kvm_write_cptr_el2(u64 val)
575574
{
576575
if (has_vhe() || has_hvhe())

arch/arm64/include/asm/kvm_host.h

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ extern unsigned int __ro_after_init kvm_sve_max_vl;
7878
int __init kvm_arm_init_sve(void);
7979

8080
u32 __attribute_const__ kvm_target_cpu(void);
81-
int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
81+
void kvm_reset_vcpu(struct kvm_vcpu *vcpu);
8282
void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu);
8383

8484
struct kvm_hyp_memcache {
@@ -158,6 +158,16 @@ struct kvm_s2_mmu {
158158
phys_addr_t pgd_phys;
159159
struct kvm_pgtable *pgt;
160160

161+
/*
162+
* VTCR value used on the host. For a non-NV guest (or a NV
163+
* guest that runs in a context where its own S2 doesn't
164+
* apply), its T0SZ value reflects that of the IPA size.
165+
*
166+
* For a shadow S2 MMU, T0SZ reflects the PARange exposed to
167+
* the guest.
168+
*/
169+
u64 vtcr;
170+
161171
/* The last vcpu id that ran on each physical CPU */
162172
int __percpu *last_vcpu_ran;
163173

@@ -202,12 +212,34 @@ struct kvm_protected_vm {
202212
struct kvm_hyp_memcache teardown_mc;
203213
};
204214

215+
struct kvm_mpidr_data {
216+
u64 mpidr_mask;
217+
DECLARE_FLEX_ARRAY(u16, cmpidr_to_idx);
218+
};
219+
220+
static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
221+
{
222+
unsigned long mask = data->mpidr_mask;
223+
u64 aff = mpidr & MPIDR_HWID_BITMASK;
224+
int nbits, bit, bit_idx = 0;
225+
u16 index = 0;
226+
227+
/*
228+
* If this looks like RISC-V's BEXT or x86's PEXT
229+
* instructions, it isn't by accident.
230+
*/
231+
nbits = fls(mask);
232+
for_each_set_bit(bit, &mask, nbits) {
233+
index |= (aff & BIT(bit)) >> (bit - bit_idx);
234+
bit_idx++;
235+
}
236+
237+
return index;
238+
}
239+
205240
struct kvm_arch {
206241
struct kvm_s2_mmu mmu;
207242

208-
/* VTCR_EL2 value for this VM */
209-
u64 vtcr;
210-
211243
/* Interrupt controller */
212244
struct vgic_dist vgic;
213245

@@ -239,15 +271,16 @@ struct kvm_arch {
239271
#define KVM_ARCH_FLAG_VM_COUNTER_OFFSET 5
240272
/* Timer PPIs made immutable */
241273
#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 6
242-
/* SMCCC filter initialized for the VM */
243-
#define KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED 7
244274
/* Initial ID reg values loaded */
245-
#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 8
275+
#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 7
246276
unsigned long flags;
247277

248278
/* VM-wide vCPU feature set */
249279
DECLARE_BITMAP(vcpu_features, KVM_VCPU_MAX_FEATURES);
250280

281+
/* MPIDR to vcpu index mapping, optional */
282+
struct kvm_mpidr_data *mpidr_data;
283+
251284
/*
252285
* VM-wide PMU filter, implemented as a bitmap and big enough for
253286
* up to 2^10 events (ARMv8.0) or 2^16 events (ARMv8.1+).
@@ -257,6 +290,9 @@ struct kvm_arch {
257290

258291
cpumask_var_t supported_cpus;
259292

293+
/* PMCR_EL0.N value for the guest */
294+
u8 pmcr_n;
295+
260296
/* Hypercall features firmware registers' descriptor */
261297
struct kvm_smccc_features smccc_feat;
262298
struct maple_tree smccc_filter;
@@ -574,9 +610,6 @@ struct kvm_vcpu_arch {
574610
/* Cache some mmu pages needed inside spinlock regions */
575611
struct kvm_mmu_memory_cache mmu_page_cache;
576612

577-
/* feature flags */
578-
DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
579-
580613
/* Virtual SError ESR to restore when HCR_EL2.VSE is set */
581614
u64 vsesr_el2;
582615

@@ -1025,7 +1058,7 @@ int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
10251058
extern unsigned int __ro_after_init kvm_arm_vmid_bits;
10261059
int __init kvm_arm_vmid_alloc_init(void);
10271060
void __init kvm_arm_vmid_alloc_free(void);
1028-
void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
1061+
bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
10291062
void kvm_arm_vmid_clear_active(void);
10301063

10311064
static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
@@ -1078,6 +1111,8 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
10781111
struct kvm_arm_copy_mte_tags *copy_tags);
10791112
int kvm_vm_ioctl_set_counter_offset(struct kvm *kvm,
10801113
struct kvm_arm_counter_offset *offset);
1114+
int kvm_vm_ioctl_get_reg_writable_masks(struct kvm *kvm,
1115+
struct reg_mask_range *range);
10811116

10821117
/* Guest/host FPSIMD coordination helpers */
10831118
int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
@@ -1109,8 +1144,8 @@ static inline bool kvm_set_pmuserenr(u64 val)
11091144
}
11101145
#endif
11111146

1112-
void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu);
1113-
void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu);
1147+
void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
1148+
void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu);
11141149

11151150
int __init kvm_set_ipa_limit(void);
11161151

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ void __timer_disable_traps(struct kvm_vcpu *vcpu);
9393
void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
9494
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
9595
#else
96+
void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu);
97+
void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu);
9698
void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
9799
void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
98100
void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
@@ -111,11 +113,6 @@ void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
111113
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
112114
void __sve_restore_state(void *sve_pffr, u32 *fpsr);
113115

114-
#ifndef __KVM_NVHE_HYPERVISOR__
115-
void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
116-
void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
117-
#endif
118-
119116
u64 __guest_enter(struct kvm_vcpu *vcpu);
120117

121118
bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);

0 commit comments

Comments
 (0)