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
69506950 currently implmented Hyper-V features are provided unconditionally when
69516951 Hyper-V identification is set in the HYPERV_CPUID_INTERFACE (0x40000001)
69526952 leaf.
6953+
6954+8.34 KVM_CAP_EXIT_HYPERCALL
6955+---------------------------
6956+
6957+:Capability: KVM_CAP_EXIT_HYPERCALL
6958+:Architectures: x86
6959+:Type: vm
6960+
6961+This capability, if enabled, will cause KVM to exit to userspace
6962+with KVM_EXIT_HYPERCALL exit reason to process some hypercalls.
6963+
6964+Calling KVM_CHECK_EXTENSION for this capability will return a bitmask
6965+of hypercalls that can be configured to exit to userspace.
6966+Right now, the only such hypercall is KVM_HC_MAP_GPA_RANGE.
6967+
6968+The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
6969+of the result of KVM_CHECK_EXTENSION. KVM will forward to userspace
6970+the hypercalls whose corresponding bit is in the argument, and return
6971+ENOSYS 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
9696 before using extended destination
9797 ID bits in MSI address bits 11-5.
9898
99+KVM_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+
103+KVM_FEATURE_MIGRATION_CONTROL 17 guest checks this feature bit before
104+ using MSR_KVM_MIGRATION_CONTROL
105+
99106 KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side
100107 per-cpu warps are expected in
101108 kvmclock
Documentation/virt/kvm/hypercalls.rst+21−0
@@ -169,3 +169,24 @@ a0: destination APIC ID · 168 unmodified lines
169169
170170 :Usage example: When sending a call-function IPI-many to vCPUs, yield if
171171 any of the IPI target vCPUs was preempted.
172+
173+8. 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+
179+a0: the guest physical address of the start page
180+a1: the number of (4kb) pages (must be contiguous in GPA space)
181+a2: 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
189+the KVM_CAP_EXIT_HYPERCALL capability. Userspace must enable that capability
190+before advertising KVM_FEATURE_HC_MAP_GPA_RANGE in the guest CPUID. In
191+addition, if the guest supports KVM_FEATURE_MIGRATION_CONTROL, userspace
192+must 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
376376 write '1' to bit 0 of the MSR, this causes the host to re-scan its queue
377377 and check if there are more notifications pending. The MSR is available
378378 if KVM_FEATURE_ASYNC_PF_INT is present in CPUID.
379+
380+MSR_KVM_MIGRATION_CONTROL:
381+ 0x4b564d08
382+
383+data:
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
10871087 u32 user_space_msr_mask;
10881088 struct kvm_x86_msr_filter __rcu *msr_filter;
10891089
1090+ u32 hypercall_exit_enabled;
1091+
10901092 /* Guest can access the SGX PROVISIONKEY. */
10911093 bool sgx_provisioning_allowed;
10921094
arch/x86/include/uapi/asm/kvm_para.h+13−0
@@ -33,6 +33,8 @@ · 32 unmodified lines
3333 #define KVM_FEATURE_PV_SCHED_YIELD 13
3434 #define KVM_FEATURE_ASYNC_PF_INT 14
3535 #define KVM_FEATURE_MSI_EXT_DEST_ID 15
36+#define KVM_FEATURE_HC_MAP_GPA_RANGE 16
37+#define KVM_FEATURE_MIGRATION_CONTROL 17
3638
3739 #define KVM_HINTS_REALTIME 0
3840
@@ -54,6 +56,7 @@ · 15 unmodified lines
5456 #define MSR_KVM_POLL_CONTROL 0x4b564d05
5557 #define MSR_KVM_ASYNC_PF_INT 0x4b564d06
5658 #define MSR_KVM_ASYNC_PF_ACK 0x4b564d07
59+#define MSR_KVM_MIGRATION_CONTROL 0x4b564d08
5760
5861 struct kvm_steal_time {
5962 __u64 steal;
@@ -90,6 +93,16 @@ struct kvm_clock_pairing { · 30 unmodified lines
9093 /* MSR_KVM_ASYNC_PF_INT */
9194 #define KVM_ASYNC_PF_VEC_MASK GENMASK(7, 0)
9295
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)
93106
94107 /* Operations for KVM_HC_MMU_OP */
95108 #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
103103
104104 static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;
105105
106+#define KVM_EXIT_HYPERCALL_VALID_MASK (1 << KVM_HC_MAP_GPA_RANGE)
107+
106108 #define KVM_X2APIC_API_VALID_FLAGS (KVM_X2APIC_API_USE_32BIT_IDS | \
107109 KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK)
108110
@@ -3996,6 +3998,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 3887 unmodified lines
39963998 case KVM_CAP_SREGS2:
39973999 r = 1;
39984000 break;
4001+ case KVM_CAP_EXIT_HYPERCALL:
4002+ r = KVM_EXIT_HYPERCALL_VALID_MASK;
4003+ break;
39994004 case KVM_CAP_SET_GUEST_DEBUG2:
40004005 return KVM_GUESTDBG_VALID_MASK;
40014006 #ifdef CONFIG_KVM_XEN
@@ -5622,6 +5627,14 @@ split_irqchip_unlock: · 1620 unmodified lines
56225627 if (kvm_x86_ops.vm_copy_enc_context_from)
56235628 r = kvm_x86_ops.vm_copy_enc_context_from(kvm, cap->args[0]);
56245629 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;
56255638 default:
56265639 r = -EINVAL;
56275640 break;
@@ -8548,6 +8561,17 @@ no_yield: · 2920 unmodified lines
85488561 return;
85498562 }
85508563
8564+static 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+
85518575 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
85528576 {
85538577 unsigned long nr, a0, a1, a2, a3, ret;
@@ -8613,6 +8637,28 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · 59 unmodified lines
86138637 kvm_sched_yield(vcpu, a0);
86148638 ret = 0;
86158639 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+ }
86168662 default:
86178663 ret = -KVM_ENOSYS;
86188664 break;
include/uapi/linux/kvm.h+1−0
@@ -1085,6 +1085,7 @@ struct kvm_ppc_resize_hpt { · 1084 unmodified lines
10851085 #define KVM_CAP_PTP_KVM 198
10861086 #define KVM_CAP_HYPERV_ENFORCE_CPUID 199
10871087 #define KVM_CAP_SREGS2 200
1088+#define KVM_CAP_EXIT_HYPERCALL 201
10881089
10891090 #ifdef KVM_CAP_IRQ_ROUTING
10901091
include/uapi/linux/kvm_para.h+1−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
2929 #define KVM_HC_CLOCK_PAIRING 9
3030 #define KVM_HC_SEND_IPI 10
3131 #define KVM_HC_SCHED_YIELD 11
32+#define KVM_HC_MAP_GPA_RANGE 12
3233
3334 /*
3435 * hypercalls use architecture specific