Skip to content

Commit 58772e9

Browse files
Steven PriceMarc Zyngier
authored andcommitted
KVM: arm64: Provide VCPU attributes for stolen time
Allow user space to inform the KVM host where in the physical memory map the paravirtualized time structures should be located. User space can set an attribute on the VCPU providing the IPA base address of the stolen time structure for that VCPU. This must be repeated for every VCPU in the VM. The address is given in terms of the physical address visible to the guest and must be 64 byte aligned. The guest will discover the address via a hypercall. Signed-off-by: Steven Price <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent 8538cb2 commit 58772e9

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,13 @@ long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
490490
gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu);
491491
void kvm_update_stolen_time(struct kvm_vcpu *vcpu);
492492

493+
int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
494+
struct kvm_device_attr *attr);
495+
int kvm_arm_pvtime_get_attr(struct kvm_vcpu *vcpu,
496+
struct kvm_device_attr *attr);
497+
int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
498+
struct kvm_device_attr *attr);
499+
493500
static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
494501
{
495502
vcpu_arch->steal.base = GPA_INVALID;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ struct kvm_vcpu_events {
323323
#define KVM_ARM_VCPU_TIMER_CTRL 1
324324
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
325325
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
326+
#define KVM_ARM_VCPU_PVTIME_CTRL 2
327+
#define KVM_ARM_VCPU_PVTIME_IPA 0
326328

327329
/* KVM_IRQ_LINE irq field index values */
328330
#define KVM_ARM_IRQ_VCPU2_SHIFT 28

arch/arm64/kvm/guest.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,9 @@ int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
858858
case KVM_ARM_VCPU_TIMER_CTRL:
859859
ret = kvm_arm_timer_set_attr(vcpu, attr);
860860
break;
861+
case KVM_ARM_VCPU_PVTIME_CTRL:
862+
ret = kvm_arm_pvtime_set_attr(vcpu, attr);
863+
break;
861864
default:
862865
ret = -ENXIO;
863866
break;
@@ -878,6 +881,9 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
878881
case KVM_ARM_VCPU_TIMER_CTRL:
879882
ret = kvm_arm_timer_get_attr(vcpu, attr);
880883
break;
884+
case KVM_ARM_VCPU_PVTIME_CTRL:
885+
ret = kvm_arm_pvtime_get_attr(vcpu, attr);
886+
break;
881887
default:
882888
ret = -ENXIO;
883889
break;
@@ -898,6 +904,9 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
898904
case KVM_ARM_VCPU_TIMER_CTRL:
899905
ret = kvm_arm_timer_has_attr(vcpu, attr);
900906
break;
907+
case KVM_ARM_VCPU_PVTIME_CTRL:
908+
ret = kvm_arm_pvtime_has_attr(vcpu, attr);
909+
break;
901910
default:
902911
ret = -ENXIO;
903912
break;

include/uapi/linux/kvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,8 @@ enum kvm_device_type {
12271227
#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
12281228
KVM_DEV_TYPE_XIVE,
12291229
#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
1230+
KVM_DEV_TYPE_ARM_PV_TIME,
1231+
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
12301232
KVM_DEV_TYPE_MAX,
12311233
};
12321234

virt/kvm/arm/pvtime.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Copyright (C) 2019 Arm Ltd.
33

44
#include <linux/arm-smccc.h>
5+
#include <linux/kvm_host.h>
56

7+
#include <asm/kvm_mmu.h>
68
#include <asm/pvclock-abi.h>
79

810
#include <kvm/arm_hypercalls.h>
@@ -70,3 +72,60 @@ gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
7072

7173
return base;
7274
}
75+
76+
int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
77+
struct kvm_device_attr *attr)
78+
{
79+
u64 __user *user = (u64 __user *)attr->addr;
80+
struct kvm *kvm = vcpu->kvm;
81+
u64 ipa;
82+
int ret = 0;
83+
int idx;
84+
85+
if (attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
86+
return -ENXIO;
87+
88+
if (get_user(ipa, user))
89+
return -EFAULT;
90+
if (!IS_ALIGNED(ipa, 64))
91+
return -EINVAL;
92+
if (vcpu->arch.steal.base != GPA_INVALID)
93+
return -EEXIST;
94+
95+
/* Check the address is in a valid memslot */
96+
idx = srcu_read_lock(&kvm->srcu);
97+
if (kvm_is_error_hva(gfn_to_hva(kvm, ipa >> PAGE_SHIFT)))
98+
ret = -EINVAL;
99+
srcu_read_unlock(&kvm->srcu, idx);
100+
101+
if (!ret)
102+
vcpu->arch.steal.base = ipa;
103+
104+
return ret;
105+
}
106+
107+
int kvm_arm_pvtime_get_attr(struct kvm_vcpu *vcpu,
108+
struct kvm_device_attr *attr)
109+
{
110+
u64 __user *user = (u64 __user *)attr->addr;
111+
u64 ipa;
112+
113+
if (attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
114+
return -ENXIO;
115+
116+
ipa = vcpu->arch.steal.base;
117+
118+
if (put_user(ipa, user))
119+
return -EFAULT;
120+
return 0;
121+
}
122+
123+
int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
124+
struct kvm_device_attr *attr)
125+
{
126+
switch (attr->attr) {
127+
case KVM_ARM_VCPU_PVTIME_IPA:
128+
return 0;
129+
}
130+
return -ENXIO;
131+
}

0 commit comments

Comments
 (0)