~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm64/kvm/pvtime.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 // Copyright (C) 2019 Arm Ltd.
  3 
  4 #include <linux/arm-smccc.h>
  5 #include <linux/kvm_host.h>
  6 #include <linux/sched/stat.h>
  7 
  8 #include <asm/kvm_mmu.h>
  9 #include <asm/pvclock-abi.h>
 10 
 11 #include <kvm/arm_hypercalls.h>
 12 
 13 void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
 14 {
 15         struct kvm *kvm = vcpu->kvm;
 16         u64 base = vcpu->arch.steal.base;
 17         u64 last_steal = vcpu->arch.steal.last_steal;
 18         u64 offset = offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
 19         u64 steal = 0;
 20         int idx;
 21 
 22         if (base == INVALID_GPA)
 23                 return;
 24 
 25         idx = srcu_read_lock(&kvm->srcu);
 26         if (!kvm_get_guest(kvm, base + offset, steal)) {
 27                 steal = le64_to_cpu(steal);
 28                 vcpu->arch.steal.last_steal = READ_ONCE(current->sched_info.run_delay);
 29                 steal += vcpu->arch.steal.last_steal - last_steal;
 30                 kvm_put_guest(kvm, base + offset, cpu_to_le64(steal));
 31         }
 32         srcu_read_unlock(&kvm->srcu, idx);
 33 }
 34 
 35 long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
 36 {
 37         u32 feature = smccc_get_arg1(vcpu);
 38         long val = SMCCC_RET_NOT_SUPPORTED;
 39 
 40         switch (feature) {
 41         case ARM_SMCCC_HV_PV_TIME_FEATURES:
 42         case ARM_SMCCC_HV_PV_TIME_ST:
 43                 if (vcpu->arch.steal.base != INVALID_GPA)
 44                         val = SMCCC_RET_SUCCESS;
 45                 break;
 46         }
 47 
 48         return val;
 49 }
 50 
 51 gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
 52 {
 53         struct pvclock_vcpu_stolen_time init_values = {};
 54         struct kvm *kvm = vcpu->kvm;
 55         u64 base = vcpu->arch.steal.base;
 56 
 57         if (base == INVALID_GPA)
 58                 return base;
 59 
 60         /*
 61          * Start counting stolen time from the time the guest requests
 62          * the feature enabled.
 63          */
 64         vcpu->arch.steal.last_steal = current->sched_info.run_delay;
 65         kvm_write_guest_lock(kvm, base, &init_values, sizeof(init_values));
 66 
 67         return base;
 68 }
 69 
 70 bool kvm_arm_pvtime_supported(void)
 71 {
 72         return !!sched_info_on();
 73 }
 74 
 75 int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
 76                             struct kvm_device_attr *attr)
 77 {
 78         u64 __user *user = (u64 __user *)attr->addr;
 79         struct kvm *kvm = vcpu->kvm;
 80         u64 ipa;
 81         int ret = 0;
 82         int idx;
 83 
 84         if (!kvm_arm_pvtime_supported() ||
 85             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 != INVALID_GPA)
 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 (!kvm_arm_pvtime_supported() ||
114             attr->attr != KVM_ARM_VCPU_PVTIME_IPA)
115                 return -ENXIO;
116 
117         ipa = vcpu->arch.steal.base;
118 
119         if (put_user(ipa, user))
120                 return -EFAULT;
121         return 0;
122 }
123 
124 int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
125                             struct kvm_device_attr *attr)
126 {
127         switch (attr->attr) {
128         case KVM_ARM_VCPU_PVTIME_IPA:
129                 if (kvm_arm_pvtime_supported())
130                         return 0;
131         }
132         return -ENXIO;
133 }
134 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php