Commit a53071bd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fixes from Paolo Bonzini:
 "x86 bug fixes"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: X86: Narrow down the IPI fastpath to single target IPI
  KVM: LAPIC: Also cancel preemption timer when disarm LAPIC timer
  KVM: VMX: don't allow memory operands for inline asm that modifies SP
  KVM: LAPIC: Mark hrtimer for period or oneshot mode to expire in hard interrupt context
  KVM: SVM: Issue WBINVD after deactivating an SEV guest
  KVM: SVM: document KVM_MEM_ENCRYPT_OP, let userspace detect if SEV is available
  KVM: x86: remove bogus user-triggerable WARN_ON
parents 23cb8490 e1be9ac8
...@@ -53,6 +53,29 @@ key management interface to perform common hypervisor activities such as ...@@ -53,6 +53,29 @@ key management interface to perform common hypervisor activities such as
encrypting bootstrap code, snapshot, migrating and debugging the guest. For more encrypting bootstrap code, snapshot, migrating and debugging the guest. For more
information, see the SEV Key Management spec [api-spec]_ information, see the SEV Key Management spec [api-spec]_
The main ioctl to access SEV is KVM_MEM_ENCRYPT_OP. If the argument
to KVM_MEM_ENCRYPT_OP is NULL, the ioctl returns 0 if SEV is enabled
and ``ENOTTY` if it is disabled (on some older versions of Linux,
the ioctl runs normally even with a NULL argument, and therefore will
likely return ``EFAULT``). If non-NULL, the argument to KVM_MEM_ENCRYPT_OP
must be a struct kvm_sev_cmd::
struct kvm_sev_cmd {
__u32 id;
__u64 data;
__u32 error;
__u32 sev_fd;
};
The ``id`` field contains the subcommand, and the ``data`` field points to
another struct containing arguments specific to command. The ``sev_fd``
should point to a file descriptor that is opened on the ``/dev/sev``
device, if needed (see individual commands).
On output, ``error`` is zero on success, or an error code. Error codes
are defined in ``<linux/psp-dev.h>`.
KVM implements the following commands to support common lifecycle events of SEV KVM implements the following commands to support common lifecycle events of SEV
guests, such as launching, running, snapshotting, migrating and decommissioning. guests, such as launching, running, snapshotting, migrating and decommissioning.
...@@ -90,6 +113,8 @@ Returns: 0 on success, -negative on error ...@@ -90,6 +113,8 @@ Returns: 0 on success, -negative on error
On success, the 'handle' field contains a new handle and on error, a negative value. On success, the 'handle' field contains a new handle and on error, a negative value.
KVM_SEV_LAUNCH_START requires the ``sev_fd`` field to be valid.
For more details, see SEV spec Section 6.2. For more details, see SEV spec Section 6.2.
3. KVM_SEV_LAUNCH_UPDATE_DATA 3. KVM_SEV_LAUNCH_UPDATE_DATA
......
...@@ -1445,6 +1445,8 @@ static void limit_periodic_timer_frequency(struct kvm_lapic *apic) ...@@ -1445,6 +1445,8 @@ static void limit_periodic_timer_frequency(struct kvm_lapic *apic)
} }
} }
static void cancel_hv_timer(struct kvm_lapic *apic);
static void apic_update_lvtt(struct kvm_lapic *apic) static void apic_update_lvtt(struct kvm_lapic *apic)
{ {
u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) & u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) &
...@@ -1454,6 +1456,10 @@ static void apic_update_lvtt(struct kvm_lapic *apic) ...@@ -1454,6 +1456,10 @@ static void apic_update_lvtt(struct kvm_lapic *apic)
if (apic_lvtt_tscdeadline(apic) != (timer_mode == if (apic_lvtt_tscdeadline(apic) != (timer_mode ==
APIC_LVT_TIMER_TSCDEADLINE)) { APIC_LVT_TIMER_TSCDEADLINE)) {
hrtimer_cancel(&apic->lapic_timer.timer); hrtimer_cancel(&apic->lapic_timer.timer);
preempt_disable();
if (apic->lapic_timer.hv_timer_in_use)
cancel_hv_timer(apic);
preempt_enable();
kvm_lapic_set_reg(apic, APIC_TMICT, 0); kvm_lapic_set_reg(apic, APIC_TMICT, 0);
apic->lapic_timer.period = 0; apic->lapic_timer.period = 0;
apic->lapic_timer.tscdeadline = 0; apic->lapic_timer.tscdeadline = 0;
...@@ -1715,7 +1721,7 @@ static void start_sw_period(struct kvm_lapic *apic) ...@@ -1715,7 +1721,7 @@ static void start_sw_period(struct kvm_lapic *apic)
hrtimer_start(&apic->lapic_timer.timer, hrtimer_start(&apic->lapic_timer.timer,
apic->lapic_timer.target_expiration, apic->lapic_timer.target_expiration,
HRTIMER_MODE_ABS); HRTIMER_MODE_ABS_HARD);
} }
bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu) bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
......
...@@ -1933,14 +1933,6 @@ static void sev_clflush_pages(struct page *pages[], unsigned long npages) ...@@ -1933,14 +1933,6 @@ static void sev_clflush_pages(struct page *pages[], unsigned long npages)
static void __unregister_enc_region_locked(struct kvm *kvm, static void __unregister_enc_region_locked(struct kvm *kvm,
struct enc_region *region) struct enc_region *region)
{ {
/*
* The guest may change the memory encryption attribute from C=0 -> C=1
* or vice versa for this memory range. Lets make sure caches are
* flushed to ensure that guest data gets written into memory with
* correct C-bit.
*/
sev_clflush_pages(region->pages, region->npages);
sev_unpin_memory(kvm, region->pages, region->npages); sev_unpin_memory(kvm, region->pages, region->npages);
list_del(&region->list); list_del(&region->list);
kfree(region); kfree(region);
...@@ -1970,6 +1962,13 @@ static void sev_vm_destroy(struct kvm *kvm) ...@@ -1970,6 +1962,13 @@ static void sev_vm_destroy(struct kvm *kvm)
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
/*
* Ensure that all guest tagged cache entries are flushed before
* releasing the pages back to the system for use. CLFLUSH will
* not do this, so issue a WBINVD.
*/
wbinvd_on_all_cpus();
/* /*
* if userspace was terminated before unregistering the memory regions * if userspace was terminated before unregistering the memory regions
* then lets unpin all the registered memory. * then lets unpin all the registered memory.
...@@ -7158,6 +7157,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) ...@@ -7158,6 +7157,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
if (!svm_sev_enabled()) if (!svm_sev_enabled())
return -ENOTTY; return -ENOTTY;
if (!argp)
return 0;
if (copy_from_user(&sev_cmd, argp, sizeof(struct kvm_sev_cmd))) if (copy_from_user(&sev_cmd, argp, sizeof(struct kvm_sev_cmd)))
return -EFAULT; return -EFAULT;
...@@ -7285,6 +7287,13 @@ static int svm_unregister_enc_region(struct kvm *kvm, ...@@ -7285,6 +7287,13 @@ static int svm_unregister_enc_region(struct kvm *kvm,
goto failed; goto failed;
} }
/*
* Ensure that all guest tagged cache entries are flushed before
* releasing the pages back to the system for use. CLFLUSH will
* not do this, so issue a WBINVD.
*/
wbinvd_on_all_cpus();
__unregister_enc_region_locked(kvm, region); __unregister_enc_region_locked(kvm, region);
mutex_unlock(&kvm->lock); mutex_unlock(&kvm->lock);
......
...@@ -6287,7 +6287,7 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu) ...@@ -6287,7 +6287,7 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu)
#endif #endif
ASM_CALL_CONSTRAINT ASM_CALL_CONSTRAINT
: :
THUNK_TARGET(entry), [thunk_target]"r"(entry),
[ss]"i"(__KERNEL_DS), [ss]"i"(__KERNEL_DS),
[cs]"i"(__KERNEL_CS) [cs]"i"(__KERNEL_CS)
); );
......
...@@ -1554,7 +1554,10 @@ EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr); ...@@ -1554,7 +1554,10 @@ EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr);
*/ */
static int handle_fastpath_set_x2apic_icr_irqoff(struct kvm_vcpu *vcpu, u64 data) static int handle_fastpath_set_x2apic_icr_irqoff(struct kvm_vcpu *vcpu, u64 data)
{ {
if (lapic_in_kernel(vcpu) && apic_x2apic_mode(vcpu->arch.apic) && if (!lapic_in_kernel(vcpu) || !apic_x2apic_mode(vcpu->arch.apic))
return 1;
if (((data & APIC_SHORT_MASK) == APIC_DEST_NOSHORT) &&
((data & APIC_DEST_MASK) == APIC_DEST_PHYSICAL) && ((data & APIC_DEST_MASK) == APIC_DEST_PHYSICAL) &&
((data & APIC_MODE_MASK) == APIC_DM_FIXED)) { ((data & APIC_MODE_MASK) == APIC_DM_FIXED)) {
...@@ -2444,7 +2447,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) ...@@ -2444,7 +2447,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
vcpu->hv_clock.tsc_timestamp = tsc_timestamp; vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset; vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
vcpu->last_guest_tsc = tsc_timestamp; vcpu->last_guest_tsc = tsc_timestamp;
WARN_ON((s64)vcpu->hv_clock.system_time < 0);
/* If the host uses TSC clocksource, then it is stable */ /* If the host uses TSC clocksource, then it is stable */
pvclock_flags = 0; pvclock_flags = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment