diff options
Diffstat (limited to 'arch/x86/kvm/hyperv.c')
-rw-r--r-- | arch/x86/kvm/hyperv.c | 192 |
1 files changed, 171 insertions, 21 deletions
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index dc97f2544b6f..98618e397342 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/kvm_host.h> | 29 | #include <linux/kvm_host.h> |
30 | #include <linux/highmem.h> | 30 | #include <linux/highmem.h> |
31 | #include <linux/sched/cputime.h> | 31 | #include <linux/sched/cputime.h> |
32 | #include <linux/eventfd.h> | ||
32 | 33 | ||
33 | #include <asm/apicdef.h> | 34 | #include <asm/apicdef.h> |
34 | #include <trace/events/kvm.h> | 35 | #include <trace/events/kvm.h> |
@@ -74,13 +75,38 @@ static bool synic_has_vector_auto_eoi(struct kvm_vcpu_hv_synic *synic, | |||
74 | return false; | 75 | return false; |
75 | } | 76 | } |
76 | 77 | ||
78 | static void synic_update_vector(struct kvm_vcpu_hv_synic *synic, | ||
79 | int vector) | ||
80 | { | ||
81 | if (vector < HV_SYNIC_FIRST_VALID_VECTOR) | ||
82 | return; | ||
83 | |||
84 | if (synic_has_vector_connected(synic, vector)) | ||
85 | __set_bit(vector, synic->vec_bitmap); | ||
86 | else | ||
87 | __clear_bit(vector, synic->vec_bitmap); | ||
88 | |||
89 | if (synic_has_vector_auto_eoi(synic, vector)) | ||
90 | __set_bit(vector, synic->auto_eoi_bitmap); | ||
91 | else | ||
92 | __clear_bit(vector, synic->auto_eoi_bitmap); | ||
93 | } | ||
94 | |||
77 | static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, | 95 | static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, |
78 | u64 data, bool host) | 96 | u64 data, bool host) |
79 | { | 97 | { |
80 | int vector; | 98 | int vector, old_vector; |
99 | bool masked; | ||
81 | 100 | ||
82 | vector = data & HV_SYNIC_SINT_VECTOR_MASK; | 101 | vector = data & HV_SYNIC_SINT_VECTOR_MASK; |
83 | if (vector < 16 && !host) | 102 | masked = data & HV_SYNIC_SINT_MASKED; |
103 | |||
104 | /* | ||
105 | * Valid vectors are 16-255, however, nested Hyper-V attempts to write | ||
106 | * default '0x10000' value on boot and this should not #GP. We need to | ||
107 | * allow zero-initing the register from host as well. | ||
108 | */ | ||
109 | if (vector < HV_SYNIC_FIRST_VALID_VECTOR && !host && !masked) | ||
84 | return 1; | 110 | return 1; |
85 | /* | 111 | /* |
86 | * Guest may configure multiple SINTs to use the same vector, so | 112 | * Guest may configure multiple SINTs to use the same vector, so |
@@ -88,18 +114,13 @@ static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, | |||
88 | * bitmap of vectors with auto-eoi behavior. The bitmaps are | 114 | * bitmap of vectors with auto-eoi behavior. The bitmaps are |
89 | * updated here, and atomically queried on fast paths. | 115 | * updated here, and atomically queried on fast paths. |
90 | */ | 116 | */ |
117 | old_vector = synic_read_sint(synic, sint) & HV_SYNIC_SINT_VECTOR_MASK; | ||
91 | 118 | ||
92 | atomic64_set(&synic->sint[sint], data); | 119 | atomic64_set(&synic->sint[sint], data); |
93 | 120 | ||
94 | if (synic_has_vector_connected(synic, vector)) | 121 | synic_update_vector(synic, old_vector); |
95 | __set_bit(vector, synic->vec_bitmap); | ||
96 | else | ||
97 | __clear_bit(vector, synic->vec_bitmap); | ||
98 | 122 | ||
99 | if (synic_has_vector_auto_eoi(synic, vector)) | 123 | synic_update_vector(synic, vector); |
100 | __set_bit(vector, synic->auto_eoi_bitmap); | ||
101 | else | ||
102 | __clear_bit(vector, synic->auto_eoi_bitmap); | ||
103 | 124 | ||
104 | /* Load SynIC vectors into EOI exit bitmap */ | 125 | /* Load SynIC vectors into EOI exit bitmap */ |
105 | kvm_make_request(KVM_REQ_SCAN_IOAPIC, synic_to_vcpu(synic)); | 126 | kvm_make_request(KVM_REQ_SCAN_IOAPIC, synic_to_vcpu(synic)); |
@@ -736,6 +757,9 @@ static bool kvm_hv_msr_partition_wide(u32 msr) | |||
736 | case HV_X64_MSR_CRASH_CTL: | 757 | case HV_X64_MSR_CRASH_CTL: |
737 | case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4: | 758 | case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4: |
738 | case HV_X64_MSR_RESET: | 759 | case HV_X64_MSR_RESET: |
760 | case HV_X64_MSR_REENLIGHTENMENT_CONTROL: | ||
761 | case HV_X64_MSR_TSC_EMULATION_CONTROL: | ||
762 | case HV_X64_MSR_TSC_EMULATION_STATUS: | ||
739 | r = true; | 763 | r = true; |
740 | break; | 764 | break; |
741 | } | 765 | } |
@@ -981,6 +1005,15 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, | |||
981 | kvm_make_request(KVM_REQ_HV_RESET, vcpu); | 1005 | kvm_make_request(KVM_REQ_HV_RESET, vcpu); |
982 | } | 1006 | } |
983 | break; | 1007 | break; |
1008 | case HV_X64_MSR_REENLIGHTENMENT_CONTROL: | ||
1009 | hv->hv_reenlightenment_control = data; | ||
1010 | break; | ||
1011 | case HV_X64_MSR_TSC_EMULATION_CONTROL: | ||
1012 | hv->hv_tsc_emulation_control = data; | ||
1013 | break; | ||
1014 | case HV_X64_MSR_TSC_EMULATION_STATUS: | ||
1015 | hv->hv_tsc_emulation_status = data; | ||
1016 | break; | ||
984 | default: | 1017 | default: |
985 | vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n", | 1018 | vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n", |
986 | msr, data); | 1019 | msr, data); |
@@ -1009,17 +1042,17 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) | |||
1009 | return 1; | 1042 | return 1; |
1010 | hv->vp_index = (u32)data; | 1043 | hv->vp_index = (u32)data; |
1011 | break; | 1044 | break; |
1012 | case HV_X64_MSR_APIC_ASSIST_PAGE: { | 1045 | case HV_X64_MSR_VP_ASSIST_PAGE: { |
1013 | u64 gfn; | 1046 | u64 gfn; |
1014 | unsigned long addr; | 1047 | unsigned long addr; |
1015 | 1048 | ||
1016 | if (!(data & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE)) { | 1049 | if (!(data & HV_X64_MSR_VP_ASSIST_PAGE_ENABLE)) { |
1017 | hv->hv_vapic = data; | 1050 | hv->hv_vapic = data; |
1018 | if (kvm_lapic_enable_pv_eoi(vcpu, 0)) | 1051 | if (kvm_lapic_enable_pv_eoi(vcpu, 0)) |
1019 | return 1; | 1052 | return 1; |
1020 | break; | 1053 | break; |
1021 | } | 1054 | } |
1022 | gfn = data >> HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT; | 1055 | gfn = data >> HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT; |
1023 | addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); | 1056 | addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); |
1024 | if (kvm_is_error_hva(addr)) | 1057 | if (kvm_is_error_hva(addr)) |
1025 | return 1; | 1058 | return 1; |
@@ -1105,6 +1138,15 @@ static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
1105 | case HV_X64_MSR_RESET: | 1138 | case HV_X64_MSR_RESET: |
1106 | data = 0; | 1139 | data = 0; |
1107 | break; | 1140 | break; |
1141 | case HV_X64_MSR_REENLIGHTENMENT_CONTROL: | ||
1142 | data = hv->hv_reenlightenment_control; | ||
1143 | break; | ||
1144 | case HV_X64_MSR_TSC_EMULATION_CONTROL: | ||
1145 | data = hv->hv_tsc_emulation_control; | ||
1146 | break; | ||
1147 | case HV_X64_MSR_TSC_EMULATION_STATUS: | ||
1148 | data = hv->hv_tsc_emulation_status; | ||
1149 | break; | ||
1108 | default: | 1150 | default: |
1109 | vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); | 1151 | vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr); |
1110 | return 1; | 1152 | return 1; |
@@ -1129,7 +1171,7 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
1129 | return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata); | 1171 | return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata); |
1130 | case HV_X64_MSR_TPR: | 1172 | case HV_X64_MSR_TPR: |
1131 | return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata); | 1173 | return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata); |
1132 | case HV_X64_MSR_APIC_ASSIST_PAGE: | 1174 | case HV_X64_MSR_VP_ASSIST_PAGE: |
1133 | data = hv->hv_vapic; | 1175 | data = hv->hv_vapic; |
1134 | break; | 1176 | break; |
1135 | case HV_X64_MSR_VP_RUNTIME: | 1177 | case HV_X64_MSR_VP_RUNTIME: |
@@ -1226,10 +1268,47 @@ static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu) | |||
1226 | return 1; | 1268 | return 1; |
1227 | } | 1269 | } |
1228 | 1270 | ||
1271 | static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param) | ||
1272 | { | ||
1273 | struct eventfd_ctx *eventfd; | ||
1274 | |||
1275 | if (unlikely(!fast)) { | ||
1276 | int ret; | ||
1277 | gpa_t gpa = param; | ||
1278 | |||
1279 | if ((gpa & (__alignof__(param) - 1)) || | ||
1280 | offset_in_page(gpa) + sizeof(param) > PAGE_SIZE) | ||
1281 | return HV_STATUS_INVALID_ALIGNMENT; | ||
1282 | |||
1283 | ret = kvm_vcpu_read_guest(vcpu, gpa, ¶m, sizeof(param)); | ||
1284 | if (ret < 0) | ||
1285 | return HV_STATUS_INVALID_ALIGNMENT; | ||
1286 | } | ||
1287 | |||
1288 | /* | ||
1289 | * Per spec, bits 32-47 contain the extra "flag number". However, we | ||
1290 | * have no use for it, and in all known usecases it is zero, so just | ||
1291 | * report lookup failure if it isn't. | ||
1292 | */ | ||
1293 | if (param & 0xffff00000000ULL) | ||
1294 | return HV_STATUS_INVALID_PORT_ID; | ||
1295 | /* remaining bits are reserved-zero */ | ||
1296 | if (param & ~KVM_HYPERV_CONN_ID_MASK) | ||
1297 | return HV_STATUS_INVALID_HYPERCALL_INPUT; | ||
1298 | |||
1299 | /* conn_to_evt is protected by vcpu->kvm->srcu */ | ||
1300 | eventfd = idr_find(&vcpu->kvm->arch.hyperv.conn_to_evt, param); | ||
1301 | if (!eventfd) | ||
1302 | return HV_STATUS_INVALID_PORT_ID; | ||
1303 | |||
1304 | eventfd_signal(eventfd, 1); | ||
1305 | return HV_STATUS_SUCCESS; | ||
1306 | } | ||
1307 | |||
1229 | int kvm_hv_hypercall(struct kvm_vcpu *vcpu) | 1308 | int kvm_hv_hypercall(struct kvm_vcpu *vcpu) |
1230 | { | 1309 | { |
1231 | u64 param, ingpa, outgpa, ret; | 1310 | u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS; |
1232 | uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0; | 1311 | uint16_t code, rep_idx, rep_cnt; |
1233 | bool fast, longmode; | 1312 | bool fast, longmode; |
1234 | 1313 | ||
1235 | /* | 1314 | /* |
@@ -1268,7 +1347,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) | |||
1268 | 1347 | ||
1269 | /* Hypercall continuation is not supported yet */ | 1348 | /* Hypercall continuation is not supported yet */ |
1270 | if (rep_cnt || rep_idx) { | 1349 | if (rep_cnt || rep_idx) { |
1271 | res = HV_STATUS_INVALID_HYPERCALL_CODE; | 1350 | ret = HV_STATUS_INVALID_HYPERCALL_CODE; |
1272 | goto set_result; | 1351 | goto set_result; |
1273 | } | 1352 | } |
1274 | 1353 | ||
@@ -1276,11 +1355,15 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) | |||
1276 | case HVCALL_NOTIFY_LONG_SPIN_WAIT: | 1355 | case HVCALL_NOTIFY_LONG_SPIN_WAIT: |
1277 | kvm_vcpu_on_spin(vcpu, true); | 1356 | kvm_vcpu_on_spin(vcpu, true); |
1278 | break; | 1357 | break; |
1279 | case HVCALL_POST_MESSAGE: | ||
1280 | case HVCALL_SIGNAL_EVENT: | 1358 | case HVCALL_SIGNAL_EVENT: |
1359 | ret = kvm_hvcall_signal_event(vcpu, fast, ingpa); | ||
1360 | if (ret != HV_STATUS_INVALID_PORT_ID) | ||
1361 | break; | ||
1362 | /* maybe userspace knows this conn_id: fall through */ | ||
1363 | case HVCALL_POST_MESSAGE: | ||
1281 | /* don't bother userspace if it has no way to handle it */ | 1364 | /* don't bother userspace if it has no way to handle it */ |
1282 | if (!vcpu_to_synic(vcpu)->active) { | 1365 | if (!vcpu_to_synic(vcpu)->active) { |
1283 | res = HV_STATUS_INVALID_HYPERCALL_CODE; | 1366 | ret = HV_STATUS_INVALID_HYPERCALL_CODE; |
1284 | break; | 1367 | break; |
1285 | } | 1368 | } |
1286 | vcpu->run->exit_reason = KVM_EXIT_HYPERV; | 1369 | vcpu->run->exit_reason = KVM_EXIT_HYPERV; |
@@ -1292,12 +1375,79 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) | |||
1292 | kvm_hv_hypercall_complete_userspace; | 1375 | kvm_hv_hypercall_complete_userspace; |
1293 | return 0; | 1376 | return 0; |
1294 | default: | 1377 | default: |
1295 | res = HV_STATUS_INVALID_HYPERCALL_CODE; | 1378 | ret = HV_STATUS_INVALID_HYPERCALL_CODE; |
1296 | break; | 1379 | break; |
1297 | } | 1380 | } |
1298 | 1381 | ||
1299 | set_result: | 1382 | set_result: |
1300 | ret = res | (((u64)rep_done & 0xfff) << 32); | ||
1301 | kvm_hv_hypercall_set_result(vcpu, ret); | 1383 | kvm_hv_hypercall_set_result(vcpu, ret); |
1302 | return 1; | 1384 | return 1; |
1303 | } | 1385 | } |
1386 | |||
1387 | void kvm_hv_init_vm(struct kvm *kvm) | ||
1388 | { | ||
1389 | mutex_init(&kvm->arch.hyperv.hv_lock); | ||
1390 | idr_init(&kvm->arch.hyperv.conn_to_evt); | ||
1391 | } | ||
1392 | |||
1393 | void kvm_hv_destroy_vm(struct kvm *kvm) | ||
1394 | { | ||
1395 | struct eventfd_ctx *eventfd; | ||
1396 | int i; | ||
1397 | |||
1398 | idr_for_each_entry(&kvm->arch.hyperv.conn_to_evt, eventfd, i) | ||
1399 | eventfd_ctx_put(eventfd); | ||
1400 | idr_destroy(&kvm->arch.hyperv.conn_to_evt); | ||
1401 | } | ||
1402 | |||
1403 | static int kvm_hv_eventfd_assign(struct kvm *kvm, u32 conn_id, int fd) | ||
1404 | { | ||
1405 | struct kvm_hv *hv = &kvm->arch.hyperv; | ||
1406 | struct eventfd_ctx *eventfd; | ||
1407 | int ret; | ||
1408 | |||
1409 | eventfd = eventfd_ctx_fdget(fd); | ||
1410 | if (IS_ERR(eventfd)) | ||
1411 | return PTR_ERR(eventfd); | ||
1412 | |||
1413 | mutex_lock(&hv->hv_lock); | ||
1414 | ret = idr_alloc(&hv->conn_to_evt, eventfd, conn_id, conn_id + 1, | ||
1415 | GFP_KERNEL); | ||
1416 | mutex_unlock(&hv->hv_lock); | ||
1417 | |||
1418 | if (ret >= 0) | ||
1419 | return 0; | ||
1420 | |||
1421 | if (ret == -ENOSPC) | ||
1422 | ret = -EEXIST; | ||
1423 | eventfd_ctx_put(eventfd); | ||
1424 | return ret; | ||
1425 | } | ||
1426 | |||
1427 | static int kvm_hv_eventfd_deassign(struct kvm *kvm, u32 conn_id) | ||
1428 | { | ||
1429 | struct kvm_hv *hv = &kvm->arch.hyperv; | ||
1430 | struct eventfd_ctx *eventfd; | ||
1431 | |||
1432 | mutex_lock(&hv->hv_lock); | ||
1433 | eventfd = idr_remove(&hv->conn_to_evt, conn_id); | ||
1434 | mutex_unlock(&hv->hv_lock); | ||
1435 | |||
1436 | if (!eventfd) | ||
1437 | return -ENOENT; | ||
1438 | |||
1439 | synchronize_srcu(&kvm->srcu); | ||
1440 | eventfd_ctx_put(eventfd); | ||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct kvm_hyperv_eventfd *args) | ||
1445 | { | ||
1446 | if ((args->flags & ~KVM_HYPERV_EVENTFD_DEASSIGN) || | ||
1447 | (args->conn_id & ~KVM_HYPERV_CONN_ID_MASK)) | ||
1448 | return -EINVAL; | ||
1449 | |||
1450 | if (args->flags == KVM_HYPERV_EVENTFD_DEASSIGN) | ||
1451 | return kvm_hv_eventfd_deassign(kvm, args->conn_id); | ||
1452 | return kvm_hv_eventfd_assign(kvm, args->conn_id, args->fd); | ||
1453 | } | ||