Skip to content

Commit b22498c

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/timer-vm-offsets into kvmarm-master/next
* kvm-arm64/timer-vm-offsets: (21 commits) : . : This series aims at satisfying multiple goals: : : - allow a VMM to atomically restore a timer offset for a whole VM : instead of updating the offset each time a vcpu get its counter : written : : - allow a VMM to save/restore the physical timer context, something : that we cannot do at the moment due to the lack of offsetting : : - provide a framework that is suitable for NV support, where we get : both global and per timer, per vcpu offsetting, and manage : interrupts in a less braindead way. : : Conflict resolution involves using the new per-vcpu config lock instead : of the home-grown timer lock. : . KVM: arm64: Handle 32bit CNTPCTSS traps KVM: arm64: selftests: Augment existing timer test to handle variable offset KVM: arm64: selftests: Deal with spurious timer interrupts KVM: arm64: selftests: Add physical timer registers to the sysreg list KVM: arm64: nv: timers: Support hyp timer emulation KVM: arm64: nv: timers: Add a per-timer, per-vcpu offset KVM: arm64: Document KVM_ARM_SET_CNT_OFFSETS and co KVM: arm64: timers: Abstract the number of valid timers per vcpu KVM: arm64: timers: Fast-track CNTPCT_EL0 trap handling KVM: arm64: Elide kern_hyp_va() in VHE-specific parts of the hypervisor KVM: arm64: timers: Move the timer IRQs into arch_timer_vm_data KVM: arm64: timers: Abstract per-timer IRQ access KVM: arm64: timers: Rationalise per-vcpu timer init KVM: arm64: timers: Allow save/restoring of the physical timer KVM: arm64: timers: Allow userspace to set the global counter offset KVM: arm64: Expose {un,}lock_all_vcpus() to the rest of KVM KVM: arm64: timers: Allow physical offset without CNTPOFF_EL2 KVM: arm64: timers: Use CNTPOFF_EL2 to offset the physical timer arm64: Add HAS_ECV_CNTPOFF capability arm64: Add CNTPOFF_EL2 register definition ... Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents ef5f97e + a661043 commit b22498c

25 files changed

Lines changed: 758 additions & 204 deletions

File tree

Documentation/virt/kvm/api.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6029,6 +6029,44 @@ delivery must be provided via the "reg_aen" struct.
60296029
The "pad" and "reserved" fields may be used for future extensions and should be
60306030
set to 0s by userspace.
60316031

6032+
4.138 KVM_ARM_SET_COUNTER_OFFSET
6033+
--------------------------------
6034+
6035+
:Capability: KVM_CAP_COUNTER_OFFSET
6036+
:Architectures: arm64
6037+
:Type: vm ioctl
6038+
:Parameters: struct kvm_arm_counter_offset (in)
6039+
:Returns: 0 on success, < 0 on error
6040+
6041+
This capability indicates that userspace is able to apply a single VM-wide
6042+
offset to both the virtual and physical counters as viewed by the guest
6043+
using the KVM_ARM_SET_CNT_OFFSET ioctl and the following data structure:
6044+
6045+
::
6046+
6047+
struct kvm_arm_counter_offset {
6048+
__u64 counter_offset;
6049+
__u64 reserved;
6050+
};
6051+
6052+
The offset describes a number of counter cycles that are subtracted from
6053+
both virtual and physical counter views (similar to the effects of the
6054+
CNTVOFF_EL2 and CNTPOFF_EL2 system registers, but only global). The offset
6055+
always applies to all vcpus (already created or created after this ioctl)
6056+
for this VM.
6057+
6058+
It is userspace's responsibility to compute the offset based, for example,
6059+
on previous values of the guest counters.
6060+
6061+
Any value other than 0 for the "reserved" field may result in an error
6062+
(-EINVAL) being returned. This ioctl can also return -EBUSY if any vcpu
6063+
ioctl is issued concurrently.
6064+
6065+
Note that using this ioctl results in KVM ignoring subsequent userspace
6066+
writes to the CNTVCT_EL0 and CNTPCT_EL0 registers using the SET_ONE_REG
6067+
interface. No error will be returned, but the resulting offset will not be
6068+
applied.
6069+
60326070
5. The kvm_run structure
60336071
========================
60346072

arch/arm64/include/asm/kvm_host.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ struct kvm_arch {
224224
#define KVM_ARCH_FLAG_EL1_32BIT 4
225225
/* PSCI SYSTEM_SUSPEND enabled for the guest */
226226
#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED 5
227+
/* VM counter offset */
228+
#define KVM_ARCH_FLAG_VM_COUNTER_OFFSET 6
229+
/* Timer PPIs made immutable */
230+
#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 7
227231

228232
unsigned long flags;
229233

@@ -368,6 +372,10 @@ enum vcpu_sysreg {
368372
TPIDR_EL2, /* EL2 Software Thread ID Register */
369373
CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */
370374
SP_EL2, /* EL2 Stack Pointer */
375+
CNTHP_CTL_EL2,
376+
CNTHP_CVAL_EL2,
377+
CNTHV_CTL_EL2,
378+
CNTHV_CVAL_EL2,
371379

372380
NR_SYS_REGS /* Nothing after this line! */
373381
};
@@ -926,6 +934,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
926934

927935
int __init kvm_sys_reg_table_init(void);
928936

937+
bool lock_all_vcpus(struct kvm *kvm);
938+
void unlock_all_vcpus(struct kvm *kvm);
939+
929940
/* MMIO helpers */
930941
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
931942
unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
@@ -1011,6 +1022,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
10111022

10121023
long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
10131024
struct kvm_arm_copy_mte_tags *copy_tags);
1025+
int kvm_vm_ioctl_set_counter_offset(struct kvm *kvm,
1026+
struct kvm_arm_counter_offset *offset);
10141027

