@@ -6766,3 +6766,22 @@ they will get passed on to user space. So user space still has to have
an implementation for these despite the in kernel acceleration.
This capability is always enabled.
+
+8.32 KVM_CAP_EXIT_HYPERCALL
+---------------------------
+
+:Capability: KVM_CAP_EXIT_HYPERCALL
+:Architectures: x86
+:Type: vm
+
+This capability, if enabled, will cause KVM to exit to userspace
+with KVM_EXIT_HYPERCALL exit reason to process some hypercalls.
+
+The arguments to KVM_ENABLE_CAP are a bitmask of hypercalls that
+will exit to userspace. The bits that can be set are returned by
+KVM_CHECK_EXTENSION. The behavior of hypercalls that are not enabled
+depends on the individual hypercall.
+
+Right now, the only bit that can be set is bit 12, corresponding to
+KVM_HC_PAGE_ENC_STATUS. The hypercall returns ENOSYS if bit 12 is not
+set or KVM_CAP_EXIT_HYPERCALL is not enabled.
@@ -96,6 +96,11 @@ KVM_FEATURE_MSI_EXT_DEST_ID 15 guest checks this feature bit
before using extended destination
ID bits in MSI address bits 11-5.
+KVM_FEATURE_HC_PAGE_ENC_STATUS 16 guest checks this feature bit before
+ using the page encryption state
+ hypercall to notify the page state
+ change
+
KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side
per-cpu warps are expected in
kvmclock
@@ -169,3 +169,18 @@ a0: destination APIC ID
:Usage example: When sending a call-function IPI-many to vCPUs, yield if
any of the IPI target vCPUs was preempted.
+
+
+8. KVM_HC_PAGE_ENC_STATUS
+-------------------------
+:Architecture: x86
+:Status: active
+:Purpose: Notify the encryption status changes in guest page table (SEV guest)
+
+a0: the guest physical address of the start page
+a1: the number of pages
+a2: page encryption status
+
+ Where:
+ * 1: Page is encrypted
+ * 0: Page is decrypted
@@ -1050,6 +1050,8 @@ struct kvm_arch {
/* Guest can access the SGX PROVISIONKEY. */
bool sgx_provisioning_allowed;
+ u64 hypercall_exit_enabled;
+
struct kvm_pmu_event_filter __rcu *pmu_event_filter;
struct task_struct *nx_lpage_recovery_thread;
@@ -33,6 +33,7 @@
#define KVM_FEATURE_PV_SCHED_YIELD 13
#define KVM_FEATURE_ASYNC_PF_INT 14
#define KVM_FEATURE_MSI_EXT_DEST_ID 15
+#define KVM_FEATURE_HC_PAGE_ENC_STATUS 16
#define KVM_HINTS_REALTIME 0
@@ -3809,6 +3809,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_SGX_ATTRIBUTE:
#endif
case KVM_CAP_VM_COPY_ENC_CONTEXT_FROM:
+ case KVM_CAP_EXIT_HYPERCALL:
r = 1;
break;
case KVM_CAP_SET_GUEST_DEBUG2:
@@ -5413,6 +5414,14 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
break;
}
#endif
+ case KVM_CAP_EXIT_HYPERCALL:
+ r = -EINVAL;
+ if ((cap->args[0] & ~(1 << KVM_HC_PAGE_ENC_STATUS)) ||
+ cap->args[1] || cap->args[2] || cap->args[3])
+ break;
+ r = 0;
+ kvm->arch.hypercall_exit_enabled = cap->args[0];
+ break;
case KVM_CAP_VM_COPY_ENC_CONTEXT_FROM:
r = -EINVAL;
if (kvm_x86_ops.vm_copy_enc_context_from)
@@ -8269,6 +8278,13 @@ static void kvm_sched_yield(struct kvm_vcpu *vcpu, unsigned long dest_id)
return;
}
+static int complete_hypercall_exit(struct kvm_vcpu *vcpu)
+{
+ kvm_rax_write(vcpu, vcpu->run->hypercall.ret);
+ ++vcpu->stat.hypercalls;
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
unsigned long nr, a0, a1, a2, a3, ret;
@@ -8334,6 +8350,26 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
kvm_sched_yield(vcpu, a0);
ret = 0;
break;
+ case KVM_HC_PAGE_ENC_STATUS: {
+ u64 gpa = a0, npages = a1, enc = a2;
+ if (!guest_pv_has(vcpu, KVM_FEATURE_HC_PAGE_ENC_STATUS)
+ || !(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_PAGE_ENC_STATUS)))
+ break;
+
+ ret = -KVM_EINVAL;
+ if (!PAGE_ALIGNED(gpa) || !npages ||
+ gpa_to_gfn(gpa) + npages <= gpa_to_gfn(gpa))
+ break;
+
+ vcpu->run->exit_reason = KVM_EXIT_HYPERCALL;
+ vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS;
+ vcpu->run->hypercall.args[0] = gpa;
+ vcpu->run->hypercall.args[1] = npages;
+ vcpu->run->hypercall.args[2] = enc;
+ vcpu->run->hypercall.longmode = op_64_bit;
+ vcpu->arch.complete_userspace_io = complete_hypercall_exit;
+ return 0;
+ }
default:
ret = -KVM_ENOSYS;
break;
@@ -1081,6 +1081,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_SET_GUEST_DEBUG2 195
#define KVM_CAP_SGX_ATTRIBUTE 196
#define KVM_CAP_VM_COPY_ENC_CONTEXT_FROM 197
+#define KVM_CAP_EXIT_HYPERCALL 198
#ifdef KVM_CAP_IRQ_ROUTING
@@ -29,6 +29,7 @@
#define KVM_HC_CLOCK_PAIRING 9
#define KVM_HC_SEND_IPI 10
#define KVM_HC_SCHED_YIELD 11
+#define KVM_HC_PAGE_ENC_STATUS 12
/*
* hypercalls use architecture specific