aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>2016-05-04 15:09:46 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2016-05-18 12:04:28 -0400
commit44a95dae1d229a4967bbfcc56fb2116a9b4fe942 (patch)
treea4d63ca6d968ca8878b9e6d833c6c0b16f59be39
parent3d5615e5342781453633af7107d72afd601b36a7 (diff)
KVM: x86: Detect and Initialize AVIC support
This patch introduces AVIC-related data structure, and AVIC initialization code. There are three main data structures for AVIC: * Virtual APIC (vAPIC) backing page (per-VCPU) * Physical APIC ID table (per-VM) * Logical APIC ID table (per-VM) Currently, AVIC is disabled by default. Users can manually enable AVIC via kernel boot option kvm-amd.avic=1 or during kvm-amd module loading with parameter avic=1. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> [Avoid extra indentation (Boris). - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h4
-rw-r--r--arch/x86/include/asm/svm.h3
-rw-r--r--arch/x86/kvm/svm.c225
3 files changed, 231 insertions, 1 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 2df5db6fb58b..337e13b0d01d 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -773,6 +773,10 @@ struct kvm_arch {
773 u8 nr_reserved_ioapic_pins; 773 u8 nr_reserved_ioapic_pins;
774 774
775 bool disabled_lapic_found; 775 bool disabled_lapic_found;
776
777 /* Struct members for AVIC */
778 struct page *avic_logical_id_table_page;
779 struct page *avic_physical_id_table_page;
776}; 780};
777 781
778struct kvm_vm_stat { 782struct kvm_vm_stat {
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 4711fa4457f3..d0fe23ec7e98 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -116,6 +116,9 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
116#define V_INTR_MASKING_SHIFT 24 116#define V_INTR_MASKING_SHIFT 24
117#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT) 117#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
118 118
119#define AVIC_ENABLE_SHIFT 31
120#define AVIC_ENABLE_MASK (1 << AVIC_ENABLE_SHIFT)
121
119#define SVM_INTERRUPT_SHADOW_MASK 1 122#define SVM_INTERRUPT_SHADOW_MASK 1
120 123
121#define SVM_IOIO_STR_SHIFT 2 124#define SVM_IOIO_STR_SHIFT 2
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 31346a3f20a5..192cad25d321 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -14,6 +14,9 @@
14 * the COPYING file in the top-level directory. 14 * the COPYING file in the top-level directory.
15 * 15 *
16 */ 16 */
17
18#define pr_fmt(fmt) "SVM: " fmt
19
17#include <linux/kvm_host.h> 20#include <linux/kvm_host.h>
18 21
19#include "irq.h" 22#include "irq.h"
@@ -78,6 +81,14 @@ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
78#define TSC_RATIO_MIN 0x0000000000000001ULL 81#define TSC_RATIO_MIN 0x0000000000000001ULL
79#define TSC_RATIO_MAX 0x000000ffffffffffULL 82#define TSC_RATIO_MAX 0x000000ffffffffffULL
80 83
84#define AVIC_HPA_MASK ~((0xFFFULL << 52) || 0xFFF)
85
86/*
87 * 0xff is broadcast, so the max index allowed for physical APIC ID
88 * table is 0xfe. APIC IDs above 0xff are reserved.
89 */
90#define AVIC_MAX_PHYSICAL_ID_COUNT 255
91
81static bool erratum_383_found __read_mostly; 92static bool erratum_383_found __read_mostly;
82 93
83static const u32 host_save_user_msrs[] = { 94static const u32 host_save_user_msrs[] = {
@@ -162,8 +173,19 @@ struct vcpu_svm {
162 173
163 /* cached guest cpuid flags for faster access */ 174 /* cached guest cpuid flags for faster access */
164 bool nrips_enabled : 1; 175 bool nrips_enabled : 1;
176
177 struct page *avic_backing_page;
178 u64 *avic_physical_id_cache;
165}; 179};
166 180
181#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFF)
182#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
183
184#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK (0xFFULL)
185#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
186#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
187#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
188
167static DEFINE_PER_CPU(u64, current_tsc_ratio); 189static DEFINE_PER_CPU(u64, current_tsc_ratio);
168#define TSC_RATIO_DEFAULT 0x0100000000ULL 190#define TSC_RATIO_DEFAULT 0x0100000000ULL
169 191
@@ -205,6 +227,10 @@ module_param(npt, int, S_IRUGO);
205static int nested = true; 227static int nested = true;
206module_param(nested, int, S_IRUGO); 228module_param(nested, int, S_IRUGO);
207 229
230/* enable / disable AVIC */
231static int avic;
232module_param(avic, int, S_IRUGO);
233
208static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); 234static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
209static void svm_flush_tlb(struct kvm_vcpu *vcpu); 235static void svm_flush_tlb(struct kvm_vcpu *vcpu);
210static void svm_complete_interrupts(struct vcpu_svm *svm); 236static void svm_complete_interrupts(struct vcpu_svm *svm);
@@ -228,12 +254,18 @@ enum {
228 VMCB_SEG, /* CS, DS, SS, ES, CPL */ 254 VMCB_SEG, /* CS, DS, SS, ES, CPL */
229 VMCB_CR2, /* CR2 only */ 255 VMCB_CR2, /* CR2 only */
230 VMCB_LBR, /* DBGCTL, BR_FROM, BR_TO, LAST_EX_FROM, LAST_EX_TO */ 256 VMCB_LBR, /* DBGCTL, BR_FROM, BR_TO, LAST_EX_FROM, LAST_EX_TO */
257 VMCB_AVIC, /* AVIC APIC_BAR, AVIC APIC_BACKING_PAGE,
258 * AVIC PHYSICAL_TABLE pointer,
259 * AVIC LOGICAL_TABLE pointer
260 */
231 VMCB_DIRTY_MAX, 261 VMCB_DIRTY_MAX,
232}; 262};
233 263
234/* TPR and CR2 are always written before VMRUN */ 264/* TPR and CR2 are always written before VMRUN */
235#define VMCB_ALWAYS_DIRTY_MASK ((1U << VMCB_INTR) | (1U << VMCB_CR2)) 265#define VMCB_ALWAYS_DIRTY_MASK ((1U << VMCB_INTR) | (1U << VMCB_CR2))
236 266
267#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
268
237static inline void mark_all_dirty(struct vmcb *vmcb) 269static inline void mark_all_dirty(struct vmcb *vmcb)
238{ 270{
239 vmcb->control.clean = 0; 271 vmcb->control.clean = 0;
@@ -255,6 +287,12 @@ static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
255 return container_of(vcpu, struct vcpu_svm, vcpu); 287 return container_of(vcpu, struct vcpu_svm, vcpu);
256} 288}
257 289
290static inline void avic_update_vapic_bar(struct vcpu_svm *svm, u64 data)
291{
292 svm->vmcb->control.avic_vapic_bar = data & VMCB_AVIC_APIC_BAR_MASK;
293 mark_dirty(svm->vmcb, VMCB_AVIC);
294}
295
258static void recalc_intercepts(struct vcpu_svm *svm) 296static void recalc_intercepts(struct vcpu_svm *svm)
259{ 297{
260 struct vmcb_control_area *c, *h; 298 struct vmcb_control_area *c, *h;
@@ -923,6 +961,12 @@ static __init int svm_hardware_setup(void)
923 } else 961 } else
924 kvm_disable_tdp(); 962 kvm_disable_tdp();
925 963
964 if (avic && (!npt_enabled || !boot_cpu_has(X86_FEATURE_AVIC)))
965 avic = false;
966
967 if (avic)
968 pr_info("AVIC enabled\n");
969
926 return 0; 970 return 0;
927 971
928err: 972err:
@@ -1000,6 +1044,22 @@ static void svm_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
1000 mark_dirty(svm->vmcb, VMCB_INTERCEPTS); 1044 mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
1001} 1045}
1002 1046
1047static void avic_init_vmcb(struct vcpu_svm *svm)
1048{
1049 struct vmcb *vmcb = svm->vmcb;
1050 struct kvm_arch *vm_data = &svm->vcpu.kvm->arch;
1051 phys_addr_t bpa = page_to_phys(svm->avic_backing_page);
1052 phys_addr_t lpa = page_to_phys(vm_data->avic_logical_id_table_page);
1053 phys_addr_t ppa = page_to_phys(vm_data->avic_physical_id_table_page);
1054
1055 vmcb->control.avic_backing_page = bpa & AVIC_HPA_MASK;
1056 vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK;
1057 vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK;
1058 vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT;
1059 vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
1060 svm->vcpu.arch.apicv_active = true;
1061}
1062
1003static void init_vmcb(struct vcpu_svm *svm) 1063static void init_vmcb(struct vcpu_svm *svm)
1004{ 1064{
1005 struct vmcb_control_area *control = &svm->vmcb->control; 1065 struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1110,9 +1170,131 @@ static void init_vmcb(struct vcpu_svm *svm)
1110 set_intercept(svm, INTERCEPT_PAUSE); 1170 set_intercept(svm, INTERCEPT_PAUSE);
1111 } 1171 }
1112 1172
1173 if (avic)
1174 avic_init_vmcb(svm);
1175
1113 mark_all_dirty(svm->vmcb); 1176 mark_all_dirty(svm->vmcb);
1114 1177
1115 enable_gif(svm); 1178 enable_gif(svm);
1179
1180}
1181
1182static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu, int index)
1183{
1184 u64 *avic_physical_id_table;
1185 struct kvm_arch *vm_data = &vcpu->kvm->arch;
1186
1187 if (index >= AVIC_MAX_PHYSICAL_ID_COUNT)
1188 return NULL;
1189
1190 avic_physical_id_table = page_address(vm_data->avic_physical_id_table_page);
1191
1192 return &avic_physical_id_table[index];
1193}
1194
1195/**
1196 * Note:
1197 * AVIC hardware walks the nested page table to check permissions,
1198 * but does not use the SPA address specified in the leaf page
1199 * table entry since it uses address in the AVIC_BACKING_PAGE pointer
1200 * field of the VMCB. Therefore, we set up the
1201 * APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (4KB) here.
1202 */
1203static int avic_init_access_page(struct kvm_vcpu *vcpu)
1204{
1205 struct kvm *kvm = vcpu->kvm;
1206 int ret;
1207
1208 if (kvm->arch.apic_access_page_done)
1209 return 0;
1210
1211 ret = x86_set_memory_region(kvm,
1212 APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
1213 APIC_DEFAULT_PHYS_BASE,
1214 PAGE_SIZE);
1215 if (ret)
1216 return ret;
1217
1218 kvm->arch.apic_access_page_done = true;
1219 return 0;
1220}
1221
1222static int avic_init_backing_page(struct kvm_vcpu *vcpu)
1223{
1224 int ret;
1225 u64 *entry, new_entry;
1226 int id = vcpu->vcpu_id;
1227 struct vcpu_svm *svm = to_svm(vcpu);
1228
1229 ret = avic_init_access_page(vcpu);
1230 if (ret)
1231 return ret;
1232
1233 if (id >= AVIC_MAX_PHYSICAL_ID_COUNT)
1234 return -EINVAL;
1235
1236 if (!svm->vcpu.arch.apic->regs)
1237 return -EINVAL;
1238
1239 svm->avic_backing_page = virt_to_page(svm->vcpu.arch.apic->regs);
1240
1241 /* Setting AVIC backing page address in the phy APIC ID table */
1242 entry = avic_get_physical_id_entry(vcpu, id);
1243 if (!entry)
1244 return -EINVAL;
1245
1246 new_entry = READ_ONCE(*entry);
1247 new_entry = (page_to_phys(svm->avic_backing_page) &
1248 AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK) |
1249 AVIC_PHYSICAL_ID_ENTRY_VALID_MASK;
1250 WRITE_ONCE(*entry, new_entry);
1251
1252 svm->avic_physical_id_cache = entry;
1253
1254 return 0;
1255}
1256
1257static void avic_vm_destroy(struct kvm *kvm)
1258{
1259 struct kvm_arch *vm_data = &kvm->arch;
1260
1261 if (vm_data->avic_logical_id_table_page)
1262 __free_page(vm_data->avic_logical_id_table_page);
1263 if (vm_data->avic_physical_id_table_page)
1264 __free_page(vm_data->avic_physical_id_table_page);
1265}
1266
1267static int avic_vm_init(struct kvm *kvm)
1268{
1269 int err = -ENOMEM;
1270 struct kvm_arch *vm_data = &kvm->arch;
1271 struct page *p_page;
1272 struct page *l_page;
1273
1274 if (!avic)
1275 return 0;
1276
1277 /* Allocating physical APIC ID table (4KB) */
1278 p_page = alloc_page(GFP_KERNEL);
1279 if (!p_page)
1280 goto free_avic;
1281
1282 vm_data->avic_physical_id_table_page = p_page;
1283 clear_page(page_address(p_page));
1284
1285 /* Allocating logical APIC ID table (4KB) */
1286 l_page = alloc_page(GFP_KERNEL);
1287 if (!l_page)
1288 goto free_avic;
1289
1290 vm_data->avic_logical_id_table_page = l_page;
1291 clear_page(page_address(l_page));
1292
1293 return 0;
1294
1295free_avic:
1296 avic_vm_destroy(kvm);
1297 return err;
1116} 1298}
1117 1299
1118static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) 1300static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
@@ -1131,6 +1313,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
1131 1313
1132 kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy); 1314 kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
1133 kvm_register_write(vcpu, VCPU_REGS_RDX, eax); 1315 kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
1316
1317 if (kvm_vcpu_apicv_active(vcpu) && !init_event)
1318 avic_update_vapic_bar(svm, APIC_DEFAULT_PHYS_BASE);
1134} 1319}
1135 1320
1136static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) 1321static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
@@ -1169,6 +1354,12 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
1169 if (!hsave_page) 1354 if (!hsave_page)
1170 goto free_page3; 1355 goto free_page3;
1171 1356
1357 if (avic) {
1358 err = avic_init_backing_page(&svm->vcpu);
1359 if (err)
1360 goto free_page4;
1361 }
1362
1172 svm->nested.hsave = page_address(hsave_page); 1363 svm->nested.hsave = page_address(hsave_page);
1173 1364
1174 svm->msrpm = page_address(msrpm_pages); 1365 svm->msrpm = page_address(msrpm_pages);
@@ -1187,6 +1378,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
1187 1378
1188 return &svm->vcpu; 1379 return &svm->vcpu;
1189 1380
1381free_page4:
1382 __free_page(hsave_page);
1190free_page3: 1383free_page3:
1191 __free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER); 1384 __free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER);
1192free_page2: 1385free_page2:
@@ -3212,6 +3405,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
3212 case MSR_VM_IGNNE: 3405 case MSR_VM_IGNNE:
3213 vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data); 3406 vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
3214 break; 3407 break;
3408 case MSR_IA32_APICBASE:
3409 if (kvm_vcpu_apicv_active(vcpu))
3410 avic_update_vapic_bar(to_svm(vcpu), data);
3411 /* Follow through */
3215 default: 3412 default:
3216 return kvm_set_msr_common(vcpu, msr); 3413 return kvm_set_msr_common(vcpu, msr);
3217 } 3414 }
@@ -3375,10 +3572,14 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
3375 pr_err("%-20s%08x\n", "exit_int_info_err:", control->exit_int_info_err); 3572 pr_err("%-20s%08x\n", "exit_int_info_err:", control->exit_int_info_err);
3376 pr_err("%-20s%lld\n", "nested_ctl:", control->nested_ctl); 3573 pr_err("%-20s%lld\n", "nested_ctl:", control->nested_ctl);
3377 pr_err("%-20s%016llx\n", "nested_cr3:", control->nested_cr3); 3574 pr_err("%-20s%016llx\n", "nested_cr3:", control->nested_cr3);
3575 pr_err("%-20s%016llx\n", "avic_vapic_bar:", control->avic_vapic_bar);
3378 pr_err("%-20s%08x\n", "event_inj:", control->event_inj); 3576 pr_err("%-20s%08x\n", "event_inj:", control->event_inj);
3379 pr_err("%-20s%08x\n", "event_inj_err:", control->event_inj_err); 3577 pr_err("%-20s%08x\n", "event_inj_err:", control->event_inj_err);
3380 pr_err("%-20s%lld\n", "lbr_ctl:", control->lbr_ctl); 3578 pr_err("%-20s%lld\n", "lbr_ctl:", control->lbr_ctl);
3381 pr_err("%-20s%016llx\n", "next_rip:", control->next_rip); 3579 pr_err("%-20s%016llx\n", "next_rip:", control->next_rip);
3580 pr_err("%-20s%016llx\n", "avic_backing_page:", control->avic_backing_page);
3581 pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
3582 pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
3382 pr_err("VMCB State Save Area:\n"); 3583 pr_err("VMCB State Save Area:\n");
3383 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n", 3584 pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
3384 "es:", 3585 "es:",
@@ -3606,11 +3807,28 @@ static void svm_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
3606 3807
3607static bool svm_get_enable_apicv(void) 3808static bool svm_get_enable_apicv(void)
3608{ 3809{
3609 return false; 3810 return avic;
3811}
3812
3813static void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
3814{
3815}
3816
3817static void svm_hwapic_isr_update(struct kvm *kvm, int isr)
3818{
3610} 3819}
3611 3820
3821/* Note: Currently only used by Hyper-V. */
3612static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) 3822static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
3613{ 3823{
3824 struct vcpu_svm *svm = to_svm(vcpu);
3825 struct vmcb *vmcb = svm->vmcb;
3826
3827 if (!avic)
3828 return;
3829
3830 vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
3831 mark_dirty(vmcb, VMCB_INTR);
3614} 3832}
3615 3833
3616static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) 3834static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
@@ -4322,6 +4540,9 @@ static struct kvm_x86_ops svm_x86_ops = {
4322 .vcpu_free = svm_free_vcpu, 4540 .vcpu_free = svm_free_vcpu,
4323 .vcpu_reset = svm_vcpu_reset, 4541 .vcpu_reset = svm_vcpu_reset,
4324 4542
4543 .vm_init = avic_vm_init,
4544 .vm_destroy = avic_vm_destroy,
4545
4325 .prepare_guest_switch = svm_prepare_guest_switch, 4546 .prepare_guest_switch = svm_prepare_guest_switch,
4326 .vcpu_load = svm_vcpu_load, 4547 .vcpu_load = svm_vcpu_load,
4327 .vcpu_put = svm_vcpu_put, 4548 .vcpu_put = svm_vcpu_put,
@@ -4382,6 +4603,8 @@ static struct kvm_x86_ops svm_x86_ops = {
4382 .refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl, 4603 .refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
4383 .load_eoi_exitmap = svm_load_eoi_exitmap, 4604 .load_eoi_exitmap = svm_load_eoi_exitmap,
4384 .sync_pir_to_irr = svm_sync_pir_to_irr, 4605 .sync_pir_to_irr = svm_sync_pir_to_irr,
4606 .hwapic_irr_update = svm_hwapic_irr_update,
4607 .hwapic_isr_update = svm_hwapic_isr_update,
4385 4608
4386 .set_tss_addr = svm_set_tss_addr, 4609 .set_tss_addr = svm_set_tss_addr,
4387 .get_tdp_level = get_npt_level, 4610 .get_tdp_level = get_npt_level,