10151028
/* Guest/host FPSIMD coordination helpers */
10161029
int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);

arch/arm64/include/asm/kvm_mmu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,15 @@
6363
* specific registers encoded in the instructions).
6464
*/
6565
.macro kern_hyp_va reg
66+
#ifndef __KVM_VHE_HYPERVISOR__
6667
alternative_cb ARM64_ALWAYS_SYSTEM, kvm_update_va_mask
6768
and \reg, \reg, #1 /* mask with va_mask */
6869
ror \reg, \reg, #1 /* rotate to the first tag bit */
6970
add \reg, \reg, #0 /* insert the low 12 bits of the tag */
7071
add \reg, \reg, #0, lsl 12 /* insert the top 12 bits of the tag */
7172
ror \reg, \reg, #63 /* rotate back */
7273
alternative_cb_end
74+
#endif
7375
.endm
7476

7577
/*
@@ -127,6 +129,7 @@ void kvm_apply_hyp_relocations(void);
127129

128130
static __always_inline unsigned long __kern_hyp_va(unsigned long v)
129131
{
132+
#ifndef __KVM_VHE_HYPERVISOR__
130133
asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
131134
"ror %0, %0, #1\n"
132135
"add %0, %0, #0\n"
@@ -135,6 +138,7 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v)
135138
ARM64_ALWAYS_SYSTEM,
136139
kvm_update_va_mask)
137140
: "+r" (v));
141+
#endif
138142
return v;
139143
}
140144

arch/arm64/include/asm/sysreg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@
388388

389389
#define SYS_CNTFRQ_EL0 sys_reg(3, 3, 14, 0, 0)
390390

391+
#define SYS_CNTPCT_EL0 sys_reg(3, 3, 14, 0, 1)
391392
#define SYS_CNTPCTSS_EL0 sys_reg(3, 3, 14, 0, 5)
392393
#define SYS_CNTVCTSS_EL0 sys_reg(3, 3, 14, 0, 6)
393394

@@ -400,7 +401,9 @@
400401

401402
#define SYS_AARCH32_CNTP_TVAL sys_reg(0, 0, 14, 2, 0)
402403
#define SYS_AARCH32_CNTP_CTL sys_reg(0, 0, 14, 2, 1)
404+
#define SYS_AARCH32_CNTPCT sys_reg(0, 0, 0, 14, 0)
403405
#define SYS_AARCH32_CNTP_CVAL sys_reg(0, 2, 0, 14, 0)
406+
#define SYS_AARCH32_CNTPCTSS sys_reg(0, 8, 0, 14, 0)
404407

405408
#define __PMEV_op2(n) ((n) & 0x7)
406409
#define __CNTR_CRm(n) (0x8 | (((n) >> 3) & 0x3))

arch/arm64/include/uapi/asm/kvm.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ struct kvm_arm_copy_mte_tags {
198198
__u64 reserved[2];
199199
};
200200

201+
/*
202+
* Counter/Timer offset structure. Describe the virtual/physical offset.
203+
* To be used with KVM_ARM_SET_COUNTER_OFFSET.
204+
*/
205+
struct kvm_arm_counter_offset {
206+
__u64 counter_offset;
207+
__u64 reserved;
208+
};
209+
201210
#define KVM_ARM_TAGS_TO_GUEST 0
202211
#define KVM_ARM_TAGS_FROM_GUEST 1
203212

@@ -411,6 +420,8 @@ enum {
411420
#define KVM_ARM_VCPU_TIMER_CTRL 1
412421
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
413422
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
423+
#define KVM_ARM_VCPU_TIMER_IRQ_HVTIMER 2
424+
#define KVM_ARM_VCPU_TIMER_IRQ_HPTIMER 3
414425
#define KVM_ARM_VCPU_PVTIME_CTRL 2
415426
#define KVM_ARM_VCPU_PVTIME_IPA 0
416427

arch/arm64/kernel/cpufeature.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,6 +2223,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
22232223
.sign = FTR_UNSIGNED,
22242224
.min_field_value = 1,
22252225
},
2226+
{
2227+
.desc = "Enhanced Counter Virtualization (CNTPOFF)",
2228+
.capability = ARM64_HAS_ECV_CNTPOFF,
2229+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
2230+
.matches = has_cpuid_feature,
2231+
.sys_reg = SYS_ID_AA64MMFR0_EL1,
2232+
.field_pos = ID_AA64MMFR0_EL1_ECV_SHIFT,
2233+
.field_width = 4,
2234+
.sign = FTR_UNSIGNED,
2235+
.min_field_value = ID_AA64MMFR0_EL1_ECV_CNTPOFF,
2236+
},
22262237
#ifdef CONFIG_ARM64_PAN
22272238
{
22282239
.desc = "Privileged Access Never",

0 commit comments

Comments
 (0)