History

KVM: X86: Introduce KVM_HC_MAP_GPA_RANGE hypercall

This hypercall is used by the SEV guest to notify a change in the page encryption status to the hypervisor. The hypercall should be invoked only when the encryption attribute is changed from encrypted -> decrypted and vice versa. By default all guest pages are considered encrypted. The hypercall exits to userspace to manage the guest shared regions and integrate with the userspace VMM's migration code.

Ashish Kalra committed 5 years ago

Commit 0dbb1121 parent e3cb6fa9 files · +123 −0Browse files

Unified · Split

9 files
  1. Documentation/virt/kvm/api.rst +19 −0
  2. Documentation/virt/kvm/cpuid.rst +7 −0
  3. Documentation/virt/kvm/hypercalls.rst +21 −0
  4. Documentation/virt/kvm/msr.rst +13 −0
  5. arch/x86/include/asm/kvm_host.h +2 −0
  6. arch/x86/include/uapi/asm/kvm_para.h +13 −0
  7. arch/x86/kvm/x86.c +46 −0
  8. include/uapi/linux/kvm.h +1 −0
  9. include/uapi/linux/kvm_para.h +1 −0
Documentation/virt/kvm/api.rst+19−0
@@ -6950,3 +6950,22 @@ guest according to the bits Hyper-V CPUID feature leaves. Otherwise, all · 6949 unmodified lines
6950currently implmented Hyper-V features are provided unconditionally when6950currently implmented Hyper-V features are provided unconditionally when
6951Hyper-V identification is set in the HYPERV_CPUID_INTERFACE (0x40000001)6951Hyper-V identification is set in the HYPERV_CPUID_INTERFACE (0x40000001)
6952leaf.6952leaf.
6953
69548.34 KVM_CAP_EXIT_HYPERCALL
6955---------------------------
6956
6957:Capability: KVM_CAP_EXIT_HYPERCALL
6958:Architectures: x86
6959:Type: vm
6960
6961This capability, if enabled, will cause KVM to exit to userspace
6962with KVM_EXIT_HYPERCALL exit reason to process some hypercalls.
6963
6964Calling KVM_CHECK_EXTENSION for this capability will return a bitmask
6965of hypercalls that can be configured to exit to userspace.
6966Right now, the only such hypercall is KVM_HC_MAP_GPA_RANGE.
6967
6968The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
6969of the result of KVM_CHECK_EXTENSION. KVM will forward to userspace
6970the hypercalls whose corresponding bit is in the argument, and return
6971ENOSYS for the others.
Documentation/virt/kvm/cpuid.rst+7−0
@@ -96,6 +96,13 @@ KVM_FEATURE_MSI_EXT_DEST_ID 15 guest checks this feature bit · 95 unmodified lines
96 before using extended destination96 before using extended destination
97 ID bits in MSI address bits 11-5.97 ID bits in MSI address bits 11-5.
98 98
99KVM_FEATURE_HC_MAP_GPA_RANGE 16 guest checks this feature bit before
100 using the map gpa range hypercall
101 to notify the page state change
102
103KVM_FEATURE_MIGRATION_CONTROL 17 guest checks this feature bit before
104 using MSR_KVM_MIGRATION_CONTROL
105
99KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side106KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side
100 per-cpu warps are expected in107 per-cpu warps are expected in
101 kvmclock108 kvmclock
Documentation/virt/kvm/hypercalls.rst+21−0
@@ -169,3 +169,24 @@ a0: destination APIC ID · 168 unmodified lines
169 169
170:Usage example: When sending a call-function IPI-many to vCPUs, yield if170:Usage example: When sending a call-function IPI-many to vCPUs, yield if
171 any of the IPI target vCPUs was preempted.171 any of the IPI target vCPUs was preempted.
172
1738. KVM_HC_MAP_GPA_RANGE
174-------------------------
175:Architecture: x86
176:Status: active
177:Purpose: Request KVM to map a GPA range with the specified attributes.
178
179a0: the guest physical address of the start page
180a1: the number of (4kb) pages (must be contiguous in GPA space)
181a2: attributes
182
183 Where 'attributes' :
184 * bits 3:0 - preferred page size encoding 0 = 4kb, 1 = 2mb, 2 = 1gb, etc...
185 * bit 4 - plaintext = 0, encrypted = 1
186 * bits 63:5 - reserved (must be zero)
187
188**Implementation note**: this hypercall is implemented in userspace via
189the KVM_CAP_EXIT_HYPERCALL capability. Userspace must enable that capability
190before advertising KVM_FEATURE_HC_MAP_GPA_RANGE in the guest CPUID. In
191addition, if the guest supports KVM_FEATURE_MIGRATION_CONTROL, userspace
192must also set up an MSR filter to process writes to MSR_KVM_MIGRATION_CONTROL.
Documentation/virt/kvm/msr.rst+13−0
@@ -376,3 +376,16 @@ data: · 375 unmodified lines
376 write '1' to bit 0 of the MSR, this causes the host to re-scan its queue376 write '1' to bit 0 of the MSR, this causes the host to re-scan its queue
377 and check if there are more notifications pending. The MSR is available377 and check if there are more notifications pending. The MSR is available
378 if KVM_FEATURE_ASYNC_PF_INT is present in CPUID.378 if KVM_FEATURE_ASYNC_PF_INT is present in CPUID.
379
380MSR_KVM_MIGRATION_CONTROL:
381 0x4b564d08
382
383data:
384 This MSR is available if KVM_FEATURE_MIGRATION_CONTROL is present in
385 CPUID. Bit 0 represents whether live migration of the guest is allowed.
386
387 When a guest is started, bit 0 will be 0 if the guest has encrypted
388 memory and 1 if the guest does not have encrypted memory. If the
389 guest is communicating page encryption status to the host using the
390 ``KVM_HC_MAP_GPA_RANGE`` hypercall, it can set bit 0 in this MSR to
391 allow live migration of the guest.
arch/x86/include/asm/kvm_host.h+2−0
@@ -1087,6 +1087,8 @@ struct kvm_arch { · 1086 unmodified lines
1087 u32 user_space_msr_mask;1087 u32 user_space_msr_mask;
1088 struct kvm_x86_msr_filter __rcu *msr_filter;1088 struct kvm_x86_msr_filter __rcu *msr_filter;
1089 1089
1090 u32 hypercall_exit_enabled;
1091
1090 /* Guest can access the SGX PROVISIONKEY. */1092 /* Guest can access the SGX PROVISIONKEY. */
1091 bool sgx_provisioning_allowed;1093 bool sgx_provisioning_allowed;
1092 1094
arch/x86/include/uapi/asm/kvm_para.h+13−0
@@ -33,6 +33,8 @@ · 32 unmodified lines
33#define KVM_FEATURE_PV_SCHED_YIELD 1333#define KVM_FEATURE_PV_SCHED_YIELD 13
34#define KVM_FEATURE_ASYNC_PF_INT 1434#define KVM_FEATURE_ASYNC_PF_INT 14
35#define KVM_FEATURE_MSI_EXT_DEST_ID 1535#define KVM_FEATURE_MSI_EXT_DEST_ID 15
36#define KVM_FEATURE_HC_MAP_GPA_RANGE 16
37#define KVM_FEATURE_MIGRATION_CONTROL 17
36 38
37#define KVM_HINTS_REALTIME 039#define KVM_HINTS_REALTIME 0
38 40
@@ -54,6 +56,7 @@ · 15 unmodified lines
54#define MSR_KVM_POLL_CONTROL 0x4b564d0556#define MSR_KVM_POLL_CONTROL 0x4b564d05
55#define MSR_KVM_ASYNC_PF_INT 0x4b564d0657#define MSR_KVM_ASYNC_PF_INT 0x4b564d06
56#define MSR_KVM_ASYNC_PF_ACK 0x4b564d0758#define MSR_KVM_ASYNC_PF_ACK 0x4b564d07
59#define MSR_KVM_MIGRATION_CONTROL 0x4b564d08
57 60
58struct kvm_steal_time {61struct kvm_steal_time {
59 __u64 steal;62 __u64 steal;
@@ -90,6 +93,16 @@ struct kvm_clock_pairing { · 30 unmodified lines
90/* MSR_KVM_ASYNC_PF_INT */93/* MSR_KVM_ASYNC_PF_INT */
91#define KVM_ASYNC_PF_VEC_MASK GENMASK(7, 0)94#define KVM_ASYNC_PF_VEC_MASK GENMASK(7, 0)
92 95
96/* MSR_KVM_MIGRATION_CONTROL */
97#define KVM_MIGRATION_READY (1 << 0)
98
99/* KVM_HC_MAP_GPA_RANGE */
100#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K 0
101#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M (1 << 0)
102#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G (1 << 1)
103#define KVM_MAP_GPA_RANGE_ENC_STAT(n) (n << 4)
104#define KVM_MAP_GPA_RANGE_ENCRYPTED KVM_MAP_GPA_RANGE_ENC_STAT(1)
105#define KVM_MAP_GPA_RANGE_DECRYPTED KVM_MAP_GPA_RANGE_ENC_STAT(0)
93 106
94/* Operations for KVM_HC_MMU_OP */107/* Operations for KVM_HC_MMU_OP */
95#define KVM_MMU_OP_WRITE_PTE 1108#define KVM_MMU_OP_WRITE_PTE 1
arch/x86/kvm/x86.c+46−0
@@ -103,6 +103,8 @@ static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE); · 102 unmodified lines
103 103
104static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;104static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;
105 105
106#define KVM_EXIT_HYPERCALL_VALID_MASK (1 << KVM_HC_MAP_GPA_RANGE)
107
106#define KVM_X2APIC_API_VALID_FLAGS (KVM_X2APIC_API_USE_32BIT_IDS | \108#define KVM_X2APIC_API_VALID_FLAGS (KVM_X2APIC_API_USE_32BIT_IDS | \
107 KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK)109 KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK)
108 110
@@ -3996,6 +3998,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 3887 unmodified lines
3996 case KVM_CAP_SREGS2:3998 case KVM_CAP_SREGS2:
3997 r = 1;3999 r = 1;
3998 break;4000 break;
4001 case KVM_CAP_EXIT_HYPERCALL:
4002 r = KVM_EXIT_HYPERCALL_VALID_MASK;
4003 break;
3999 case KVM_CAP_SET_GUEST_DEBUG2:4004 case KVM_CAP_SET_GUEST_DEBUG2:
4000 return KVM_GUESTDBG_VALID_MASK;4005 return KVM_GUESTDBG_VALID_MASK;
4001#ifdef CONFIG_KVM_XEN4006#ifdef CONFIG_KVM_XEN
@@ -5622,6 +5627,14 @@ split_irqchip_unlock: · 1620 unmodified lines
5622 if (kvm_x86_ops.vm_copy_enc_context_from)5627 if (kvm_x86_ops.vm_copy_enc_context_from)
5623 r = kvm_x86_ops.vm_copy_enc_context_from(kvm, cap->args[0]);5628 r = kvm_x86_ops.vm_copy_enc_context_from(kvm, cap->args[0]);
5624 return r;5629 return r;
5630 case KVM_CAP_EXIT_HYPERCALL:
5631 if (cap->args[0] & ~KVM_EXIT_HYPERCALL_VALID_MASK) {
5632 r = -EINVAL;
5633 break;
5634 }
5635 kvm->arch.hypercall_exit_enabled = cap->args[0];
5636 r = 0;
5637 break;
5625 default:5638 default:
5626 r = -EINVAL;5639 r = -EINVAL;
5627 break;5640 break;
@@ -8548,6 +8561,17 @@ no_yield: · 2920 unmodified lines
8548 return;8561 return;
8549}8562}
8550 8563
8564static int complete_hypercall_exit(struct kvm_vcpu *vcpu)
8565{
8566 u64 ret = vcpu->run->hypercall.ret;
8567
8568 if (!is_64_bit_mode(vcpu))
8569 ret = (u32)ret;
8570 kvm_rax_write(vcpu, ret);
8571 ++vcpu->stat.hypercalls;
8572 return kvm_skip_emulated_instruction(vcpu);
8573}
8574
8551int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)8575int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
8552{8576{
8553 unsigned long nr, a0, a1, a2, a3, ret;8577 unsigned long nr, a0, a1, a2, a3, ret;
@@ -8613,6 +8637,28 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · 59 unmodified lines
8613 kvm_sched_yield(vcpu, a0);8637 kvm_sched_yield(vcpu, a0);
8614 ret = 0;8638 ret = 0;
8615 break;8639 break;
8640 case KVM_HC_MAP_GPA_RANGE: {
8641 u64 gpa = a0, npages = a1, attrs = a2;
8642
8643 ret = -KVM_ENOSYS;
8644 if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE)))
8645 break;
8646
8647 if (!PAGE_ALIGNED(gpa) || !npages ||
8648 gpa_to_gfn(gpa) + npages <= gpa_to_gfn(gpa)) {
8649 ret = -KVM_EINVAL;
8650 break;
8651 }
8652
8653 vcpu->run->exit_reason = KVM_EXIT_HYPERCALL;
8654 vcpu->run->hypercall.nr = KVM_HC_MAP_GPA_RANGE;
8655 vcpu->run->hypercall.args[0] = gpa;
8656 vcpu->run->hypercall.args[1] = npages;
8657 vcpu->run->hypercall.args[2] = attrs;
8658 vcpu->run->hypercall.longmode = op_64_bit;
8659 vcpu->arch.complete_userspace_io = complete_hypercall_exit;
8660 return 0;
8661 }
8616 default:8662 default:
8617 ret = -KVM_ENOSYS;8663 ret = -KVM_ENOSYS;
8618 break;8664 break;
include/uapi/linux/kvm.h+1−0
@@ -1085,6 +1085,7 @@ struct kvm_ppc_resize_hpt { · 1084 unmodified lines
1085#define KVM_CAP_PTP_KVM 1981085#define KVM_CAP_PTP_KVM 198
1086#define KVM_CAP_HYPERV_ENFORCE_CPUID 1991086#define KVM_CAP_HYPERV_ENFORCE_CPUID 199
1087#define KVM_CAP_SREGS2 2001087#define KVM_CAP_SREGS2 200
1088#define KVM_CAP_EXIT_HYPERCALL 201
1088 1089
1089#ifdef KVM_CAP_IRQ_ROUTING1090#ifdef KVM_CAP_IRQ_ROUTING
1090 1091
include/uapi/linux/kvm_para.h+1−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
29#define KVM_HC_CLOCK_PAIRING 929#define KVM_HC_CLOCK_PAIRING 9
30#define KVM_HC_SEND_IPI 1030#define KVM_HC_SEND_IPI 10
31#define KVM_HC_SCHED_YIELD 1131#define KVM_HC_SCHED_YIELD 11
32#define KVM_HC_MAP_GPA_RANGE 12
32 33
33/*34/*
34 * hypercalls use architecture specific35 * hypercalls use architecture specific