blob: 27e37d8044b3793d23f4aa8afe6625dfcdd6a65a [file] [log] [blame]
Avi Kivity6aa8b732006-12-10 02:21:36 -08001/*
2 * Kernel-based Virtual Machine driver for Linux
3 *
4 * AMD SVM support
5 *
6 * Copyright (C) 2006 Qumranet, Inc.
Nicolas Kaiser9611c182010-10-06 14:23:22 +02007 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
Avi Kivity6aa8b732006-12-10 02:21:36 -08008 *
9 * Authors:
10 * Yaniv Kamay <yaniv@qumranet.com>
11 * Avi Kivity <avi@qumranet.com>
12 *
13 * This work is licensed under the terms of the GNU GPL, version 2. See
14 * the COPYING file in the top-level directory.
15 *
16 */
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -050017
18#define pr_fmt(fmt) "SVM: " fmt
19
Avi Kivityedf88412007-12-16 11:02:48 +020020#include <linux/kvm_host.h>
21
Eddie Dong85f455f2007-07-06 12:20:49 +030022#include "irq.h"
Zhang Xiantao1d737c82007-12-14 09:35:10 +080023#include "mmu.h"
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -030024#include "kvm_cache_regs.h"
Gleb Natapovfe4c7b12009-03-23 11:23:18 +020025#include "x86.h"
Julian Stecklina66f7b722012-12-05 15:26:19 +010026#include "cpuid.h"
Wei Huang25462f72015-06-19 15:45:05 +020027#include "pmu.h"
Avi Kivitye4956062007-06-28 14:15:57 -040028
Avi Kivity6aa8b732006-12-10 02:21:36 -080029#include <linux/module.h>
Josh Triplettae759542012-03-28 11:32:28 -070030#include <linux/mod_devicetable.h>
Ahmed S. Darwish9d8f5492007-02-19 14:37:46 +020031#include <linux/kernel.h>
Avi Kivity6aa8b732006-12-10 02:21:36 -080032#include <linux/vmalloc.h>
33#include <linux/highmem.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040034#include <linux/sched.h>
Steven Rostedt (Red Hat)af658dc2015-04-29 14:36:05 -040035#include <linux/trace_events.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Avi Kivity6aa8b732006-12-10 02:21:36 -080037
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -050038#include <asm/apic.h>
Joerg Roedel1018faa2012-02-29 14:57:32 +010039#include <asm/perf_event.h>
Joerg Roedel67ec6602010-05-17 14:43:35 +020040#include <asm/tlbflush.h>
Avi Kivitye4956062007-06-28 14:15:57 -040041#include <asm/desc.h>
Paolo Bonzinifacb0132014-02-21 10:32:27 +010042#include <asm/debugreg.h>
Gleb Natapov631bc482010-10-14 11:22:52 +020043#include <asm/kvm_para.h>
Avi Kivity6aa8b732006-12-10 02:21:36 -080044
Eduardo Habkost63d11422008-11-17 19:03:20 -020045#include <asm/virtext.h>
Marcelo Tosatti229456f2009-06-17 09:22:14 -030046#include "trace.h"
Eduardo Habkost63d11422008-11-17 19:03:20 -020047
Avi Kivity4ecac3f2008-05-13 13:23:38 +030048#define __ex(x) __kvm_handle_fault_on_reboot(x)
49
Avi Kivity6aa8b732006-12-10 02:21:36 -080050MODULE_AUTHOR("Qumranet");
51MODULE_LICENSE("GPL");
52
Josh Triplettae759542012-03-28 11:32:28 -070053static const struct x86_cpu_id svm_cpu_id[] = {
54 X86_FEATURE_MATCH(X86_FEATURE_SVM),
55 {}
56};
57MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
58
Avi Kivity6aa8b732006-12-10 02:21:36 -080059#define IOPM_ALLOC_ORDER 2
60#define MSRPM_ALLOC_ORDER 1
61
Avi Kivity6aa8b732006-12-10 02:21:36 -080062#define SEG_TYPE_LDT 2
63#define SEG_TYPE_BUSY_TSS16 3
64
Andre Przywara6bc31bd2010-04-11 23:07:28 +020065#define SVM_FEATURE_NPT (1 << 0)
66#define SVM_FEATURE_LBRV (1 << 1)
67#define SVM_FEATURE_SVML (1 << 2)
68#define SVM_FEATURE_NRIP (1 << 3)
Andre Przywaraddce97a2010-12-21 11:12:03 +010069#define SVM_FEATURE_TSC_RATE (1 << 4)
70#define SVM_FEATURE_VMCB_CLEAN (1 << 5)
71#define SVM_FEATURE_FLUSH_ASID (1 << 6)
72#define SVM_FEATURE_DECODE_ASSIST (1 << 7)
Andre Przywara6bc31bd2010-04-11 23:07:28 +020073#define SVM_FEATURE_PAUSE_FILTER (1 << 10)
Joerg Roedel80b77062007-03-30 17:02:14 +030074
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -050075#define SVM_AVIC_DOORBELL 0xc001011b
76
Joerg Roedel410e4d52009-08-07 11:49:44 +020077#define NESTED_EXIT_HOST 0 /* Exit handled on host level */
78#define NESTED_EXIT_DONE 1 /* Exit caused nested vmexit */
79#define NESTED_EXIT_CONTINUE 2 /* Further checks needed */
80
Joerg Roedel24e09cb2008-02-13 18:58:47 +010081#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
82
Joerg Roedelfbc0db72011-03-25 09:44:46 +010083#define TSC_RATIO_RSVD 0xffffff0000000000ULL
Joerg Roedel92a1f122011-03-25 09:44:51 +010084#define TSC_RATIO_MIN 0x0000000000000001ULL
85#define TSC_RATIO_MAX 0x000000ffffffffffULL
Joerg Roedelfbc0db72011-03-25 09:44:46 +010086
Dan Carpenter5446a972016-05-23 13:20:10 +030087#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF)
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -050088
89/*
90 * 0xff is broadcast, so the max index allowed for physical APIC ID
91 * table is 0xfe. APIC IDs above 0xff are reserved.
92 */
93#define AVIC_MAX_PHYSICAL_ID_COUNT 255
94
Suravee Suthikulpanit18f40c52016-05-04 14:09:48 -050095#define AVIC_UNACCEL_ACCESS_WRITE_MASK 1
96#define AVIC_UNACCEL_ACCESS_OFFSET_MASK 0xFF0
97#define AVIC_UNACCEL_ACCESS_VECTOR_MASK 0xFFFFFFFF
98
Suravee Suthikulpanit5ea11f22016-08-23 13:52:41 -050099/* AVIC GATAG is encoded using VM and VCPU IDs */
100#define AVIC_VCPU_ID_BITS 8
101#define AVIC_VCPU_ID_MASK ((1 << AVIC_VCPU_ID_BITS) - 1)
102
103#define AVIC_VM_ID_BITS 24
104#define AVIC_VM_ID_NR (1 << AVIC_VM_ID_BITS)
105#define AVIC_VM_ID_MASK ((1 << AVIC_VM_ID_BITS) - 1)
106
107#define AVIC_GATAG(x, y) (((x & AVIC_VM_ID_MASK) << AVIC_VCPU_ID_BITS) | \
108 (y & AVIC_VCPU_ID_MASK))
109#define AVIC_GATAG_TO_VMID(x) ((x >> AVIC_VCPU_ID_BITS) & AVIC_VM_ID_MASK)
110#define AVIC_GATAG_TO_VCPUID(x) (x & AVIC_VCPU_ID_MASK)
111
Joerg Roedel67ec6602010-05-17 14:43:35 +0200112static bool erratum_383_found __read_mostly;
113
Avi Kivity6c8166a2009-05-31 18:15:37 +0300114static const u32 host_save_user_msrs[] = {
115#ifdef CONFIG_X86_64
116 MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
117 MSR_FS_BASE,
118#endif
119 MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
Paolo Bonzini46896c72015-11-12 14:49:16 +0100120 MSR_TSC_AUX,
Avi Kivity6c8166a2009-05-31 18:15:37 +0300121};
122
123#define NR_HOST_SAVE_USER_MSRS ARRAY_SIZE(host_save_user_msrs)
124
125struct kvm_vcpu;
126
Joerg Roedele6aa9ab2009-08-07 11:49:33 +0200127struct nested_state {
128 struct vmcb *hsave;
129 u64 hsave_msr;
Joerg Roedel4a810182010-02-24 18:59:15 +0100130 u64 vm_cr_msr;
Joerg Roedele6aa9ab2009-08-07 11:49:33 +0200131 u64 vmcb;
132
133 /* These are the merged vectors */
134 u32 *msrpm;
135
136 /* gpa pointers to the real vectors */
137 u64 vmcb_msrpm;
Joerg Roedelce2ac082010-03-01 15:34:39 +0100138 u64 vmcb_iopm;
Joerg Roedelaad42c62009-08-07 11:49:34 +0200139
Joerg Roedelcd3ff652009-10-09 16:08:26 +0200140 /* A VMEXIT is required but not yet emulated */
141 bool exit_required;
142
Joerg Roedelaad42c62009-08-07 11:49:34 +0200143 /* cache for intercepts of the guest */
Roedel, Joerg4ee546b2010-12-03 10:50:51 +0100144 u32 intercept_cr;
Joerg Roedel3aed0412010-11-30 18:03:58 +0100145 u32 intercept_dr;
Joerg Roedelaad42c62009-08-07 11:49:34 +0200146 u32 intercept_exceptions;
147 u64 intercept;
148
Joerg Roedel5bd2edc2010-09-10 17:31:02 +0200149 /* Nested Paging related state */
150 u64 nested_cr3;
Joerg Roedele6aa9ab2009-08-07 11:49:33 +0200151};
152
Joerg Roedel323c3d82010-03-01 15:34:37 +0100153#define MSRPM_OFFSETS 16
154static u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
155
Boris Ostrovsky2b036c62012-01-09 14:00:35 -0500156/*
157 * Set osvw_len to higher value when updated Revision Guides
158 * are published and we know what the new status bits are
159 */
160static uint64_t osvw_len = 4, osvw_status;
161
Avi Kivity6c8166a2009-05-31 18:15:37 +0300162struct vcpu_svm {
163 struct kvm_vcpu vcpu;
164 struct vmcb *vmcb;
165 unsigned long vmcb_pa;
166 struct svm_cpu_data *svm_data;
167 uint64_t asid_generation;
168 uint64_t sysenter_esp;
169 uint64_t sysenter_eip;
Paolo Bonzini46896c72015-11-12 14:49:16 +0100170 uint64_t tsc_aux;
Avi Kivity6c8166a2009-05-31 18:15:37 +0300171
172 u64 next_rip;
173
174 u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
Avi Kivityafe9e662010-10-21 12:20:32 +0200175 struct {
Avi Kivitydacccfd2010-10-21 12:20:33 +0200176 u16 fs;
177 u16 gs;
178 u16 ldt;
Avi Kivityafe9e662010-10-21 12:20:32 +0200179 u64 gs_base;
180 } host;
Avi Kivity6c8166a2009-05-31 18:15:37 +0300181
182 u32 *msrpm;
Avi Kivity6c8166a2009-05-31 18:15:37 +0300183
Avi Kivitybd3d1ec2011-02-03 15:29:52 +0200184 ulong nmi_iret_rip;
185
Joerg Roedele6aa9ab2009-08-07 11:49:33 +0200186 struct nested_state nested;
Jan Kiszka6be7d302009-10-18 13:24:54 +0200187
188 bool nmi_singlestep;
Jan Kiszka66b71382010-02-23 17:47:56 +0100189
190 unsigned int3_injected;
191 unsigned long int3_rip;
Gleb Natapov631bc482010-10-14 11:22:52 +0200192 u32 apf_reason;
Joerg Roedelfbc0db72011-03-25 09:44:46 +0100193
Joerg Roedel6092d3d2015-10-14 15:10:54 +0200194 /* cached guest cpuid flags for faster access */
195 bool nrips_enabled : 1;
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500196
Suravee Suthikulpanit18f40c52016-05-04 14:09:48 -0500197 u32 ldr_reg;
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500198 struct page *avic_backing_page;
199 u64 *avic_physical_id_cache;
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -0500200 bool avic_is_running;
Avi Kivity6c8166a2009-05-31 18:15:37 +0300201};
202
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500203#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFF)
204#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
205
206#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK (0xFFULL)
207#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
208#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
209#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
210
Joerg Roedelfbc0db72011-03-25 09:44:46 +0100211static DEFINE_PER_CPU(u64, current_tsc_ratio);
212#define TSC_RATIO_DEFAULT 0x0100000000ULL
213
Joerg Roedel455716f2010-03-01 15:34:35 +0100214#define MSR_INVALID 0xffffffffU
215
Mathias Krause09941fb2012-08-30 01:30:20 +0200216static const struct svm_direct_access_msrs {
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100217 u32 index; /* Index of the MSR */
218 bool always; /* True if intercept is always on */
219} direct_access_msrs[] = {
Brian Gerst8c065852010-07-17 09:03:26 -0400220 { .index = MSR_STAR, .always = true },
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100221 { .index = MSR_IA32_SYSENTER_CS, .always = true },
222#ifdef CONFIG_X86_64
223 { .index = MSR_GS_BASE, .always = true },
224 { .index = MSR_FS_BASE, .always = true },
225 { .index = MSR_KERNEL_GS_BASE, .always = true },
226 { .index = MSR_LSTAR, .always = true },
227 { .index = MSR_CSTAR, .always = true },
228 { .index = MSR_SYSCALL_MASK, .always = true },
229#endif
230 { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
231 { .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
232 { .index = MSR_IA32_LASTINTFROMIP, .always = false },
233 { .index = MSR_IA32_LASTINTTOIP, .always = false },
234 { .index = MSR_INVALID, .always = false },
Avi Kivity6aa8b732006-12-10 02:21:36 -0800235};
236
237/* enable NPT for AMD64 and X86 with PAE */
238#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
239static bool npt_enabled = true;
240#else
Joerg Roedele0231712010-02-24 18:59:10 +0100241static bool npt_enabled;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800242#endif
243
Davidlohr Buesoe2358852012-01-17 14:09:50 +0100244/* allow nested paging (virtualized MMU) for all guests */
245static int npt = true;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800246module_param(npt, int, S_IRUGO);
247
Davidlohr Buesoe2358852012-01-17 14:09:50 +0100248/* allow nested virtualization in KVM/SVM */
249static int nested = true;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800250module_param(nested, int, S_IRUGO);
251
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500252/* enable / disable AVIC */
253static int avic;
Suravee Suthikulpanit5b8abf12016-06-15 17:24:36 -0500254#ifdef CONFIG_X86_LOCAL_APIC
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500255module_param(avic, int, S_IRUGO);
Suravee Suthikulpanit5b8abf12016-06-15 17:24:36 -0500256#endif
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500257
Suravee Suthikulpanit5ea11f22016-08-23 13:52:41 -0500258/* AVIC VM ID bit masks and lock */
259static DECLARE_BITMAP(avic_vm_id_bitmap, AVIC_VM_ID_NR);
260static DEFINE_SPINLOCK(avic_vm_id_lock);
261
Paolo Bonzini79a80592015-09-21 07:46:55 +0200262static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800263static void svm_flush_tlb(struct kvm_vcpu *vcpu);
Joerg Roedela5c38322009-08-07 11:49:32 +0200264static void svm_complete_interrupts(struct vcpu_svm *svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800265
Joerg Roedel410e4d52009-08-07 11:49:44 +0200266static int nested_svm_exit_handled(struct vcpu_svm *svm);
Joerg Roedelb8e88bc2010-02-19 16:23:02 +0100267static int nested_svm_intercept(struct vcpu_svm *svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800268static int nested_svm_vmexit(struct vcpu_svm *svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800269static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
270 bool has_error_code, u32 error_code);
271
Roedel, Joerg8d28fec2010-12-03 13:15:21 +0100272enum {
Joerg Roedel116a0a22010-12-03 11:45:49 +0100273 VMCB_INTERCEPTS, /* Intercept vectors, TSC offset,
274 pause filter count */
Joerg Roedelf56838e2010-12-03 11:45:50 +0100275 VMCB_PERM_MAP, /* IOPM Base and MSRPM Base */
Joerg Roedeld48086d2010-12-03 11:45:51 +0100276 VMCB_ASID, /* ASID */
Joerg Roedeldecdbf62010-12-03 11:45:52 +0100277 VMCB_INTR, /* int_ctl, int_vector */
Joerg Roedelb2747162010-12-03 11:45:53 +0100278 VMCB_NPT, /* npt_en, nCR3, gPAT */
Joerg Roedeldcca1a62010-12-03 11:45:54 +0100279 VMCB_CR, /* CR0, CR3, CR4, EFER */
Joerg Roedel72214b92010-12-03 11:45:55 +0100280 VMCB_DR, /* DR6, DR7 */
Joerg Roedel17a703c2010-12-03 11:45:56 +0100281 VMCB_DT, /* GDT, IDT */
Joerg Roedel060d0c92010-12-03 11:45:57 +0100282 VMCB_SEG, /* CS, DS, SS, ES, CPL */
Joerg Roedel0574dec2010-12-03 11:45:58 +0100283 VMCB_CR2, /* CR2 only */
Joerg Roedelb53ba3f2010-12-03 11:45:59 +0100284 VMCB_LBR, /* DBGCTL, BR_FROM, BR_TO, LAST_EX_FROM, LAST_EX_TO */
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500285 VMCB_AVIC, /* AVIC APIC_BAR, AVIC APIC_BACKING_PAGE,
286 * AVIC PHYSICAL_TABLE pointer,
287 * AVIC LOGICAL_TABLE pointer
288 */
Roedel, Joerg8d28fec2010-12-03 13:15:21 +0100289 VMCB_DIRTY_MAX,
290};
291
Joerg Roedel0574dec2010-12-03 11:45:58 +0100292/* TPR and CR2 are always written before VMRUN */
293#define VMCB_ALWAYS_DIRTY_MASK ((1U << VMCB_INTR) | (1U << VMCB_CR2))
Roedel, Joerg8d28fec2010-12-03 13:15:21 +0100294
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500295#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
296
Roedel, Joerg8d28fec2010-12-03 13:15:21 +0100297static inline void mark_all_dirty(struct vmcb *vmcb)
298{
299 vmcb->control.clean = 0;
300}
301
302static inline void mark_all_clean(struct vmcb *vmcb)
303{
304 vmcb->control.clean = ((1 << VMCB_DIRTY_MAX) - 1)
305 & ~VMCB_ALWAYS_DIRTY_MASK;
306}
307
308static inline void mark_dirty(struct vmcb *vmcb, int bit)
309{
310 vmcb->control.clean &= ~(1 << bit);
311}
312
Avi Kivity6aa8b732006-12-10 02:21:36 -0800313static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
314{
315 return container_of(vcpu, struct vcpu_svm, vcpu);
316}
317
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -0500318static inline void avic_update_vapic_bar(struct vcpu_svm *svm, u64 data)
319{
320 svm->vmcb->control.avic_vapic_bar = data & VMCB_AVIC_APIC_BAR_MASK;
321 mark_dirty(svm->vmcb, VMCB_AVIC);
322}
323
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -0500324static inline bool avic_vcpu_is_running(struct kvm_vcpu *vcpu)
325{
326 struct vcpu_svm *svm = to_svm(vcpu);
327 u64 *entry = svm->avic_physical_id_cache;
328
329 if (!entry)
330 return false;
331
332 return (READ_ONCE(*entry) & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
333}
334
Joerg Roedel384c6362010-11-30 18:03:56 +0100335static void recalc_intercepts(struct vcpu_svm *svm)
336{
337 struct vmcb_control_area *c, *h;
338 struct nested_state *g;
339
Joerg Roedel116a0a22010-12-03 11:45:49 +0100340 mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
341
Joerg Roedel384c6362010-11-30 18:03:56 +0100342 if (!is_guest_mode(&svm->vcpu))
343 return;
344
345 c = &svm->vmcb->control;
346 h = &svm->nested.hsave->control;
347 g = &svm->nested;
348
Roedel, Joerg4ee546b2010-12-03 10:50:51 +0100349 c->intercept_cr = h->intercept_cr | g->intercept_cr;
Joerg Roedel3aed0412010-11-30 18:03:58 +0100350 c->intercept_dr = h->intercept_dr | g->intercept_dr;
Joerg Roedel384c6362010-11-30 18:03:56 +0100351 c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions;
352 c->intercept = h->intercept | g->intercept;
353}
354
Roedel, Joerg4ee546b2010-12-03 10:50:51 +0100355static inline struct vmcb *get_host_vmcb(struct vcpu_svm *svm)
356{
357 if (is_guest_mode(&svm->vcpu))
358 return svm->nested.hsave;
359 else
360 return svm->vmcb;
361}
362
363static inline void set_cr_intercept(struct vcpu_svm *svm, int bit)
364{
365 struct vmcb *vmcb = get_host_vmcb(svm);
366
367 vmcb->control.intercept_cr |= (1U << bit);
368
369 recalc_intercepts(svm);
370}
371
372static inline void clr_cr_intercept(struct vcpu_svm *svm, int bit)
373{
374 struct vmcb *vmcb = get_host_vmcb(svm);
375
376 vmcb->control.intercept_cr &= ~(1U << bit);
377
378 recalc_intercepts(svm);
379}
380
381static inline bool is_cr_intercept(struct vcpu_svm *svm, int bit)
382{
383 struct vmcb *vmcb = get_host_vmcb(svm);
384
385 return vmcb->control.intercept_cr & (1U << bit);
386}
387
Paolo Bonzini5315c712014-03-03 13:08:29 +0100388static inline void set_dr_intercepts(struct vcpu_svm *svm)
Joerg Roedel3aed0412010-11-30 18:03:58 +0100389{
390 struct vmcb *vmcb = get_host_vmcb(svm);
391
Paolo Bonzini5315c712014-03-03 13:08:29 +0100392 vmcb->control.intercept_dr = (1 << INTERCEPT_DR0_READ)
393 | (1 << INTERCEPT_DR1_READ)
394 | (1 << INTERCEPT_DR2_READ)
395 | (1 << INTERCEPT_DR3_READ)
396 | (1 << INTERCEPT_DR4_READ)
397 | (1 << INTERCEPT_DR5_READ)
398 | (1 << INTERCEPT_DR6_READ)
399 | (1 << INTERCEPT_DR7_READ)
400 | (1 << INTERCEPT_DR0_WRITE)
401 | (1 << INTERCEPT_DR1_WRITE)
402 | (1 << INTERCEPT_DR2_WRITE)
403 | (1 << INTERCEPT_DR3_WRITE)
404 | (1 << INTERCEPT_DR4_WRITE)
405 | (1 << INTERCEPT_DR5_WRITE)
406 | (1 << INTERCEPT_DR6_WRITE)
407 | (1 << INTERCEPT_DR7_WRITE);
Joerg Roedel3aed0412010-11-30 18:03:58 +0100408
409 recalc_intercepts(svm);
410}
411
Paolo Bonzini5315c712014-03-03 13:08:29 +0100412static inline void clr_dr_intercepts(struct vcpu_svm *svm)
Joerg Roedel3aed0412010-11-30 18:03:58 +0100413{
414 struct vmcb *vmcb = get_host_vmcb(svm);
415
Paolo Bonzini5315c712014-03-03 13:08:29 +0100416 vmcb->control.intercept_dr = 0;
Joerg Roedel3aed0412010-11-30 18:03:58 +0100417
418 recalc_intercepts(svm);
419}
420
Joerg Roedel18c918c2010-11-30 18:03:59 +0100421static inline void set_exception_intercept(struct vcpu_svm *svm, int bit)
422{
423 struct vmcb *vmcb = get_host_vmcb(svm);
424
425 vmcb->control.intercept_exceptions |= (1U << bit);
426
427 recalc_intercepts(svm);
428}
429
430static inline void clr_exception_intercept(struct vcpu_svm *svm, int bit)
431{
432 struct vmcb *vmcb = get_host_vmcb(svm);
433
434 vmcb->control.intercept_exceptions &= ~(1U << bit);
435
436 recalc_intercepts(svm);
437}
438
Joerg Roedel8a05a1b82010-11-30 18:04:00 +0100439static inline void set_intercept(struct vcpu_svm *svm, int bit)
440{
441 struct vmcb *vmcb = get_host_vmcb(svm);
442
443 vmcb->control.intercept |= (1ULL << bit);
444
445 recalc_intercepts(svm);
446}
447
448static inline void clr_intercept(struct vcpu_svm *svm, int bit)
449{
450 struct vmcb *vmcb = get_host_vmcb(svm);
451
452 vmcb->control.intercept &= ~(1ULL << bit);
453
454 recalc_intercepts(svm);
455}
456
Joerg Roedel2af91942009-08-07 11:49:28 +0200457static inline void enable_gif(struct vcpu_svm *svm)
458{
459 svm->vcpu.arch.hflags |= HF_GIF_MASK;
460}
461
462static inline void disable_gif(struct vcpu_svm *svm)
463{
464 svm->vcpu.arch.hflags &= ~HF_GIF_MASK;
465}
466
467static inline bool gif_set(struct vcpu_svm *svm)
468{
469 return !!(svm->vcpu.arch.hflags & HF_GIF_MASK);
470}
471
Avi Kivity6aa8b732006-12-10 02:21:36 -0800472static unsigned long iopm_base;
473
474struct kvm_ldttss_desc {
475 u16 limit0;
476 u16 base0;
Joerg Roedele0231712010-02-24 18:59:10 +0100477 unsigned base1:8, type:5, dpl:2, p:1;
478 unsigned limit1:4, zero0:3, g:1, base2:8;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800479 u32 base3;
480 u32 zero1;
481} __attribute__((packed));
482
483struct svm_cpu_data {
484 int cpu;
485
Avi Kivity5008fdf2007-04-02 13:05:50 +0300486 u64 asid_generation;
487 u32 max_asid;
488 u32 next_asid;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800489 struct kvm_ldttss_desc *tss_desc;
490
491 struct page *save_area;
492};
493
494static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
495
496struct svm_init_data {
497 int cpu;
498 int r;
499};
500
Mathias Krause09941fb2012-08-30 01:30:20 +0200501static const u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
Avi Kivity6aa8b732006-12-10 02:21:36 -0800502
Ahmed S. Darwish9d8f5492007-02-19 14:37:46 +0200503#define NUM_MSR_MAPS ARRAY_SIZE(msrpm_ranges)
Avi Kivity6aa8b732006-12-10 02:21:36 -0800504#define MSRS_RANGE_SIZE 2048
505#define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
506
Joerg Roedel455716f2010-03-01 15:34:35 +0100507static u32 svm_msrpm_offset(u32 msr)
508{
509 u32 offset;
510 int i;
511
512 for (i = 0; i < NUM_MSR_MAPS; i++) {
513 if (msr < msrpm_ranges[i] ||
514 msr >= msrpm_ranges[i] + MSRS_IN_RANGE)
515 continue;
516
517 offset = (msr - msrpm_ranges[i]) / 4; /* 4 msrs per u8 */
518 offset += (i * MSRS_RANGE_SIZE); /* add range offset */
519
520 /* Now we have the u8 offset - but need the u32 offset */
521 return offset / 4;
522 }
523
524 /* MSR not in any range */
525 return MSR_INVALID;
526}
527
Avi Kivity6aa8b732006-12-10 02:21:36 -0800528#define MAX_INST_SIZE 15
529
Avi Kivity6aa8b732006-12-10 02:21:36 -0800530static inline void clgi(void)
531{
Avi Kivity4ecac3f2008-05-13 13:23:38 +0300532 asm volatile (__ex(SVM_CLGI));
Avi Kivity6aa8b732006-12-10 02:21:36 -0800533}
534
535static inline void stgi(void)
536{
Avi Kivity4ecac3f2008-05-13 13:23:38 +0300537 asm volatile (__ex(SVM_STGI));
Avi Kivity6aa8b732006-12-10 02:21:36 -0800538}
539
540static inline void invlpga(unsigned long addr, u32 asid)
541{
Joerg Roedele0231712010-02-24 18:59:10 +0100542 asm volatile (__ex(SVM_INVLPGA) : : "a"(addr), "c"(asid));
Avi Kivity6aa8b732006-12-10 02:21:36 -0800543}
544
Joerg Roedel4b161842010-09-10 17:31:03 +0200545static int get_npt_level(void)
546{
547#ifdef CONFIG_X86_64
548 return PT64_ROOT_LEVEL;
549#else
550 return PT32E_ROOT_LEVEL;
551#endif
552}
553
Avi Kivity6aa8b732006-12-10 02:21:36 -0800554static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
555{
Zachary Amsden6dc696d2010-05-26 15:09:43 -1000556 vcpu->arch.efer = efer;
Joerg Roedel709ddeb2008-02-07 13:47:45 +0100557 if (!npt_enabled && !(efer & EFER_LMA))
Carlo Marcelo Arenas Belon2b5203e2007-12-01 06:17:11 -0600558 efer &= ~EFER_LME;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800559
Alexander Graf9962d032008-11-25 20:17:02 +0100560 to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME;
Joerg Roedeldcca1a62010-12-03 11:45:54 +0100561 mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800562}
563
Avi Kivity6aa8b732006-12-10 02:21:36 -0800564static int is_external_interrupt(u32 info)
565{
566 info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
567 return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
568}
569
Paolo Bonzini37ccdcb2014-05-20 14:29:47 +0200570static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu)
Glauber Costa2809f5d2009-05-12 16:21:05 -0400571{
572 struct vcpu_svm *svm = to_svm(vcpu);
573 u32 ret = 0;
574
575 if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
Paolo Bonzini37ccdcb2014-05-20 14:29:47 +0200576 ret = KVM_X86_SHADOW_INT_STI | KVM_X86_SHADOW_INT_MOV_SS;
577 return ret;
Glauber Costa2809f5d2009-05-12 16:21:05 -0400578}
579
580static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
581{
582 struct vcpu_svm *svm = to_svm(vcpu);
583
584 if (mask == 0)
585 svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
586 else
587 svm->vmcb->control.int_state |= SVM_INTERRUPT_SHADOW_MASK;
588
589}
590
Avi Kivity6aa8b732006-12-10 02:21:36 -0800591static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
592{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -0400593 struct vcpu_svm *svm = to_svm(vcpu);
594
Bandan Dasf1047652015-06-11 02:05:33 -0400595 if (svm->vmcb->control.next_rip != 0) {
Dirk Müllerd2922422015-10-01 13:43:42 +0200596 WARN_ON_ONCE(!static_cpu_has(X86_FEATURE_NRIPS));
Andre Przywara6bc31bd2010-04-11 23:07:28 +0200597 svm->next_rip = svm->vmcb->control.next_rip;
Bandan Dasf1047652015-06-11 02:05:33 -0400598 }
Andre Przywara6bc31bd2010-04-11 23:07:28 +0200599
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -0400600 if (!svm->next_rip) {
Andre Przywara51d8b662010-12-21 11:12:02 +0100601 if (emulate_instruction(vcpu, EMULTYPE_SKIP) !=
Gleb Natapovf629cf82009-05-11 13:35:49 +0300602 EMULATE_DONE)
603 printk(KERN_DEBUG "%s: NOP\n", __func__);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800604 return;
605 }
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -0300606 if (svm->next_rip - kvm_rip_read(vcpu) > MAX_INST_SIZE)
607 printk(KERN_ERR "%s: ip 0x%lx next 0x%llx\n",
608 __func__, kvm_rip_read(vcpu), svm->next_rip);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800609
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -0300610 kvm_rip_write(vcpu, svm->next_rip);
Glauber Costa2809f5d2009-05-12 16:21:05 -0400611 svm_set_interrupt_shadow(vcpu, 0);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800612}
613
Jan Kiszka116a4752010-02-23 17:47:54 +0100614static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
Joerg Roedelce7ddec2010-04-22 12:33:13 +0200615 bool has_error_code, u32 error_code,
616 bool reinject)
Jan Kiszka116a4752010-02-23 17:47:54 +0100617{
618 struct vcpu_svm *svm = to_svm(vcpu);
619
Joerg Roedele0231712010-02-24 18:59:10 +0100620 /*
621 * If we are within a nested VM we'd better #VMEXIT and let the guest
622 * handle the exception
623 */
Joerg Roedelce7ddec2010-04-22 12:33:13 +0200624 if (!reinject &&
625 nested_svm_check_exception(svm, nr, has_error_code, error_code))
Jan Kiszka116a4752010-02-23 17:47:54 +0100626 return;
627
Avi Kivity2a6b20b2010-11-09 16:15:42 +0200628 if (nr == BP_VECTOR && !static_cpu_has(X86_FEATURE_NRIPS)) {
Jan Kiszka66b71382010-02-23 17:47:56 +0100629 unsigned long rip, old_rip = kvm_rip_read(&svm->vcpu);
630
631 /*
632 * For guest debugging where we have to reinject #BP if some
633 * INT3 is guest-owned:
634 * Emulate nRIP by moving RIP forward. Will fail if injection
635 * raises a fault that is not intercepted. Still better than
636 * failing in all cases.
637 */
638 skip_emulated_instruction(&svm->vcpu);
639 rip = kvm_rip_read(&svm->vcpu);
640 svm->int3_rip = rip + svm->vmcb->save.cs.base;
641 svm->int3_injected = rip - old_rip;
642 }
643
Jan Kiszka116a4752010-02-23 17:47:54 +0100644 svm->vmcb->control.event_inj = nr
645 | SVM_EVTINJ_VALID
646 | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0)
647 | SVM_EVTINJ_TYPE_EXEPT;
648 svm->vmcb->control.event_inj_err = error_code;
649}
650
Joerg Roedel67ec6602010-05-17 14:43:35 +0200651static void svm_init_erratum_383(void)
652{
653 u32 low, high;
654 int err;
655 u64 val;
656
Borislav Petkove6ee94d2013-03-20 15:07:27 +0100657 if (!static_cpu_has_bug(X86_BUG_AMD_TLB_MMATCH))
Joerg Roedel67ec6602010-05-17 14:43:35 +0200658 return;
659
660 /* Use _safe variants to not break nested virtualization */
661 val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
662 if (err)
663 return;
664
665 val |= (1ULL << 47);
666
667 low = lower_32_bits(val);
668 high = upper_32_bits(val);
669
670 native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
671
672 erratum_383_found = true;
673}
674
Boris Ostrovsky2b036c62012-01-09 14:00:35 -0500675static void svm_init_osvw(struct kvm_vcpu *vcpu)
676{
677 /*
678 * Guests should see errata 400 and 415 as fixed (assuming that
679 * HLT and IO instructions are intercepted).
680 */
681 vcpu->arch.osvw.length = (osvw_len >= 3) ? (osvw_len) : 3;
682 vcpu->arch.osvw.status = osvw_status & ~(6ULL);
683
684 /*
685 * By increasing VCPU's osvw.length to 3 we are telling the guest that
686 * all osvw.status bits inside that length, including bit 0 (which is
687 * reserved for erratum 298), are valid. However, if host processor's
688 * osvw_len is 0 then osvw_status[0] carries no information. We need to
689 * be conservative here and therefore we tell the guest that erratum 298
690 * is present (because we really don't know).
691 */
692 if (osvw_len == 0 && boot_cpu_data.x86 == 0x10)
693 vcpu->arch.osvw.status |= 1;
694}
695
Avi Kivity6aa8b732006-12-10 02:21:36 -0800696static int has_svm(void)
697{
Eduardo Habkost63d11422008-11-17 19:03:20 -0200698 const char *msg;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800699
Eduardo Habkost63d11422008-11-17 19:03:20 -0200700 if (!cpu_has_svm(&msg)) {
Joe Perchesff81ff12009-01-08 11:05:17 -0800701 printk(KERN_INFO "has_svm: %s\n", msg);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800702 return 0;
703 }
704
Avi Kivity6aa8b732006-12-10 02:21:36 -0800705 return 1;
706}
707
Radim Krčmář13a34e02014-08-28 15:13:03 +0200708static void svm_hardware_disable(void)
Avi Kivity6aa8b732006-12-10 02:21:36 -0800709{
Joerg Roedelfbc0db72011-03-25 09:44:46 +0100710 /* Make sure we clean up behind us */
711 if (static_cpu_has(X86_FEATURE_TSCRATEMSR))
712 wrmsrl(MSR_AMD64_TSC_RATIO, TSC_RATIO_DEFAULT);
713
Eduardo Habkost2c8dcee2008-11-17 19:03:21 -0200714 cpu_svm_disable();
Joerg Roedel1018faa2012-02-29 14:57:32 +0100715
716 amd_pmu_disable_virt();
Avi Kivity6aa8b732006-12-10 02:21:36 -0800717}
718
Radim Krčmář13a34e02014-08-28 15:13:03 +0200719static int svm_hardware_enable(void)
Avi Kivity6aa8b732006-12-10 02:21:36 -0800720{
721
Tejun Heo0fe1e002009-10-29 22:34:14 +0900722 struct svm_cpu_data *sd;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800723 uint64_t efer;
Gleb Natapov89a27f42010-02-16 10:51:48 +0200724 struct desc_ptr gdt_descr;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800725 struct desc_struct *gdt;
726 int me = raw_smp_processor_id();
727
Alexander Graf10474ae2009-09-15 11:37:46 +0200728 rdmsrl(MSR_EFER, efer);
729 if (efer & EFER_SVME)
730 return -EBUSY;
731
Avi Kivity6aa8b732006-12-10 02:21:36 -0800732 if (!has_svm()) {
Borislav Petkov1f5b77f2012-10-20 20:20:04 +0200733 pr_err("%s: err EOPNOTSUPP on %d\n", __func__, me);
Alexander Graf10474ae2009-09-15 11:37:46 +0200734 return -EINVAL;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800735 }
Tejun Heo0fe1e002009-10-29 22:34:14 +0900736 sd = per_cpu(svm_data, me);
Tejun Heo0fe1e002009-10-29 22:34:14 +0900737 if (!sd) {
Borislav Petkov1f5b77f2012-10-20 20:20:04 +0200738 pr_err("%s: svm_data is NULL on %d\n", __func__, me);
Alexander Graf10474ae2009-09-15 11:37:46 +0200739 return -EINVAL;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800740 }
741
Tejun Heo0fe1e002009-10-29 22:34:14 +0900742 sd->asid_generation = 1;
743 sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
744 sd->next_asid = sd->max_asid + 1;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800745
Gleb Natapovd6ab1ed2010-02-25 12:43:07 +0200746 native_store_gdt(&gdt_descr);
Gleb Natapov89a27f42010-02-16 10:51:48 +0200747 gdt = (struct desc_struct *)gdt_descr.address;
Tejun Heo0fe1e002009-10-29 22:34:14 +0900748 sd->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800749
Alexander Graf9962d032008-11-25 20:17:02 +0100750 wrmsrl(MSR_EFER, efer | EFER_SVME);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800751
Linus Torvaldsd0316552009-12-14 09:58:24 -0800752 wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
Alexander Graf10474ae2009-09-15 11:37:46 +0200753
Joerg Roedelfbc0db72011-03-25 09:44:46 +0100754 if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
755 wrmsrl(MSR_AMD64_TSC_RATIO, TSC_RATIO_DEFAULT);
Christoph Lameter89cbc762014-08-17 12:30:40 -0500756 __this_cpu_write(current_tsc_ratio, TSC_RATIO_DEFAULT);
Joerg Roedelfbc0db72011-03-25 09:44:46 +0100757 }
758
Boris Ostrovsky2b036c62012-01-09 14:00:35 -0500759
760 /*
761 * Get OSVW bits.
762 *
763 * Note that it is possible to have a system with mixed processor
764 * revisions and therefore different OSVW bits. If bits are not the same
765 * on different processors then choose the worst case (i.e. if erratum
766 * is present on one processor and not on another then assume that the
767 * erratum is present everywhere).
768 */
769 if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
770 uint64_t len, status = 0;
771 int err;
772
773 len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
774 if (!err)
775 status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
776 &err);
777
778 if (err)
779 osvw_status = osvw_len = 0;
780 else {
781 if (len < osvw_len)
782 osvw_len = len;
783 osvw_status |= status;
784 osvw_status &= (1ULL << osvw_len) - 1;
785 }
786 } else
787 osvw_status = osvw_len = 0;
788
Joerg Roedel67ec6602010-05-17 14:43:35 +0200789 svm_init_erratum_383();
790
Joerg Roedel1018faa2012-02-29 14:57:32 +0100791 amd_pmu_enable_virt();
792
Alexander Graf10474ae2009-09-15 11:37:46 +0200793 return 0;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800794}
795
Joerg Roedel0da1db752008-07-02 16:02:11 +0200796static void svm_cpu_uninit(int cpu)
797{
Tejun Heo0fe1e002009-10-29 22:34:14 +0900798 struct svm_cpu_data *sd = per_cpu(svm_data, raw_smp_processor_id());
Joerg Roedel0da1db752008-07-02 16:02:11 +0200799
Tejun Heo0fe1e002009-10-29 22:34:14 +0900800 if (!sd)
Joerg Roedel0da1db752008-07-02 16:02:11 +0200801 return;
802
803 per_cpu(svm_data, raw_smp_processor_id()) = NULL;
Tejun Heo0fe1e002009-10-29 22:34:14 +0900804 __free_page(sd->save_area);
805 kfree(sd);
Joerg Roedel0da1db752008-07-02 16:02:11 +0200806}
807
Avi Kivity6aa8b732006-12-10 02:21:36 -0800808static int svm_cpu_init(int cpu)
809{
Tejun Heo0fe1e002009-10-29 22:34:14 +0900810 struct svm_cpu_data *sd;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800811 int r;
812
Tejun Heo0fe1e002009-10-29 22:34:14 +0900813 sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
814 if (!sd)
Avi Kivity6aa8b732006-12-10 02:21:36 -0800815 return -ENOMEM;
Tejun Heo0fe1e002009-10-29 22:34:14 +0900816 sd->cpu = cpu;
817 sd->save_area = alloc_page(GFP_KERNEL);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800818 r = -ENOMEM;
Tejun Heo0fe1e002009-10-29 22:34:14 +0900819 if (!sd->save_area)
Avi Kivity6aa8b732006-12-10 02:21:36 -0800820 goto err_1;
821
Tejun Heo0fe1e002009-10-29 22:34:14 +0900822 per_cpu(svm_data, cpu) = sd;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800823
824 return 0;
825
826err_1:
Tejun Heo0fe1e002009-10-29 22:34:14 +0900827 kfree(sd);
Avi Kivity6aa8b732006-12-10 02:21:36 -0800828 return r;
829
830}
831
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100832static bool valid_msr_intercept(u32 index)
Avi Kivity6aa8b732006-12-10 02:21:36 -0800833{
834 int i;
835
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100836 for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++)
837 if (direct_access_msrs[i].index == index)
838 return true;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800839
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100840 return false;
841}
842
Avi Kivity6aa8b732006-12-10 02:21:36 -0800843static void set_msr_interception(u32 *msrpm, unsigned msr,
844 int read, int write)
845{
Joerg Roedel455716f2010-03-01 15:34:35 +0100846 u8 bit_read, bit_write;
847 unsigned long tmp;
848 u32 offset;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800849
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100850 /*
851 * If this warning triggers extend the direct_access_msrs list at the
852 * beginning of the file
853 */
854 WARN_ON(!valid_msr_intercept(msr));
855
Joerg Roedel455716f2010-03-01 15:34:35 +0100856 offset = svm_msrpm_offset(msr);
857 bit_read = 2 * (msr & 0x0f);
858 bit_write = 2 * (msr & 0x0f) + 1;
859 tmp = msrpm[offset];
Avi Kivity6aa8b732006-12-10 02:21:36 -0800860
Joerg Roedel455716f2010-03-01 15:34:35 +0100861 BUG_ON(offset == MSR_INVALID);
862
863 read ? clear_bit(bit_read, &tmp) : set_bit(bit_read, &tmp);
864 write ? clear_bit(bit_write, &tmp) : set_bit(bit_write, &tmp);
865
866 msrpm[offset] = tmp;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800867}
868
Joerg Roedelf65c2292008-02-13 18:58:46 +0100869static void svm_vcpu_init_msrpm(u32 *msrpm)
870{
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100871 int i;
872
Joerg Roedelf65c2292008-02-13 18:58:46 +0100873 memset(msrpm, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
874
Joerg Roedelac72a9b2010-03-01 15:34:36 +0100875 for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
876 if (!direct_access_msrs[i].always)
877 continue;
878
879 set_msr_interception(msrpm, direct_access_msrs[i].index, 1, 1);
880 }
Joerg Roedelf65c2292008-02-13 18:58:46 +0100881}
882
Joerg Roedel323c3d82010-03-01 15:34:37 +0100883static void add_msr_offset(u32 offset)
884{
885 int i;
886
887 for (i = 0; i < MSRPM_OFFSETS; ++i) {
888
889 /* Offset already in list? */
890 if (msrpm_offsets[i] == offset)
891 return;
892
893 /* Slot used by another offset? */
894 if (msrpm_offsets[i] != MSR_INVALID)
895 continue;
896
897 /* Add offset to list */
898 msrpm_offsets[i] = offset;
899
900 return;
901 }
902
903 /*
904 * If this BUG triggers the msrpm_offsets table has an overflow. Just
905 * increase MSRPM_OFFSETS in this case.
906 */
907 BUG();
908}
909
910static void init_msrpm_offsets(void)
911{
912 int i;
913
914 memset(msrpm_offsets, 0xff, sizeof(msrpm_offsets));
915
916 for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
917 u32 offset;
918
919 offset = svm_msrpm_offset(direct_access_msrs[i].index);
920 BUG_ON(offset == MSR_INVALID);
921
922 add_msr_offset(offset);
923 }
Avi Kivity6aa8b732006-12-10 02:21:36 -0800924}
925
Joerg Roedel24e09cb2008-02-13 18:58:47 +0100926static void svm_enable_lbrv(struct vcpu_svm *svm)
927{
928 u32 *msrpm = svm->msrpm;
929
930 svm->vmcb->control.lbr_ctl = 1;
931 set_msr_interception(msrpm, MSR_IA32_LASTBRANCHFROMIP, 1, 1);
932 set_msr_interception(msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1);
933 set_msr_interception(msrpm, MSR_IA32_LASTINTFROMIP, 1, 1);
934 set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 1, 1);
935}
936
937static void svm_disable_lbrv(struct vcpu_svm *svm)
938{
939 u32 *msrpm = svm->msrpm;
940
941 svm->vmcb->control.lbr_ctl = 0;
942 set_msr_interception(msrpm, MSR_IA32_LASTBRANCHFROMIP, 0, 0);
943 set_msr_interception(msrpm, MSR_IA32_LASTBRANCHTOIP, 0, 0);
944 set_msr_interception(msrpm, MSR_IA32_LASTINTFROMIP, 0, 0);
945 set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
946}
947
Avi Kivity6aa8b732006-12-10 02:21:36 -0800948static __init int svm_hardware_setup(void)
949{
950 int cpu;
951 struct page *iopm_pages;
Joerg Roedelf65c2292008-02-13 18:58:46 +0100952 void *iopm_va;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800953 int r;
954
Avi Kivity6aa8b732006-12-10 02:21:36 -0800955 iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
956
957 if (!iopm_pages)
958 return -ENOMEM;
Anthony Liguoric8681332007-04-30 09:48:11 +0300959
960 iopm_va = page_address(iopm_pages);
961 memset(iopm_va, 0xff, PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
Avi Kivity6aa8b732006-12-10 02:21:36 -0800962 iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
963
Joerg Roedel323c3d82010-03-01 15:34:37 +0100964 init_msrpm_offsets();
965
Joerg Roedel50a37eb2008-01-31 14:57:38 +0100966 if (boot_cpu_has(X86_FEATURE_NX))
967 kvm_enable_efer_bits(EFER_NX);
968
Alexander Graf1b2fd702009-02-02 16:23:51 +0100969 if (boot_cpu_has(X86_FEATURE_FXSR_OPT))
970 kvm_enable_efer_bits(EFER_FFXSR);
971
Joerg Roedel92a1f122011-03-25 09:44:51 +0100972 if (boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
Joerg Roedel92a1f122011-03-25 09:44:51 +0100973 kvm_has_tsc_control = true;
Haozhong Zhangbc9b9612015-10-20 15:39:01 +0800974 kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX;
975 kvm_tsc_scaling_ratio_frac_bits = 32;
Joerg Roedel92a1f122011-03-25 09:44:51 +0100976 }
977
Alexander Graf236de052008-11-25 20:17:10 +0100978 if (nested) {
979 printk(KERN_INFO "kvm: Nested Virtualization enabled\n");
Joerg Roedeleec4b142010-05-05 16:04:44 +0200980 kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE);
Alexander Graf236de052008-11-25 20:17:10 +0100981 }
982
Zachary Amsden3230bb42009-09-29 11:38:37 -1000983 for_each_possible_cpu(cpu) {
Avi Kivity6aa8b732006-12-10 02:21:36 -0800984 r = svm_cpu_init(cpu);
985 if (r)
Joerg Roedelf65c2292008-02-13 18:58:46 +0100986 goto err;
Avi Kivity6aa8b732006-12-10 02:21:36 -0800987 }
Joerg Roedel33bd6a02008-02-07 13:47:38 +0100988
Avi Kivity2a6b20b2010-11-09 16:15:42 +0200989 if (!boot_cpu_has(X86_FEATURE_NPT))
Joerg Roedele3da3ac2008-02-07 13:47:39 +0100990 npt_enabled = false;
991
Joerg Roedel6c7dac72008-02-07 13:47:40 +0100992 if (npt_enabled && !npt) {
993 printk(KERN_INFO "kvm: Nested Paging disabled\n");
994 npt_enabled = false;
995 }
996
Joerg Roedel18552672008-02-07 13:47:41 +0100997 if (npt_enabled) {
Joerg Roedele3da3ac2008-02-07 13:47:39 +0100998 printk(KERN_INFO "kvm: Nested Paging enabled\n");
Joerg Roedel18552672008-02-07 13:47:41 +0100999 kvm_enable_tdp();
Joerg Roedel5f4cb662008-07-14 20:36:36 +02001000 } else
1001 kvm_disable_tdp();
Joerg Roedele3da3ac2008-02-07 13:47:39 +01001002
Suravee Suthikulpanit5b8abf12016-06-15 17:24:36 -05001003 if (avic) {
1004 if (!npt_enabled ||
1005 !boot_cpu_has(X86_FEATURE_AVIC) ||
1006 !IS_ENABLED(CONFIG_X86_LOCAL_APIC))
1007 avic = false;
1008 else
1009 pr_info("AVIC enabled\n");
1010 }
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001011
Avi Kivity6aa8b732006-12-10 02:21:36 -08001012 return 0;
1013
Joerg Roedelf65c2292008-02-13 18:58:46 +01001014err:
Avi Kivity6aa8b732006-12-10 02:21:36 -08001015 __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
1016 iopm_base = 0;
1017 return r;
1018}
1019
1020static __exit void svm_hardware_unsetup(void)
1021{
Joerg Roedel0da1db752008-07-02 16:02:11 +02001022 int cpu;
1023
Zachary Amsden3230bb42009-09-29 11:38:37 -10001024 for_each_possible_cpu(cpu)
Joerg Roedel0da1db752008-07-02 16:02:11 +02001025 svm_cpu_uninit(cpu);
1026
Avi Kivity6aa8b732006-12-10 02:21:36 -08001027 __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
Joerg Roedelf65c2292008-02-13 18:58:46 +01001028 iopm_base = 0;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001029}
1030
1031static void init_seg(struct vmcb_seg *seg)
1032{
1033 seg->selector = 0;
1034 seg->attrib = SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK |
Joerg Roedele0231712010-02-24 18:59:10 +01001035 SVM_SELECTOR_WRITE_MASK; /* Read/Write Data Segment */
Avi Kivity6aa8b732006-12-10 02:21:36 -08001036 seg->limit = 0xffff;
1037 seg->base = 0;
1038}
1039
1040static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
1041{
1042 seg->selector = 0;
1043 seg->attrib = SVM_SELECTOR_P_MASK | type;
1044 seg->limit = 0xffff;
1045 seg->base = 0;
1046}
1047
Will Auldba904632012-11-29 12:42:50 -08001048static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu)
1049{
1050 struct vcpu_svm *svm = to_svm(vcpu);
1051
1052 return svm->vmcb->control.tsc_offset;
1053}
1054
Zachary Amsdenf4e1b3c2010-08-19 22:07:16 -10001055static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
1056{
1057 struct vcpu_svm *svm = to_svm(vcpu);
1058 u64 g_tsc_offset = 0;
1059
Joerg Roedel20307532010-11-29 17:51:48 +01001060 if (is_guest_mode(vcpu)) {
Zachary Amsdenf4e1b3c2010-08-19 22:07:16 -10001061 g_tsc_offset = svm->vmcb->control.tsc_offset -
1062 svm->nested.hsave->control.tsc_offset;
1063 svm->nested.hsave->control.tsc_offset = offset;
Yoshihiro YUNOMAE489223e2013-06-12 16:43:44 +09001064 } else
1065 trace_kvm_write_tsc_offset(vcpu->vcpu_id,
1066 svm->vmcb->control.tsc_offset,
1067 offset);
Zachary Amsdenf4e1b3c2010-08-19 22:07:16 -10001068
1069 svm->vmcb->control.tsc_offset = offset + g_tsc_offset;
Joerg Roedel116a0a22010-12-03 11:45:49 +01001070
1071 mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
Zachary Amsdenf4e1b3c2010-08-19 22:07:16 -10001072}
1073
Haozhong Zhang58ea6762015-10-20 15:39:06 +08001074static void svm_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
Zachary Amsdene48672f2010-08-19 22:07:23 -10001075{
1076 struct vcpu_svm *svm = to_svm(vcpu);
1077
1078 svm->vmcb->control.tsc_offset += adjustment;
Joerg Roedel20307532010-11-29 17:51:48 +01001079 if (is_guest_mode(vcpu))
Zachary Amsdene48672f2010-08-19 22:07:23 -10001080 svm->nested.hsave->control.tsc_offset += adjustment;
Yoshihiro YUNOMAE489223e2013-06-12 16:43:44 +09001081 else
1082 trace_kvm_write_tsc_offset(vcpu->vcpu_id,
1083 svm->vmcb->control.tsc_offset - adjustment,
1084 svm->vmcb->control.tsc_offset);
1085
Joerg Roedel116a0a22010-12-03 11:45:49 +01001086 mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
Zachary Amsdene48672f2010-08-19 22:07:23 -10001087}
1088
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001089static void avic_init_vmcb(struct vcpu_svm *svm)
1090{
1091 struct vmcb *vmcb = svm->vmcb;
1092 struct kvm_arch *vm_data = &svm->vcpu.kvm->arch;
1093 phys_addr_t bpa = page_to_phys(svm->avic_backing_page);
1094 phys_addr_t lpa = page_to_phys(vm_data->avic_logical_id_table_page);
1095 phys_addr_t ppa = page_to_phys(vm_data->avic_physical_id_table_page);
1096
1097 vmcb->control.avic_backing_page = bpa & AVIC_HPA_MASK;
1098 vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK;
1099 vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK;
1100 vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT;
1101 vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
1102 svm->vcpu.arch.apicv_active = true;
1103}
1104
Paolo Bonzini56908912015-10-19 11:30:19 +02001105static void init_vmcb(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001106{
Joerg Roedele6101a92008-02-13 18:58:45 +01001107 struct vmcb_control_area *control = &svm->vmcb->control;
1108 struct vmcb_save_area *save = &svm->vmcb->save;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001109
Avi Kivitybff78272010-01-07 13:16:08 +02001110 svm->vcpu.fpu_active = 1;
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01001111 svm->vcpu.arch.hflags = 0;
Avi Kivitybff78272010-01-07 13:16:08 +02001112
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01001113 set_cr_intercept(svm, INTERCEPT_CR0_READ);
1114 set_cr_intercept(svm, INTERCEPT_CR3_READ);
1115 set_cr_intercept(svm, INTERCEPT_CR4_READ);
1116 set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
1117 set_cr_intercept(svm, INTERCEPT_CR3_WRITE);
1118 set_cr_intercept(svm, INTERCEPT_CR4_WRITE);
Suravee Suthikulpanit3bbf3562016-05-04 14:09:51 -05001119 if (!kvm_vcpu_apicv_active(&svm->vcpu))
1120 set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001121
Paolo Bonzini5315c712014-03-03 13:08:29 +01001122 set_dr_intercepts(svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001123
Joerg Roedel18c918c2010-11-30 18:03:59 +01001124 set_exception_intercept(svm, PF_VECTOR);
1125 set_exception_intercept(svm, UD_VECTOR);
1126 set_exception_intercept(svm, MC_VECTOR);
Eric Northup54a20552015-11-03 18:03:53 +01001127 set_exception_intercept(svm, AC_VECTOR);
Paolo Bonzinicbdb9672015-11-10 09:14:39 +01001128 set_exception_intercept(svm, DB_VECTOR);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001129
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01001130 set_intercept(svm, INTERCEPT_INTR);
1131 set_intercept(svm, INTERCEPT_NMI);
1132 set_intercept(svm, INTERCEPT_SMI);
1133 set_intercept(svm, INTERCEPT_SELECTIVE_CR0);
Avi Kivity332b56e2011-11-10 14:57:24 +02001134 set_intercept(svm, INTERCEPT_RDPMC);
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01001135 set_intercept(svm, INTERCEPT_CPUID);
1136 set_intercept(svm, INTERCEPT_INVD);
1137 set_intercept(svm, INTERCEPT_HLT);
1138 set_intercept(svm, INTERCEPT_INVLPG);
1139 set_intercept(svm, INTERCEPT_INVLPGA);
1140 set_intercept(svm, INTERCEPT_IOIO_PROT);
1141 set_intercept(svm, INTERCEPT_MSR_PROT);
1142 set_intercept(svm, INTERCEPT_TASK_SWITCH);
1143 set_intercept(svm, INTERCEPT_SHUTDOWN);
1144 set_intercept(svm, INTERCEPT_VMRUN);
1145 set_intercept(svm, INTERCEPT_VMMCALL);
1146 set_intercept(svm, INTERCEPT_VMLOAD);
1147 set_intercept(svm, INTERCEPT_VMSAVE);
1148 set_intercept(svm, INTERCEPT_STGI);
1149 set_intercept(svm, INTERCEPT_CLGI);
1150 set_intercept(svm, INTERCEPT_SKINIT);
1151 set_intercept(svm, INTERCEPT_WBINVD);
1152 set_intercept(svm, INTERCEPT_MONITOR);
1153 set_intercept(svm, INTERCEPT_MWAIT);
Joerg Roedel81dd35d2010-12-07 17:15:06 +01001154 set_intercept(svm, INTERCEPT_XSETBV);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001155
1156 control->iopm_base_pa = iopm_base;
Joerg Roedelf65c2292008-02-13 18:58:46 +01001157 control->msrpm_base_pa = __pa(svm->msrpm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001158 control->int_ctl = V_INTR_MASKING_MASK;
1159
1160 init_seg(&save->es);
1161 init_seg(&save->ss);
1162 init_seg(&save->ds);
1163 init_seg(&save->fs);
1164 init_seg(&save->gs);
1165
1166 save->cs.selector = 0xf000;
Paolo Bonzini04b66832013-03-19 16:30:26 +01001167 save->cs.base = 0xffff0000;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001168 /* Executable/Readable Code Segment */
1169 save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
1170 SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
1171 save->cs.limit = 0xffff;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001172
1173 save->gdtr.limit = 0xffff;
1174 save->idtr.limit = 0xffff;
1175
1176 init_sys_seg(&save->ldtr, SEG_TYPE_LDT);
1177 init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
1178
Paolo Bonzini56908912015-10-19 11:30:19 +02001179 svm_set_efer(&svm->vcpu, 0);
Mike Dayd77c26f2007-10-08 09:02:08 -04001180 save->dr6 = 0xffff0ff0;
Avi Kivityf6e78472010-08-02 15:30:20 +03001181 kvm_set_rflags(&svm->vcpu, 2);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001182 save->rip = 0x0000fff0;
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03001183 svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001184
Joerg Roedele0231712010-02-24 18:59:10 +01001185 /*
Eduardo Habkost18fa0002009-10-24 02:49:59 -02001186 * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
Nadav Amitd28bc9d2015-04-13 14:34:08 +03001187 * It also updates the guest-visible cr0 value.
Avi Kivity6aa8b732006-12-10 02:21:36 -08001188 */
Paolo Bonzini79a80592015-09-21 07:46:55 +02001189 svm_set_cr0(&svm->vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
Igor Mammedovebae8712015-09-18 15:39:05 +02001190 kvm_mmu_reset_context(&svm->vcpu);
Eduardo Habkost18fa0002009-10-24 02:49:59 -02001191
Rusty Russell66aee912007-07-17 23:34:16 +10001192 save->cr4 = X86_CR4_PAE;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001193 /* rdx = ?? */
Joerg Roedel709ddeb2008-02-07 13:47:45 +01001194
1195 if (npt_enabled) {
1196 /* Setup VMCB for Nested Paging */
1197 control->nested_ctl = 1;
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01001198 clr_intercept(svm, INTERCEPT_INVLPG);
Joerg Roedel18c918c2010-11-30 18:03:59 +01001199 clr_exception_intercept(svm, PF_VECTOR);
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01001200 clr_cr_intercept(svm, INTERCEPT_CR3_READ);
1201 clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
Radim Krčmář74545702015-04-27 15:11:25 +02001202 save->g_pat = svm->vcpu.arch.pat;
Joerg Roedel709ddeb2008-02-07 13:47:45 +01001203 save->cr3 = 0;
1204 save->cr4 = 0;
1205 }
Joerg Roedelf40f6a42010-12-03 15:25:15 +01001206 svm->asid_generation = 0;
Alexander Graf1371d902008-11-25 20:17:04 +01001207
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02001208 svm->nested.vmcb = 0;
Joerg Roedel2af91942009-08-07 11:49:28 +02001209 svm->vcpu.arch.hflags = 0;
1210
Avi Kivity2a6b20b2010-11-09 16:15:42 +02001211 if (boot_cpu_has(X86_FEATURE_PAUSEFILTER)) {
Mark Langsdorf565d0992009-10-06 14:25:02 -05001212 control->pause_filter_count = 3000;
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01001213 set_intercept(svm, INTERCEPT_PAUSE);
Mark Langsdorf565d0992009-10-06 14:25:02 -05001214 }
1215
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001216 if (avic)
1217 avic_init_vmcb(svm);
1218
Roedel, Joerg8d28fec2010-12-03 13:15:21 +01001219 mark_all_dirty(svm->vmcb);
1220
Joerg Roedel2af91942009-08-07 11:49:28 +02001221 enable_gif(svm);
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001222
1223}
1224
1225static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu, int index)
1226{
1227 u64 *avic_physical_id_table;
1228 struct kvm_arch *vm_data = &vcpu->kvm->arch;
1229
1230 if (index >= AVIC_MAX_PHYSICAL_ID_COUNT)
1231 return NULL;
1232
1233 avic_physical_id_table = page_address(vm_data->avic_physical_id_table_page);
1234
1235 return &avic_physical_id_table[index];
1236}
1237
1238/**
1239 * Note:
1240 * AVIC hardware walks the nested page table to check permissions,
1241 * but does not use the SPA address specified in the leaf page
1242 * table entry since it uses address in the AVIC_BACKING_PAGE pointer
1243 * field of the VMCB. Therefore, we set up the
1244 * APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (4KB) here.
1245 */
1246static int avic_init_access_page(struct kvm_vcpu *vcpu)
1247{
1248 struct kvm *kvm = vcpu->kvm;
1249 int ret;
1250
1251 if (kvm->arch.apic_access_page_done)
1252 return 0;
1253
1254 ret = x86_set_memory_region(kvm,
1255 APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
1256 APIC_DEFAULT_PHYS_BASE,
1257 PAGE_SIZE);
1258 if (ret)
1259 return ret;
1260
1261 kvm->arch.apic_access_page_done = true;
1262 return 0;
1263}
1264
1265static int avic_init_backing_page(struct kvm_vcpu *vcpu)
1266{
1267 int ret;
1268 u64 *entry, new_entry;
1269 int id = vcpu->vcpu_id;
1270 struct vcpu_svm *svm = to_svm(vcpu);
1271
1272 ret = avic_init_access_page(vcpu);
1273 if (ret)
1274 return ret;
1275
1276 if (id >= AVIC_MAX_PHYSICAL_ID_COUNT)
1277 return -EINVAL;
1278
1279 if (!svm->vcpu.arch.apic->regs)
1280 return -EINVAL;
1281
1282 svm->avic_backing_page = virt_to_page(svm->vcpu.arch.apic->regs);
1283
1284 /* Setting AVIC backing page address in the phy APIC ID table */
1285 entry = avic_get_physical_id_entry(vcpu, id);
1286 if (!entry)
1287 return -EINVAL;
1288
1289 new_entry = READ_ONCE(*entry);
1290 new_entry = (page_to_phys(svm->avic_backing_page) &
1291 AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK) |
1292 AVIC_PHYSICAL_ID_ENTRY_VALID_MASK;
1293 WRITE_ONCE(*entry, new_entry);
1294
1295 svm->avic_physical_id_cache = entry;
1296
1297 return 0;
1298}
1299
Suravee Suthikulpanit5ea11f22016-08-23 13:52:41 -05001300static inline int avic_get_next_vm_id(void)
1301{
1302 int id;
1303
1304 spin_lock(&avic_vm_id_lock);
1305
1306 /* AVIC VM ID is one-based. */
1307 id = find_next_zero_bit(avic_vm_id_bitmap, AVIC_VM_ID_NR, 1);
1308 if (id <= AVIC_VM_ID_MASK)
1309 __set_bit(id, avic_vm_id_bitmap);
1310 else
1311 id = -EAGAIN;
1312
1313 spin_unlock(&avic_vm_id_lock);
1314 return id;
1315}
1316
1317static inline int avic_free_vm_id(int id)
1318{
1319 if (id <= 0 || id > AVIC_VM_ID_MASK)
1320 return -EINVAL;
1321
1322 spin_lock(&avic_vm_id_lock);
1323 __clear_bit(id, avic_vm_id_bitmap);
1324 spin_unlock(&avic_vm_id_lock);
1325 return 0;
1326}
1327
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001328static void avic_vm_destroy(struct kvm *kvm)
1329{
1330 struct kvm_arch *vm_data = &kvm->arch;
1331
Suravee Suthikulpanit5ea11f22016-08-23 13:52:41 -05001332 avic_free_vm_id(vm_data->avic_vm_id);
1333
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001334 if (vm_data->avic_logical_id_table_page)
1335 __free_page(vm_data->avic_logical_id_table_page);
1336 if (vm_data->avic_physical_id_table_page)
1337 __free_page(vm_data->avic_physical_id_table_page);
1338}
1339
1340static int avic_vm_init(struct kvm *kvm)
1341{
1342 int err = -ENOMEM;
1343 struct kvm_arch *vm_data = &kvm->arch;
1344 struct page *p_page;
1345 struct page *l_page;
1346
1347 if (!avic)
1348 return 0;
1349
Suravee Suthikulpanit5ea11f22016-08-23 13:52:41 -05001350 vm_data->avic_vm_id = avic_get_next_vm_id();
1351 if (vm_data->avic_vm_id < 0)
1352 return vm_data->avic_vm_id;
1353
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001354 /* Allocating physical APIC ID table (4KB) */
1355 p_page = alloc_page(GFP_KERNEL);
1356 if (!p_page)
1357 goto free_avic;
1358
1359 vm_data->avic_physical_id_table_page = p_page;
1360 clear_page(page_address(p_page));
1361
1362 /* Allocating logical APIC ID table (4KB) */
1363 l_page = alloc_page(GFP_KERNEL);
1364 if (!l_page)
1365 goto free_avic;
1366
1367 vm_data->avic_logical_id_table_page = l_page;
1368 clear_page(page_address(l_page));
1369
1370 return 0;
1371
1372free_avic:
1373 avic_vm_destroy(kvm);
1374 return err;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001375}
1376
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001377/**
1378 * This function is called during VCPU halt/unhalt.
1379 */
1380static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
1381{
1382 u64 entry;
Suravee Suthikulpanit7d669f52016-06-15 17:23:45 -05001383 int h_physical_id = kvm_cpu_get_apicid(vcpu->cpu);
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001384 struct vcpu_svm *svm = to_svm(vcpu);
1385
1386 if (!kvm_vcpu_apicv_active(vcpu))
1387 return;
1388
1389 svm->avic_is_running = is_run;
1390
1391 /* ID = 0xff (broadcast), ID > 0xff (reserved) */
1392 if (WARN_ON(h_physical_id >= AVIC_MAX_PHYSICAL_ID_COUNT))
1393 return;
1394
1395 entry = READ_ONCE(*(svm->avic_physical_id_cache));
1396 WARN_ON(is_run == !!(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK));
1397
1398 entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
1399 if (is_run)
1400 entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
1401 WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
1402}
1403
1404static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1405{
1406 u64 entry;
1407 /* ID = 0xff (broadcast), ID > 0xff (reserved) */
Suravee Suthikulpanit7d669f52016-06-15 17:23:45 -05001408 int h_physical_id = kvm_cpu_get_apicid(cpu);
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001409 struct vcpu_svm *svm = to_svm(vcpu);
1410
1411 if (!kvm_vcpu_apicv_active(vcpu))
1412 return;
1413
1414 if (WARN_ON(h_physical_id >= AVIC_MAX_PHYSICAL_ID_COUNT))
1415 return;
1416
1417 entry = READ_ONCE(*(svm->avic_physical_id_cache));
1418 WARN_ON(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
1419
1420 entry &= ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
1421 entry |= (h_physical_id & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK);
1422
1423 entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
1424 if (svm->avic_is_running)
1425 entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
1426
1427 WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
1428}
1429
1430static void avic_vcpu_put(struct kvm_vcpu *vcpu)
1431{
1432 u64 entry;
1433 struct vcpu_svm *svm = to_svm(vcpu);
1434
1435 if (!kvm_vcpu_apicv_active(vcpu))
1436 return;
1437
1438 entry = READ_ONCE(*(svm->avic_physical_id_cache));
1439 entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
1440 WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001441}
1442
Nadav Amitd28bc9d2015-04-13 14:34:08 +03001443static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
Avi Kivity04d2cc72007-09-10 18:10:54 +03001444{
1445 struct vcpu_svm *svm = to_svm(vcpu);
Julian Stecklina66f7b722012-12-05 15:26:19 +01001446 u32 dummy;
1447 u32 eax = 1;
Avi Kivity04d2cc72007-09-10 18:10:54 +03001448
Nadav Amitd28bc9d2015-04-13 14:34:08 +03001449 if (!init_event) {
1450 svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
1451 MSR_IA32_APICBASE_ENABLE;
1452 if (kvm_vcpu_is_reset_bsp(&svm->vcpu))
1453 svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
1454 }
Paolo Bonzini56908912015-10-19 11:30:19 +02001455 init_vmcb(svm);
Avi Kivity70433382007-11-07 12:57:23 +02001456
Julian Stecklina66f7b722012-12-05 15:26:19 +01001457 kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
1458 kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001459
1460 if (kvm_vcpu_apicv_active(vcpu) && !init_event)
1461 avic_update_vapic_bar(svm, APIC_DEFAULT_PHYS_BASE);
Avi Kivity04d2cc72007-09-10 18:10:54 +03001462}
1463
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001464static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001465{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001466 struct vcpu_svm *svm;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001467 struct page *page;
Joerg Roedelf65c2292008-02-13 18:58:46 +01001468 struct page *msrpm_pages;
Alexander Grafb286d5d2008-11-25 20:17:05 +01001469 struct page *hsave_page;
Alexander Graf3d6368e2008-11-25 20:17:07 +01001470 struct page *nested_msrpm_pages;
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001471 int err;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001472
Rusty Russellc16f8622007-07-30 21:12:19 +10001473 svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001474 if (!svm) {
1475 err = -ENOMEM;
1476 goto out;
1477 }
1478
1479 err = kvm_vcpu_init(&svm->vcpu, kvm, id);
1480 if (err)
1481 goto free_svm;
1482
Joerg Roedelf65c2292008-02-13 18:58:46 +01001483 err = -ENOMEM;
Takuya Yoshikawab7af4042010-03-09 14:55:19 +09001484 page = alloc_page(GFP_KERNEL);
1485 if (!page)
1486 goto uninit;
1487
Joerg Roedelf65c2292008-02-13 18:58:46 +01001488 msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
1489 if (!msrpm_pages)
Takuya Yoshikawab7af4042010-03-09 14:55:19 +09001490 goto free_page1;
Alexander Graf3d6368e2008-11-25 20:17:07 +01001491
1492 nested_msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
1493 if (!nested_msrpm_pages)
Takuya Yoshikawab7af4042010-03-09 14:55:19 +09001494 goto free_page2;
Joerg Roedelf65c2292008-02-13 18:58:46 +01001495
Alexander Grafb286d5d2008-11-25 20:17:05 +01001496 hsave_page = alloc_page(GFP_KERNEL);
1497 if (!hsave_page)
Takuya Yoshikawab7af4042010-03-09 14:55:19 +09001498 goto free_page3;
1499
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001500 if (avic) {
1501 err = avic_init_backing_page(&svm->vcpu);
1502 if (err)
1503 goto free_page4;
1504 }
1505
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001506 /* We initialize this flag to true to make sure that the is_running
1507 * bit would be set the first time the vcpu is loaded.
1508 */
1509 svm->avic_is_running = true;
1510
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02001511 svm->nested.hsave = page_address(hsave_page);
Alexander Grafb286d5d2008-11-25 20:17:05 +01001512
Takuya Yoshikawab7af4042010-03-09 14:55:19 +09001513 svm->msrpm = page_address(msrpm_pages);
1514 svm_vcpu_init_msrpm(svm->msrpm);
1515
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02001516 svm->nested.msrpm = page_address(nested_msrpm_pages);
Joerg Roedel323c3d82010-03-01 15:34:37 +01001517 svm_vcpu_init_msrpm(svm->nested.msrpm);
Alexander Graf3d6368e2008-11-25 20:17:07 +01001518
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001519 svm->vmcb = page_address(page);
1520 clear_page(svm->vmcb);
1521 svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
1522 svm->asid_generation = 0;
Paolo Bonzini56908912015-10-19 11:30:19 +02001523 init_vmcb(svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001524
Boris Ostrovsky2b036c62012-01-09 14:00:35 -05001525 svm_init_osvw(&svm->vcpu);
1526
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001527 return &svm->vcpu;
Avi Kivity36241b82006-12-22 01:05:20 -08001528
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05001529free_page4:
1530 __free_page(hsave_page);
Takuya Yoshikawab7af4042010-03-09 14:55:19 +09001531free_page3:
1532 __free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER);
1533free_page2:
1534 __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER);
1535free_page1:
1536 __free_page(page);
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001537uninit:
1538 kvm_vcpu_uninit(&svm->vcpu);
1539free_svm:
Rusty Russella4770342007-08-01 14:46:11 +10001540 kmem_cache_free(kvm_vcpu_cache, svm);
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001541out:
1542 return ERR_PTR(err);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001543}
1544
1545static void svm_free_vcpu(struct kvm_vcpu *vcpu)
1546{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001547 struct vcpu_svm *svm = to_svm(vcpu);
1548
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001549 __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT));
Joerg Roedelf65c2292008-02-13 18:58:46 +01001550 __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER);
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02001551 __free_page(virt_to_page(svm->nested.hsave));
1552 __free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
Rusty Russellfb3f0f52007-07-27 17:16:56 +10001553 kvm_vcpu_uninit(vcpu);
Rusty Russella4770342007-08-01 14:46:11 +10001554 kmem_cache_free(kvm_vcpu_cache, svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001555}
1556
Avi Kivity15ad7142007-07-11 18:17:21 +03001557static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001558{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001559 struct vcpu_svm *svm = to_svm(vcpu);
Avi Kivity15ad7142007-07-11 18:17:21 +03001560 int i;
Avi Kivity0cc50642007-03-25 12:07:27 +02001561
Avi Kivity0cc50642007-03-25 12:07:27 +02001562 if (unlikely(cpu != vcpu->cpu)) {
Marcelo Tosatti4b656b12009-07-21 12:47:45 -03001563 svm->asid_generation = 0;
Roedel, Joerg8d28fec2010-12-03 13:15:21 +01001564 mark_all_dirty(svm->vmcb);
Avi Kivity0cc50642007-03-25 12:07:27 +02001565 }
Anthony Liguori94dfbdb2007-04-29 11:56:06 +03001566
Avi Kivity82ca2d12010-10-21 12:20:34 +02001567#ifdef CONFIG_X86_64
1568 rdmsrl(MSR_GS_BASE, to_svm(vcpu)->host.gs_base);
1569#endif
Avi Kivitydacccfd2010-10-21 12:20:33 +02001570 savesegment(fs, svm->host.fs);
1571 savesegment(gs, svm->host.gs);
1572 svm->host.ldt = kvm_read_ldt();
1573
Anthony Liguori94dfbdb2007-04-29 11:56:06 +03001574 for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001575 rdmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
Joerg Roedelfbc0db72011-03-25 09:44:46 +01001576
Haozhong Zhangad7218832015-10-20 15:39:02 +08001577 if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
1578 u64 tsc_ratio = vcpu->arch.tsc_scaling_ratio;
1579 if (tsc_ratio != __this_cpu_read(current_tsc_ratio)) {
1580 __this_cpu_write(current_tsc_ratio, tsc_ratio);
1581 wrmsrl(MSR_AMD64_TSC_RATIO, tsc_ratio);
1582 }
Joerg Roedelfbc0db72011-03-25 09:44:46 +01001583 }
Paolo Bonzini46896c72015-11-12 14:49:16 +01001584 /* This assumes that the kernel never uses MSR_TSC_AUX */
1585 if (static_cpu_has(X86_FEATURE_RDTSCP))
1586 wrmsrl(MSR_TSC_AUX, svm->tsc_aux);
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001587
1588 avic_vcpu_load(vcpu, cpu);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001589}
1590
1591static void svm_vcpu_put(struct kvm_vcpu *vcpu)
1592{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001593 struct vcpu_svm *svm = to_svm(vcpu);
Anthony Liguori94dfbdb2007-04-29 11:56:06 +03001594 int i;
1595
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001596 avic_vcpu_put(vcpu);
1597
Avi Kivitye1beb1d2007-11-18 13:50:24 +02001598 ++vcpu->stat.host_state_reload;
Avi Kivitydacccfd2010-10-21 12:20:33 +02001599 kvm_load_ldt(svm->host.ldt);
1600#ifdef CONFIG_X86_64
1601 loadsegment(fs, svm->host.fs);
Andy Lutomirski296f7812016-04-26 12:23:29 -07001602 wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gsbase);
Joerg Roedel893a5ab2011-01-14 16:45:01 +01001603 load_gs_index(svm->host.gs);
Avi Kivitydacccfd2010-10-21 12:20:33 +02001604#else
Avi Kivity831ca602011-03-08 16:09:51 +02001605#ifdef CONFIG_X86_32_LAZY_GS
Avi Kivitydacccfd2010-10-21 12:20:33 +02001606 loadsegment(gs, svm->host.gs);
1607#endif
Avi Kivity831ca602011-03-08 16:09:51 +02001608#endif
Anthony Liguori94dfbdb2007-04-29 11:56:06 +03001609 for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001610 wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001611}
1612
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05001613static void svm_vcpu_blocking(struct kvm_vcpu *vcpu)
1614{
1615 avic_set_running(vcpu, false);
1616}
1617
1618static void svm_vcpu_unblocking(struct kvm_vcpu *vcpu)
1619{
1620 avic_set_running(vcpu, true);
1621}
1622
Avi Kivity6aa8b732006-12-10 02:21:36 -08001623static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
1624{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001625 return to_svm(vcpu)->vmcb->save.rflags;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001626}
1627
1628static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
1629{
Paolo Bonziniae9fedc2014-05-14 09:39:49 +02001630 /*
Andrea Gelminibb3541f2016-05-21 14:14:44 +02001631 * Any change of EFLAGS.VM is accompanied by a reload of SS
Paolo Bonziniae9fedc2014-05-14 09:39:49 +02001632 * (caused by either a task switch or an inter-privilege IRET),
1633 * so we do not need to update the CPL here.
1634 */
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001635 to_svm(vcpu)->vmcb->save.rflags = rflags;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001636}
1637
Huaitong Hanbe94f6b2016-03-22 16:51:20 +08001638static u32 svm_get_pkru(struct kvm_vcpu *vcpu)
1639{
1640 return 0;
1641}
1642
Avi Kivity6de4f3a2009-05-31 22:58:47 +03001643static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
1644{
1645 switch (reg) {
1646 case VCPU_EXREG_PDPTR:
1647 BUG_ON(!npt_enabled);
Avi Kivity9f8fe502010-12-05 17:30:00 +02001648 load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
Avi Kivity6de4f3a2009-05-31 22:58:47 +03001649 break;
1650 default:
1651 BUG();
1652 }
1653}
1654
Alexander Graff0b85052008-11-25 20:17:01 +01001655static void svm_set_vintr(struct vcpu_svm *svm)
1656{
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01001657 set_intercept(svm, INTERCEPT_VINTR);
Alexander Graff0b85052008-11-25 20:17:01 +01001658}
1659
1660static void svm_clear_vintr(struct vcpu_svm *svm)
1661{
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01001662 clr_intercept(svm, INTERCEPT_VINTR);
Alexander Graff0b85052008-11-25 20:17:01 +01001663}
1664
Avi Kivity6aa8b732006-12-10 02:21:36 -08001665static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
1666{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001667 struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001668
1669 switch (seg) {
1670 case VCPU_SREG_CS: return &save->cs;
1671 case VCPU_SREG_DS: return &save->ds;
1672 case VCPU_SREG_ES: return &save->es;
1673 case VCPU_SREG_FS: return &save->fs;
1674 case VCPU_SREG_GS: return &save->gs;
1675 case VCPU_SREG_SS: return &save->ss;
1676 case VCPU_SREG_TR: return &save->tr;
1677 case VCPU_SREG_LDTR: return &save->ldtr;
1678 }
1679 BUG();
Al Viro8b6d44c2007-02-09 16:38:40 +00001680 return NULL;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001681}
1682
1683static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
1684{
1685 struct vmcb_seg *s = svm_seg(vcpu, seg);
1686
1687 return s->base;
1688}
1689
1690static void svm_get_segment(struct kvm_vcpu *vcpu,
1691 struct kvm_segment *var, int seg)
1692{
1693 struct vmcb_seg *s = svm_seg(vcpu, seg);
1694
1695 var->base = s->base;
1696 var->limit = s->limit;
1697 var->selector = s->selector;
1698 var->type = s->attrib & SVM_SELECTOR_TYPE_MASK;
1699 var->s = (s->attrib >> SVM_SELECTOR_S_SHIFT) & 1;
1700 var->dpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
1701 var->present = (s->attrib >> SVM_SELECTOR_P_SHIFT) & 1;
1702 var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1;
1703 var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
1704 var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
Jim Mattson80112c82014-07-08 09:47:41 +05301705
1706 /*
1707 * AMD CPUs circa 2014 track the G bit for all segments except CS.
1708 * However, the SVM spec states that the G bit is not observed by the
1709 * CPU, and some VMware virtual CPUs drop the G bit for all segments.
1710 * So let's synthesize a legal G bit for all segments, this helps
1711 * running KVM nested. It also helps cross-vendor migration, because
1712 * Intel's vmentry has a check on the 'G' bit.
1713 */
1714 var->g = s->limit > 0xfffff;
Amit Shah25022ac2008-10-27 09:04:17 +00001715
Joerg Roedele0231712010-02-24 18:59:10 +01001716 /*
1717 * AMD's VMCB does not have an explicit unusable field, so emulate it
Andre Przywara19bca6a2009-04-28 12:45:30 +02001718 * for cross vendor migration purposes by "not present"
1719 */
1720 var->unusable = !var->present || (var->type == 0);
1721
Andre Przywara1fbdc7a2009-01-11 22:39:44 +01001722 switch (seg) {
Andre Przywara1fbdc7a2009-01-11 22:39:44 +01001723 case VCPU_SREG_TR:
1724 /*
1725 * Work around a bug where the busy flag in the tr selector
1726 * isn't exposed
1727 */
Amit Shahc0d09822008-10-27 09:04:18 +00001728 var->type |= 0x2;
Andre Przywara1fbdc7a2009-01-11 22:39:44 +01001729 break;
1730 case VCPU_SREG_DS:
1731 case VCPU_SREG_ES:
1732 case VCPU_SREG_FS:
1733 case VCPU_SREG_GS:
1734 /*
1735 * The accessed bit must always be set in the segment
1736 * descriptor cache, although it can be cleared in the
1737 * descriptor, the cached bit always remains at 1. Since
1738 * Intel has a check on this, set it here to support
1739 * cross-vendor migration.
1740 */
1741 if (!var->unusable)
1742 var->type |= 0x1;
1743 break;
Andre Przywarab586eb02009-04-28 12:45:43 +02001744 case VCPU_SREG_SS:
Joerg Roedele0231712010-02-24 18:59:10 +01001745 /*
1746 * On AMD CPUs sometimes the DB bit in the segment
Andre Przywarab586eb02009-04-28 12:45:43 +02001747 * descriptor is left as 1, although the whole segment has
1748 * been made unusable. Clear it here to pass an Intel VMX
1749 * entry check when cross vendor migrating.
1750 */
1751 if (var->unusable)
1752 var->db = 0;
Jan Kiszka33b458d2014-06-29 17:12:43 +02001753 var->dpl = to_svm(vcpu)->vmcb->save.cpl;
Andre Przywarab586eb02009-04-28 12:45:43 +02001754 break;
Andre Przywara1fbdc7a2009-01-11 22:39:44 +01001755 }
Avi Kivity6aa8b732006-12-10 02:21:36 -08001756}
1757
Izik Eidus2e4d2652008-03-24 19:38:34 +02001758static int svm_get_cpl(struct kvm_vcpu *vcpu)
1759{
1760 struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
1761
1762 return save->cpl;
1763}
1764
Gleb Natapov89a27f42010-02-16 10:51:48 +02001765static void svm_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001766{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001767 struct vcpu_svm *svm = to_svm(vcpu);
1768
Gleb Natapov89a27f42010-02-16 10:51:48 +02001769 dt->size = svm->vmcb->save.idtr.limit;
1770 dt->address = svm->vmcb->save.idtr.base;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001771}
1772
Gleb Natapov89a27f42010-02-16 10:51:48 +02001773static void svm_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001774{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001775 struct vcpu_svm *svm = to_svm(vcpu);
1776
Gleb Natapov89a27f42010-02-16 10:51:48 +02001777 svm->vmcb->save.idtr.limit = dt->size;
1778 svm->vmcb->save.idtr.base = dt->address ;
Joerg Roedel17a703c2010-12-03 11:45:56 +01001779 mark_dirty(svm->vmcb, VMCB_DT);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001780}
1781
Gleb Natapov89a27f42010-02-16 10:51:48 +02001782static void svm_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001783{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001784 struct vcpu_svm *svm = to_svm(vcpu);
1785
Gleb Natapov89a27f42010-02-16 10:51:48 +02001786 dt->size = svm->vmcb->save.gdtr.limit;
1787 dt->address = svm->vmcb->save.gdtr.base;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001788}
1789
Gleb Natapov89a27f42010-02-16 10:51:48 +02001790static void svm_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001791{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001792 struct vcpu_svm *svm = to_svm(vcpu);
1793
Gleb Natapov89a27f42010-02-16 10:51:48 +02001794 svm->vmcb->save.gdtr.limit = dt->size;
1795 svm->vmcb->save.gdtr.base = dt->address ;
Joerg Roedel17a703c2010-12-03 11:45:56 +01001796 mark_dirty(svm->vmcb, VMCB_DT);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001797}
1798
Avi Kivitye8467fd2009-12-29 18:43:06 +02001799static void svm_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
1800{
1801}
1802
Avi Kivityaff48ba2010-12-05 18:56:11 +02001803static void svm_decache_cr3(struct kvm_vcpu *vcpu)
1804{
1805}
1806
Anthony Liguori25c4c272007-04-27 09:29:21 +03001807static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
Avi Kivity399badf2007-01-05 16:36:38 -08001808{
1809}
1810
Avi Kivityd2251572010-01-06 10:55:27 +02001811static void update_cr0_intercept(struct vcpu_svm *svm)
1812{
1813 ulong gcr0 = svm->vcpu.arch.cr0;
1814 u64 *hcr0 = &svm->vmcb->save.cr0;
1815
1816 if (!svm->vcpu.fpu_active)
1817 *hcr0 |= SVM_CR0_SELECTIVE_MASK;
1818 else
1819 *hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
1820 | (gcr0 & SVM_CR0_SELECTIVE_MASK);
1821
Joerg Roedeldcca1a62010-12-03 11:45:54 +01001822 mark_dirty(svm->vmcb, VMCB_CR);
Avi Kivityd2251572010-01-06 10:55:27 +02001823
1824 if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01001825 clr_cr_intercept(svm, INTERCEPT_CR0_READ);
1826 clr_cr_intercept(svm, INTERCEPT_CR0_WRITE);
Avi Kivityd2251572010-01-06 10:55:27 +02001827 } else {
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01001828 set_cr_intercept(svm, INTERCEPT_CR0_READ);
1829 set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
Avi Kivityd2251572010-01-06 10:55:27 +02001830 }
1831}
1832
Avi Kivity6aa8b732006-12-10 02:21:36 -08001833static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
1834{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001835 struct vcpu_svm *svm = to_svm(vcpu);
1836
Avi Kivity05b3e0c2006-12-13 00:33:45 -08001837#ifdef CONFIG_X86_64
Avi Kivityf6801df2010-01-21 15:31:50 +02001838 if (vcpu->arch.efer & EFER_LME) {
Rusty Russell707d92fa2007-07-17 23:19:08 +10001839 if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
Avi Kivityf6801df2010-01-21 15:31:50 +02001840 vcpu->arch.efer |= EFER_LMA;
Carlo Marcelo Arenas Belon2b5203e2007-12-01 06:17:11 -06001841 svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001842 }
1843
Mike Dayd77c26f2007-10-08 09:02:08 -04001844 if (is_paging(vcpu) && !(cr0 & X86_CR0_PG)) {
Avi Kivityf6801df2010-01-21 15:31:50 +02001845 vcpu->arch.efer &= ~EFER_LMA;
Carlo Marcelo Arenas Belon2b5203e2007-12-01 06:17:11 -06001846 svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001847 }
1848 }
1849#endif
Zhang Xiantaoad312c72007-12-13 23:50:52 +08001850 vcpu->arch.cr0 = cr0;
Avi Kivity888f9f32010-01-10 12:14:04 +02001851
1852 if (!npt_enabled)
1853 cr0 |= X86_CR0_PG | X86_CR0_WP;
Avi Kivity02daab22009-12-30 12:40:26 +02001854
1855 if (!vcpu->fpu_active)
Joerg Roedel334df502008-01-21 13:09:33 +01001856 cr0 |= X86_CR0_TS;
Paolo Bonzinibcf166a2015-10-01 13:19:55 +02001857 /*
1858 * re-enable caching here because the QEMU bios
1859 * does not do it - this results in some delay at
1860 * reboot
1861 */
1862 if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
1863 cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001864 svm->vmcb->save.cr0 = cr0;
Joerg Roedeldcca1a62010-12-03 11:45:54 +01001865 mark_dirty(svm->vmcb, VMCB_CR);
Avi Kivityd2251572010-01-06 10:55:27 +02001866 update_cr0_intercept(svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001867}
1868
Nadav Har'El5e1746d2011-05-25 23:03:24 +03001869static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001870{
Andy Lutomirski1e02ce42014-10-24 15:58:08 -07001871 unsigned long host_cr4_mce = cr4_read_shadow() & X86_CR4_MCE;
Joerg Roedele5eab0c2008-09-09 19:11:51 +02001872 unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
1873
Nadav Har'El5e1746d2011-05-25 23:03:24 +03001874 if (cr4 & X86_CR4_VMXE)
1875 return 1;
1876
Joerg Roedele5eab0c2008-09-09 19:11:51 +02001877 if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
Joerg Roedelf40f6a42010-12-03 15:25:15 +01001878 svm_flush_tlb(vcpu);
Joerg Roedel6394b642008-04-09 14:15:29 +02001879
Joerg Roedelec077262008-04-09 14:15:28 +02001880 vcpu->arch.cr4 = cr4;
1881 if (!npt_enabled)
1882 cr4 |= X86_CR4_PAE;
Joerg Roedel6394b642008-04-09 14:15:29 +02001883 cr4 |= host_cr4_mce;
Joerg Roedelec077262008-04-09 14:15:28 +02001884 to_svm(vcpu)->vmcb->save.cr4 = cr4;
Joerg Roedeldcca1a62010-12-03 11:45:54 +01001885 mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
Nadav Har'El5e1746d2011-05-25 23:03:24 +03001886 return 0;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001887}
1888
1889static void svm_set_segment(struct kvm_vcpu *vcpu,
1890 struct kvm_segment *var, int seg)
1891{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001892 struct vcpu_svm *svm = to_svm(vcpu);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001893 struct vmcb_seg *s = svm_seg(vcpu, seg);
1894
1895 s->base = var->base;
1896 s->limit = var->limit;
1897 s->selector = var->selector;
1898 if (var->unusable)
1899 s->attrib = 0;
1900 else {
1901 s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
1902 s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
1903 s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
1904 s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT;
1905 s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
1906 s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
1907 s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
1908 s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
1909 }
Paolo Bonziniae9fedc2014-05-14 09:39:49 +02001910
1911 /*
1912 * This is always accurate, except if SYSRET returned to a segment
1913 * with SS.DPL != 3. Intel does not have this quirk, and always
1914 * forces SS.DPL to 3 on sysret, so we ignore that case; fixing it
1915 * would entail passing the CPL to userspace and back.
1916 */
1917 if (seg == VCPU_SREG_SS)
1918 svm->vmcb->save.cpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001919
Joerg Roedel060d0c92010-12-03 11:45:57 +01001920 mark_dirty(svm->vmcb, VMCB_SEG);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001921}
1922
Paolo Bonzinicbdb9672015-11-10 09:14:39 +01001923static void update_bp_intercept(struct kvm_vcpu *vcpu)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001924{
Jan Kiszkad0bfb942008-12-15 13:52:10 +01001925 struct vcpu_svm *svm = to_svm(vcpu);
1926
Joerg Roedel18c918c2010-11-30 18:03:59 +01001927 clr_exception_intercept(svm, BP_VECTOR);
Gleb Natapov44c11432009-05-11 13:35:52 +03001928
Jan Kiszkad0bfb942008-12-15 13:52:10 +01001929 if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
Jan Kiszkad0bfb942008-12-15 13:52:10 +01001930 if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
Joerg Roedel18c918c2010-11-30 18:03:59 +01001931 set_exception_intercept(svm, BP_VECTOR);
Jan Kiszkad0bfb942008-12-15 13:52:10 +01001932 } else
1933 vcpu->guest_debug = 0;
Gleb Natapov44c11432009-05-11 13:35:52 +03001934}
1935
Tejun Heo0fe1e002009-10-29 22:34:14 +09001936static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001937{
Tejun Heo0fe1e002009-10-29 22:34:14 +09001938 if (sd->next_asid > sd->max_asid) {
1939 ++sd->asid_generation;
1940 sd->next_asid = 1;
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04001941 svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001942 }
1943
Tejun Heo0fe1e002009-10-29 22:34:14 +09001944 svm->asid_generation = sd->asid_generation;
1945 svm->vmcb->control.asid = sd->next_asid++;
Joerg Roedeld48086d2010-12-03 11:45:51 +01001946
1947 mark_dirty(svm->vmcb, VMCB_ASID);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001948}
1949
Jan Kiszka73aaf249e2014-01-04 18:47:16 +01001950static u64 svm_get_dr6(struct kvm_vcpu *vcpu)
1951{
1952 return to_svm(vcpu)->vmcb->save.dr6;
1953}
1954
1955static void svm_set_dr6(struct kvm_vcpu *vcpu, unsigned long value)
1956{
1957 struct vcpu_svm *svm = to_svm(vcpu);
1958
1959 svm->vmcb->save.dr6 = value;
1960 mark_dirty(svm->vmcb, VMCB_DR);
1961}
1962
Paolo Bonzinifacb0132014-02-21 10:32:27 +01001963static void svm_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
1964{
1965 struct vcpu_svm *svm = to_svm(vcpu);
1966
1967 get_debugreg(vcpu->arch.db[0], 0);
1968 get_debugreg(vcpu->arch.db[1], 1);
1969 get_debugreg(vcpu->arch.db[2], 2);
1970 get_debugreg(vcpu->arch.db[3], 3);
1971 vcpu->arch.dr6 = svm_get_dr6(vcpu);
1972 vcpu->arch.dr7 = svm->vmcb->save.dr7;
1973
1974 vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
1975 set_dr_intercepts(svm);
1976}
1977
Gleb Natapov020df072010-04-13 10:05:23 +03001978static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001979{
Jan Kiszka42dbaa52008-12-15 13:52:10 +01001980 struct vcpu_svm *svm = to_svm(vcpu);
Jan Kiszka42dbaa52008-12-15 13:52:10 +01001981
Gleb Natapov020df072010-04-13 10:05:23 +03001982 svm->vmcb->save.dr7 = value;
Joerg Roedel72214b92010-12-03 11:45:55 +01001983 mark_dirty(svm->vmcb, VMCB_DR);
Avi Kivity6aa8b732006-12-10 02:21:36 -08001984}
1985
Avi Kivity851ba692009-08-24 11:10:17 +03001986static int pf_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08001987{
Gleb Natapov631bc482010-10-14 11:22:52 +02001988 u64 fault_address = svm->vmcb->control.exit_info_2;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001989 u32 error_code;
Gleb Natapov631bc482010-10-14 11:22:52 +02001990 int r = 1;
Avi Kivity6aa8b732006-12-10 02:21:36 -08001991
Gleb Natapov631bc482010-10-14 11:22:52 +02001992 switch (svm->apf_reason) {
1993 default:
1994 error_code = svm->vmcb->control.exit_info_1;
Joerg Roedelaf9ca2d2008-04-30 17:56:03 +02001995
Gleb Natapov631bc482010-10-14 11:22:52 +02001996 trace_kvm_page_fault(fault_address, error_code);
1997 if (!npt_enabled && kvm_event_needs_reinjection(&svm->vcpu))
1998 kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
Andre Przywaradc25e892010-12-21 11:12:07 +01001999 r = kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code,
2000 svm->vmcb->control.insn_bytes,
2001 svm->vmcb->control.insn_len);
Gleb Natapov631bc482010-10-14 11:22:52 +02002002 break;
2003 case KVM_PV_REASON_PAGE_NOT_PRESENT:
2004 svm->apf_reason = 0;
2005 local_irq_disable();
2006 kvm_async_pf_task_wait(fault_address);
2007 local_irq_enable();
2008 break;
2009 case KVM_PV_REASON_PAGE_READY:
2010 svm->apf_reason = 0;
2011 local_irq_disable();
2012 kvm_async_pf_task_wake(fault_address);
2013 local_irq_enable();
2014 break;
2015 }
2016 return r;
Avi Kivity6aa8b732006-12-10 02:21:36 -08002017}
2018
Avi Kivity851ba692009-08-24 11:10:17 +03002019static int db_interception(struct vcpu_svm *svm)
Jan Kiszkad0bfb942008-12-15 13:52:10 +01002020{
Avi Kivity851ba692009-08-24 11:10:17 +03002021 struct kvm_run *kvm_run = svm->vcpu.run;
2022
Jan Kiszkad0bfb942008-12-15 13:52:10 +01002023 if (!(svm->vcpu.guest_debug &
Gleb Natapov44c11432009-05-11 13:35:52 +03002024 (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) &&
Jan Kiszka6be7d302009-10-18 13:24:54 +02002025 !svm->nmi_singlestep) {
Jan Kiszkad0bfb942008-12-15 13:52:10 +01002026 kvm_queue_exception(&svm->vcpu, DB_VECTOR);
2027 return 1;
2028 }
Gleb Natapov44c11432009-05-11 13:35:52 +03002029
Jan Kiszka6be7d302009-10-18 13:24:54 +02002030 if (svm->nmi_singlestep) {
2031 svm->nmi_singlestep = false;
Gleb Natapov44c11432009-05-11 13:35:52 +03002032 if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP))
2033 svm->vmcb->save.rflags &=
2034 ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
Gleb Natapov44c11432009-05-11 13:35:52 +03002035 }
2036
2037 if (svm->vcpu.guest_debug &
Joerg Roedele0231712010-02-24 18:59:10 +01002038 (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) {
Gleb Natapov44c11432009-05-11 13:35:52 +03002039 kvm_run->exit_reason = KVM_EXIT_DEBUG;
2040 kvm_run->debug.arch.pc =
2041 svm->vmcb->save.cs.base + svm->vmcb->save.rip;
2042 kvm_run->debug.arch.exception = DB_VECTOR;
2043 return 0;
2044 }
2045
2046 return 1;
Jan Kiszkad0bfb942008-12-15 13:52:10 +01002047}
2048
Avi Kivity851ba692009-08-24 11:10:17 +03002049static int bp_interception(struct vcpu_svm *svm)
Jan Kiszkad0bfb942008-12-15 13:52:10 +01002050{
Avi Kivity851ba692009-08-24 11:10:17 +03002051 struct kvm_run *kvm_run = svm->vcpu.run;
2052
Jan Kiszkad0bfb942008-12-15 13:52:10 +01002053 kvm_run->exit_reason = KVM_EXIT_DEBUG;
2054 kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
2055 kvm_run->debug.arch.exception = BP_VECTOR;
2056 return 0;
2057}
2058
Avi Kivity851ba692009-08-24 11:10:17 +03002059static int ud_interception(struct vcpu_svm *svm)
Anthony Liguori7aa81cc2007-09-17 14:57:50 -05002060{
2061 int er;
2062
Andre Przywara51d8b662010-12-21 11:12:02 +01002063 er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD);
Anthony Liguori7aa81cc2007-09-17 14:57:50 -05002064 if (er != EMULATE_DONE)
Avi Kivity7ee5d9402007-11-25 15:22:50 +02002065 kvm_queue_exception(&svm->vcpu, UD_VECTOR);
Anthony Liguori7aa81cc2007-09-17 14:57:50 -05002066 return 1;
2067}
2068
Eric Northup54a20552015-11-03 18:03:53 +01002069static int ac_interception(struct vcpu_svm *svm)
2070{
2071 kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0);
2072 return 1;
2073}
2074
Avi Kivity6b52d182010-01-21 15:31:47 +02002075static void svm_fpu_activate(struct kvm_vcpu *vcpu)
Anthony Liguori7807fa62007-04-23 09:17:21 -05002076{
Avi Kivity6b52d182010-01-21 15:31:47 +02002077 struct vcpu_svm *svm = to_svm(vcpu);
Joerg Roedel66a562f2010-02-19 16:23:08 +01002078
Joerg Roedel18c918c2010-11-30 18:03:59 +01002079 clr_exception_intercept(svm, NM_VECTOR);
Joerg Roedel66a562f2010-02-19 16:23:08 +01002080
Rusty Russelle756fc62007-07-30 20:07:08 +10002081 svm->vcpu.fpu_active = 1;
Avi Kivityd2251572010-01-06 10:55:27 +02002082 update_cr0_intercept(svm);
Avi Kivity6b52d182010-01-21 15:31:47 +02002083}
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04002084
Avi Kivity6b52d182010-01-21 15:31:47 +02002085static int nm_interception(struct vcpu_svm *svm)
2086{
2087 svm_fpu_activate(&svm->vcpu);
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04002088 return 1;
Anthony Liguori7807fa62007-04-23 09:17:21 -05002089}
2090
Joerg Roedel67ec6602010-05-17 14:43:35 +02002091static bool is_erratum_383(void)
2092{
2093 int err, i;
2094 u64 value;
2095
2096 if (!erratum_383_found)
2097 return false;
2098
2099 value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
2100 if (err)
2101 return false;
2102
2103 /* Bit 62 may or may not be set for this mce */
2104 value &= ~(1ULL << 62);
2105
2106 if (value != 0xb600000000010015ULL)
2107 return false;
2108
2109 /* Clear MCi_STATUS registers */
2110 for (i = 0; i < 6; ++i)
2111 native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
2112
2113 value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
2114 if (!err) {
2115 u32 low, high;
2116
2117 value &= ~(1ULL << 2);
2118 low = lower_32_bits(value);
2119 high = upper_32_bits(value);
2120
2121 native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
2122 }
2123
2124 /* Flush tlb to evict multi-match entries */
2125 __flush_tlb_all();
2126
2127 return true;
2128}
2129
Joerg Roedelfe5913e2010-05-17 14:43:34 +02002130static void svm_handle_mce(struct vcpu_svm *svm)
Joerg Roedel53371b52008-04-09 14:15:30 +02002131{
Joerg Roedel67ec6602010-05-17 14:43:35 +02002132 if (is_erratum_383()) {
2133 /*
2134 * Erratum 383 triggered. Guest state is corrupt so kill the
2135 * guest.
2136 */
2137 pr_err("KVM: Guest triggered AMD Erratum 383\n");
2138
Avi Kivitya8eeb042010-05-10 12:34:53 +03002139 kvm_make_request(KVM_REQ_TRIPLE_FAULT, &svm->vcpu);
Joerg Roedel67ec6602010-05-17 14:43:35 +02002140
2141 return;
2142 }
2143
Joerg Roedel53371b52008-04-09 14:15:30 +02002144 /*
2145 * On an #MC intercept the MCE handler is not called automatically in
2146 * the host. So do it by hand here.
2147 */
2148 asm volatile (
2149 "int $0x12\n");
2150 /* not sure if we ever come back to this point */
2151
Joerg Roedelfe5913e2010-05-17 14:43:34 +02002152 return;
2153}
2154
2155static int mc_interception(struct vcpu_svm *svm)
2156{
Joerg Roedel53371b52008-04-09 14:15:30 +02002157 return 1;
2158}
2159
Avi Kivity851ba692009-08-24 11:10:17 +03002160static int shutdown_interception(struct vcpu_svm *svm)
Joerg Roedel46fe4dd2007-01-26 00:56:42 -08002161{
Avi Kivity851ba692009-08-24 11:10:17 +03002162 struct kvm_run *kvm_run = svm->vcpu.run;
2163
Joerg Roedel46fe4dd2007-01-26 00:56:42 -08002164 /*
2165 * VMCB is undefined after a SHUTDOWN intercept
2166 * so reinitialize it.
2167 */
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04002168 clear_page(svm->vmcb);
Paolo Bonzini56908912015-10-19 11:30:19 +02002169 init_vmcb(svm);
Joerg Roedel46fe4dd2007-01-26 00:56:42 -08002170
2171 kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
2172 return 0;
2173}
2174
Avi Kivity851ba692009-08-24 11:10:17 +03002175static int io_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08002176{
Gleb Natapovcf8f70b2010-03-18 15:20:23 +02002177 struct kvm_vcpu *vcpu = &svm->vcpu;
Mike Dayd77c26f2007-10-08 09:02:08 -04002178 u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */
Jan Kiszka34c33d12009-02-08 13:28:15 +01002179 int size, in, string;
Avi Kivity039576c2007-03-20 12:46:50 +02002180 unsigned port;
Avi Kivity6aa8b732006-12-10 02:21:36 -08002181
Rusty Russelle756fc62007-07-30 20:07:08 +10002182 ++svm->vcpu.stat.io_exits;
Laurent Viviere70669a2007-08-05 10:36:40 +03002183 string = (io_info & SVM_IOIO_STR_MASK) != 0;
Avi Kivity039576c2007-03-20 12:46:50 +02002184 in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
Gleb Natapovcf8f70b2010-03-18 15:20:23 +02002185 if (string || in)
Andre Przywara51d8b662010-12-21 11:12:02 +01002186 return emulate_instruction(vcpu, 0) == EMULATE_DONE;
Gleb Natapovcf8f70b2010-03-18 15:20:23 +02002187
Avi Kivity039576c2007-03-20 12:46:50 +02002188 port = io_info >> 16;
2189 size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
Gleb Natapovcf8f70b2010-03-18 15:20:23 +02002190 svm->next_rip = svm->vmcb->control.exit_info_2;
Guillaume Thouvenine93f36b2008-10-28 10:51:30 +01002191 skip_emulated_instruction(&svm->vcpu);
Gleb Natapovcf8f70b2010-03-18 15:20:23 +02002192
2193 return kvm_fast_pio_out(vcpu, size, port);
Avi Kivity6aa8b732006-12-10 02:21:36 -08002194}
2195
Avi Kivity851ba692009-08-24 11:10:17 +03002196static int nmi_interception(struct vcpu_svm *svm)
Joerg Roedelc47f0982008-04-30 17:56:00 +02002197{
2198 return 1;
2199}
2200
Avi Kivity851ba692009-08-24 11:10:17 +03002201static int intr_interception(struct vcpu_svm *svm)
Joerg Roedela0698052008-04-30 17:56:01 +02002202{
2203 ++svm->vcpu.stat.irq_exits;
2204 return 1;
2205}
2206
Avi Kivity851ba692009-08-24 11:10:17 +03002207static int nop_on_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08002208{
2209 return 1;
2210}
2211
Avi Kivity851ba692009-08-24 11:10:17 +03002212static int halt_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08002213{
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03002214 svm->next_rip = kvm_rip_read(&svm->vcpu) + 1;
Rusty Russelle756fc62007-07-30 20:07:08 +10002215 return kvm_emulate_halt(&svm->vcpu);
Avi Kivity6aa8b732006-12-10 02:21:36 -08002216}
2217
Avi Kivity851ba692009-08-24 11:10:17 +03002218static int vmmcall_interception(struct vcpu_svm *svm)
Avi Kivity02e235b2007-02-19 14:37:47 +02002219{
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03002220 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
Andrey Smetanin0d9c0552016-02-11 16:44:59 +03002221 return kvm_emulate_hypercall(&svm->vcpu);
Avi Kivity02e235b2007-02-19 14:37:47 +02002222}
2223
Joerg Roedel5bd2edc2010-09-10 17:31:02 +02002224static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu)
2225{
2226 struct vcpu_svm *svm = to_svm(vcpu);
2227
2228 return svm->nested.nested_cr3;
2229}
2230
Avi Kivitye4e517b2011-07-28 11:36:17 +03002231static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index)
2232{
2233 struct vcpu_svm *svm = to_svm(vcpu);
2234 u64 cr3 = svm->nested.nested_cr3;
2235 u64 pdpte;
2236 int ret;
2237
Paolo Bonzini54bf36a2015-04-08 15:39:23 +02002238 ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(cr3), &pdpte,
2239 offset_in_page(cr3) + index * 8, 8);
Avi Kivitye4e517b2011-07-28 11:36:17 +03002240 if (ret)
2241 return 0;
2242 return pdpte;
2243}
2244
Joerg Roedel5bd2edc2010-09-10 17:31:02 +02002245static void nested_svm_set_tdp_cr3(struct kvm_vcpu *vcpu,
2246 unsigned long root)
2247{
2248 struct vcpu_svm *svm = to_svm(vcpu);
2249
2250 svm->vmcb->control.nested_cr3 = root;
Joerg Roedelb2747162010-12-03 11:45:53 +01002251 mark_dirty(svm->vmcb, VMCB_NPT);
Joerg Roedelf40f6a42010-12-03 15:25:15 +01002252 svm_flush_tlb(vcpu);
Joerg Roedel5bd2edc2010-09-10 17:31:02 +02002253}
2254
Avi Kivity6389ee92010-11-29 16:12:30 +02002255static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
2256 struct x86_exception *fault)
Joerg Roedel5bd2edc2010-09-10 17:31:02 +02002257{
2258 struct vcpu_svm *svm = to_svm(vcpu);
2259
Paolo Bonzini5e352512014-09-02 13:18:37 +02002260 if (svm->vmcb->control.exit_code != SVM_EXIT_NPF) {
2261 /*
2262 * TODO: track the cause of the nested page fault, and
2263 * correctly fill in the high bits of exit_info_1.
2264 */
2265 svm->vmcb->control.exit_code = SVM_EXIT_NPF;
2266 svm->vmcb->control.exit_code_hi = 0;
2267 svm->vmcb->control.exit_info_1 = (1ULL << 32);
2268 svm->vmcb->control.exit_info_2 = fault->address;
2269 }
2270
2271 svm->vmcb->control.exit_info_1 &= ~0xffffffffULL;
2272 svm->vmcb->control.exit_info_1 |= fault->error_code;
2273
2274 /*
2275 * The present bit is always zero for page structure faults on real
2276 * hardware.
2277 */
2278 if (svm->vmcb->control.exit_info_1 & (2ULL << 32))
2279 svm->vmcb->control.exit_info_1 &= ~1;
Joerg Roedel5bd2edc2010-09-10 17:31:02 +02002280
2281 nested_svm_vmexit(svm);
2282}
2283
Paolo Bonzini8a3c1a332013-10-02 16:56:13 +02002284static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
Joerg Roedel4b161842010-09-10 17:31:03 +02002285{
Paolo Bonziniad896af2013-10-02 16:56:14 +02002286 WARN_ON(mmu_is_nested(vcpu));
2287 kvm_init_shadow_mmu(vcpu);
Joerg Roedel4b161842010-09-10 17:31:03 +02002288 vcpu->arch.mmu.set_cr3 = nested_svm_set_tdp_cr3;
2289 vcpu->arch.mmu.get_cr3 = nested_svm_get_tdp_cr3;
Avi Kivitye4e517b2011-07-28 11:36:17 +03002290 vcpu->arch.mmu.get_pdptr = nested_svm_get_tdp_pdptr;
Joerg Roedel4b161842010-09-10 17:31:03 +02002291 vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
2292 vcpu->arch.mmu.shadow_root_level = get_npt_level();
Xiao Guangrongc258b622015-08-05 12:04:24 +08002293 reset_shadow_zero_bits_mask(vcpu, &vcpu->arch.mmu);
Joerg Roedel4b161842010-09-10 17:31:03 +02002294 vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu;
Joerg Roedel4b161842010-09-10 17:31:03 +02002295}
2296
2297static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu)
2298{
2299 vcpu->arch.walk_mmu = &vcpu->arch.mmu;
2300}
2301
Alexander Grafc0725422008-11-25 20:17:03 +01002302static int nested_svm_check_permissions(struct vcpu_svm *svm)
2303{
Avi Kivityf6801df2010-01-21 15:31:50 +02002304 if (!(svm->vcpu.arch.efer & EFER_SVME)
Alexander Grafc0725422008-11-25 20:17:03 +01002305 || !is_paging(&svm->vcpu)) {
2306 kvm_queue_exception(&svm->vcpu, UD_VECTOR);
2307 return 1;
2308 }
2309
2310 if (svm->vmcb->save.cpl) {
2311 kvm_inject_gp(&svm->vcpu, 0);
2312 return 1;
2313 }
2314
2315 return 0;
2316}
2317
Alexander Grafcf74a782008-11-25 20:17:08 +01002318static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
2319 bool has_error_code, u32 error_code)
2320{
Joerg Roedelb8e88bc2010-02-19 16:23:02 +01002321 int vmexit;
2322
Joerg Roedel20307532010-11-29 17:51:48 +01002323 if (!is_guest_mode(&svm->vcpu))
Joerg Roedel0295ad72009-08-07 11:49:37 +02002324 return 0;
Alexander Grafcf74a782008-11-25 20:17:08 +01002325
Joerg Roedel0295ad72009-08-07 11:49:37 +02002326 svm->vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + nr;
2327 svm->vmcb->control.exit_code_hi = 0;
2328 svm->vmcb->control.exit_info_1 = error_code;
2329 svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2;
2330
Joerg Roedelb8e88bc2010-02-19 16:23:02 +01002331 vmexit = nested_svm_intercept(svm);
2332 if (vmexit == NESTED_EXIT_DONE)
2333 svm->nested.exit_required = true;
2334
2335 return vmexit;
Alexander Grafcf74a782008-11-25 20:17:08 +01002336}
2337
Joerg Roedel8fe54652010-02-19 16:23:01 +01002338/* This function returns true if it is save to enable the irq window */
2339static inline bool nested_svm_intr(struct vcpu_svm *svm)
Alexander Grafcf74a782008-11-25 20:17:08 +01002340{
Joerg Roedel20307532010-11-29 17:51:48 +01002341 if (!is_guest_mode(&svm->vcpu))
Joerg Roedel8fe54652010-02-19 16:23:01 +01002342 return true;
Alexander Grafcf74a782008-11-25 20:17:08 +01002343
Joerg Roedel26666952009-08-07 11:49:46 +02002344 if (!(svm->vcpu.arch.hflags & HF_VINTR_MASK))
Joerg Roedel8fe54652010-02-19 16:23:01 +01002345 return true;
Alexander Grafcf74a782008-11-25 20:17:08 +01002346
Joerg Roedel26666952009-08-07 11:49:46 +02002347 if (!(svm->vcpu.arch.hflags & HF_HIF_MASK))
Joerg Roedel8fe54652010-02-19 16:23:01 +01002348 return false;
Alexander Grafcf74a782008-11-25 20:17:08 +01002349
Gleb Natapova0a07cd2010-09-20 10:15:32 +02002350 /*
2351 * if vmexit was already requested (by intercepted exception
2352 * for instance) do not overwrite it with "external interrupt"
2353 * vmexit.
2354 */
2355 if (svm->nested.exit_required)
2356 return false;
2357
Joerg Roedel197717d2010-02-24 18:59:19 +01002358 svm->vmcb->control.exit_code = SVM_EXIT_INTR;
2359 svm->vmcb->control.exit_info_1 = 0;
2360 svm->vmcb->control.exit_info_2 = 0;
Joerg Roedel26666952009-08-07 11:49:46 +02002361
Joerg Roedelcd3ff652009-10-09 16:08:26 +02002362 if (svm->nested.intercept & 1ULL) {
2363 /*
2364 * The #vmexit can't be emulated here directly because this
Guo Chaoc5ec2e52012-06-28 15:16:43 +08002365 * code path runs with irqs and preemption disabled. A
Joerg Roedelcd3ff652009-10-09 16:08:26 +02002366 * #vmexit emulation might sleep. Only signal request for
2367 * the #vmexit here.
2368 */
2369 svm->nested.exit_required = true;
Joerg Roedel236649d2009-10-09 16:08:30 +02002370 trace_kvm_nested_intr_vmexit(svm->vmcb->save.rip);
Joerg Roedel8fe54652010-02-19 16:23:01 +01002371 return false;
Alexander Grafcf74a782008-11-25 20:17:08 +01002372 }
2373
Joerg Roedel8fe54652010-02-19 16:23:01 +01002374 return true;
Alexander Grafcf74a782008-11-25 20:17:08 +01002375}
2376
Joerg Roedel887f5002010-02-24 18:59:12 +01002377/* This function returns true if it is save to enable the nmi window */
2378static inline bool nested_svm_nmi(struct vcpu_svm *svm)
2379{
Joerg Roedel20307532010-11-29 17:51:48 +01002380 if (!is_guest_mode(&svm->vcpu))
Joerg Roedel887f5002010-02-24 18:59:12 +01002381 return true;
2382
2383 if (!(svm->nested.intercept & (1ULL << INTERCEPT_NMI)))
2384 return true;
2385
2386 svm->vmcb->control.exit_code = SVM_EXIT_NMI;
2387 svm->nested.exit_required = true;
2388
2389 return false;
2390}
2391
Joerg Roedel7597f122010-02-19 16:23:00 +01002392static void *nested_svm_map(struct vcpu_svm *svm, u64 gpa, struct page **_page)
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002393{
2394 struct page *page;
2395
Joerg Roedel6c3bd3d2010-02-19 16:23:04 +01002396 might_sleep();
2397
Paolo Bonzini54bf36a2015-04-08 15:39:23 +02002398 page = kvm_vcpu_gfn_to_page(&svm->vcpu, gpa >> PAGE_SHIFT);
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002399 if (is_error_page(page))
2400 goto error;
2401
Joerg Roedel7597f122010-02-19 16:23:00 +01002402 *_page = page;
2403
2404 return kmap(page);
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002405
2406error:
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002407 kvm_inject_gp(&svm->vcpu, 0);
2408
2409 return NULL;
2410}
2411
Joerg Roedel7597f122010-02-19 16:23:00 +01002412static void nested_svm_unmap(struct page *page)
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002413{
Joerg Roedel7597f122010-02-19 16:23:00 +01002414 kunmap(page);
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002415 kvm_release_page_dirty(page);
2416}
2417
Joerg Roedelce2ac082010-03-01 15:34:39 +01002418static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
Alexander Grafcf74a782008-11-25 20:17:08 +01002419{
Jan Kiszka9bf41832014-06-30 10:54:17 +02002420 unsigned port, size, iopm_len;
2421 u16 val, mask;
2422 u8 start_bit;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002423 u64 gpa;
2424
2425 if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT)))
2426 return NESTED_EXIT_HOST;
2427
2428 port = svm->vmcb->control.exit_info_1 >> 16;
Jan Kiszka9bf41832014-06-30 10:54:17 +02002429 size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >>
2430 SVM_IOIO_SIZE_SHIFT;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002431 gpa = svm->nested.vmcb_iopm + (port / 8);
Jan Kiszka9bf41832014-06-30 10:54:17 +02002432 start_bit = port % 8;
2433 iopm_len = (start_bit + size > 8) ? 2 : 1;
2434 mask = (0xf >> (4 - size)) << start_bit;
2435 val = 0;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002436
Paolo Bonzini54bf36a2015-04-08 15:39:23 +02002437 if (kvm_vcpu_read_guest(&svm->vcpu, gpa, &val, iopm_len))
Jan Kiszka9bf41832014-06-30 10:54:17 +02002438 return NESTED_EXIT_DONE;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002439
Jan Kiszka9bf41832014-06-30 10:54:17 +02002440 return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002441}
2442
Joerg Roedeld2477822010-03-01 15:34:34 +01002443static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
Alexander Grafcf74a782008-11-25 20:17:08 +01002444{
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002445 u32 offset, msr, value;
2446 int write, mask;
Joerg Roedel4c2161a2009-08-07 11:49:35 +02002447
Joerg Roedel3d62d9a2009-08-07 11:49:39 +02002448 if (!(svm->nested.intercept & (1ULL << INTERCEPT_MSR_PROT)))
Joerg Roedeld2477822010-03-01 15:34:34 +01002449 return NESTED_EXIT_HOST;
Joerg Roedel3d62d9a2009-08-07 11:49:39 +02002450
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002451 msr = svm->vcpu.arch.regs[VCPU_REGS_RCX];
2452 offset = svm_msrpm_offset(msr);
2453 write = svm->vmcb->control.exit_info_1 & 1;
2454 mask = 1 << ((2 * (msr & 0xf)) + write);
Joerg Roedel3d62d9a2009-08-07 11:49:39 +02002455
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002456 if (offset == MSR_INVALID)
2457 return NESTED_EXIT_DONE;
Joerg Roedel4c2161a2009-08-07 11:49:35 +02002458
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002459 /* Offset is in 32 bit units but need in 8 bit units */
2460 offset *= 4;
Joerg Roedel4c2161a2009-08-07 11:49:35 +02002461
Paolo Bonzini54bf36a2015-04-08 15:39:23 +02002462 if (kvm_vcpu_read_guest(&svm->vcpu, svm->nested.vmcb_msrpm + offset, &value, 4))
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002463 return NESTED_EXIT_DONE;
Joerg Roedel3d62d9a2009-08-07 11:49:39 +02002464
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002465 return (value & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
Joerg Roedel4c2161a2009-08-07 11:49:35 +02002466}
2467
Joerg Roedel410e4d52009-08-07 11:49:44 +02002468static int nested_svm_exit_special(struct vcpu_svm *svm)
Joerg Roedel4c2161a2009-08-07 11:49:35 +02002469{
Alexander Grafcf74a782008-11-25 20:17:08 +01002470 u32 exit_code = svm->vmcb->control.exit_code;
Joerg Roedel4c2161a2009-08-07 11:49:35 +02002471
Joerg Roedel410e4d52009-08-07 11:49:44 +02002472 switch (exit_code) {
2473 case SVM_EXIT_INTR:
2474 case SVM_EXIT_NMI:
Joerg Roedelff47a492010-04-22 12:33:14 +02002475 case SVM_EXIT_EXCP_BASE + MC_VECTOR:
Joerg Roedel410e4d52009-08-07 11:49:44 +02002476 return NESTED_EXIT_HOST;
Joerg Roedel410e4d52009-08-07 11:49:44 +02002477 case SVM_EXIT_NPF:
Joerg Roedele0231712010-02-24 18:59:10 +01002478 /* For now we are always handling NPFs when using them */
Joerg Roedel410e4d52009-08-07 11:49:44 +02002479 if (npt_enabled)
2480 return NESTED_EXIT_HOST;
2481 break;
Joerg Roedel410e4d52009-08-07 11:49:44 +02002482 case SVM_EXIT_EXCP_BASE + PF_VECTOR:
Gleb Natapov631bc482010-10-14 11:22:52 +02002483 /* When we're shadowing, trap PFs, but not async PF */
2484 if (!npt_enabled && svm->apf_reason == 0)
Joerg Roedel410e4d52009-08-07 11:49:44 +02002485 return NESTED_EXIT_HOST;
2486 break;
Joerg Roedel66a562f2010-02-19 16:23:08 +01002487 case SVM_EXIT_EXCP_BASE + NM_VECTOR:
2488 nm_interception(svm);
2489 break;
Joerg Roedel410e4d52009-08-07 11:49:44 +02002490 default:
2491 break;
Alexander Grafcf74a782008-11-25 20:17:08 +01002492 }
2493
Joerg Roedel410e4d52009-08-07 11:49:44 +02002494 return NESTED_EXIT_CONTINUE;
2495}
2496
2497/*
2498 * If this function returns true, this #vmexit was already handled
2499 */
Joerg Roedelb8e88bc2010-02-19 16:23:02 +01002500static int nested_svm_intercept(struct vcpu_svm *svm)
Joerg Roedel410e4d52009-08-07 11:49:44 +02002501{
2502 u32 exit_code = svm->vmcb->control.exit_code;
2503 int vmexit = NESTED_EXIT_HOST;
2504
Alexander Grafcf74a782008-11-25 20:17:08 +01002505 switch (exit_code) {
Joerg Roedel9c4e40b92009-08-07 11:49:36 +02002506 case SVM_EXIT_MSR:
Joerg Roedel3d62d9a2009-08-07 11:49:39 +02002507 vmexit = nested_svm_exit_handled_msr(svm);
Joerg Roedel9c4e40b92009-08-07 11:49:36 +02002508 break;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002509 case SVM_EXIT_IOIO:
2510 vmexit = nested_svm_intercept_ioio(svm);
2511 break;
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01002512 case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR8: {
2513 u32 bit = 1U << (exit_code - SVM_EXIT_READ_CR0);
2514 if (svm->nested.intercept_cr & bit)
Joerg Roedel410e4d52009-08-07 11:49:44 +02002515 vmexit = NESTED_EXIT_DONE;
Alexander Grafcf74a782008-11-25 20:17:08 +01002516 break;
2517 }
Joerg Roedel3aed0412010-11-30 18:03:58 +01002518 case SVM_EXIT_READ_DR0 ... SVM_EXIT_WRITE_DR7: {
2519 u32 bit = 1U << (exit_code - SVM_EXIT_READ_DR0);
2520 if (svm->nested.intercept_dr & bit)
Joerg Roedel410e4d52009-08-07 11:49:44 +02002521 vmexit = NESTED_EXIT_DONE;
Alexander Grafcf74a782008-11-25 20:17:08 +01002522 break;
2523 }
2524 case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
2525 u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE);
Joerg Roedelaad42c62009-08-07 11:49:34 +02002526 if (svm->nested.intercept_exceptions & excp_bits)
Joerg Roedel410e4d52009-08-07 11:49:44 +02002527 vmexit = NESTED_EXIT_DONE;
Gleb Natapov631bc482010-10-14 11:22:52 +02002528 /* async page fault always cause vmexit */
2529 else if ((exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR) &&
2530 svm->apf_reason != 0)
2531 vmexit = NESTED_EXIT_DONE;
Alexander Grafcf74a782008-11-25 20:17:08 +01002532 break;
2533 }
Joerg Roedel228070b2010-04-22 12:33:10 +02002534 case SVM_EXIT_ERR: {
2535 vmexit = NESTED_EXIT_DONE;
2536 break;
2537 }
Alexander Grafcf74a782008-11-25 20:17:08 +01002538 default: {
2539 u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR);
Joerg Roedelaad42c62009-08-07 11:49:34 +02002540 if (svm->nested.intercept & exit_bits)
Joerg Roedel410e4d52009-08-07 11:49:44 +02002541 vmexit = NESTED_EXIT_DONE;
Alexander Grafcf74a782008-11-25 20:17:08 +01002542 }
2543 }
2544
Joerg Roedelb8e88bc2010-02-19 16:23:02 +01002545 return vmexit;
2546}
2547
2548static int nested_svm_exit_handled(struct vcpu_svm *svm)
2549{
2550 int vmexit;
2551
2552 vmexit = nested_svm_intercept(svm);
2553
2554 if (vmexit == NESTED_EXIT_DONE)
Joerg Roedel9c4e40b92009-08-07 11:49:36 +02002555 nested_svm_vmexit(svm);
Joerg Roedel9c4e40b92009-08-07 11:49:36 +02002556
2557 return vmexit;
Alexander Grafcf74a782008-11-25 20:17:08 +01002558}
2559
Joerg Roedel0460a972009-08-07 11:49:31 +02002560static inline void copy_vmcb_control_area(struct vmcb *dst_vmcb, struct vmcb *from_vmcb)
2561{
2562 struct vmcb_control_area *dst = &dst_vmcb->control;
2563 struct vmcb_control_area *from = &from_vmcb->control;
2564
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01002565 dst->intercept_cr = from->intercept_cr;
Joerg Roedel3aed0412010-11-30 18:03:58 +01002566 dst->intercept_dr = from->intercept_dr;
Joerg Roedel0460a972009-08-07 11:49:31 +02002567 dst->intercept_exceptions = from->intercept_exceptions;
2568 dst->intercept = from->intercept;
2569 dst->iopm_base_pa = from->iopm_base_pa;
2570 dst->msrpm_base_pa = from->msrpm_base_pa;
2571 dst->tsc_offset = from->tsc_offset;
2572 dst->asid = from->asid;
2573 dst->tlb_ctl = from->tlb_ctl;
2574 dst->int_ctl = from->int_ctl;
2575 dst->int_vector = from->int_vector;
2576 dst->int_state = from->int_state;
2577 dst->exit_code = from->exit_code;
2578 dst->exit_code_hi = from->exit_code_hi;
2579 dst->exit_info_1 = from->exit_info_1;
2580 dst->exit_info_2 = from->exit_info_2;
2581 dst->exit_int_info = from->exit_int_info;
2582 dst->exit_int_info_err = from->exit_int_info_err;
2583 dst->nested_ctl = from->nested_ctl;
2584 dst->event_inj = from->event_inj;
2585 dst->event_inj_err = from->event_inj_err;
2586 dst->nested_cr3 = from->nested_cr3;
2587 dst->lbr_ctl = from->lbr_ctl;
2588}
2589
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002590static int nested_svm_vmexit(struct vcpu_svm *svm)
Alexander Grafcf74a782008-11-25 20:17:08 +01002591{
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002592 struct vmcb *nested_vmcb;
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02002593 struct vmcb *hsave = svm->nested.hsave;
Joerg Roedel33740e42009-08-07 11:49:29 +02002594 struct vmcb *vmcb = svm->vmcb;
Joerg Roedel7597f122010-02-19 16:23:00 +01002595 struct page *page;
Alexander Grafcf74a782008-11-25 20:17:08 +01002596
Joerg Roedel17897f32009-10-09 16:08:29 +02002597 trace_kvm_nested_vmexit_inject(vmcb->control.exit_code,
2598 vmcb->control.exit_info_1,
2599 vmcb->control.exit_info_2,
2600 vmcb->control.exit_int_info,
Stefan Hajnoczie097e5f2011-07-22 12:46:52 +01002601 vmcb->control.exit_int_info_err,
2602 KVM_ISA_SVM);
Joerg Roedel17897f32009-10-09 16:08:29 +02002603
Joerg Roedel7597f122010-02-19 16:23:00 +01002604 nested_vmcb = nested_svm_map(svm, svm->nested.vmcb, &page);
Joerg Roedel34f80cf2009-08-07 11:49:38 +02002605 if (!nested_vmcb)
2606 return 1;
2607
Joerg Roedel20307532010-11-29 17:51:48 +01002608 /* Exit Guest-Mode */
2609 leave_guest_mode(&svm->vcpu);
Joerg Roedel06fc77722010-02-19 16:23:07 +01002610 svm->nested.vmcb = 0;
2611
Alexander Grafcf74a782008-11-25 20:17:08 +01002612 /* Give the current vmcb to the guest */
Joerg Roedel33740e42009-08-07 11:49:29 +02002613 disable_gif(svm);
2614
2615 nested_vmcb->save.es = vmcb->save.es;
2616 nested_vmcb->save.cs = vmcb->save.cs;
2617 nested_vmcb->save.ss = vmcb->save.ss;
2618 nested_vmcb->save.ds = vmcb->save.ds;
2619 nested_vmcb->save.gdtr = vmcb->save.gdtr;
2620 nested_vmcb->save.idtr = vmcb->save.idtr;
Joerg Roedel3f6a9d12010-07-27 18:14:20 +02002621 nested_vmcb->save.efer = svm->vcpu.arch.efer;
Joerg Roedelcdbbdc12010-02-19 16:23:03 +01002622 nested_vmcb->save.cr0 = kvm_read_cr0(&svm->vcpu);
Avi Kivity9f8fe502010-12-05 17:30:00 +02002623 nested_vmcb->save.cr3 = kvm_read_cr3(&svm->vcpu);
Joerg Roedel33740e42009-08-07 11:49:29 +02002624 nested_vmcb->save.cr2 = vmcb->save.cr2;
Joerg Roedelcdbbdc12010-02-19 16:23:03 +01002625 nested_vmcb->save.cr4 = svm->vcpu.arch.cr4;
Avi Kivityf6e78472010-08-02 15:30:20 +03002626 nested_vmcb->save.rflags = kvm_get_rflags(&svm->vcpu);
Joerg Roedel33740e42009-08-07 11:49:29 +02002627 nested_vmcb->save.rip = vmcb->save.rip;
2628 nested_vmcb->save.rsp = vmcb->save.rsp;
2629 nested_vmcb->save.rax = vmcb->save.rax;
2630 nested_vmcb->save.dr7 = vmcb->save.dr7;
2631 nested_vmcb->save.dr6 = vmcb->save.dr6;
2632 nested_vmcb->save.cpl = vmcb->save.cpl;
2633
2634 nested_vmcb->control.int_ctl = vmcb->control.int_ctl;
2635 nested_vmcb->control.int_vector = vmcb->control.int_vector;
2636 nested_vmcb->control.int_state = vmcb->control.int_state;
2637 nested_vmcb->control.exit_code = vmcb->control.exit_code;
2638 nested_vmcb->control.exit_code_hi = vmcb->control.exit_code_hi;
2639 nested_vmcb->control.exit_info_1 = vmcb->control.exit_info_1;
2640 nested_vmcb->control.exit_info_2 = vmcb->control.exit_info_2;
2641 nested_vmcb->control.exit_int_info = vmcb->control.exit_int_info;
2642 nested_vmcb->control.exit_int_info_err = vmcb->control.exit_int_info_err;
Joerg Roedel6092d3d2015-10-14 15:10:54 +02002643
2644 if (svm->nrips_enabled)
2645 nested_vmcb->control.next_rip = vmcb->control.next_rip;
Alexander Graf8d23c462009-10-09 16:08:25 +02002646
2647 /*
2648 * If we emulate a VMRUN/#VMEXIT in the same host #vmexit cycle we have
2649 * to make sure that we do not lose injected events. So check event_inj
2650 * here and copy it to exit_int_info if it is valid.
2651 * Exit_int_info and event_inj can't be both valid because the case
2652 * below only happens on a VMRUN instruction intercept which has
2653 * no valid exit_int_info set.
2654 */
2655 if (vmcb->control.event_inj & SVM_EVTINJ_VALID) {
2656 struct vmcb_control_area *nc = &nested_vmcb->control;
2657
2658 nc->exit_int_info = vmcb->control.event_inj;
2659 nc->exit_int_info_err = vmcb->control.event_inj_err;
2660 }
2661
Joerg Roedel33740e42009-08-07 11:49:29 +02002662 nested_vmcb->control.tlb_ctl = 0;
2663 nested_vmcb->control.event_inj = 0;
2664 nested_vmcb->control.event_inj_err = 0;
Alexander Grafcf74a782008-11-25 20:17:08 +01002665
2666 /* We always set V_INTR_MASKING and remember the old value in hflags */
2667 if (!(svm->vcpu.arch.hflags & HF_VINTR_MASK))
2668 nested_vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK;
2669
Alexander Grafcf74a782008-11-25 20:17:08 +01002670 /* Restore the original control entries */
Joerg Roedel0460a972009-08-07 11:49:31 +02002671 copy_vmcb_control_area(vmcb, hsave);
Alexander Grafcf74a782008-11-25 20:17:08 +01002672
Alexander Graf219b65d2009-06-15 15:21:25 +02002673 kvm_clear_exception_queue(&svm->vcpu);
2674 kvm_clear_interrupt_queue(&svm->vcpu);
Alexander Grafcf74a782008-11-25 20:17:08 +01002675
Joerg Roedel4b161842010-09-10 17:31:03 +02002676 svm->nested.nested_cr3 = 0;
2677
Alexander Grafcf74a782008-11-25 20:17:08 +01002678 /* Restore selected save entries */
2679 svm->vmcb->save.es = hsave->save.es;
2680 svm->vmcb->save.cs = hsave->save.cs;
2681 svm->vmcb->save.ss = hsave->save.ss;
2682 svm->vmcb->save.ds = hsave->save.ds;
2683 svm->vmcb->save.gdtr = hsave->save.gdtr;
2684 svm->vmcb->save.idtr = hsave->save.idtr;
Avi Kivityf6e78472010-08-02 15:30:20 +03002685 kvm_set_rflags(&svm->vcpu, hsave->save.rflags);
Alexander Grafcf74a782008-11-25 20:17:08 +01002686 svm_set_efer(&svm->vcpu, hsave->save.efer);
2687 svm_set_cr0(&svm->vcpu, hsave->save.cr0 | X86_CR0_PE);
2688 svm_set_cr4(&svm->vcpu, hsave->save.cr4);
2689 if (npt_enabled) {
2690 svm->vmcb->save.cr3 = hsave->save.cr3;
2691 svm->vcpu.arch.cr3 = hsave->save.cr3;
2692 } else {
Avi Kivity23902182010-06-10 17:02:16 +03002693 (void)kvm_set_cr3(&svm->vcpu, hsave->save.cr3);
Alexander Grafcf74a782008-11-25 20:17:08 +01002694 }
2695 kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, hsave->save.rax);
2696 kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, hsave->save.rsp);
2697 kvm_register_write(&svm->vcpu, VCPU_REGS_RIP, hsave->save.rip);
2698 svm->vmcb->save.dr7 = 0;
2699 svm->vmcb->save.cpl = 0;
2700 svm->vmcb->control.exit_int_info = 0;
2701
Roedel, Joerg8d28fec2010-12-03 13:15:21 +01002702 mark_all_dirty(svm->vmcb);
2703
Joerg Roedel7597f122010-02-19 16:23:00 +01002704 nested_svm_unmap(page);
Alexander Grafcf74a782008-11-25 20:17:08 +01002705
Joerg Roedel4b161842010-09-10 17:31:03 +02002706 nested_svm_uninit_mmu_context(&svm->vcpu);
Alexander Grafcf74a782008-11-25 20:17:08 +01002707 kvm_mmu_reset_context(&svm->vcpu);
2708 kvm_mmu_load(&svm->vcpu);
2709
2710 return 0;
2711}
Alexander Graf3d6368e2008-11-25 20:17:07 +01002712
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002713static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
Alexander Graf3d6368e2008-11-25 20:17:07 +01002714{
Joerg Roedel323c3d82010-03-01 15:34:37 +01002715 /*
2716 * This function merges the msr permission bitmaps of kvm and the
Guo Chaoc5ec2e52012-06-28 15:16:43 +08002717 * nested vmcb. It is optimized in that it only merges the parts where
Joerg Roedel323c3d82010-03-01 15:34:37 +01002718 * the kvm msr permission bitmap may contain zero bits
2719 */
Alexander Graf3d6368e2008-11-25 20:17:07 +01002720 int i;
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002721
Joerg Roedel323c3d82010-03-01 15:34:37 +01002722 if (!(svm->nested.intercept & (1ULL << INTERCEPT_MSR_PROT)))
2723 return true;
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002724
Joerg Roedel323c3d82010-03-01 15:34:37 +01002725 for (i = 0; i < MSRPM_OFFSETS; i++) {
2726 u32 value, p;
2727 u64 offset;
2728
2729 if (msrpm_offsets[i] == 0xffffffff)
2730 break;
2731
Joerg Roedel0d6b3532010-03-01 15:34:38 +01002732 p = msrpm_offsets[i];
2733 offset = svm->nested.vmcb_msrpm + (p * 4);
Joerg Roedel323c3d82010-03-01 15:34:37 +01002734
Paolo Bonzini54bf36a2015-04-08 15:39:23 +02002735 if (kvm_vcpu_read_guest(&svm->vcpu, offset, &value, 4))
Joerg Roedel323c3d82010-03-01 15:34:37 +01002736 return false;
2737
2738 svm->nested.msrpm[p] = svm->msrpm[p] | value;
2739 }
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002740
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02002741 svm->vmcb->control.msrpm_base_pa = __pa(svm->nested.msrpm);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002742
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002743 return true;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002744}
2745
Joerg Roedel52c65a302010-08-02 16:46:44 +02002746static bool nested_vmcb_checks(struct vmcb *vmcb)
2747{
2748 if ((vmcb->control.intercept & (1ULL << INTERCEPT_VMRUN)) == 0)
2749 return false;
2750
Joerg Roedeldbe77582010-08-02 16:46:45 +02002751 if (vmcb->control.asid == 0)
2752 return false;
2753
Joerg Roedel4b161842010-09-10 17:31:03 +02002754 if (vmcb->control.nested_ctl && !npt_enabled)
2755 return false;
2756
Joerg Roedel52c65a302010-08-02 16:46:44 +02002757 return true;
2758}
2759
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002760static bool nested_svm_vmrun(struct vcpu_svm *svm)
Alexander Graf3d6368e2008-11-25 20:17:07 +01002761{
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002762 struct vmcb *nested_vmcb;
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02002763 struct vmcb *hsave = svm->nested.hsave;
Joerg Roedeldefbba52009-08-07 11:49:30 +02002764 struct vmcb *vmcb = svm->vmcb;
Joerg Roedel7597f122010-02-19 16:23:00 +01002765 struct page *page;
Joerg Roedel06fc77722010-02-19 16:23:07 +01002766 u64 vmcb_gpa;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002767
Joerg Roedel06fc77722010-02-19 16:23:07 +01002768 vmcb_gpa = svm->vmcb->save.rax;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002769
Joerg Roedel7597f122010-02-19 16:23:00 +01002770 nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002771 if (!nested_vmcb)
2772 return false;
2773
Joerg Roedel52c65a302010-08-02 16:46:44 +02002774 if (!nested_vmcb_checks(nested_vmcb)) {
2775 nested_vmcb->control.exit_code = SVM_EXIT_ERR;
2776 nested_vmcb->control.exit_code_hi = 0;
2777 nested_vmcb->control.exit_info_1 = 0;
2778 nested_vmcb->control.exit_info_2 = 0;
2779
2780 nested_svm_unmap(page);
2781
2782 return false;
2783 }
2784
Roedel, Joergb75f4eb2010-09-03 14:21:40 +02002785 trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb_gpa,
Joerg Roedel0ac406d2009-10-09 16:08:27 +02002786 nested_vmcb->save.rip,
2787 nested_vmcb->control.int_ctl,
2788 nested_vmcb->control.event_inj,
2789 nested_vmcb->control.nested_ctl);
2790
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01002791 trace_kvm_nested_intercepts(nested_vmcb->control.intercept_cr & 0xffff,
2792 nested_vmcb->control.intercept_cr >> 16,
Joerg Roedel2e554e82010-02-24 18:59:14 +01002793 nested_vmcb->control.intercept_exceptions,
2794 nested_vmcb->control.intercept);
2795
Alexander Graf3d6368e2008-11-25 20:17:07 +01002796 /* Clear internal status */
Alexander Graf219b65d2009-06-15 15:21:25 +02002797 kvm_clear_exception_queue(&svm->vcpu);
2798 kvm_clear_interrupt_queue(&svm->vcpu);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002799
Joerg Roedele0231712010-02-24 18:59:10 +01002800 /*
2801 * Save the old vmcb, so we don't need to pick what we save, but can
2802 * restore everything when a VMEXIT occurs
2803 */
Joerg Roedeldefbba52009-08-07 11:49:30 +02002804 hsave->save.es = vmcb->save.es;
2805 hsave->save.cs = vmcb->save.cs;
2806 hsave->save.ss = vmcb->save.ss;
2807 hsave->save.ds = vmcb->save.ds;
2808 hsave->save.gdtr = vmcb->save.gdtr;
2809 hsave->save.idtr = vmcb->save.idtr;
Avi Kivityf6801df2010-01-21 15:31:50 +02002810 hsave->save.efer = svm->vcpu.arch.efer;
Avi Kivity4d4ec082009-12-29 18:07:30 +02002811 hsave->save.cr0 = kvm_read_cr0(&svm->vcpu);
Joerg Roedeldefbba52009-08-07 11:49:30 +02002812 hsave->save.cr4 = svm->vcpu.arch.cr4;
Avi Kivityf6e78472010-08-02 15:30:20 +03002813 hsave->save.rflags = kvm_get_rflags(&svm->vcpu);
Roedel, Joergb75f4eb2010-09-03 14:21:40 +02002814 hsave->save.rip = kvm_rip_read(&svm->vcpu);
Joerg Roedeldefbba52009-08-07 11:49:30 +02002815 hsave->save.rsp = vmcb->save.rsp;
2816 hsave->save.rax = vmcb->save.rax;
2817 if (npt_enabled)
2818 hsave->save.cr3 = vmcb->save.cr3;
2819 else
Avi Kivity9f8fe502010-12-05 17:30:00 +02002820 hsave->save.cr3 = kvm_read_cr3(&svm->vcpu);
Joerg Roedeldefbba52009-08-07 11:49:30 +02002821
Joerg Roedel0460a972009-08-07 11:49:31 +02002822 copy_vmcb_control_area(hsave, vmcb);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002823
Avi Kivityf6e78472010-08-02 15:30:20 +03002824 if (kvm_get_rflags(&svm->vcpu) & X86_EFLAGS_IF)
Alexander Graf3d6368e2008-11-25 20:17:07 +01002825 svm->vcpu.arch.hflags |= HF_HIF_MASK;
2826 else
2827 svm->vcpu.arch.hflags &= ~HF_HIF_MASK;
2828
Joerg Roedel4b161842010-09-10 17:31:03 +02002829 if (nested_vmcb->control.nested_ctl) {
2830 kvm_mmu_unload(&svm->vcpu);
2831 svm->nested.nested_cr3 = nested_vmcb->control.nested_cr3;
2832 nested_svm_init_mmu_context(&svm->vcpu);
2833 }
2834
Alexander Graf3d6368e2008-11-25 20:17:07 +01002835 /* Load the nested guest state */
2836 svm->vmcb->save.es = nested_vmcb->save.es;
2837 svm->vmcb->save.cs = nested_vmcb->save.cs;
2838 svm->vmcb->save.ss = nested_vmcb->save.ss;
2839 svm->vmcb->save.ds = nested_vmcb->save.ds;
2840 svm->vmcb->save.gdtr = nested_vmcb->save.gdtr;
2841 svm->vmcb->save.idtr = nested_vmcb->save.idtr;
Avi Kivityf6e78472010-08-02 15:30:20 +03002842 kvm_set_rflags(&svm->vcpu, nested_vmcb->save.rflags);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002843 svm_set_efer(&svm->vcpu, nested_vmcb->save.efer);
2844 svm_set_cr0(&svm->vcpu, nested_vmcb->save.cr0);
2845 svm_set_cr4(&svm->vcpu, nested_vmcb->save.cr4);
2846 if (npt_enabled) {
2847 svm->vmcb->save.cr3 = nested_vmcb->save.cr3;
2848 svm->vcpu.arch.cr3 = nested_vmcb->save.cr3;
Joerg Roedel0e5cbe32010-02-24 18:59:11 +01002849 } else
Avi Kivity23902182010-06-10 17:02:16 +03002850 (void)kvm_set_cr3(&svm->vcpu, nested_vmcb->save.cr3);
Joerg Roedel0e5cbe32010-02-24 18:59:11 +01002851
2852 /* Guest paging mode is active - reset mmu */
2853 kvm_mmu_reset_context(&svm->vcpu);
2854
Joerg Roedeldefbba52009-08-07 11:49:30 +02002855 svm->vmcb->save.cr2 = svm->vcpu.arch.cr2 = nested_vmcb->save.cr2;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002856 kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, nested_vmcb->save.rax);
2857 kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, nested_vmcb->save.rsp);
2858 kvm_register_write(&svm->vcpu, VCPU_REGS_RIP, nested_vmcb->save.rip);
Joerg Roedele0231712010-02-24 18:59:10 +01002859
Alexander Graf3d6368e2008-11-25 20:17:07 +01002860 /* In case we don't even reach vcpu_run, the fields are not updated */
2861 svm->vmcb->save.rax = nested_vmcb->save.rax;
2862 svm->vmcb->save.rsp = nested_vmcb->save.rsp;
2863 svm->vmcb->save.rip = nested_vmcb->save.rip;
2864 svm->vmcb->save.dr7 = nested_vmcb->save.dr7;
2865 svm->vmcb->save.dr6 = nested_vmcb->save.dr6;
2866 svm->vmcb->save.cpl = nested_vmcb->save.cpl;
2867
Joerg Roedelf7138532010-03-01 15:34:40 +01002868 svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa & ~0x0fffULL;
Joerg Roedelce2ac082010-03-01 15:34:39 +01002869 svm->nested.vmcb_iopm = nested_vmcb->control.iopm_base_pa & ~0x0fffULL;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002870
Joerg Roedelaad42c62009-08-07 11:49:34 +02002871 /* cache intercepts */
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01002872 svm->nested.intercept_cr = nested_vmcb->control.intercept_cr;
Joerg Roedel3aed0412010-11-30 18:03:58 +01002873 svm->nested.intercept_dr = nested_vmcb->control.intercept_dr;
Joerg Roedelaad42c62009-08-07 11:49:34 +02002874 svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions;
2875 svm->nested.intercept = nested_vmcb->control.intercept;
2876
Joerg Roedelf40f6a42010-12-03 15:25:15 +01002877 svm_flush_tlb(&svm->vcpu);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002878 svm->vmcb->control.int_ctl = nested_vmcb->control.int_ctl | V_INTR_MASKING_MASK;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002879 if (nested_vmcb->control.int_ctl & V_INTR_MASKING_MASK)
2880 svm->vcpu.arch.hflags |= HF_VINTR_MASK;
2881 else
2882 svm->vcpu.arch.hflags &= ~HF_VINTR_MASK;
2883
Joerg Roedel88ab24a2010-02-19 16:23:06 +01002884 if (svm->vcpu.arch.hflags & HF_VINTR_MASK) {
2885 /* We only want the cr8 intercept bits of the guest */
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01002886 clr_cr_intercept(svm, INTERCEPT_CR8_READ);
2887 clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
Joerg Roedel88ab24a2010-02-19 16:23:06 +01002888 }
2889
Joerg Roedel0d945bd2010-05-05 16:04:45 +02002890 /* We don't want to see VMMCALLs from a nested guest */
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01002891 clr_intercept(svm, INTERCEPT_VMMCALL);
Joerg Roedel0d945bd2010-05-05 16:04:45 +02002892
Joerg Roedel88ab24a2010-02-19 16:23:06 +01002893 svm->vmcb->control.lbr_ctl = nested_vmcb->control.lbr_ctl;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002894 svm->vmcb->control.int_vector = nested_vmcb->control.int_vector;
2895 svm->vmcb->control.int_state = nested_vmcb->control.int_state;
2896 svm->vmcb->control.tsc_offset += nested_vmcb->control.tsc_offset;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002897 svm->vmcb->control.event_inj = nested_vmcb->control.event_inj;
2898 svm->vmcb->control.event_inj_err = nested_vmcb->control.event_inj_err;
2899
Joerg Roedel7597f122010-02-19 16:23:00 +01002900 nested_svm_unmap(page);
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002901
Joerg Roedel20307532010-11-29 17:51:48 +01002902 /* Enter Guest-Mode */
2903 enter_guest_mode(&svm->vcpu);
2904
Joerg Roedel384c6362010-11-30 18:03:56 +01002905 /*
2906 * Merge guest and host intercepts - must be called with vcpu in
2907 * guest-mode to take affect here
2908 */
2909 recalc_intercepts(svm);
2910
Joerg Roedel06fc77722010-02-19 16:23:07 +01002911 svm->nested.vmcb = vmcb_gpa;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002912
Joerg Roedel2af91942009-08-07 11:49:28 +02002913 enable_gif(svm);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002914
Roedel, Joerg8d28fec2010-12-03 13:15:21 +01002915 mark_all_dirty(svm->vmcb);
2916
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002917 return true;
Alexander Graf3d6368e2008-11-25 20:17:07 +01002918}
2919
Joerg Roedel9966bf62009-08-07 11:49:40 +02002920static void nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb)
Alexander Graf55426752008-11-25 20:17:06 +01002921{
2922 to_vmcb->save.fs = from_vmcb->save.fs;
2923 to_vmcb->save.gs = from_vmcb->save.gs;
2924 to_vmcb->save.tr = from_vmcb->save.tr;
2925 to_vmcb->save.ldtr = from_vmcb->save.ldtr;
2926 to_vmcb->save.kernel_gs_base = from_vmcb->save.kernel_gs_base;
2927 to_vmcb->save.star = from_vmcb->save.star;
2928 to_vmcb->save.lstar = from_vmcb->save.lstar;
2929 to_vmcb->save.cstar = from_vmcb->save.cstar;
2930 to_vmcb->save.sfmask = from_vmcb->save.sfmask;
2931 to_vmcb->save.sysenter_cs = from_vmcb->save.sysenter_cs;
2932 to_vmcb->save.sysenter_esp = from_vmcb->save.sysenter_esp;
2933 to_vmcb->save.sysenter_eip = from_vmcb->save.sysenter_eip;
Alexander Graf55426752008-11-25 20:17:06 +01002934}
2935
Avi Kivity851ba692009-08-24 11:10:17 +03002936static int vmload_interception(struct vcpu_svm *svm)
Alexander Graf55426752008-11-25 20:17:06 +01002937{
Joerg Roedel9966bf62009-08-07 11:49:40 +02002938 struct vmcb *nested_vmcb;
Joerg Roedel7597f122010-02-19 16:23:00 +01002939 struct page *page;
Joerg Roedel9966bf62009-08-07 11:49:40 +02002940
Alexander Graf55426752008-11-25 20:17:06 +01002941 if (nested_svm_check_permissions(svm))
2942 return 1;
2943
Joerg Roedel7597f122010-02-19 16:23:00 +01002944 nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
Joerg Roedel9966bf62009-08-07 11:49:40 +02002945 if (!nested_vmcb)
2946 return 1;
2947
Joerg Roedele3e9ed32011-04-06 12:30:03 +02002948 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
2949 skip_emulated_instruction(&svm->vcpu);
2950
Joerg Roedel9966bf62009-08-07 11:49:40 +02002951 nested_svm_vmloadsave(nested_vmcb, svm->vmcb);
Joerg Roedel7597f122010-02-19 16:23:00 +01002952 nested_svm_unmap(page);
Alexander Graf55426752008-11-25 20:17:06 +01002953
2954 return 1;
2955}
2956
Avi Kivity851ba692009-08-24 11:10:17 +03002957static int vmsave_interception(struct vcpu_svm *svm)
Alexander Graf55426752008-11-25 20:17:06 +01002958{
Joerg Roedel9966bf62009-08-07 11:49:40 +02002959 struct vmcb *nested_vmcb;
Joerg Roedel7597f122010-02-19 16:23:00 +01002960 struct page *page;
Joerg Roedel9966bf62009-08-07 11:49:40 +02002961
Alexander Graf55426752008-11-25 20:17:06 +01002962 if (nested_svm_check_permissions(svm))
2963 return 1;
2964
Joerg Roedel7597f122010-02-19 16:23:00 +01002965 nested_vmcb = nested_svm_map(svm, svm->vmcb->save.rax, &page);
Joerg Roedel9966bf62009-08-07 11:49:40 +02002966 if (!nested_vmcb)
2967 return 1;
2968
Joerg Roedele3e9ed32011-04-06 12:30:03 +02002969 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
2970 skip_emulated_instruction(&svm->vcpu);
2971
Joerg Roedel9966bf62009-08-07 11:49:40 +02002972 nested_svm_vmloadsave(svm->vmcb, nested_vmcb);
Joerg Roedel7597f122010-02-19 16:23:00 +01002973 nested_svm_unmap(page);
Alexander Graf55426752008-11-25 20:17:06 +01002974
2975 return 1;
2976}
2977
Avi Kivity851ba692009-08-24 11:10:17 +03002978static int vmrun_interception(struct vcpu_svm *svm)
Alexander Graf3d6368e2008-11-25 20:17:07 +01002979{
Alexander Graf3d6368e2008-11-25 20:17:07 +01002980 if (nested_svm_check_permissions(svm))
2981 return 1;
2982
Roedel, Joergb75f4eb2010-09-03 14:21:40 +02002983 /* Save rip after vmrun instruction */
2984 kvm_rip_write(&svm->vcpu, kvm_rip_read(&svm->vcpu) + 3);
Alexander Graf3d6368e2008-11-25 20:17:07 +01002985
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002986 if (!nested_svm_vmrun(svm))
Alexander Graf3d6368e2008-11-25 20:17:07 +01002987 return 1;
2988
Joerg Roedel9738b2c2009-08-07 11:49:41 +02002989 if (!nested_svm_vmrun_msrpm(svm))
Joerg Roedel1f8da472009-08-07 11:49:43 +02002990 goto failed;
2991
2992 return 1;
2993
2994failed:
2995
2996 svm->vmcb->control.exit_code = SVM_EXIT_ERR;
2997 svm->vmcb->control.exit_code_hi = 0;
2998 svm->vmcb->control.exit_info_1 = 0;
2999 svm->vmcb->control.exit_info_2 = 0;
3000
3001 nested_svm_vmexit(svm);
Alexander Graf3d6368e2008-11-25 20:17:07 +01003002
3003 return 1;
3004}
3005
Avi Kivity851ba692009-08-24 11:10:17 +03003006static int stgi_interception(struct vcpu_svm *svm)
Alexander Graf1371d902008-11-25 20:17:04 +01003007{
3008 if (nested_svm_check_permissions(svm))
3009 return 1;
3010
3011 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
3012 skip_emulated_instruction(&svm->vcpu);
Avi Kivity3842d132010-07-27 12:30:24 +03003013 kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
Alexander Graf1371d902008-11-25 20:17:04 +01003014
Joerg Roedel2af91942009-08-07 11:49:28 +02003015 enable_gif(svm);
Alexander Graf1371d902008-11-25 20:17:04 +01003016
3017 return 1;
3018}
3019
Avi Kivity851ba692009-08-24 11:10:17 +03003020static int clgi_interception(struct vcpu_svm *svm)
Alexander Graf1371d902008-11-25 20:17:04 +01003021{
3022 if (nested_svm_check_permissions(svm))
3023 return 1;
3024
3025 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
3026 skip_emulated_instruction(&svm->vcpu);
3027
Joerg Roedel2af91942009-08-07 11:49:28 +02003028 disable_gif(svm);
Alexander Graf1371d902008-11-25 20:17:04 +01003029
3030 /* After a CLGI no interrupts should come */
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -05003031 if (!kvm_vcpu_apicv_active(&svm->vcpu)) {
3032 svm_clear_vintr(svm);
3033 svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
3034 mark_dirty(svm->vmcb, VMCB_INTR);
3035 }
Joerg Roedeldecdbf62010-12-03 11:45:52 +01003036
Alexander Graf1371d902008-11-25 20:17:04 +01003037 return 1;
3038}
3039
Avi Kivity851ba692009-08-24 11:10:17 +03003040static int invlpga_interception(struct vcpu_svm *svm)
Alexander Grafff092382009-06-15 15:21:24 +02003041{
3042 struct kvm_vcpu *vcpu = &svm->vcpu;
Alexander Grafff092382009-06-15 15:21:24 +02003043
David Kaplan668f1982015-02-20 16:02:10 -06003044 trace_kvm_invlpga(svm->vmcb->save.rip, kvm_register_read(&svm->vcpu, VCPU_REGS_RCX),
3045 kvm_register_read(&svm->vcpu, VCPU_REGS_RAX));
Joerg Roedelec1ff792009-10-09 16:08:31 +02003046
Alexander Grafff092382009-06-15 15:21:24 +02003047 /* Let's treat INVLPGA the same as INVLPG (can be optimized!) */
David Kaplan668f1982015-02-20 16:02:10 -06003048 kvm_mmu_invlpg(vcpu, kvm_register_read(&svm->vcpu, VCPU_REGS_RAX));
Alexander Grafff092382009-06-15 15:21:24 +02003049
3050 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
3051 skip_emulated_instruction(&svm->vcpu);
3052 return 1;
3053}
3054
Joerg Roedel532a46b2009-10-09 16:08:32 +02003055static int skinit_interception(struct vcpu_svm *svm)
3056{
David Kaplan668f1982015-02-20 16:02:10 -06003057 trace_kvm_skinit(svm->vmcb->save.rip, kvm_register_read(&svm->vcpu, VCPU_REGS_RAX));
Joerg Roedel532a46b2009-10-09 16:08:32 +02003058
3059 kvm_queue_exception(&svm->vcpu, UD_VECTOR);
3060 return 1;
3061}
3062
David Kaplandab429a2015-03-02 13:43:37 -06003063static int wbinvd_interception(struct vcpu_svm *svm)
3064{
3065 kvm_emulate_wbinvd(&svm->vcpu);
3066 return 1;
3067}
3068
Joerg Roedel81dd35d2010-12-07 17:15:06 +01003069static int xsetbv_interception(struct vcpu_svm *svm)
3070{
3071 u64 new_bv = kvm_read_edx_eax(&svm->vcpu);
3072 u32 index = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
3073
3074 if (kvm_set_xcr(&svm->vcpu, index, new_bv) == 0) {
3075 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
3076 skip_emulated_instruction(&svm->vcpu);
3077 }
3078
3079 return 1;
3080}
3081
Avi Kivity851ba692009-08-24 11:10:17 +03003082static int task_switch_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003083{
Izik Eidus37817f22008-03-24 23:14:53 +02003084 u16 tss_selector;
Gleb Natapov64a7ec02009-03-30 16:03:29 +03003085 int reason;
3086 int int_type = svm->vmcb->control.exit_int_info &
3087 SVM_EXITINTINFO_TYPE_MASK;
Gleb Natapov8317c292009-04-12 13:37:02 +03003088 int int_vec = svm->vmcb->control.exit_int_info & SVM_EVTINJ_VEC_MASK;
Gleb Natapovfe8e7f82009-04-23 17:03:48 +03003089 uint32_t type =
3090 svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
3091 uint32_t idt_v =
3092 svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID;
Jan Kiszkae269fb22010-04-14 15:51:09 +02003093 bool has_error_code = false;
3094 u32 error_code = 0;
Izik Eidus37817f22008-03-24 23:14:53 +02003095
3096 tss_selector = (u16)svm->vmcb->control.exit_info_1;
Gleb Natapov64a7ec02009-03-30 16:03:29 +03003097
Izik Eidus37817f22008-03-24 23:14:53 +02003098 if (svm->vmcb->control.exit_info_2 &
3099 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
Gleb Natapov64a7ec02009-03-30 16:03:29 +03003100 reason = TASK_SWITCH_IRET;
3101 else if (svm->vmcb->control.exit_info_2 &
3102 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
3103 reason = TASK_SWITCH_JMP;
Gleb Natapovfe8e7f82009-04-23 17:03:48 +03003104 else if (idt_v)
Gleb Natapov64a7ec02009-03-30 16:03:29 +03003105 reason = TASK_SWITCH_GATE;
3106 else
3107 reason = TASK_SWITCH_CALL;
3108
Gleb Natapovfe8e7f82009-04-23 17:03:48 +03003109 if (reason == TASK_SWITCH_GATE) {
3110 switch (type) {
3111 case SVM_EXITINTINFO_TYPE_NMI:
3112 svm->vcpu.arch.nmi_injected = false;
3113 break;
3114 case SVM_EXITINTINFO_TYPE_EXEPT:
Jan Kiszkae269fb22010-04-14 15:51:09 +02003115 if (svm->vmcb->control.exit_info_2 &
3116 (1ULL << SVM_EXITINFOSHIFT_TS_HAS_ERROR_CODE)) {
3117 has_error_code = true;
3118 error_code =
3119 (u32)svm->vmcb->control.exit_info_2;
3120 }
Gleb Natapovfe8e7f82009-04-23 17:03:48 +03003121 kvm_clear_exception_queue(&svm->vcpu);
3122 break;
3123 case SVM_EXITINTINFO_TYPE_INTR:
3124 kvm_clear_interrupt_queue(&svm->vcpu);
3125 break;
3126 default:
3127 break;
3128 }
3129 }
Gleb Natapov64a7ec02009-03-30 16:03:29 +03003130
Gleb Natapov8317c292009-04-12 13:37:02 +03003131 if (reason != TASK_SWITCH_GATE ||
3132 int_type == SVM_EXITINTINFO_TYPE_SOFT ||
3133 (int_type == SVM_EXITINTINFO_TYPE_EXEPT &&
Gleb Natapovf629cf82009-05-11 13:35:49 +03003134 (int_vec == OF_VECTOR || int_vec == BP_VECTOR)))
3135 skip_emulated_instruction(&svm->vcpu);
Gleb Natapov64a7ec02009-03-30 16:03:29 +03003136
Kevin Wolf7f3d35f2012-02-08 14:34:38 +01003137 if (int_type != SVM_EXITINTINFO_TYPE_SOFT)
3138 int_vec = -1;
3139
3140 if (kvm_task_switch(&svm->vcpu, tss_selector, int_vec, reason,
Gleb Natapovacb54512010-04-15 21:03:50 +03003141 has_error_code, error_code) == EMULATE_FAIL) {
3142 svm->vcpu.run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
3143 svm->vcpu.run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
3144 svm->vcpu.run->internal.ndata = 0;
3145 return 0;
3146 }
3147 return 1;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003148}
3149
Avi Kivity851ba692009-08-24 11:10:17 +03003150static int cpuid_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003151{
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03003152 svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
Rusty Russelle756fc62007-07-30 20:07:08 +10003153 kvm_emulate_cpuid(&svm->vcpu);
Avi Kivity06465c52007-02-28 20:46:53 +02003154 return 1;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003155}
3156
Avi Kivity851ba692009-08-24 11:10:17 +03003157static int iret_interception(struct vcpu_svm *svm)
Gleb Natapov95ba8273132009-04-21 17:45:08 +03003158{
3159 ++svm->vcpu.stat.nmi_window_exits;
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01003160 clr_intercept(svm, INTERCEPT_IRET);
Gleb Natapov44c11432009-05-11 13:35:52 +03003161 svm->vcpu.arch.hflags |= HF_IRET_MASK;
Avi Kivitybd3d1ec2011-02-03 15:29:52 +02003162 svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
Radim Krčmářf303b4c2014-01-17 20:52:42 +01003163 kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
Gleb Natapov95ba8273132009-04-21 17:45:08 +03003164 return 1;
3165}
3166
Avi Kivity851ba692009-08-24 11:10:17 +03003167static int invlpg_interception(struct vcpu_svm *svm)
Marcelo Tosattia7052892008-09-23 13:18:35 -03003168{
Andre Przywaradf4f31082010-12-21 11:12:06 +01003169 if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
3170 return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
3171
3172 kvm_mmu_invlpg(&svm->vcpu, svm->vmcb->control.exit_info_1);
3173 skip_emulated_instruction(&svm->vcpu);
3174 return 1;
Marcelo Tosattia7052892008-09-23 13:18:35 -03003175}
3176
Avi Kivity851ba692009-08-24 11:10:17 +03003177static int emulate_on_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003178{
Andre Przywara51d8b662010-12-21 11:12:02 +01003179 return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003180}
3181
Avi Kivity332b56e2011-11-10 14:57:24 +02003182static int rdpmc_interception(struct vcpu_svm *svm)
3183{
3184 int err;
3185
3186 if (!static_cpu_has(X86_FEATURE_NRIPS))
3187 return emulate_on_interception(svm);
3188
3189 err = kvm_rdpmc(&svm->vcpu);
3190 kvm_complete_insn_gp(&svm->vcpu, err);
3191
3192 return 1;
3193}
3194
Xiubo Li52eb5a62015-03-13 17:39:45 +08003195static bool check_selective_cr0_intercepted(struct vcpu_svm *svm,
3196 unsigned long val)
Joerg Roedel628afd22011-04-04 12:39:36 +02003197{
3198 unsigned long cr0 = svm->vcpu.arch.cr0;
3199 bool ret = false;
3200 u64 intercept;
3201
3202 intercept = svm->nested.intercept;
3203
3204 if (!is_guest_mode(&svm->vcpu) ||
3205 (!(intercept & (1ULL << INTERCEPT_SELECTIVE_CR0))))
3206 return false;
3207
3208 cr0 &= ~SVM_CR0_SELECTIVE_MASK;
3209 val &= ~SVM_CR0_SELECTIVE_MASK;
3210
3211 if (cr0 ^ val) {
3212 svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE;
3213 ret = (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE);
3214 }
3215
3216 return ret;
3217}
3218
Andre Przywara7ff76d52010-12-21 11:12:04 +01003219#define CR_VALID (1ULL << 63)
3220
3221static int cr_interception(struct vcpu_svm *svm)
3222{
3223 int reg, cr;
3224 unsigned long val;
3225 int err;
3226
3227 if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
3228 return emulate_on_interception(svm);
3229
3230 if (unlikely((svm->vmcb->control.exit_info_1 & CR_VALID) == 0))
3231 return emulate_on_interception(svm);
3232
3233 reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
David Kaplan5e575182015-03-06 14:44:35 -06003234 if (svm->vmcb->control.exit_code == SVM_EXIT_CR0_SEL_WRITE)
3235 cr = SVM_EXIT_WRITE_CR0 - SVM_EXIT_READ_CR0;
3236 else
3237 cr = svm->vmcb->control.exit_code - SVM_EXIT_READ_CR0;
Andre Przywara7ff76d52010-12-21 11:12:04 +01003238
3239 err = 0;
3240 if (cr >= 16) { /* mov to cr */
3241 cr -= 16;
3242 val = kvm_register_read(&svm->vcpu, reg);
3243 switch (cr) {
3244 case 0:
Joerg Roedel628afd22011-04-04 12:39:36 +02003245 if (!check_selective_cr0_intercepted(svm, val))
3246 err = kvm_set_cr0(&svm->vcpu, val);
Joerg Roedel977b2d02011-04-18 11:42:52 +02003247 else
3248 return 1;
3249
Andre Przywara7ff76d52010-12-21 11:12:04 +01003250 break;
3251 case 3:
3252 err = kvm_set_cr3(&svm->vcpu, val);
3253 break;
3254 case 4:
3255 err = kvm_set_cr4(&svm->vcpu, val);
3256 break;
3257 case 8:
3258 err = kvm_set_cr8(&svm->vcpu, val);
3259 break;
3260 default:
3261 WARN(1, "unhandled write to CR%d", cr);
3262 kvm_queue_exception(&svm->vcpu, UD_VECTOR);
3263 return 1;
3264 }
3265 } else { /* mov from cr */
3266 switch (cr) {
3267 case 0:
3268 val = kvm_read_cr0(&svm->vcpu);
3269 break;
3270 case 2:
3271 val = svm->vcpu.arch.cr2;
3272 break;
3273 case 3:
Avi Kivity9f8fe502010-12-05 17:30:00 +02003274 val = kvm_read_cr3(&svm->vcpu);
Andre Przywara7ff76d52010-12-21 11:12:04 +01003275 break;
3276 case 4:
3277 val = kvm_read_cr4(&svm->vcpu);
3278 break;
3279 case 8:
3280 val = kvm_get_cr8(&svm->vcpu);
3281 break;
3282 default:
3283 WARN(1, "unhandled read from CR%d", cr);
3284 kvm_queue_exception(&svm->vcpu, UD_VECTOR);
3285 return 1;
3286 }
3287 kvm_register_write(&svm->vcpu, reg, val);
3288 }
3289 kvm_complete_insn_gp(&svm->vcpu, err);
3290
3291 return 1;
3292}
3293
Andre Przywaracae37972010-12-21 11:12:05 +01003294static int dr_interception(struct vcpu_svm *svm)
3295{
3296 int reg, dr;
3297 unsigned long val;
Andre Przywaracae37972010-12-21 11:12:05 +01003298
Paolo Bonzinifacb0132014-02-21 10:32:27 +01003299 if (svm->vcpu.guest_debug == 0) {
3300 /*
3301 * No more DR vmexits; force a reload of the debug registers
3302 * and reenter on this instruction. The next vmexit will
3303 * retrieve the full state of the debug registers.
3304 */
3305 clr_dr_intercepts(svm);
3306 svm->vcpu.arch.switch_db_regs |= KVM_DEBUGREG_WONT_EXIT;
3307 return 1;
3308 }
3309
Andre Przywaracae37972010-12-21 11:12:05 +01003310 if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS))
3311 return emulate_on_interception(svm);
3312
3313 reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
3314 dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0;
3315
3316 if (dr >= 16) { /* mov to DRn */
Nadav Amit16f8a6f2014-10-03 01:10:05 +03003317 if (!kvm_require_dr(&svm->vcpu, dr - 16))
3318 return 1;
Andre Przywaracae37972010-12-21 11:12:05 +01003319 val = kvm_register_read(&svm->vcpu, reg);
3320 kvm_set_dr(&svm->vcpu, dr - 16, val);
3321 } else {
Nadav Amit16f8a6f2014-10-03 01:10:05 +03003322 if (!kvm_require_dr(&svm->vcpu, dr))
3323 return 1;
3324 kvm_get_dr(&svm->vcpu, dr, &val);
3325 kvm_register_write(&svm->vcpu, reg, val);
Andre Przywaracae37972010-12-21 11:12:05 +01003326 }
3327
Joerg Roedel2c46d2a2011-02-09 18:29:39 +01003328 skip_emulated_instruction(&svm->vcpu);
3329
Andre Przywaracae37972010-12-21 11:12:05 +01003330 return 1;
3331}
3332
Avi Kivity851ba692009-08-24 11:10:17 +03003333static int cr8_write_interception(struct vcpu_svm *svm)
Joerg Roedel1d075432007-12-06 21:02:25 +01003334{
Avi Kivity851ba692009-08-24 11:10:17 +03003335 struct kvm_run *kvm_run = svm->vcpu.run;
Andre Przywaraeea1cff2010-12-21 11:12:00 +01003336 int r;
Avi Kivity851ba692009-08-24 11:10:17 +03003337
Gleb Natapov0a5fff192009-04-21 17:45:06 +03003338 u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
3339 /* instruction emulation calls kvm_set_cr8() */
Andre Przywara7ff76d52010-12-21 11:12:04 +01003340 r = cr_interception(svm);
Paolo Bonzini35754c92015-07-29 12:05:37 +02003341 if (lapic_in_kernel(&svm->vcpu))
Andre Przywara7ff76d52010-12-21 11:12:04 +01003342 return r;
Gleb Natapov0a5fff192009-04-21 17:45:06 +03003343 if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
Andre Przywara7ff76d52010-12-21 11:12:04 +01003344 return r;
Joerg Roedel1d075432007-12-06 21:02:25 +01003345 kvm_run->exit_reason = KVM_EXIT_SET_TPR;
3346 return 0;
3347}
3348
Paolo Bonzini48d89b92014-08-26 13:27:46 +02003349static u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
Nadav Har'Eld5c17852011-08-02 15:54:20 +03003350{
3351 struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
Haozhong Zhang4ba76532015-10-20 15:39:07 +08003352 return vmcb->control.tsc_offset + host_tsc;
Nadav Har'Eld5c17852011-08-02 15:54:20 +03003353}
3354
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003355static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003356{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003357 struct vcpu_svm *svm = to_svm(vcpu);
3358
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003359 switch (msr_info->index) {
Jaswinder Singh Rajputaf24a4e2009-05-15 18:42:05 +05303360 case MSR_IA32_TSC: {
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003361 msr_info->data = svm->vmcb->control.tsc_offset +
Haozhong Zhang35181e82015-10-20 15:39:03 +08003362 kvm_scale_tsc(vcpu, rdtsc());
Joerg Roedelfbc0db72011-03-25 09:44:46 +01003363
Avi Kivity6aa8b732006-12-10 02:21:36 -08003364 break;
3365 }
Brian Gerst8c065852010-07-17 09:03:26 -04003366 case MSR_STAR:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003367 msr_info->data = svm->vmcb->save.star;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003368 break;
Avi Kivity0e859ca2006-12-22 01:05:08 -08003369#ifdef CONFIG_X86_64
Avi Kivity6aa8b732006-12-10 02:21:36 -08003370 case MSR_LSTAR:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003371 msr_info->data = svm->vmcb->save.lstar;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003372 break;
3373 case MSR_CSTAR:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003374 msr_info->data = svm->vmcb->save.cstar;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003375 break;
3376 case MSR_KERNEL_GS_BASE:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003377 msr_info->data = svm->vmcb->save.kernel_gs_base;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003378 break;
3379 case MSR_SYSCALL_MASK:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003380 msr_info->data = svm->vmcb->save.sfmask;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003381 break;
3382#endif
3383 case MSR_IA32_SYSENTER_CS:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003384 msr_info->data = svm->vmcb->save.sysenter_cs;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003385 break;
3386 case MSR_IA32_SYSENTER_EIP:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003387 msr_info->data = svm->sysenter_eip;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003388 break;
3389 case MSR_IA32_SYSENTER_ESP:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003390 msr_info->data = svm->sysenter_esp;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003391 break;
Paolo Bonzini46896c72015-11-12 14:49:16 +01003392 case MSR_TSC_AUX:
3393 if (!boot_cpu_has(X86_FEATURE_RDTSCP))
3394 return 1;
3395 msr_info->data = svm->tsc_aux;
3396 break;
Joerg Roedele0231712010-02-24 18:59:10 +01003397 /*
3398 * Nobody will change the following 5 values in the VMCB so we can
3399 * safely return them on rdmsr. They will always be 0 until LBRV is
3400 * implemented.
3401 */
Joerg Roedela2938c82008-02-13 16:30:28 +01003402 case MSR_IA32_DEBUGCTLMSR:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003403 msr_info->data = svm->vmcb->save.dbgctl;
Joerg Roedela2938c82008-02-13 16:30:28 +01003404 break;
3405 case MSR_IA32_LASTBRANCHFROMIP:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003406 msr_info->data = svm->vmcb->save.br_from;
Joerg Roedela2938c82008-02-13 16:30:28 +01003407 break;
3408 case MSR_IA32_LASTBRANCHTOIP:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003409 msr_info->data = svm->vmcb->save.br_to;
Joerg Roedela2938c82008-02-13 16:30:28 +01003410 break;
3411 case MSR_IA32_LASTINTFROMIP:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003412 msr_info->data = svm->vmcb->save.last_excp_from;
Joerg Roedela2938c82008-02-13 16:30:28 +01003413 break;
3414 case MSR_IA32_LASTINTTOIP:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003415 msr_info->data = svm->vmcb->save.last_excp_to;
Joerg Roedela2938c82008-02-13 16:30:28 +01003416 break;
Alexander Grafb286d5d2008-11-25 20:17:05 +01003417 case MSR_VM_HSAVE_PA:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003418 msr_info->data = svm->nested.hsave_msr;
Alexander Grafb286d5d2008-11-25 20:17:05 +01003419 break;
Joerg Roedeleb6f3022008-11-25 20:17:09 +01003420 case MSR_VM_CR:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003421 msr_info->data = svm->nested.vm_cr_msr;
Joerg Roedeleb6f3022008-11-25 20:17:09 +01003422 break;
Alexander Grafc8a73f12009-01-05 16:02:47 +01003423 case MSR_IA32_UCODE_REV:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003424 msr_info->data = 0x01000065;
Alexander Grafc8a73f12009-01-05 16:02:47 +01003425 break;
Borislav Petkovae8b7872015-11-23 11:12:23 +01003426 case MSR_F15H_IC_CFG: {
3427
3428 int family, model;
3429
3430 family = guest_cpuid_family(vcpu);
3431 model = guest_cpuid_model(vcpu);
3432
3433 if (family < 0 || model < 0)
3434 return kvm_get_msr_common(vcpu, msr_info);
3435
3436 msr_info->data = 0;
3437
3438 if (family == 0x15 &&
3439 (model >= 0x2 && model < 0x20))
3440 msr_info->data = 0x1E;
3441 }
3442 break;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003443 default:
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003444 return kvm_get_msr_common(vcpu, msr_info);
Avi Kivity6aa8b732006-12-10 02:21:36 -08003445 }
3446 return 0;
3447}
3448
Avi Kivity851ba692009-08-24 11:10:17 +03003449static int rdmsr_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003450{
David Kaplan668f1982015-02-20 16:02:10 -06003451 u32 ecx = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003452 struct msr_data msr_info;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003453
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003454 msr_info.index = ecx;
3455 msr_info.host_initiated = false;
3456 if (svm_get_msr(&svm->vcpu, &msr_info)) {
Avi Kivity59200272010-01-25 19:47:02 +02003457 trace_kvm_msr_read_ex(ecx);
Avi Kivityc1a5d4f2007-11-25 14:12:03 +02003458 kvm_inject_gp(&svm->vcpu, 0);
Avi Kivity59200272010-01-25 19:47:02 +02003459 } else {
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003460 trace_kvm_msr_read(ecx, msr_info.data);
Joerg Roedelaf9ca2d2008-04-30 17:56:03 +02003461
Paolo Bonzini609e36d2015-04-08 15:30:38 +02003462 kvm_register_write(&svm->vcpu, VCPU_REGS_RAX,
3463 msr_info.data & 0xffffffff);
3464 kvm_register_write(&svm->vcpu, VCPU_REGS_RDX,
3465 msr_info.data >> 32);
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03003466 svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
Rusty Russelle756fc62007-07-30 20:07:08 +10003467 skip_emulated_instruction(&svm->vcpu);
Avi Kivity6aa8b732006-12-10 02:21:36 -08003468 }
3469 return 1;
3470}
3471
Joerg Roedel4a810182010-02-24 18:59:15 +01003472static int svm_set_vm_cr(struct kvm_vcpu *vcpu, u64 data)
3473{
3474 struct vcpu_svm *svm = to_svm(vcpu);
3475 int svm_dis, chg_mask;
3476
3477 if (data & ~SVM_VM_CR_VALID_MASK)
3478 return 1;
3479
3480 chg_mask = SVM_VM_CR_VALID_MASK;
3481
3482 if (svm->nested.vm_cr_msr & SVM_VM_CR_SVM_DIS_MASK)
3483 chg_mask &= ~(SVM_VM_CR_SVM_LOCK_MASK | SVM_VM_CR_SVM_DIS_MASK);
3484
3485 svm->nested.vm_cr_msr &= ~chg_mask;
3486 svm->nested.vm_cr_msr |= (data & chg_mask);
3487
3488 svm_dis = svm->nested.vm_cr_msr & SVM_VM_CR_SVM_DIS_MASK;
3489
3490 /* check for svm_disable while efer.svme is set */
3491 if (svm_dis && (vcpu->arch.efer & EFER_SVME))
3492 return 1;
3493
3494 return 0;
3495}
3496
Will Auld8fe8ab42012-11-29 12:42:12 -08003497static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003498{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003499 struct vcpu_svm *svm = to_svm(vcpu);
3500
Will Auld8fe8ab42012-11-29 12:42:12 -08003501 u32 ecx = msr->index;
3502 u64 data = msr->data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003503 switch (ecx) {
Zachary Amsdenf4e1b3c2010-08-19 22:07:16 -10003504 case MSR_IA32_TSC:
Will Auld8fe8ab42012-11-29 12:42:12 -08003505 kvm_write_tsc(vcpu, msr);
Avi Kivity6aa8b732006-12-10 02:21:36 -08003506 break;
Brian Gerst8c065852010-07-17 09:03:26 -04003507 case MSR_STAR:
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003508 svm->vmcb->save.star = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003509 break;
Robert P. J. Day49b14f22007-01-29 13:19:50 -08003510#ifdef CONFIG_X86_64
Avi Kivity6aa8b732006-12-10 02:21:36 -08003511 case MSR_LSTAR:
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003512 svm->vmcb->save.lstar = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003513 break;
3514 case MSR_CSTAR:
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003515 svm->vmcb->save.cstar = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003516 break;
3517 case MSR_KERNEL_GS_BASE:
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003518 svm->vmcb->save.kernel_gs_base = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003519 break;
3520 case MSR_SYSCALL_MASK:
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003521 svm->vmcb->save.sfmask = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003522 break;
3523#endif
3524 case MSR_IA32_SYSENTER_CS:
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003525 svm->vmcb->save.sysenter_cs = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003526 break;
3527 case MSR_IA32_SYSENTER_EIP:
Andre Przywara017cb992009-05-28 11:56:31 +02003528 svm->sysenter_eip = data;
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003529 svm->vmcb->save.sysenter_eip = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003530 break;
3531 case MSR_IA32_SYSENTER_ESP:
Andre Przywara017cb992009-05-28 11:56:31 +02003532 svm->sysenter_esp = data;
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04003533 svm->vmcb->save.sysenter_esp = data;
Avi Kivity6aa8b732006-12-10 02:21:36 -08003534 break;
Paolo Bonzini46896c72015-11-12 14:49:16 +01003535 case MSR_TSC_AUX:
3536 if (!boot_cpu_has(X86_FEATURE_RDTSCP))
3537 return 1;
3538
3539 /*
3540 * This is rare, so we update the MSR here instead of using
3541 * direct_access_msrs. Doing that would require a rdmsr in
3542 * svm_vcpu_put.
3543 */
3544 svm->tsc_aux = data;
3545 wrmsrl(MSR_TSC_AUX, svm->tsc_aux);
3546 break;
Joerg Roedela2938c82008-02-13 16:30:28 +01003547 case MSR_IA32_DEBUGCTLMSR:
Avi Kivity2a6b20b2010-11-09 16:15:42 +02003548 if (!boot_cpu_has(X86_FEATURE_LBRV)) {
Christoffer Dalla737f252012-06-03 21:17:48 +03003549 vcpu_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTL 0x%llx, nop\n",
3550 __func__, data);
Joerg Roedel24e09cb2008-02-13 18:58:47 +01003551 break;
3552 }
3553 if (data & DEBUGCTL_RESERVED_BITS)
3554 return 1;
3555
3556 svm->vmcb->save.dbgctl = data;
Joerg Roedelb53ba3f2010-12-03 11:45:59 +01003557 mark_dirty(svm->vmcb, VMCB_LBR);
Joerg Roedel24e09cb2008-02-13 18:58:47 +01003558 if (data & (1ULL<<0))
3559 svm_enable_lbrv(svm);
3560 else
3561 svm_disable_lbrv(svm);
Joerg Roedela2938c82008-02-13 16:30:28 +01003562 break;
Alexander Grafb286d5d2008-11-25 20:17:05 +01003563 case MSR_VM_HSAVE_PA:
Joerg Roedele6aa9ab2009-08-07 11:49:33 +02003564 svm->nested.hsave_msr = data;
Alexander Grafb286d5d2008-11-25 20:17:05 +01003565 break;
Alexander Graf3c5d0a42009-06-15 15:21:23 +02003566 case MSR_VM_CR:
Joerg Roedel4a810182010-02-24 18:59:15 +01003567 return svm_set_vm_cr(vcpu, data);
Alexander Graf3c5d0a42009-06-15 15:21:23 +02003568 case MSR_VM_IGNNE:
Christoffer Dalla737f252012-06-03 21:17:48 +03003569 vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
Alexander Graf3c5d0a42009-06-15 15:21:23 +02003570 break;
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05003571 case MSR_IA32_APICBASE:
3572 if (kvm_vcpu_apicv_active(vcpu))
3573 avic_update_vapic_bar(to_svm(vcpu), data);
3574 /* Follow through */
Avi Kivity6aa8b732006-12-10 02:21:36 -08003575 default:
Will Auld8fe8ab42012-11-29 12:42:12 -08003576 return kvm_set_msr_common(vcpu, msr);
Avi Kivity6aa8b732006-12-10 02:21:36 -08003577 }
3578 return 0;
3579}
3580
Avi Kivity851ba692009-08-24 11:10:17 +03003581static int wrmsr_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003582{
Will Auld8fe8ab42012-11-29 12:42:12 -08003583 struct msr_data msr;
David Kaplan668f1982015-02-20 16:02:10 -06003584 u32 ecx = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
3585 u64 data = kvm_read_edx_eax(&svm->vcpu);
Joerg Roedelaf9ca2d2008-04-30 17:56:03 +02003586
Will Auld8fe8ab42012-11-29 12:42:12 -08003587 msr.data = data;
3588 msr.index = ecx;
3589 msr.host_initiated = false;
Joerg Roedelaf9ca2d2008-04-30 17:56:03 +02003590
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03003591 svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
Nadav Amit854e8bb2014-09-16 03:24:05 +03003592 if (kvm_set_msr(&svm->vcpu, &msr)) {
Avi Kivity59200272010-01-25 19:47:02 +02003593 trace_kvm_msr_write_ex(ecx, data);
Avi Kivityc1a5d4f2007-11-25 14:12:03 +02003594 kvm_inject_gp(&svm->vcpu, 0);
Avi Kivity59200272010-01-25 19:47:02 +02003595 } else {
3596 trace_kvm_msr_write(ecx, data);
Rusty Russelle756fc62007-07-30 20:07:08 +10003597 skip_emulated_instruction(&svm->vcpu);
Avi Kivity59200272010-01-25 19:47:02 +02003598 }
Avi Kivity6aa8b732006-12-10 02:21:36 -08003599 return 1;
3600}
3601
Avi Kivity851ba692009-08-24 11:10:17 +03003602static int msr_interception(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08003603{
Rusty Russelle756fc62007-07-30 20:07:08 +10003604 if (svm->vmcb->control.exit_info_1)
Avi Kivity851ba692009-08-24 11:10:17 +03003605 return wrmsr_interception(svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08003606 else
Avi Kivity851ba692009-08-24 11:10:17 +03003607 return rdmsr_interception(svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08003608}
3609
Avi Kivity851ba692009-08-24 11:10:17 +03003610static int interrupt_window_interception(struct vcpu_svm *svm)
Dor Laorc1150d82007-01-05 16:36:24 -08003611{
Avi Kivity3842d132010-07-27 12:30:24 +03003612 kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
Alexander Graff0b85052008-11-25 20:17:01 +01003613 svm_clear_vintr(svm);
Eddie Dong85f455f2007-07-06 12:20:49 +03003614 svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
Joerg Roedeldecdbf62010-12-03 11:45:52 +01003615 mark_dirty(svm->vmcb, VMCB_INTR);
Jason Wang675acb72012-03-08 18:07:56 +08003616 ++svm->vcpu.stat.irq_window_exits;
Dor Laorc1150d82007-01-05 16:36:24 -08003617 return 1;
3618}
3619
Mark Langsdorf565d0992009-10-06 14:25:02 -05003620static int pause_interception(struct vcpu_svm *svm)
3621{
3622 kvm_vcpu_on_spin(&(svm->vcpu));
3623 return 1;
3624}
3625
Gabriel L. Somlo87c00572014-05-07 16:52:13 -04003626static int nop_interception(struct vcpu_svm *svm)
3627{
3628 skip_emulated_instruction(&(svm->vcpu));
3629 return 1;
3630}
3631
3632static int monitor_interception(struct vcpu_svm *svm)
3633{
3634 printk_once(KERN_WARNING "kvm: MONITOR instruction emulated as NOP!\n");
3635 return nop_interception(svm);
3636}
3637
3638static int mwait_interception(struct vcpu_svm *svm)
3639{
3640 printk_once(KERN_WARNING "kvm: MWAIT instruction emulated as NOP!\n");
3641 return nop_interception(svm);
3642}
3643
Suravee Suthikulpanit18f40c52016-05-04 14:09:48 -05003644enum avic_ipi_failure_cause {
3645 AVIC_IPI_FAILURE_INVALID_INT_TYPE,
3646 AVIC_IPI_FAILURE_TARGET_NOT_RUNNING,
3647 AVIC_IPI_FAILURE_INVALID_TARGET,
3648 AVIC_IPI_FAILURE_INVALID_BACKING_PAGE,
3649};
3650
3651static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
3652{
3653 u32 icrh = svm->vmcb->control.exit_info_1 >> 32;
3654 u32 icrl = svm->vmcb->control.exit_info_1;
3655 u32 id = svm->vmcb->control.exit_info_2 >> 32;
Dan Carpenter5446a972016-05-23 13:20:10 +03003656 u32 index = svm->vmcb->control.exit_info_2 & 0xFF;
Suravee Suthikulpanit18f40c52016-05-04 14:09:48 -05003657 struct kvm_lapic *apic = svm->vcpu.arch.apic;
3658
3659 trace_kvm_avic_incomplete_ipi(svm->vcpu.vcpu_id, icrh, icrl, id, index);
3660
3661 switch (id) {
3662 case AVIC_IPI_FAILURE_INVALID_INT_TYPE:
3663 /*
3664 * AVIC hardware handles the generation of
3665 * IPIs when the specified Message Type is Fixed
3666 * (also known as fixed delivery mode) and
3667 * the Trigger Mode is edge-triggered. The hardware
3668 * also supports self and broadcast delivery modes
3669 * specified via the Destination Shorthand(DSH)
3670 * field of the ICRL. Logical and physical APIC ID
3671 * formats are supported. All other IPI types cause
3672 * a #VMEXIT, which needs to emulated.
3673 */
3674 kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
3675 kvm_lapic_reg_write(apic, APIC_ICR, icrl);
3676 break;
3677 case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
3678 int i;
3679 struct kvm_vcpu *vcpu;
3680 struct kvm *kvm = svm->vcpu.kvm;
3681 struct kvm_lapic *apic = svm->vcpu.arch.apic;
3682
3683 /*
3684 * At this point, we expect that the AVIC HW has already
3685 * set the appropriate IRR bits on the valid target
3686 * vcpus. So, we just need to kick the appropriate vcpu.
3687 */
3688 kvm_for_each_vcpu(i, vcpu, kvm) {
3689 bool m = kvm_apic_match_dest(vcpu, apic,
3690 icrl & KVM_APIC_SHORT_MASK,
3691 GET_APIC_DEST_FIELD(icrh),
3692 icrl & KVM_APIC_DEST_MASK);
3693
3694 if (m && !avic_vcpu_is_running(vcpu))
3695 kvm_vcpu_wake_up(vcpu);
3696 }
3697 break;
3698 }
3699 case AVIC_IPI_FAILURE_INVALID_TARGET:
3700 break;
3701 case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
3702 WARN_ONCE(1, "Invalid backing page\n");
3703 break;
3704 default:
3705 pr_err("Unknown IPI interception\n");
3706 }
3707
3708 return 1;
3709}
3710
3711static u32 *avic_get_logical_id_entry(struct kvm_vcpu *vcpu, u32 ldr, bool flat)
3712{
3713 struct kvm_arch *vm_data = &vcpu->kvm->arch;
3714 int index;
3715 u32 *logical_apic_id_table;
3716 int dlid = GET_APIC_LOGICAL_ID(ldr);
3717
3718 if (!dlid)
3719 return NULL;
3720
3721 if (flat) { /* flat */
3722 index = ffs(dlid) - 1;
3723 if (index > 7)
3724 return NULL;
3725 } else { /* cluster */
3726 int cluster = (dlid & 0xf0) >> 4;
3727 int apic = ffs(dlid & 0x0f) - 1;
3728
3729 if ((apic < 0) || (apic > 7) ||
3730 (cluster >= 0xf))
3731 return NULL;
3732 index = (cluster << 2) + apic;
3733 }
3734
3735 logical_apic_id_table = (u32 *) page_address(vm_data->avic_logical_id_table_page);
3736
3737 return &logical_apic_id_table[index];
3738}
3739
3740static int avic_ldr_write(struct kvm_vcpu *vcpu, u8 g_physical_id, u32 ldr,
3741 bool valid)
3742{
3743 bool flat;
3744 u32 *entry, new_entry;
3745
3746 flat = kvm_lapic_get_reg(vcpu->arch.apic, APIC_DFR) == APIC_DFR_FLAT;
3747 entry = avic_get_logical_id_entry(vcpu, ldr, flat);
3748 if (!entry)
3749 return -EINVAL;
3750
3751 new_entry = READ_ONCE(*entry);
3752 new_entry &= ~AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK;
3753 new_entry |= (g_physical_id & AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK);
3754 if (valid)
3755 new_entry |= AVIC_LOGICAL_ID_ENTRY_VALID_MASK;
3756 else
3757 new_entry &= ~AVIC_LOGICAL_ID_ENTRY_VALID_MASK;
3758 WRITE_ONCE(*entry, new_entry);
3759
3760 return 0;
3761}
3762
3763static int avic_handle_ldr_update(struct kvm_vcpu *vcpu)
3764{
3765 int ret;
3766 struct vcpu_svm *svm = to_svm(vcpu);
3767 u32 ldr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_LDR);
3768
3769 if (!ldr)
3770 return 1;
3771
3772 ret = avic_ldr_write(vcpu, vcpu->vcpu_id, ldr, true);
3773 if (ret && svm->ldr_reg) {
3774 avic_ldr_write(vcpu, 0, svm->ldr_reg, false);
3775 svm->ldr_reg = 0;
3776 } else {
3777 svm->ldr_reg = ldr;
3778 }
3779 return ret;
3780}
3781
3782static int avic_handle_apic_id_update(struct kvm_vcpu *vcpu)
3783{
3784 u64 *old, *new;
3785 struct vcpu_svm *svm = to_svm(vcpu);
3786 u32 apic_id_reg = kvm_lapic_get_reg(vcpu->arch.apic, APIC_ID);
3787 u32 id = (apic_id_reg >> 24) & 0xff;
3788
3789 if (vcpu->vcpu_id == id)
3790 return 0;
3791
3792 old = avic_get_physical_id_entry(vcpu, vcpu->vcpu_id);
3793 new = avic_get_physical_id_entry(vcpu, id);
3794 if (!new || !old)
3795 return 1;
3796
3797 /* We need to move physical_id_entry to new offset */
3798 *new = *old;
3799 *old = 0ULL;
3800 to_svm(vcpu)->avic_physical_id_cache = new;
3801
3802 /*
3803 * Also update the guest physical APIC ID in the logical
3804 * APIC ID table entry if already setup the LDR.
3805 */
3806 if (svm->ldr_reg)
3807 avic_handle_ldr_update(vcpu);
3808
3809 return 0;
3810}
3811
3812static int avic_handle_dfr_update(struct kvm_vcpu *vcpu)
3813{
3814 struct vcpu_svm *svm = to_svm(vcpu);
3815 struct kvm_arch *vm_data = &vcpu->kvm->arch;
3816 u32 dfr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_DFR);
3817 u32 mod = (dfr >> 28) & 0xf;
3818
3819 /*
3820 * We assume that all local APICs are using the same type.
3821 * If this changes, we need to flush the AVIC logical
3822 * APID id table.
3823 */
3824 if (vm_data->ldr_mode == mod)
3825 return 0;
3826
3827 clear_page(page_address(vm_data->avic_logical_id_table_page));
3828 vm_data->ldr_mode = mod;
3829
3830 if (svm->ldr_reg)
3831 avic_handle_ldr_update(vcpu);
3832 return 0;
3833}
3834
3835static int avic_unaccel_trap_write(struct vcpu_svm *svm)
3836{
3837 struct kvm_lapic *apic = svm->vcpu.arch.apic;
3838 u32 offset = svm->vmcb->control.exit_info_1 &
3839 AVIC_UNACCEL_ACCESS_OFFSET_MASK;
3840
3841 switch (offset) {
3842 case APIC_ID:
3843 if (avic_handle_apic_id_update(&svm->vcpu))
3844 return 0;
3845 break;
3846 case APIC_LDR:
3847 if (avic_handle_ldr_update(&svm->vcpu))
3848 return 0;
3849 break;
3850 case APIC_DFR:
3851 avic_handle_dfr_update(&svm->vcpu);
3852 break;
3853 default:
3854 break;
3855 }
3856
3857 kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset));
3858
3859 return 1;
3860}
3861
3862static bool is_avic_unaccelerated_access_trap(u32 offset)
3863{
3864 bool ret = false;
3865
3866 switch (offset) {
3867 case APIC_ID:
3868 case APIC_EOI:
3869 case APIC_RRR:
3870 case APIC_LDR:
3871 case APIC_DFR:
3872 case APIC_SPIV:
3873 case APIC_ESR:
3874 case APIC_ICR:
3875 case APIC_LVTT:
3876 case APIC_LVTTHMR:
3877 case APIC_LVTPC:
3878 case APIC_LVT0:
3879 case APIC_LVT1:
3880 case APIC_LVTERR:
3881 case APIC_TMICT:
3882 case APIC_TDCR:
3883 ret = true;
3884 break;
3885 default:
3886 break;
3887 }
3888 return ret;
3889}
3890
3891static int avic_unaccelerated_access_interception(struct vcpu_svm *svm)
3892{
3893 int ret = 0;
3894 u32 offset = svm->vmcb->control.exit_info_1 &
3895 AVIC_UNACCEL_ACCESS_OFFSET_MASK;
3896 u32 vector = svm->vmcb->control.exit_info_2 &
3897 AVIC_UNACCEL_ACCESS_VECTOR_MASK;
3898 bool write = (svm->vmcb->control.exit_info_1 >> 32) &
3899 AVIC_UNACCEL_ACCESS_WRITE_MASK;
3900 bool trap = is_avic_unaccelerated_access_trap(offset);
3901
3902 trace_kvm_avic_unaccelerated_access(svm->vcpu.vcpu_id, offset,
3903 trap, write, vector);
3904 if (trap) {
3905 /* Handling Trap */
3906 WARN_ONCE(!write, "svm: Handling trap read.\n");
3907 ret = avic_unaccel_trap_write(svm);
3908 } else {
3909 /* Handling Fault */
3910 ret = (emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE);
3911 }
3912
3913 return ret;
3914}
3915
Mathias Krause09941fb2012-08-30 01:30:20 +02003916static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
Andre Przywara7ff76d52010-12-21 11:12:04 +01003917 [SVM_EXIT_READ_CR0] = cr_interception,
3918 [SVM_EXIT_READ_CR3] = cr_interception,
3919 [SVM_EXIT_READ_CR4] = cr_interception,
3920 [SVM_EXIT_READ_CR8] = cr_interception,
David Kaplan5e575182015-03-06 14:44:35 -06003921 [SVM_EXIT_CR0_SEL_WRITE] = cr_interception,
Joerg Roedel628afd22011-04-04 12:39:36 +02003922 [SVM_EXIT_WRITE_CR0] = cr_interception,
Andre Przywara7ff76d52010-12-21 11:12:04 +01003923 [SVM_EXIT_WRITE_CR3] = cr_interception,
3924 [SVM_EXIT_WRITE_CR4] = cr_interception,
Joerg Roedele0231712010-02-24 18:59:10 +01003925 [SVM_EXIT_WRITE_CR8] = cr8_write_interception,
Andre Przywaracae37972010-12-21 11:12:05 +01003926 [SVM_EXIT_READ_DR0] = dr_interception,
3927 [SVM_EXIT_READ_DR1] = dr_interception,
3928 [SVM_EXIT_READ_DR2] = dr_interception,
3929 [SVM_EXIT_READ_DR3] = dr_interception,
3930 [SVM_EXIT_READ_DR4] = dr_interception,
3931 [SVM_EXIT_READ_DR5] = dr_interception,
3932 [SVM_EXIT_READ_DR6] = dr_interception,
3933 [SVM_EXIT_READ_DR7] = dr_interception,
3934 [SVM_EXIT_WRITE_DR0] = dr_interception,
3935 [SVM_EXIT_WRITE_DR1] = dr_interception,
3936 [SVM_EXIT_WRITE_DR2] = dr_interception,
3937 [SVM_EXIT_WRITE_DR3] = dr_interception,
3938 [SVM_EXIT_WRITE_DR4] = dr_interception,
3939 [SVM_EXIT_WRITE_DR5] = dr_interception,
3940 [SVM_EXIT_WRITE_DR6] = dr_interception,
3941 [SVM_EXIT_WRITE_DR7] = dr_interception,
Jan Kiszkad0bfb942008-12-15 13:52:10 +01003942 [SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception,
3943 [SVM_EXIT_EXCP_BASE + BP_VECTOR] = bp_interception,
Anthony Liguori7aa81cc2007-09-17 14:57:50 -05003944 [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception,
Joerg Roedele0231712010-02-24 18:59:10 +01003945 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
3946 [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
3947 [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
Eric Northup54a20552015-11-03 18:03:53 +01003948 [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
Joerg Roedele0231712010-02-24 18:59:10 +01003949 [SVM_EXIT_INTR] = intr_interception,
Joerg Roedelc47f0982008-04-30 17:56:00 +02003950 [SVM_EXIT_NMI] = nmi_interception,
Avi Kivity6aa8b732006-12-10 02:21:36 -08003951 [SVM_EXIT_SMI] = nop_on_interception,
3952 [SVM_EXIT_INIT] = nop_on_interception,
Dor Laorc1150d82007-01-05 16:36:24 -08003953 [SVM_EXIT_VINTR] = interrupt_window_interception,
Avi Kivity332b56e2011-11-10 14:57:24 +02003954 [SVM_EXIT_RDPMC] = rdpmc_interception,
Avi Kivity6aa8b732006-12-10 02:21:36 -08003955 [SVM_EXIT_CPUID] = cpuid_interception,
Gleb Natapov95ba8273132009-04-21 17:45:08 +03003956 [SVM_EXIT_IRET] = iret_interception,
Avi Kivitycf5a94d2007-10-28 16:11:58 +02003957 [SVM_EXIT_INVD] = emulate_on_interception,
Mark Langsdorf565d0992009-10-06 14:25:02 -05003958 [SVM_EXIT_PAUSE] = pause_interception,
Avi Kivity6aa8b732006-12-10 02:21:36 -08003959 [SVM_EXIT_HLT] = halt_interception,
Marcelo Tosattia7052892008-09-23 13:18:35 -03003960 [SVM_EXIT_INVLPG] = invlpg_interception,
Alexander Grafff092382009-06-15 15:21:24 +02003961 [SVM_EXIT_INVLPGA] = invlpga_interception,
Joerg Roedele0231712010-02-24 18:59:10 +01003962 [SVM_EXIT_IOIO] = io_interception,
Avi Kivity6aa8b732006-12-10 02:21:36 -08003963 [SVM_EXIT_MSR] = msr_interception,
3964 [SVM_EXIT_TASK_SWITCH] = task_switch_interception,
Joerg Roedel46fe4dd2007-01-26 00:56:42 -08003965 [SVM_EXIT_SHUTDOWN] = shutdown_interception,
Alexander Graf3d6368e2008-11-25 20:17:07 +01003966 [SVM_EXIT_VMRUN] = vmrun_interception,
Avi Kivity02e235b2007-02-19 14:37:47 +02003967 [SVM_EXIT_VMMCALL] = vmmcall_interception,
Alexander Graf55426752008-11-25 20:17:06 +01003968 [SVM_EXIT_VMLOAD] = vmload_interception,
3969 [SVM_EXIT_VMSAVE] = vmsave_interception,
Alexander Graf1371d902008-11-25 20:17:04 +01003970 [SVM_EXIT_STGI] = stgi_interception,
3971 [SVM_EXIT_CLGI] = clgi_interception,
Joerg Roedel532a46b2009-10-09 16:08:32 +02003972 [SVM_EXIT_SKINIT] = skinit_interception,
David Kaplandab429a2015-03-02 13:43:37 -06003973 [SVM_EXIT_WBINVD] = wbinvd_interception,
Gabriel L. Somlo87c00572014-05-07 16:52:13 -04003974 [SVM_EXIT_MONITOR] = monitor_interception,
3975 [SVM_EXIT_MWAIT] = mwait_interception,
Joerg Roedel81dd35d2010-12-07 17:15:06 +01003976 [SVM_EXIT_XSETBV] = xsetbv_interception,
Joerg Roedel709ddeb2008-02-07 13:47:45 +01003977 [SVM_EXIT_NPF] = pf_interception,
Paolo Bonzini64d60672015-05-07 11:36:11 +02003978 [SVM_EXIT_RSM] = emulate_on_interception,
Suravee Suthikulpanit18f40c52016-05-04 14:09:48 -05003979 [SVM_EXIT_AVIC_INCOMPLETE_IPI] = avic_incomplete_ipi_interception,
3980 [SVM_EXIT_AVIC_UNACCELERATED_ACCESS] = avic_unaccelerated_access_interception,
Avi Kivity6aa8b732006-12-10 02:21:36 -08003981};
3982
Joe Perchesae8cc052011-04-24 22:00:50 -07003983static void dump_vmcb(struct kvm_vcpu *vcpu)
Joerg Roedel3f10c842010-05-05 16:04:42 +02003984{
3985 struct vcpu_svm *svm = to_svm(vcpu);
3986 struct vmcb_control_area *control = &svm->vmcb->control;
3987 struct vmcb_save_area *save = &svm->vmcb->save;
3988
3989 pr_err("VMCB Control Area:\n");
Joe Perchesae8cc052011-04-24 22:00:50 -07003990 pr_err("%-20s%04x\n", "cr_read:", control->intercept_cr & 0xffff);
3991 pr_err("%-20s%04x\n", "cr_write:", control->intercept_cr >> 16);
3992 pr_err("%-20s%04x\n", "dr_read:", control->intercept_dr & 0xffff);
3993 pr_err("%-20s%04x\n", "dr_write:", control->intercept_dr >> 16);
3994 pr_err("%-20s%08x\n", "exceptions:", control->intercept_exceptions);
3995 pr_err("%-20s%016llx\n", "intercepts:", control->intercept);
3996 pr_err("%-20s%d\n", "pause filter count:", control->pause_filter_count);
3997 pr_err("%-20s%016llx\n", "iopm_base_pa:", control->iopm_base_pa);
3998 pr_err("%-20s%016llx\n", "msrpm_base_pa:", control->msrpm_base_pa);
3999 pr_err("%-20s%016llx\n", "tsc_offset:", control->tsc_offset);
4000 pr_err("%-20s%d\n", "asid:", control->asid);
4001 pr_err("%-20s%d\n", "tlb_ctl:", control->tlb_ctl);
4002 pr_err("%-20s%08x\n", "int_ctl:", control->int_ctl);
4003 pr_err("%-20s%08x\n", "int_vector:", control->int_vector);
4004 pr_err("%-20s%08x\n", "int_state:", control->int_state);
4005 pr_err("%-20s%08x\n", "exit_code:", control->exit_code);
4006 pr_err("%-20s%016llx\n", "exit_info1:", control->exit_info_1);
4007 pr_err("%-20s%016llx\n", "exit_info2:", control->exit_info_2);
4008 pr_err("%-20s%08x\n", "exit_int_info:", control->exit_int_info);
4009 pr_err("%-20s%08x\n", "exit_int_info_err:", control->exit_int_info_err);
4010 pr_err("%-20s%lld\n", "nested_ctl:", control->nested_ctl);
4011 pr_err("%-20s%016llx\n", "nested_cr3:", control->nested_cr3);
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05004012 pr_err("%-20s%016llx\n", "avic_vapic_bar:", control->avic_vapic_bar);
Joe Perchesae8cc052011-04-24 22:00:50 -07004013 pr_err("%-20s%08x\n", "event_inj:", control->event_inj);
4014 pr_err("%-20s%08x\n", "event_inj_err:", control->event_inj_err);
4015 pr_err("%-20s%lld\n", "lbr_ctl:", control->lbr_ctl);
4016 pr_err("%-20s%016llx\n", "next_rip:", control->next_rip);
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05004017 pr_err("%-20s%016llx\n", "avic_backing_page:", control->avic_backing_page);
4018 pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
4019 pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
Joerg Roedel3f10c842010-05-05 16:04:42 +02004020 pr_err("VMCB State Save Area:\n");
Joe Perchesae8cc052011-04-24 22:00:50 -07004021 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4022 "es:",
4023 save->es.selector, save->es.attrib,
4024 save->es.limit, save->es.base);
4025 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4026 "cs:",
4027 save->cs.selector, save->cs.attrib,
4028 save->cs.limit, save->cs.base);
4029 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4030 "ss:",
4031 save->ss.selector, save->ss.attrib,
4032 save->ss.limit, save->ss.base);
4033 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4034 "ds:",
4035 save->ds.selector, save->ds.attrib,
4036 save->ds.limit, save->ds.base);
4037 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4038 "fs:",
4039 save->fs.selector, save->fs.attrib,
4040 save->fs.limit, save->fs.base);
4041 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4042 "gs:",
4043 save->gs.selector, save->gs.attrib,
4044 save->gs.limit, save->gs.base);
4045 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4046 "gdtr:",
4047 save->gdtr.selector, save->gdtr.attrib,
4048 save->gdtr.limit, save->gdtr.base);
4049 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4050 "ldtr:",
4051 save->ldtr.selector, save->ldtr.attrib,
4052 save->ldtr.limit, save->ldtr.base);
4053 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4054 "idtr:",
4055 save->idtr.selector, save->idtr.attrib,
4056 save->idtr.limit, save->idtr.base);
4057 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
4058 "tr:",
4059 save->tr.selector, save->tr.attrib,
4060 save->tr.limit, save->tr.base);
Joerg Roedel3f10c842010-05-05 16:04:42 +02004061 pr_err("cpl: %d efer: %016llx\n",
4062 save->cpl, save->efer);
Joe Perchesae8cc052011-04-24 22:00:50 -07004063 pr_err("%-15s %016llx %-13s %016llx\n",
4064 "cr0:", save->cr0, "cr2:", save->cr2);
4065 pr_err("%-15s %016llx %-13s %016llx\n",
4066 "cr3:", save->cr3, "cr4:", save->cr4);
4067 pr_err("%-15s %016llx %-13s %016llx\n",
4068 "dr6:", save->dr6, "dr7:", save->dr7);
4069 pr_err("%-15s %016llx %-13s %016llx\n",
4070 "rip:", save->rip, "rflags:", save->rflags);
4071 pr_err("%-15s %016llx %-13s %016llx\n",
4072 "rsp:", save->rsp, "rax:", save->rax);
4073 pr_err("%-15s %016llx %-13s %016llx\n",
4074 "star:", save->star, "lstar:", save->lstar);
4075 pr_err("%-15s %016llx %-13s %016llx\n",
4076 "cstar:", save->cstar, "sfmask:", save->sfmask);
4077 pr_err("%-15s %016llx %-13s %016llx\n",
4078 "kernel_gs_base:", save->kernel_gs_base,
4079 "sysenter_cs:", save->sysenter_cs);
4080 pr_err("%-15s %016llx %-13s %016llx\n",
4081 "sysenter_esp:", save->sysenter_esp,
4082 "sysenter_eip:", save->sysenter_eip);
4083 pr_err("%-15s %016llx %-13s %016llx\n",
4084 "gpat:", save->g_pat, "dbgctl:", save->dbgctl);
4085 pr_err("%-15s %016llx %-13s %016llx\n",
4086 "br_from:", save->br_from, "br_to:", save->br_to);
4087 pr_err("%-15s %016llx %-13s %016llx\n",
4088 "excp_from:", save->last_excp_from,
4089 "excp_to:", save->last_excp_to);
Joerg Roedel3f10c842010-05-05 16:04:42 +02004090}
4091
Avi Kivity586f9602010-11-18 13:09:54 +02004092static void svm_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
4093{
4094 struct vmcb_control_area *control = &to_svm(vcpu)->vmcb->control;
4095
4096 *info1 = control->exit_info_1;
4097 *info2 = control->exit_info_2;
4098}
4099
Avi Kivity851ba692009-08-24 11:10:17 +03004100static int handle_exit(struct kvm_vcpu *vcpu)
Avi Kivity6aa8b732006-12-10 02:21:36 -08004101{
Avi Kivity04d2cc72007-09-10 18:10:54 +03004102 struct vcpu_svm *svm = to_svm(vcpu);
Avi Kivity851ba692009-08-24 11:10:17 +03004103 struct kvm_run *kvm_run = vcpu->run;
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04004104 u32 exit_code = svm->vmcb->control.exit_code;
Avi Kivity6aa8b732006-12-10 02:21:36 -08004105
Paolo Bonzini8b89fe12015-12-10 18:37:32 +01004106 trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
4107
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01004108 if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
Joerg Roedel2be4fc72010-04-22 12:33:09 +02004109 vcpu->arch.cr0 = svm->vmcb->save.cr0;
4110 if (npt_enabled)
4111 vcpu->arch.cr3 = svm->vmcb->save.cr3;
Joerg Roedelaf9ca2d2008-04-30 17:56:03 +02004112
Joerg Roedelcd3ff652009-10-09 16:08:26 +02004113 if (unlikely(svm->nested.exit_required)) {
4114 nested_svm_vmexit(svm);
4115 svm->nested.exit_required = false;
4116
4117 return 1;
4118 }
4119
Joerg Roedel20307532010-11-29 17:51:48 +01004120 if (is_guest_mode(vcpu)) {
Joerg Roedel410e4d52009-08-07 11:49:44 +02004121 int vmexit;
4122
Joerg Roedeld8cabdd2009-10-09 16:08:28 +02004123 trace_kvm_nested_vmexit(svm->vmcb->save.rip, exit_code,
4124 svm->vmcb->control.exit_info_1,
4125 svm->vmcb->control.exit_info_2,
4126 svm->vmcb->control.exit_int_info,
Stefan Hajnoczie097e5f2011-07-22 12:46:52 +01004127 svm->vmcb->control.exit_int_info_err,
4128 KVM_ISA_SVM);
Joerg Roedeld8cabdd2009-10-09 16:08:28 +02004129
Joerg Roedel410e4d52009-08-07 11:49:44 +02004130 vmexit = nested_svm_exit_special(svm);
4131
4132 if (vmexit == NESTED_EXIT_CONTINUE)
4133 vmexit = nested_svm_exit_handled(svm);
4134
4135 if (vmexit == NESTED_EXIT_DONE)
Alexander Grafcf74a782008-11-25 20:17:08 +01004136 return 1;
Alexander Grafcf74a782008-11-25 20:17:08 +01004137 }
4138
Joerg Roedela5c38322009-08-07 11:49:32 +02004139 svm_complete_interrupts(svm);
4140
Avi Kivity04d2cc72007-09-10 18:10:54 +03004141 if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
4142 kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
4143 kvm_run->fail_entry.hardware_entry_failure_reason
4144 = svm->vmcb->control.exit_code;
Joerg Roedel3f10c842010-05-05 16:04:42 +02004145 pr_err("KVM: FAILED VMRUN WITH VMCB:\n");
4146 dump_vmcb(vcpu);
Avi Kivity04d2cc72007-09-10 18:10:54 +03004147 return 0;
4148 }
4149
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04004150 if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
Joerg Roedel709ddeb2008-02-07 13:47:45 +01004151 exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
Joerg Roedel55c5e462010-09-10 17:31:04 +02004152 exit_code != SVM_EXIT_NPF && exit_code != SVM_EXIT_TASK_SWITCH &&
4153 exit_code != SVM_EXIT_INTR && exit_code != SVM_EXIT_NMI)
Borislav Petkov6614c7d2013-04-26 00:22:01 +02004154 printk(KERN_ERR "%s: unexpected exit_int_info 0x%x "
Avi Kivity6aa8b732006-12-10 02:21:36 -08004155 "exit_code 0x%x\n",
Harvey Harrisonb8688d52008-03-03 12:59:56 -08004156 __func__, svm->vmcb->control.exit_int_info,
Avi Kivity6aa8b732006-12-10 02:21:36 -08004157 exit_code);
4158
Ahmed S. Darwish9d8f5492007-02-19 14:37:46 +02004159 if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
Joe Perches56919c52007-11-12 20:06:51 -08004160 || !svm_exit_handlers[exit_code]) {
Bandan Dasfaac2452015-03-16 17:18:25 -04004161 WARN_ONCE(1, "svm: unexpected exit reason 0x%x\n", exit_code);
Michael S. Tsirkin2bc19dc2014-09-18 16:21:16 +03004162 kvm_queue_exception(vcpu, UD_VECTOR);
4163 return 1;
Avi Kivity6aa8b732006-12-10 02:21:36 -08004164 }
4165
Avi Kivity851ba692009-08-24 11:10:17 +03004166 return svm_exit_handlers[exit_code](svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004167}
4168
4169static void reload_tss(struct kvm_vcpu *vcpu)
4170{
4171 int cpu = raw_smp_processor_id();
4172
Tejun Heo0fe1e002009-10-29 22:34:14 +09004173 struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
4174 sd->tss_desc->type = 9; /* available 32/64-bit TSS */
Avi Kivity6aa8b732006-12-10 02:21:36 -08004175 load_TR_desc();
4176}
4177
Rusty Russelle756fc62007-07-30 20:07:08 +10004178static void pre_svm_run(struct vcpu_svm *svm)
Avi Kivity6aa8b732006-12-10 02:21:36 -08004179{
4180 int cpu = raw_smp_processor_id();
4181
Tejun Heo0fe1e002009-10-29 22:34:14 +09004182 struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004183
Marcelo Tosatti4b656b12009-07-21 12:47:45 -03004184 /* FIXME: handle wraparound of asid_generation */
Tejun Heo0fe1e002009-10-29 22:34:14 +09004185 if (svm->asid_generation != sd->asid_generation)
4186 new_asid(svm, sd);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004187}
4188
Gleb Natapov95ba8273132009-04-21 17:45:08 +03004189static void svm_inject_nmi(struct kvm_vcpu *vcpu)
4190{
4191 struct vcpu_svm *svm = to_svm(vcpu);
4192
4193 svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
4194 vcpu->arch.hflags |= HF_NMI_MASK;
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01004195 set_intercept(svm, INTERCEPT_IRET);
Gleb Natapov95ba8273132009-04-21 17:45:08 +03004196 ++vcpu->stat.nmi_injections;
4197}
Avi Kivity6aa8b732006-12-10 02:21:36 -08004198
Eddie Dong85f455f2007-07-06 12:20:49 +03004199static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
Avi Kivity6aa8b732006-12-10 02:21:36 -08004200{
4201 struct vmcb_control_area *control;
4202
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -05004203 /* The following fields are ignored when AVIC is enabled */
Rusty Russelle756fc62007-07-30 20:07:08 +10004204 control = &svm->vmcb->control;
Eddie Dong85f455f2007-07-06 12:20:49 +03004205 control->int_vector = irq;
Avi Kivity6aa8b732006-12-10 02:21:36 -08004206 control->int_ctl &= ~V_INTR_PRIO_MASK;
4207 control->int_ctl |= V_IRQ_MASK |
4208 ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
Joerg Roedeldecdbf62010-12-03 11:45:52 +01004209 mark_dirty(svm->vmcb, VMCB_INTR);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004210}
4211
Gleb Natapov66fd3f72009-05-11 13:35:50 +03004212static void svm_set_irq(struct kvm_vcpu *vcpu)
Eddie Dong2a8067f2007-08-06 16:29:07 +03004213{
4214 struct vcpu_svm *svm = to_svm(vcpu);
4215
Joerg Roedel2af91942009-08-07 11:49:28 +02004216 BUG_ON(!(gif_set(svm)));
Alexander Grafcf74a782008-11-25 20:17:08 +01004217
Gleb Natapov9fb2d2b2010-05-23 14:28:26 +03004218 trace_kvm_inj_virq(vcpu->arch.interrupt.nr);
4219 ++vcpu->stat.irq_injections;
4220
Alexander Graf219b65d2009-06-15 15:21:25 +02004221 svm->vmcb->control.event_inj = vcpu->arch.interrupt.nr |
4222 SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
Eddie Dong2a8067f2007-08-06 16:29:07 +03004223}
4224
Suravee Suthikulpanit3bbf3562016-05-04 14:09:51 -05004225static inline bool svm_nested_virtualize_tpr(struct kvm_vcpu *vcpu)
4226{
4227 return is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK);
4228}
4229
Gleb Natapov95ba8273132009-04-21 17:45:08 +03004230static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
4231{
4232 struct vcpu_svm *svm = to_svm(vcpu);
4233
Suravee Suthikulpanit3bbf3562016-05-04 14:09:51 -05004234 if (svm_nested_virtualize_tpr(vcpu) ||
4235 kvm_vcpu_apicv_active(vcpu))
Joerg Roedel88ab24a2010-02-19 16:23:06 +01004236 return;
4237
Radim Krčmář596f3142014-03-11 19:11:18 +01004238 clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
4239
Gleb Natapov95ba8273132009-04-21 17:45:08 +03004240 if (irr == -1)
4241 return;
4242
4243 if (tpr >= irr)
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01004244 set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
Gleb Natapov95ba8273132009-04-21 17:45:08 +03004245}
4246
Yang Zhang8d146952013-01-25 10:18:50 +08004247static void svm_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
4248{
4249 return;
4250}
4251
Andrey Smetanind62caab2015-11-10 15:36:33 +03004252static bool svm_get_enable_apicv(void)
Yang Zhangc7c9c562013-01-25 10:18:51 +08004253{
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05004254 return avic;
Yang Zhangc7c9c562013-01-25 10:18:51 +08004255}
4256
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05004257static void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
4258{
4259}
4260
Paolo Bonzini67c9ddd2016-05-10 17:01:23 +02004261static void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05004262{
4263}
4264
4265/* Note: Currently only used by Hyper-V. */
Andrey Smetanind62caab2015-11-10 15:36:33 +03004266static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
4267{
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05004268 struct vcpu_svm *svm = to_svm(vcpu);
4269 struct vmcb *vmcb = svm->vmcb;
4270
4271 if (!avic)
4272 return;
4273
4274 vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
4275 mark_dirty(vmcb, VMCB_INTR);
Yang Zhangc7c9c562013-01-25 10:18:51 +08004276}
4277
Andrey Smetanin63086302015-11-10 15:36:32 +03004278static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
Yang Zhangc7c9c562013-01-25 10:18:51 +08004279{
4280 return;
4281}
4282
Yang Zhanga20ed542013-04-11 19:25:15 +08004283static void svm_sync_pir_to_irr(struct kvm_vcpu *vcpu)
4284{
4285 return;
4286}
4287
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -05004288static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
4289{
4290 kvm_lapic_set_irr(vec, vcpu->arch.apic);
4291 smp_mb__after_atomic();
4292
4293 if (avic_vcpu_is_running(vcpu))
4294 wrmsrl(SVM_AVIC_DOORBELL,
Suravee Suthikulpanit7d669f52016-06-15 17:23:45 -05004295 kvm_cpu_get_apicid(vcpu->cpu));
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -05004296 else
4297 kvm_vcpu_wake_up(vcpu);
4298}
4299
Gleb Natapov95ba8273132009-04-21 17:45:08 +03004300static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
Joerg Roedelaaacfc92008-04-16 16:51:18 +02004301{
4302 struct vcpu_svm *svm = to_svm(vcpu);
4303 struct vmcb *vmcb = svm->vmcb;
Joerg Roedel924584c2010-04-22 12:33:07 +02004304 int ret;
4305 ret = !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) &&
4306 !(svm->vcpu.arch.hflags & HF_NMI_MASK);
4307 ret = ret && gif_set(svm) && nested_svm_nmi(svm);
4308
4309 return ret;
Joerg Roedelaaacfc92008-04-16 16:51:18 +02004310}
4311
Jan Kiszka3cfc3092009-11-12 01:04:25 +01004312static bool svm_get_nmi_mask(struct kvm_vcpu *vcpu)
4313{
4314 struct vcpu_svm *svm = to_svm(vcpu);
4315
4316 return !!(svm->vcpu.arch.hflags & HF_NMI_MASK);
4317}
4318
4319static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
4320{
4321 struct vcpu_svm *svm = to_svm(vcpu);
4322
4323 if (masked) {
4324 svm->vcpu.arch.hflags |= HF_NMI_MASK;
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01004325 set_intercept(svm, INTERCEPT_IRET);
Jan Kiszka3cfc3092009-11-12 01:04:25 +01004326 } else {
4327 svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
Joerg Roedel8a05a1b82010-11-30 18:04:00 +01004328 clr_intercept(svm, INTERCEPT_IRET);
Jan Kiszka3cfc3092009-11-12 01:04:25 +01004329 }
4330}
4331
Gleb Natapov78646122009-03-23 12:12:11 +02004332static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
4333{
4334 struct vcpu_svm *svm = to_svm(vcpu);
4335 struct vmcb *vmcb = svm->vmcb;
Joerg Roedel7fcdb512009-09-16 15:24:15 +02004336 int ret;
4337
4338 if (!gif_set(svm) ||
4339 (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK))
4340 return 0;
4341
Avi Kivityf6e78472010-08-02 15:30:20 +03004342 ret = !!(kvm_get_rflags(vcpu) & X86_EFLAGS_IF);
Joerg Roedel7fcdb512009-09-16 15:24:15 +02004343
Joerg Roedel20307532010-11-29 17:51:48 +01004344 if (is_guest_mode(vcpu))
Joerg Roedel7fcdb512009-09-16 15:24:15 +02004345 return ret && !(svm->vcpu.arch.hflags & HF_VINTR_MASK);
4346
4347 return ret;
Gleb Natapov78646122009-03-23 12:12:11 +02004348}
4349
Jan Kiszkac9a79532014-03-07 20:03:15 +01004350static void enable_irq_window(struct kvm_vcpu *vcpu)
Gleb Natapov9222be12009-04-23 17:14:37 +03004351{
Alexander Graf219b65d2009-06-15 15:21:25 +02004352 struct vcpu_svm *svm = to_svm(vcpu);
Alexander Graf219b65d2009-06-15 15:21:25 +02004353
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -05004354 if (kvm_vcpu_apicv_active(vcpu))
4355 return;
4356
Joerg Roedele0231712010-02-24 18:59:10 +01004357 /*
4358 * In case GIF=0 we can't rely on the CPU to tell us when GIF becomes
4359 * 1, because that's a separate STGI/VMRUN intercept. The next time we
4360 * get that intercept, this function will be called again though and
4361 * we'll get the vintr intercept.
4362 */
Joerg Roedel8fe54652010-02-19 16:23:01 +01004363 if (gif_set(svm) && nested_svm_intr(svm)) {
Alexander Graf219b65d2009-06-15 15:21:25 +02004364 svm_set_vintr(svm);
4365 svm_inject_irq(svm, 0x0);
4366 }
Gleb Natapov9222be12009-04-23 17:14:37 +03004367}
4368
Jan Kiszkac9a79532014-03-07 20:03:15 +01004369static void enable_nmi_window(struct kvm_vcpu *vcpu)
Avi Kivity6aa8b732006-12-10 02:21:36 -08004370{
Avi Kivity04d2cc72007-09-10 18:10:54 +03004371 struct vcpu_svm *svm = to_svm(vcpu);
Eddie Dong85f455f2007-07-06 12:20:49 +03004372
Gleb Natapov44c11432009-05-11 13:35:52 +03004373 if ((svm->vcpu.arch.hflags & (HF_NMI_MASK | HF_IRET_MASK))
4374 == HF_NMI_MASK)
Jan Kiszkac9a79532014-03-07 20:03:15 +01004375 return; /* IRET will cause a vm exit */
Gleb Natapov44c11432009-05-11 13:35:52 +03004376
Joerg Roedele0231712010-02-24 18:59:10 +01004377 /*
4378 * Something prevents NMI from been injected. Single step over possible
4379 * problem (IRET or exception injection or interrupt shadow)
4380 */
Jan Kiszka6be7d302009-10-18 13:24:54 +02004381 svm->nmi_singlestep = true;
Gleb Natapov44c11432009-05-11 13:35:52 +03004382 svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
Eddie Dong85f455f2007-07-06 12:20:49 +03004383}
4384
Izik Eiduscbc94022007-10-25 00:29:55 +02004385static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
4386{
4387 return 0;
4388}
4389
Avi Kivityd9e368d2007-06-07 19:18:30 +03004390static void svm_flush_tlb(struct kvm_vcpu *vcpu)
4391{
Joerg Roedel38e5e922010-12-03 15:25:16 +01004392 struct vcpu_svm *svm = to_svm(vcpu);
4393
4394 if (static_cpu_has(X86_FEATURE_FLUSHBYASID))
4395 svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
4396 else
4397 svm->asid_generation--;
Avi Kivityd9e368d2007-06-07 19:18:30 +03004398}
4399
Avi Kivity04d2cc72007-09-10 18:10:54 +03004400static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
4401{
4402}
4403
Joerg Roedeld7bf8222008-04-16 16:51:17 +02004404static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
4405{
4406 struct vcpu_svm *svm = to_svm(vcpu);
4407
Suravee Suthikulpanit3bbf3562016-05-04 14:09:51 -05004408 if (svm_nested_virtualize_tpr(vcpu))
Joerg Roedel88ab24a2010-02-19 16:23:06 +01004409 return;
4410
Roedel, Joerg4ee546b2010-12-03 10:50:51 +01004411 if (!is_cr_intercept(svm, INTERCEPT_CR8_WRITE)) {
Joerg Roedeld7bf8222008-04-16 16:51:17 +02004412 int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
Gleb Natapov615d5192009-04-21 17:45:05 +03004413 kvm_set_cr8(vcpu, cr8);
Joerg Roedeld7bf8222008-04-16 16:51:17 +02004414 }
4415}
4416
Joerg Roedel649d6862008-04-16 16:51:15 +02004417static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
4418{
4419 struct vcpu_svm *svm = to_svm(vcpu);
4420 u64 cr8;
4421
Suravee Suthikulpanit3bbf3562016-05-04 14:09:51 -05004422 if (svm_nested_virtualize_tpr(vcpu) ||
4423 kvm_vcpu_apicv_active(vcpu))
Joerg Roedel88ab24a2010-02-19 16:23:06 +01004424 return;
4425
Joerg Roedel649d6862008-04-16 16:51:15 +02004426 cr8 = kvm_get_cr8(vcpu);
4427 svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
4428 svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
4429}
4430
Gleb Natapov9222be12009-04-23 17:14:37 +03004431static void svm_complete_interrupts(struct vcpu_svm *svm)
4432{
4433 u8 vector;
4434 int type;
4435 u32 exitintinfo = svm->vmcb->control.exit_int_info;
Jan Kiszka66b71382010-02-23 17:47:56 +01004436 unsigned int3_injected = svm->int3_injected;
4437
4438 svm->int3_injected = 0;
Gleb Natapov9222be12009-04-23 17:14:37 +03004439
Avi Kivitybd3d1ec2011-02-03 15:29:52 +02004440 /*
4441 * If we've made progress since setting HF_IRET_MASK, we've
4442 * executed an IRET and can allow NMI injection.
4443 */
4444 if ((svm->vcpu.arch.hflags & HF_IRET_MASK)
4445 && kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip) {
Gleb Natapov44c11432009-05-11 13:35:52 +03004446 svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
Avi Kivity3842d132010-07-27 12:30:24 +03004447 kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
4448 }
Gleb Natapov44c11432009-05-11 13:35:52 +03004449
Gleb Natapov9222be12009-04-23 17:14:37 +03004450 svm->vcpu.arch.nmi_injected = false;
4451 kvm_clear_exception_queue(&svm->vcpu);
4452 kvm_clear_interrupt_queue(&svm->vcpu);
4453
4454 if (!(exitintinfo & SVM_EXITINTINFO_VALID))
4455 return;
4456
Avi Kivity3842d132010-07-27 12:30:24 +03004457 kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
4458
Gleb Natapov9222be12009-04-23 17:14:37 +03004459 vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
4460 type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
4461
4462 switch (type) {
4463 case SVM_EXITINTINFO_TYPE_NMI:
4464 svm->vcpu.arch.nmi_injected = true;
4465 break;
4466 case SVM_EXITINTINFO_TYPE_EXEPT:
Jan Kiszka66b71382010-02-23 17:47:56 +01004467 /*
4468 * In case of software exceptions, do not reinject the vector,
4469 * but re-execute the instruction instead. Rewind RIP first
4470 * if we emulated INT3 before.
4471 */
4472 if (kvm_exception_is_soft(vector)) {
4473 if (vector == BP_VECTOR && int3_injected &&
4474 kvm_is_linear_rip(&svm->vcpu, svm->int3_rip))
4475 kvm_rip_write(&svm->vcpu,
4476 kvm_rip_read(&svm->vcpu) -
4477 int3_injected);
Alexander Graf219b65d2009-06-15 15:21:25 +02004478 break;
Jan Kiszka66b71382010-02-23 17:47:56 +01004479 }
Gleb Natapov9222be12009-04-23 17:14:37 +03004480 if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
4481 u32 err = svm->vmcb->control.exit_int_info_err;
Joerg Roedelce7ddec2010-04-22 12:33:13 +02004482 kvm_requeue_exception_e(&svm->vcpu, vector, err);
Gleb Natapov9222be12009-04-23 17:14:37 +03004483
4484 } else
Joerg Roedelce7ddec2010-04-22 12:33:13 +02004485 kvm_requeue_exception(&svm->vcpu, vector);
Gleb Natapov9222be12009-04-23 17:14:37 +03004486 break;
4487 case SVM_EXITINTINFO_TYPE_INTR:
Gleb Natapov66fd3f72009-05-11 13:35:50 +03004488 kvm_queue_interrupt(&svm->vcpu, vector, false);
Gleb Natapov9222be12009-04-23 17:14:37 +03004489 break;
4490 default:
4491 break;
4492 }
4493}
4494
Avi Kivityb463a6f2010-07-20 15:06:17 +03004495static void svm_cancel_injection(struct kvm_vcpu *vcpu)
4496{
4497 struct vcpu_svm *svm = to_svm(vcpu);
4498 struct vmcb_control_area *control = &svm->vmcb->control;
4499
4500 control->exit_int_info = control->event_inj;
4501 control->exit_int_info_err = control->event_inj_err;
4502 control->event_inj = 0;
4503 svm_complete_interrupts(svm);
4504}
4505
Avi Kivity851ba692009-08-24 11:10:17 +03004506static void svm_vcpu_run(struct kvm_vcpu *vcpu)
Avi Kivity6aa8b732006-12-10 02:21:36 -08004507{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04004508 struct vcpu_svm *svm = to_svm(vcpu);
Avi Kivityd9e368d2007-06-07 19:18:30 +03004509
Joerg Roedel2041a062010-04-22 12:33:08 +02004510 svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
4511 svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
4512 svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
4513
Joerg Roedelcd3ff652009-10-09 16:08:26 +02004514 /*
4515 * A vmexit emulation is required before the vcpu can be executed
4516 * again.
4517 */
4518 if (unlikely(svm->nested.exit_required))
4519 return;
4520
Rusty Russelle756fc62007-07-30 20:07:08 +10004521 pre_svm_run(svm);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004522
Joerg Roedel649d6862008-04-16 16:51:15 +02004523 sync_lapic_to_cr8(vcpu);
4524
Joerg Roedelcda0ffd2009-08-07 11:49:45 +02004525 svm->vmcb->save.cr2 = vcpu->arch.cr2;
Avi Kivity6aa8b732006-12-10 02:21:36 -08004526
Avi Kivity04d2cc72007-09-10 18:10:54 +03004527 clgi();
4528
4529 local_irq_enable();
Avi Kivity36241b82006-12-22 01:05:20 -08004530
Avi Kivity6aa8b732006-12-10 02:21:36 -08004531 asm volatile (
Avi Kivity74547662012-09-16 15:10:59 +03004532 "push %%" _ASM_BP "; \n\t"
4533 "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
4534 "mov %c[rcx](%[svm]), %%" _ASM_CX " \n\t"
4535 "mov %c[rdx](%[svm]), %%" _ASM_DX " \n\t"
4536 "mov %c[rsi](%[svm]), %%" _ASM_SI " \n\t"
4537 "mov %c[rdi](%[svm]), %%" _ASM_DI " \n\t"
4538 "mov %c[rbp](%[svm]), %%" _ASM_BP " \n\t"
Avi Kivity05b3e0c2006-12-13 00:33:45 -08004539#ifdef CONFIG_X86_64
Rusty Russellfb3f0f52007-07-27 17:16:56 +10004540 "mov %c[r8](%[svm]), %%r8 \n\t"
4541 "mov %c[r9](%[svm]), %%r9 \n\t"
4542 "mov %c[r10](%[svm]), %%r10 \n\t"
4543 "mov %c[r11](%[svm]), %%r11 \n\t"
4544 "mov %c[r12](%[svm]), %%r12 \n\t"
4545 "mov %c[r13](%[svm]), %%r13 \n\t"
4546 "mov %c[r14](%[svm]), %%r14 \n\t"
4547 "mov %c[r15](%[svm]), %%r15 \n\t"
Avi Kivity6aa8b732006-12-10 02:21:36 -08004548#endif
4549
Avi Kivity6aa8b732006-12-10 02:21:36 -08004550 /* Enter guest mode */
Avi Kivity74547662012-09-16 15:10:59 +03004551 "push %%" _ASM_AX " \n\t"
4552 "mov %c[vmcb](%[svm]), %%" _ASM_AX " \n\t"
Avi Kivity4ecac3f2008-05-13 13:23:38 +03004553 __ex(SVM_VMLOAD) "\n\t"
4554 __ex(SVM_VMRUN) "\n\t"
4555 __ex(SVM_VMSAVE) "\n\t"
Avi Kivity74547662012-09-16 15:10:59 +03004556 "pop %%" _ASM_AX " \n\t"
Avi Kivity6aa8b732006-12-10 02:21:36 -08004557
4558 /* Save guest registers, load host registers */
Avi Kivity74547662012-09-16 15:10:59 +03004559 "mov %%" _ASM_BX ", %c[rbx](%[svm]) \n\t"
4560 "mov %%" _ASM_CX ", %c[rcx](%[svm]) \n\t"
4561 "mov %%" _ASM_DX ", %c[rdx](%[svm]) \n\t"
4562 "mov %%" _ASM_SI ", %c[rsi](%[svm]) \n\t"
4563 "mov %%" _ASM_DI ", %c[rdi](%[svm]) \n\t"
4564 "mov %%" _ASM_BP ", %c[rbp](%[svm]) \n\t"
Avi Kivity05b3e0c2006-12-13 00:33:45 -08004565#ifdef CONFIG_X86_64
Rusty Russellfb3f0f52007-07-27 17:16:56 +10004566 "mov %%r8, %c[r8](%[svm]) \n\t"
4567 "mov %%r9, %c[r9](%[svm]) \n\t"
4568 "mov %%r10, %c[r10](%[svm]) \n\t"
4569 "mov %%r11, %c[r11](%[svm]) \n\t"
4570 "mov %%r12, %c[r12](%[svm]) \n\t"
4571 "mov %%r13, %c[r13](%[svm]) \n\t"
4572 "mov %%r14, %c[r14](%[svm]) \n\t"
4573 "mov %%r15, %c[r15](%[svm]) \n\t"
Avi Kivity6aa8b732006-12-10 02:21:36 -08004574#endif
Avi Kivity74547662012-09-16 15:10:59 +03004575 "pop %%" _ASM_BP
Avi Kivity6aa8b732006-12-10 02:21:36 -08004576 :
Rusty Russellfb3f0f52007-07-27 17:16:56 +10004577 : [svm]"a"(svm),
Avi Kivity6aa8b732006-12-10 02:21:36 -08004578 [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)),
Zhang Xiantaoad312c72007-12-13 23:50:52 +08004579 [rbx]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_RBX])),
4580 [rcx]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_RCX])),
4581 [rdx]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_RDX])),
4582 [rsi]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_RSI])),
4583 [rdi]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_RDI])),
4584 [rbp]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_RBP]))
Avi Kivity05b3e0c2006-12-13 00:33:45 -08004585#ifdef CONFIG_X86_64
Zhang Xiantaoad312c72007-12-13 23:50:52 +08004586 , [r8]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R8])),
4587 [r9]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R9])),
4588 [r10]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R10])),
4589 [r11]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R11])),
4590 [r12]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R12])),
4591 [r13]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R13])),
4592 [r14]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R14])),
4593 [r15]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R15]))
Avi Kivity6aa8b732006-12-10 02:21:36 -08004594#endif
Laurent Vivier54a08c02007-10-25 14:18:53 +02004595 : "cc", "memory"
4596#ifdef CONFIG_X86_64
Avi Kivity74547662012-09-16 15:10:59 +03004597 , "rbx", "rcx", "rdx", "rsi", "rdi"
Laurent Vivier54a08c02007-10-25 14:18:53 +02004598 , "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15"
Avi Kivity74547662012-09-16 15:10:59 +03004599#else
4600 , "ebx", "ecx", "edx", "esi", "edi"
Laurent Vivier54a08c02007-10-25 14:18:53 +02004601#endif
4602 );
Avi Kivity6aa8b732006-12-10 02:21:36 -08004603
Avi Kivity82ca2d12010-10-21 12:20:34 +02004604#ifdef CONFIG_X86_64
4605 wrmsrl(MSR_GS_BASE, svm->host.gs_base);
4606#else
Avi Kivitydacccfd2010-10-21 12:20:33 +02004607 loadsegment(fs, svm->host.fs);
Avi Kivity831ca602011-03-08 16:09:51 +02004608#ifndef CONFIG_X86_32_LAZY_GS
4609 loadsegment(gs, svm->host.gs);
4610#endif
Avi Kivity9581d442010-10-19 16:46:55 +02004611#endif
Avi Kivity6aa8b732006-12-10 02:21:36 -08004612
4613 reload_tss(vcpu);
4614
Avi Kivity56ba47d2007-11-07 17:14:18 +02004615 local_irq_disable();
4616
Avi Kivity13c34e02010-10-21 12:20:31 +02004617 vcpu->arch.cr2 = svm->vmcb->save.cr2;
4618 vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
4619 vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
4620 vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
4621
Joerg Roedel3781c012011-01-14 16:45:02 +01004622 if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
4623 kvm_before_handle_nmi(&svm->vcpu);
4624
4625 stgi();
4626
4627 /* Any pending NMI will happen here */
4628
4629 if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
4630 kvm_after_handle_nmi(&svm->vcpu);
4631
Joerg Roedeld7bf8222008-04-16 16:51:17 +02004632 sync_cr8_to_lapic(vcpu);
4633
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04004634 svm->next_rip = 0;
Gleb Natapov9222be12009-04-23 17:14:37 +03004635
Joerg Roedel38e5e922010-12-03 15:25:16 +01004636 svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
4637
Gleb Natapov631bc482010-10-14 11:22:52 +02004638 /* if exit due to PF check for async PF */
4639 if (svm->vmcb->control.exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR)
4640 svm->apf_reason = kvm_read_and_reset_pf_reason();
4641
Avi Kivity6de4f3a2009-05-31 22:58:47 +03004642 if (npt_enabled) {
4643 vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR);
4644 vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR);
4645 }
Joerg Roedelfe5913e2010-05-17 14:43:34 +02004646
4647 /*
4648 * We need to handle MC intercepts here before the vcpu has a chance to
4649 * change the physical cpu
4650 */
4651 if (unlikely(svm->vmcb->control.exit_code ==
4652 SVM_EXIT_EXCP_BASE + MC_VECTOR))
4653 svm_handle_mce(svm);
Roedel, Joerg8d28fec2010-12-03 13:15:21 +01004654
4655 mark_all_clean(svm->vmcb);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004656}
4657
Avi Kivity6aa8b732006-12-10 02:21:36 -08004658static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
4659{
Gregory Haskinsa2fa3e92007-07-27 08:13:10 -04004660 struct vcpu_svm *svm = to_svm(vcpu);
4661
4662 svm->vmcb->save.cr3 = root;
Joerg Roedeldcca1a62010-12-03 11:45:54 +01004663 mark_dirty(svm->vmcb, VMCB_CR);
Joerg Roedelf40f6a42010-12-03 15:25:15 +01004664 svm_flush_tlb(vcpu);
Avi Kivity6aa8b732006-12-10 02:21:36 -08004665}
4666
Joerg Roedel1c97f0a2010-09-10 17:30:41 +02004667static void set_tdp_cr3(struct kvm_vcpu *vcpu, unsigned long root)
4668{
4669 struct vcpu_svm *svm = to_svm(vcpu);
4670
4671 svm->vmcb->control.nested_cr3 = root;
Joerg Roedelb2747162010-12-03 11:45:53 +01004672 mark_dirty(svm->vmcb, VMCB_NPT);
Joerg Roedel1c97f0a2010-09-10 17:30:41 +02004673
4674 /* Also sync guest cr3 here in case we live migrate */
Avi Kivity9f8fe502010-12-05 17:30:00 +02004675 svm->vmcb->save.cr3 = kvm_read_cr3(vcpu);
Joerg Roedeldcca1a62010-12-03 11:45:54 +01004676 mark_dirty(svm->vmcb, VMCB_CR);
Joerg Roedel1c97f0a2010-09-10 17:30:41 +02004677
Joerg Roedelf40f6a42010-12-03 15:25:15 +01004678 svm_flush_tlb(vcpu);
Joerg Roedel1c97f0a2010-09-10 17:30:41 +02004679}
4680
Avi Kivity6aa8b732006-12-10 02:21:36 -08004681static int is_disabled(void)
4682{
Joerg Roedel6031a612007-06-22 12:29:50 +03004683 u64 vm_cr;
4684
4685 rdmsrl(MSR_VM_CR, vm_cr);
4686 if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE))
4687 return 1;
4688
Avi Kivity6aa8b732006-12-10 02:21:36 -08004689 return 0;
4690}
4691
Ingo Molnar102d8322007-02-19 14:37:47 +02004692static void
4693svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
4694{
4695 /*
4696 * Patch in the VMMCALL instruction:
4697 */
4698 hypercall[0] = 0x0f;
4699 hypercall[1] = 0x01;
4700 hypercall[2] = 0xd9;
Ingo Molnar102d8322007-02-19 14:37:47 +02004701}
4702
Yang, Sheng002c7f72007-07-31 14:23:01 +03004703static void svm_check_processor_compat(void *rtn)
4704{
4705 *(int *)rtn = 0;
4706}
4707
Avi Kivity774ead32007-12-26 13:57:04 +02004708static bool svm_cpu_has_accelerated_tpr(void)
4709{
4710 return false;
4711}
4712
Paolo Bonzini6d396b52015-04-01 14:25:33 +02004713static bool svm_has_high_real_mode_segbase(void)
4714{
4715 return true;
4716}
4717
Paolo Bonzinifc07e762015-10-01 13:20:22 +02004718static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
4719{
4720 return 0;
4721}
4722
Sheng Yang0e851882009-12-18 16:48:46 +08004723static void svm_cpuid_update(struct kvm_vcpu *vcpu)
4724{
Joerg Roedel6092d3d2015-10-14 15:10:54 +02004725 struct vcpu_svm *svm = to_svm(vcpu);
Suravee Suthikulpanit46781ea2016-05-04 14:09:50 -05004726 struct kvm_cpuid_entry2 *entry;
Joerg Roedel6092d3d2015-10-14 15:10:54 +02004727
4728 /* Update nrips enabled cache */
4729 svm->nrips_enabled = !!guest_cpuid_has_nrips(&svm->vcpu);
Suravee Suthikulpanit46781ea2016-05-04 14:09:50 -05004730
4731 if (!kvm_vcpu_apicv_active(vcpu))
4732 return;
4733
4734 entry = kvm_find_cpuid_entry(vcpu, 1, 0);
4735 if (entry)
4736 entry->ecx &= ~bit(X86_FEATURE_X2APIC);
Sheng Yang0e851882009-12-18 16:48:46 +08004737}
4738
Joerg Roedeld4330ef2010-04-22 12:33:11 +02004739static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
4740{
Joerg Roedelc2c63a42010-04-22 12:33:12 +02004741 switch (func) {
Suravee Suthikulpanit46781ea2016-05-04 14:09:50 -05004742 case 0x1:
4743 if (avic)
4744 entry->ecx &= ~bit(X86_FEATURE_X2APIC);
4745 break;
Joerg Roedel4c62a2d2010-09-10 17:31:06 +02004746 case 0x80000001:
4747 if (nested)
4748 entry->ecx |= (1 << 2); /* Set SVM bit */
4749 break;
Joerg Roedelc2c63a42010-04-22 12:33:12 +02004750 case 0x8000000A:
4751 entry->eax = 1; /* SVM revision 1 */
4752 entry->ebx = 8; /* Lets support 8 ASIDs in case we add proper
4753 ASID emulation to nested SVM */
4754 entry->ecx = 0; /* Reserved */
Joerg Roedel7a190662010-07-27 18:14:21 +02004755 entry->edx = 0; /* Per default do not support any
4756 additional features */
4757
4758 /* Support next_rip if host supports it */
Avi Kivity2a6b20b2010-11-09 16:15:42 +02004759 if (boot_cpu_has(X86_FEATURE_NRIPS))
Joerg Roedel7a190662010-07-27 18:14:21 +02004760 entry->edx |= SVM_FEATURE_NRIP;
Joerg Roedelc2c63a42010-04-22 12:33:12 +02004761
Joerg Roedel3d4aeaa2010-09-10 17:31:05 +02004762 /* Support NPT for the guest if enabled */
4763 if (npt_enabled)
4764 entry->edx |= SVM_FEATURE_NPT;
4765
Joerg Roedelc2c63a42010-04-22 12:33:12 +02004766 break;
4767 }
Joerg Roedeld4330ef2010-04-22 12:33:11 +02004768}
4769
Sheng Yang17cc3932010-01-05 19:02:27 +08004770static int svm_get_lpage_level(void)
Joerg Roedel344f4142009-07-27 16:30:48 +02004771{
Sheng Yang17cc3932010-01-05 19:02:27 +08004772 return PT_PDPE_LEVEL;
Joerg Roedel344f4142009-07-27 16:30:48 +02004773}
4774
Sheng Yang4e47c7a2009-12-18 16:48:47 +08004775static bool svm_rdtscp_supported(void)
4776{
Paolo Bonzini46896c72015-11-12 14:49:16 +01004777 return boot_cpu_has(X86_FEATURE_RDTSCP);
Sheng Yang4e47c7a2009-12-18 16:48:47 +08004778}
4779
Mao, Junjiead756a12012-07-02 01:18:48 +00004780static bool svm_invpcid_supported(void)
4781{
4782 return false;
4783}
4784
Paolo Bonzini93c4adc2014-03-05 23:19:52 +01004785static bool svm_mpx_supported(void)
4786{
4787 return false;
4788}
4789
Wanpeng Li55412b22014-12-02 19:21:30 +08004790static bool svm_xsaves_supported(void)
4791{
4792 return false;
4793}
4794
Sheng Yangf5f48ee2010-06-30 12:25:15 +08004795static bool svm_has_wbinvd_exit(void)
4796{
4797 return true;
4798}
4799
Avi Kivity02daab22009-12-30 12:40:26 +02004800static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
4801{
4802 struct vcpu_svm *svm = to_svm(vcpu);
4803
Joerg Roedel18c918c2010-11-30 18:03:59 +01004804 set_exception_intercept(svm, NM_VECTOR);
Joerg Roedel66a562f2010-02-19 16:23:08 +01004805 update_cr0_intercept(svm);
Avi Kivity02daab22009-12-30 12:40:26 +02004806}
4807
Joerg Roedel80612522011-04-04 12:39:33 +02004808#define PRE_EX(exit) { .exit_code = (exit), \
Avi Kivity40e19b52011-04-21 12:35:41 +03004809 .stage = X86_ICPT_PRE_EXCEPT, }
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004810#define POST_EX(exit) { .exit_code = (exit), \
Avi Kivity40e19b52011-04-21 12:35:41 +03004811 .stage = X86_ICPT_POST_EXCEPT, }
Joerg Roedeld7eb8202011-04-04 12:39:32 +02004812#define POST_MEM(exit) { .exit_code = (exit), \
Avi Kivity40e19b52011-04-21 12:35:41 +03004813 .stage = X86_ICPT_POST_MEMACCESS, }
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004814
Mathias Krause09941fb2012-08-30 01:30:20 +02004815static const struct __x86_intercept {
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004816 u32 exit_code;
4817 enum x86_intercept_stage stage;
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004818} x86_intercept_map[] = {
4819 [x86_intercept_cr_read] = POST_EX(SVM_EXIT_READ_CR0),
4820 [x86_intercept_cr_write] = POST_EX(SVM_EXIT_WRITE_CR0),
4821 [x86_intercept_clts] = POST_EX(SVM_EXIT_WRITE_CR0),
4822 [x86_intercept_lmsw] = POST_EX(SVM_EXIT_WRITE_CR0),
4823 [x86_intercept_smsw] = POST_EX(SVM_EXIT_READ_CR0),
Joerg Roedel3b88e412011-04-04 12:39:29 +02004824 [x86_intercept_dr_read] = POST_EX(SVM_EXIT_READ_DR0),
4825 [x86_intercept_dr_write] = POST_EX(SVM_EXIT_WRITE_DR0),
Joerg Roedeldee6bb72011-04-04 12:39:30 +02004826 [x86_intercept_sldt] = POST_EX(SVM_EXIT_LDTR_READ),
4827 [x86_intercept_str] = POST_EX(SVM_EXIT_TR_READ),
4828 [x86_intercept_lldt] = POST_EX(SVM_EXIT_LDTR_WRITE),
4829 [x86_intercept_ltr] = POST_EX(SVM_EXIT_TR_WRITE),
4830 [x86_intercept_sgdt] = POST_EX(SVM_EXIT_GDTR_READ),
4831 [x86_intercept_sidt] = POST_EX(SVM_EXIT_IDTR_READ),
4832 [x86_intercept_lgdt] = POST_EX(SVM_EXIT_GDTR_WRITE),
4833 [x86_intercept_lidt] = POST_EX(SVM_EXIT_IDTR_WRITE),
Joerg Roedel01de8b02011-04-04 12:39:31 +02004834 [x86_intercept_vmrun] = POST_EX(SVM_EXIT_VMRUN),
4835 [x86_intercept_vmmcall] = POST_EX(SVM_EXIT_VMMCALL),
4836 [x86_intercept_vmload] = POST_EX(SVM_EXIT_VMLOAD),
4837 [x86_intercept_vmsave] = POST_EX(SVM_EXIT_VMSAVE),
4838 [x86_intercept_stgi] = POST_EX(SVM_EXIT_STGI),
4839 [x86_intercept_clgi] = POST_EX(SVM_EXIT_CLGI),
4840 [x86_intercept_skinit] = POST_EX(SVM_EXIT_SKINIT),
4841 [x86_intercept_invlpga] = POST_EX(SVM_EXIT_INVLPGA),
Joerg Roedeld7eb8202011-04-04 12:39:32 +02004842 [x86_intercept_rdtscp] = POST_EX(SVM_EXIT_RDTSCP),
4843 [x86_intercept_monitor] = POST_MEM(SVM_EXIT_MONITOR),
4844 [x86_intercept_mwait] = POST_EX(SVM_EXIT_MWAIT),
Joerg Roedel80612522011-04-04 12:39:33 +02004845 [x86_intercept_invlpg] = POST_EX(SVM_EXIT_INVLPG),
4846 [x86_intercept_invd] = POST_EX(SVM_EXIT_INVD),
4847 [x86_intercept_wbinvd] = POST_EX(SVM_EXIT_WBINVD),
4848 [x86_intercept_wrmsr] = POST_EX(SVM_EXIT_MSR),
4849 [x86_intercept_rdtsc] = POST_EX(SVM_EXIT_RDTSC),
4850 [x86_intercept_rdmsr] = POST_EX(SVM_EXIT_MSR),
4851 [x86_intercept_rdpmc] = POST_EX(SVM_EXIT_RDPMC),
4852 [x86_intercept_cpuid] = PRE_EX(SVM_EXIT_CPUID),
4853 [x86_intercept_rsm] = PRE_EX(SVM_EXIT_RSM),
Joerg Roedelbf608f82011-04-04 12:39:34 +02004854 [x86_intercept_pause] = PRE_EX(SVM_EXIT_PAUSE),
4855 [x86_intercept_pushf] = PRE_EX(SVM_EXIT_PUSHF),
4856 [x86_intercept_popf] = PRE_EX(SVM_EXIT_POPF),
4857 [x86_intercept_intn] = PRE_EX(SVM_EXIT_SWINT),
4858 [x86_intercept_iret] = PRE_EX(SVM_EXIT_IRET),
4859 [x86_intercept_icebp] = PRE_EX(SVM_EXIT_ICEBP),
4860 [x86_intercept_hlt] = POST_EX(SVM_EXIT_HLT),
Joerg Roedelf6511932011-04-04 12:39:35 +02004861 [x86_intercept_in] = POST_EX(SVM_EXIT_IOIO),
4862 [x86_intercept_ins] = POST_EX(SVM_EXIT_IOIO),
4863 [x86_intercept_out] = POST_EX(SVM_EXIT_IOIO),
4864 [x86_intercept_outs] = POST_EX(SVM_EXIT_IOIO),
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004865};
4866
Joerg Roedel80612522011-04-04 12:39:33 +02004867#undef PRE_EX
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004868#undef POST_EX
Joerg Roedeld7eb8202011-04-04 12:39:32 +02004869#undef POST_MEM
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004870
Joerg Roedel8a76d7f2011-04-04 12:39:27 +02004871static int svm_check_intercept(struct kvm_vcpu *vcpu,
4872 struct x86_instruction_info *info,
4873 enum x86_intercept_stage stage)
4874{
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004875 struct vcpu_svm *svm = to_svm(vcpu);
4876 int vmexit, ret = X86EMUL_CONTINUE;
4877 struct __x86_intercept icpt_info;
4878 struct vmcb *vmcb = svm->vmcb;
4879
4880 if (info->intercept >= ARRAY_SIZE(x86_intercept_map))
4881 goto out;
4882
4883 icpt_info = x86_intercept_map[info->intercept];
4884
Avi Kivity40e19b52011-04-21 12:35:41 +03004885 if (stage != icpt_info.stage)
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004886 goto out;
4887
4888 switch (icpt_info.exit_code) {
4889 case SVM_EXIT_READ_CR0:
4890 if (info->intercept == x86_intercept_cr_read)
4891 icpt_info.exit_code += info->modrm_reg;
4892 break;
4893 case SVM_EXIT_WRITE_CR0: {
4894 unsigned long cr0, val;
4895 u64 intercept;
4896
4897 if (info->intercept == x86_intercept_cr_write)
4898 icpt_info.exit_code += info->modrm_reg;
4899
Jan Kiszka62baf442014-06-29 21:55:53 +02004900 if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0 ||
4901 info->intercept == x86_intercept_clts)
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004902 break;
4903
4904 intercept = svm->nested.intercept;
4905
4906 if (!(intercept & (1ULL << INTERCEPT_SELECTIVE_CR0)))
4907 break;
4908
4909 cr0 = vcpu->arch.cr0 & ~SVM_CR0_SELECTIVE_MASK;
4910 val = info->src_val & ~SVM_CR0_SELECTIVE_MASK;
4911
4912 if (info->intercept == x86_intercept_lmsw) {
4913 cr0 &= 0xfUL;
4914 val &= 0xfUL;
4915 /* lmsw can't clear PE - catch this here */
4916 if (cr0 & X86_CR0_PE)
4917 val |= X86_CR0_PE;
4918 }
4919
4920 if (cr0 ^ val)
4921 icpt_info.exit_code = SVM_EXIT_CR0_SEL_WRITE;
4922
4923 break;
4924 }
Joerg Roedel3b88e412011-04-04 12:39:29 +02004925 case SVM_EXIT_READ_DR0:
4926 case SVM_EXIT_WRITE_DR0:
4927 icpt_info.exit_code += info->modrm_reg;
4928 break;
Joerg Roedel80612522011-04-04 12:39:33 +02004929 case SVM_EXIT_MSR:
4930 if (info->intercept == x86_intercept_wrmsr)
4931 vmcb->control.exit_info_1 = 1;
4932 else
4933 vmcb->control.exit_info_1 = 0;
4934 break;
Joerg Roedelbf608f82011-04-04 12:39:34 +02004935 case SVM_EXIT_PAUSE:
4936 /*
4937 * We get this for NOP only, but pause
4938 * is rep not, check this here
4939 */
4940 if (info->rep_prefix != REPE_PREFIX)
4941 goto out;
Joerg Roedelf6511932011-04-04 12:39:35 +02004942 case SVM_EXIT_IOIO: {
4943 u64 exit_info;
4944 u32 bytes;
4945
Joerg Roedelf6511932011-04-04 12:39:35 +02004946 if (info->intercept == x86_intercept_in ||
4947 info->intercept == x86_intercept_ins) {
Jan Kiszka6cbc5f52014-06-30 12:52:55 +02004948 exit_info = ((info->src_val & 0xffff) << 16) |
4949 SVM_IOIO_TYPE_MASK;
Joerg Roedelf6511932011-04-04 12:39:35 +02004950 bytes = info->dst_bytes;
Jan Kiszka6493f152014-06-30 11:07:05 +02004951 } else {
Jan Kiszka6cbc5f52014-06-30 12:52:55 +02004952 exit_info = (info->dst_val & 0xffff) << 16;
Jan Kiszka6493f152014-06-30 11:07:05 +02004953 bytes = info->src_bytes;
Joerg Roedelf6511932011-04-04 12:39:35 +02004954 }
4955
4956 if (info->intercept == x86_intercept_outs ||
4957 info->intercept == x86_intercept_ins)
4958 exit_info |= SVM_IOIO_STR_MASK;
4959
4960 if (info->rep_prefix)
4961 exit_info |= SVM_IOIO_REP_MASK;
4962
4963 bytes = min(bytes, 4u);
4964
4965 exit_info |= bytes << SVM_IOIO_SIZE_SHIFT;
4966
4967 exit_info |= (u32)info->ad_bytes << (SVM_IOIO_ASIZE_SHIFT - 1);
4968
4969 vmcb->control.exit_info_1 = exit_info;
4970 vmcb->control.exit_info_2 = info->next_rip;
4971
4972 break;
4973 }
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004974 default:
4975 break;
4976 }
4977
Bandan Dasf1047652015-06-11 02:05:33 -04004978 /* TODO: Advertise NRIPS to guest hypervisor unconditionally */
4979 if (static_cpu_has(X86_FEATURE_NRIPS))
4980 vmcb->control.next_rip = info->next_rip;
Joerg Roedelcfec82c2011-04-04 12:39:28 +02004981 vmcb->control.exit_code = icpt_info.exit_code;
4982 vmexit = nested_svm_exit_handled(svm);
4983
4984 ret = (vmexit == NESTED_EXIT_DONE) ? X86EMUL_INTERCEPTED
4985 : X86EMUL_CONTINUE;
4986
4987out:
4988 return ret;
Joerg Roedel8a76d7f2011-04-04 12:39:27 +02004989}
4990
Yang Zhanga547c6d2013-04-11 19:25:10 +08004991static void svm_handle_external_intr(struct kvm_vcpu *vcpu)
4992{
4993 local_irq_enable();
Paolo Bonzinif2485b32016-06-15 15:23:11 +02004994 /*
4995 * We must have an instruction with interrupts enabled, so
4996 * the timer interrupt isn't delayed by the interrupt shadow.
4997 */
4998 asm("nop");
4999 local_irq_disable();
Yang Zhanga547c6d2013-04-11 19:25:10 +08005000}
5001
Radim Krčmářae97a3b2014-08-21 18:08:06 +02005002static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
5003{
5004}
5005
Suravee Suthikulpanitbe8ca172016-05-04 14:09:49 -05005006static inline void avic_post_state_restore(struct kvm_vcpu *vcpu)
5007{
5008 if (avic_handle_apic_id_update(vcpu) != 0)
5009 return;
5010 if (avic_handle_dfr_update(vcpu) != 0)
5011 return;
5012 avic_handle_ldr_update(vcpu);
5013}
5014
Christian Ehrhardtcbdd1be2007-09-09 15:41:59 +03005015static struct kvm_x86_ops svm_x86_ops = {
Avi Kivity6aa8b732006-12-10 02:21:36 -08005016 .cpu_has_kvm_support = has_svm,
5017 .disabled_by_bios = is_disabled,
5018 .hardware_setup = svm_hardware_setup,
5019 .hardware_unsetup = svm_hardware_unsetup,
Yang, Sheng002c7f72007-07-31 14:23:01 +03005020 .check_processor_compatibility = svm_check_processor_compat,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005021 .hardware_enable = svm_hardware_enable,
5022 .hardware_disable = svm_hardware_disable,
Avi Kivity774ead32007-12-26 13:57:04 +02005023 .cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
Paolo Bonzini6d396b52015-04-01 14:25:33 +02005024 .cpu_has_high_real_mode_segbase = svm_has_high_real_mode_segbase,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005025
5026 .vcpu_create = svm_create_vcpu,
5027 .vcpu_free = svm_free_vcpu,
Avi Kivity04d2cc72007-09-10 18:10:54 +03005028 .vcpu_reset = svm_vcpu_reset,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005029
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05005030 .vm_init = avic_vm_init,
5031 .vm_destroy = avic_vm_destroy,
5032
Avi Kivity04d2cc72007-09-10 18:10:54 +03005033 .prepare_guest_switch = svm_prepare_guest_switch,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005034 .vcpu_load = svm_vcpu_load,
5035 .vcpu_put = svm_vcpu_put,
Suravee Suthikulpanit8221c132016-05-04 14:09:52 -05005036 .vcpu_blocking = svm_vcpu_blocking,
5037 .vcpu_unblocking = svm_vcpu_unblocking,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005038
Paolo Bonzinia96036b2015-11-10 11:55:36 +01005039 .update_bp_intercept = update_bp_intercept,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005040 .get_msr = svm_get_msr,
5041 .set_msr = svm_set_msr,
5042 .get_segment_base = svm_get_segment_base,
5043 .get_segment = svm_get_segment,
5044 .set_segment = svm_set_segment,
Izik Eidus2e4d2652008-03-24 19:38:34 +02005045 .get_cpl = svm_get_cpl,
Rusty Russell1747fb72007-09-06 01:21:32 +10005046 .get_cs_db_l_bits = kvm_get_cs_db_l_bits,
Avi Kivitye8467fd2009-12-29 18:43:06 +02005047 .decache_cr0_guest_bits = svm_decache_cr0_guest_bits,
Avi Kivityaff48ba2010-12-05 18:56:11 +02005048 .decache_cr3 = svm_decache_cr3,
Anthony Liguori25c4c272007-04-27 09:29:21 +03005049 .decache_cr4_guest_bits = svm_decache_cr4_guest_bits,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005050 .set_cr0 = svm_set_cr0,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005051 .set_cr3 = svm_set_cr3,
5052 .set_cr4 = svm_set_cr4,
5053 .set_efer = svm_set_efer,
5054 .get_idt = svm_get_idt,
5055 .set_idt = svm_set_idt,
5056 .get_gdt = svm_get_gdt,
5057 .set_gdt = svm_set_gdt,
Jan Kiszka73aaf249e2014-01-04 18:47:16 +01005058 .get_dr6 = svm_get_dr6,
5059 .set_dr6 = svm_set_dr6,
Gleb Natapov020df072010-04-13 10:05:23 +03005060 .set_dr7 = svm_set_dr7,
Paolo Bonzinifacb0132014-02-21 10:32:27 +01005061 .sync_dirty_debug_regs = svm_sync_dirty_debug_regs,
Avi Kivity6de4f3a2009-05-31 22:58:47 +03005062 .cache_reg = svm_cache_reg,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005063 .get_rflags = svm_get_rflags,
5064 .set_rflags = svm_set_rflags,
Huaitong Hanbe94f6b2016-03-22 16:51:20 +08005065
5066 .get_pkru = svm_get_pkru,
5067
Paolo Bonzini0fdd74f2015-05-20 11:33:43 +02005068 .fpu_activate = svm_fpu_activate,
Avi Kivity02daab22009-12-30 12:40:26 +02005069 .fpu_deactivate = svm_fpu_deactivate,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005070
Avi Kivity6aa8b732006-12-10 02:21:36 -08005071 .tlb_flush = svm_flush_tlb,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005072
Avi Kivity6aa8b732006-12-10 02:21:36 -08005073 .run = svm_vcpu_run,
Avi Kivity04d2cc72007-09-10 18:10:54 +03005074 .handle_exit = handle_exit,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005075 .skip_emulated_instruction = skip_emulated_instruction,
Glauber Costa2809f5d2009-05-12 16:21:05 -04005076 .set_interrupt_shadow = svm_set_interrupt_shadow,
5077 .get_interrupt_shadow = svm_get_interrupt_shadow,
Ingo Molnar102d8322007-02-19 14:37:47 +02005078 .patch_hypercall = svm_patch_hypercall,
Eddie Dong2a8067f2007-08-06 16:29:07 +03005079 .set_irq = svm_set_irq,
Gleb Natapov95ba8273132009-04-21 17:45:08 +03005080 .set_nmi = svm_inject_nmi,
Avi Kivity298101d2007-11-25 13:41:11 +02005081 .queue_exception = svm_queue_exception,
Avi Kivityb463a6f2010-07-20 15:06:17 +03005082 .cancel_injection = svm_cancel_injection,
Gleb Natapov78646122009-03-23 12:12:11 +02005083 .interrupt_allowed = svm_interrupt_allowed,
Gleb Natapov95ba8273132009-04-21 17:45:08 +03005084 .nmi_allowed = svm_nmi_allowed,
Jan Kiszka3cfc3092009-11-12 01:04:25 +01005085 .get_nmi_mask = svm_get_nmi_mask,
5086 .set_nmi_mask = svm_set_nmi_mask,
Gleb Natapov95ba8273132009-04-21 17:45:08 +03005087 .enable_nmi_window = enable_nmi_window,
5088 .enable_irq_window = enable_irq_window,
5089 .update_cr8_intercept = update_cr8_intercept,
Yang Zhang8d146952013-01-25 10:18:50 +08005090 .set_virtual_x2apic_mode = svm_set_virtual_x2apic_mode,
Andrey Smetanind62caab2015-11-10 15:36:33 +03005091 .get_enable_apicv = svm_get_enable_apicv,
5092 .refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
Yang Zhangc7c9c562013-01-25 10:18:51 +08005093 .load_eoi_exitmap = svm_load_eoi_exitmap,
Yang Zhanga20ed542013-04-11 19:25:15 +08005094 .sync_pir_to_irr = svm_sync_pir_to_irr,
Suravee Suthikulpanit44a95da2016-05-04 14:09:46 -05005095 .hwapic_irr_update = svm_hwapic_irr_update,
5096 .hwapic_isr_update = svm_hwapic_isr_update,
Suravee Suthikulpanitbe8ca172016-05-04 14:09:49 -05005097 .apicv_post_state_restore = avic_post_state_restore,
Izik Eiduscbc94022007-10-25 00:29:55 +02005098
5099 .set_tss_addr = svm_set_tss_addr,
Sheng Yang67253af2008-04-25 10:20:22 +08005100 .get_tdp_level = get_npt_level,
Sheng Yang4b12f0d2009-04-27 20:35:42 +08005101 .get_mt_mask = svm_get_mt_mask,
Marcelo Tosatti229456f2009-06-17 09:22:14 -03005102
Avi Kivity586f9602010-11-18 13:09:54 +02005103 .get_exit_info = svm_get_exit_info,
Avi Kivity586f9602010-11-18 13:09:54 +02005104
Sheng Yang17cc3932010-01-05 19:02:27 +08005105 .get_lpage_level = svm_get_lpage_level,
Sheng Yang0e851882009-12-18 16:48:46 +08005106
5107 .cpuid_update = svm_cpuid_update,
Sheng Yang4e47c7a2009-12-18 16:48:47 +08005108
5109 .rdtscp_supported = svm_rdtscp_supported,
Mao, Junjiead756a12012-07-02 01:18:48 +00005110 .invpcid_supported = svm_invpcid_supported,
Paolo Bonzini93c4adc2014-03-05 23:19:52 +01005111 .mpx_supported = svm_mpx_supported,
Wanpeng Li55412b22014-12-02 19:21:30 +08005112 .xsaves_supported = svm_xsaves_supported,
Joerg Roedeld4330ef2010-04-22 12:33:11 +02005113
5114 .set_supported_cpuid = svm_set_supported_cpuid,
Sheng Yangf5f48ee2010-06-30 12:25:15 +08005115
5116 .has_wbinvd_exit = svm_has_wbinvd_exit,
Zachary Amsden99e3e302010-08-19 22:07:17 -10005117
Will Auldba904632012-11-29 12:42:50 -08005118 .read_tsc_offset = svm_read_tsc_offset,
Zachary Amsden99e3e302010-08-19 22:07:17 -10005119 .write_tsc_offset = svm_write_tsc_offset,
Haozhong Zhang58ea6762015-10-20 15:39:06 +08005120 .adjust_tsc_offset_guest = svm_adjust_tsc_offset_guest,
Nadav Har'Eld5c17852011-08-02 15:54:20 +03005121 .read_l1_tsc = svm_read_l1_tsc,
Joerg Roedel1c97f0a2010-09-10 17:30:41 +02005122
5123 .set_tdp_cr3 = set_tdp_cr3,
Joerg Roedel8a76d7f2011-04-04 12:39:27 +02005124
5125 .check_intercept = svm_check_intercept,
Yang Zhanga547c6d2013-04-11 19:25:10 +08005126 .handle_external_intr = svm_handle_external_intr,
Radim Krčmářae97a3b2014-08-21 18:08:06 +02005127
5128 .sched_in = svm_sched_in,
Wei Huang25462f72015-06-19 15:45:05 +02005129
5130 .pmu_ops = &amd_pmu_ops,
Suravee Suthikulpanit340d3bc2016-05-04 14:09:47 -05005131 .deliver_posted_interrupt = svm_deliver_avic_intr,
Avi Kivity6aa8b732006-12-10 02:21:36 -08005132};
5133
5134static int __init svm_init(void)
5135{
Zhang Xiantaocb498ea2007-11-14 20:39:31 +08005136 return kvm_init(&svm_x86_ops, sizeof(struct vcpu_svm),
Avi Kivity0ee75be2010-04-28 15:39:01 +03005137 __alignof__(struct vcpu_svm), THIS_MODULE);
Avi Kivity6aa8b732006-12-10 02:21:36 -08005138}
5139
5140static void __exit svm_exit(void)
5141{
Zhang Xiantaocb498ea2007-11-14 20:39:31 +08005142 kvm_exit();
Avi Kivity6aa8b732006-12-10 02:21:36 -08005143}
5144
5145module_init(svm_init)
5146module_exit(svm_exit)