aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/hyperv.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/hyperv.c')
-rw-r--r--arch/x86/kvm/hyperv.c192
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
78static 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
77static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint, 95static 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
1271static 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, &param, 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
1229int kvm_hv_hypercall(struct kvm_vcpu *vcpu) 1308int 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
1299set_result: 1382set_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
1387void 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
1393void 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
1403static 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
1427static 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
1444int 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}