diff options
| -rw-r--r-- | drivers/kvm/kvm.h | 5 | ||||
| -rw-r--r-- | drivers/kvm/kvm_main.c | 71 | ||||
| -rw-r--r-- | drivers/kvm/svm.c | 47 | ||||
| -rw-r--r-- | drivers/kvm/vmx.c | 59 |
4 files changed, 84 insertions, 98 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index c2db4218d6cc..2670219a9264 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
| @@ -374,9 +374,8 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0); | |||
| 374 | void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0); | 374 | void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0); |
| 375 | void lmsw(struct kvm_vcpu *vcpu, unsigned long msw); | 375 | void lmsw(struct kvm_vcpu *vcpu, unsigned long msw); |
| 376 | 376 | ||
| 377 | #ifdef CONFIG_X86_64 | 377 | int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); |
| 378 | void set_efer(struct kvm_vcpu *vcpu, u64 efer); | 378 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data); |
| 379 | #endif | ||
| 380 | 379 | ||
| 381 | void fx_init(struct kvm_vcpu *vcpu); | 380 | void fx_init(struct kvm_vcpu *vcpu); |
| 382 | 381 | ||
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 06314071c6d2..567121d9142a 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
| @@ -1103,6 +1103,47 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val, | |||
| 1103 | } | 1103 | } |
| 1104 | } | 1104 | } |
| 1105 | 1105 | ||
| 1106 | int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | ||
| 1107 | { | ||
| 1108 | u64 data; | ||
| 1109 | |||
| 1110 | switch (msr) { | ||
| 1111 | case 0xc0010010: /* SYSCFG */ | ||
| 1112 | case 0xc0010015: /* HWCR */ | ||
| 1113 | case MSR_IA32_PLATFORM_ID: | ||
| 1114 | case MSR_IA32_P5_MC_ADDR: | ||
| 1115 | case MSR_IA32_P5_MC_TYPE: | ||
| 1116 | case MSR_IA32_MC0_CTL: | ||
| 1117 | case MSR_IA32_MCG_STATUS: | ||
| 1118 | case MSR_IA32_MCG_CAP: | ||
| 1119 | case MSR_IA32_MC0_MISC: | ||
| 1120 | case MSR_IA32_MC0_MISC+4: | ||
| 1121 | case MSR_IA32_MC0_MISC+8: | ||
| 1122 | case MSR_IA32_MC0_MISC+12: | ||
| 1123 | case MSR_IA32_MC0_MISC+16: | ||
| 1124 | case MSR_IA32_UCODE_REV: | ||
| 1125 | /* MTRR registers */ | ||
| 1126 | case 0xfe: | ||
| 1127 | case 0x200 ... 0x2ff: | ||
| 1128 | data = 0; | ||
| 1129 | break; | ||
| 1130 | case MSR_IA32_APICBASE: | ||
| 1131 | data = vcpu->apic_base; | ||
| 1132 | break; | ||
| 1133 | #ifdef CONFIG_X86_64 | ||
| 1134 | case MSR_EFER: | ||
| 1135 | data = vcpu->shadow_efer; | ||
| 1136 | break; | ||
| 1137 | #endif | ||
| 1138 | default: | ||
| 1139 | printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", msr); | ||
| 1140 | return 1; | ||
| 1141 | } | ||
| 1142 | *pdata = data; | ||
| 1143 | return 0; | ||
| 1144 | } | ||
| 1145 | EXPORT_SYMBOL_GPL(kvm_get_msr_common); | ||
| 1146 | |||
| 1106 | /* | 1147 | /* |
| 1107 | * Reads an msr value (of 'msr_index') into 'pdata'. | 1148 | * Reads an msr value (of 'msr_index') into 'pdata'. |
| 1108 | * Returns 0 on success, non-0 otherwise. | 1149 | * Returns 0 on success, non-0 otherwise. |
| @@ -1115,7 +1156,7 @@ static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | |||
| 1115 | 1156 | ||
| 1116 | #ifdef CONFIG_X86_64 | 1157 | #ifdef CONFIG_X86_64 |
| 1117 | 1158 | ||
| 1118 | void set_efer(struct kvm_vcpu *vcpu, u64 efer) | 1159 | static void set_efer(struct kvm_vcpu *vcpu, u64 efer) |
| 1119 | { | 1160 | { |
| 1120 | if (efer & EFER_RESERVED_BITS) { | 1161 | if (efer & EFER_RESERVED_BITS) { |
| 1121 | printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n", | 1162 | printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n", |
| @@ -1138,10 +1179,36 @@ void set_efer(struct kvm_vcpu *vcpu, u64 efer) | |||
| 1138 | 1179 | ||
| 1139 | vcpu->shadow_efer = efer; | 1180 | vcpu->shadow_efer = efer; |
| 1140 | } | 1181 | } |
| 1141 | EXPORT_SYMBOL_GPL(set_efer); | ||
| 1142 | 1182 | ||
| 1143 | #endif | 1183 | #endif |
| 1144 | 1184 | ||
| 1185 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | ||
| 1186 | { | ||
| 1187 | switch (msr) { | ||
| 1188 | #ifdef CONFIG_X86_64 | ||
| 1189 | case MSR_EFER: | ||
| 1190 | set_efer(vcpu, data); | ||
| 1191 | break; | ||
| 1192 | #endif | ||
| 1193 | case MSR_IA32_MC0_STATUS: | ||
| 1194 | printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n", | ||
| 1195 | __FUNCTION__, data); | ||
| 1196 | break; | ||
| 1197 | case MSR_IA32_UCODE_REV: | ||
| 1198 | case MSR_IA32_UCODE_WRITE: | ||
| 1199 | case 0x200 ... 0x2ff: /* MTRRs */ | ||
| 1200 | break; | ||
| 1201 | case MSR_IA32_APICBASE: | ||
| 1202 | vcpu->apic_base = data; | ||
| 1203 | break; | ||
| 1204 | default: | ||
| 1205 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); | ||
| 1206 | return 1; | ||
| 1207 | } | ||
| 1208 | return 0; | ||
| 1209 | } | ||
| 1210 | EXPORT_SYMBOL_GPL(kvm_set_msr_common); | ||
| 1211 | |||
| 1145 | /* | 1212 | /* |
| 1146 | * Writes msr value into into the appropriate "register". | 1213 | * Writes msr value into into the appropriate "register". |
| 1147 | * Returns 0 on success, non-0 otherwise. | 1214 | * Returns 0 on success, non-0 otherwise. |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 6cd97c69ab3b..fa0428735717 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
| @@ -1068,25 +1068,6 @@ static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_ru | |||
| 1068 | static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) | 1068 | static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) |
| 1069 | { | 1069 | { |
| 1070 | switch (ecx) { | 1070 | switch (ecx) { |
| 1071 | case 0xc0010010: /* SYSCFG */ | ||
| 1072 | case 0xc0010015: /* HWCR */ | ||
| 1073 | case MSR_IA32_PLATFORM_ID: | ||
| 1074 | case MSR_IA32_P5_MC_ADDR: | ||
| 1075 | case MSR_IA32_P5_MC_TYPE: | ||
| 1076 | case MSR_IA32_MC0_CTL: | ||
| 1077 | case MSR_IA32_MCG_STATUS: | ||
| 1078 | case MSR_IA32_MCG_CAP: | ||
| 1079 | case MSR_IA32_MC0_MISC: | ||
| 1080 | case MSR_IA32_MC0_MISC+4: | ||
| 1081 | case MSR_IA32_MC0_MISC+8: | ||
| 1082 | case MSR_IA32_MC0_MISC+12: | ||
| 1083 | case MSR_IA32_MC0_MISC+16: | ||
| 1084 | case MSR_IA32_UCODE_REV: | ||
| 1085 | /* MTRR registers */ | ||
| 1086 | case 0xfe: | ||
| 1087 | case 0x200 ... 0x2ff: | ||
| 1088 | *data = 0; | ||
| 1089 | break; | ||
| 1090 | case MSR_IA32_TIME_STAMP_COUNTER: { | 1071 | case MSR_IA32_TIME_STAMP_COUNTER: { |
| 1091 | u64 tsc; | 1072 | u64 tsc; |
| 1092 | 1073 | ||
| @@ -1094,12 +1075,6 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) | |||
| 1094 | *data = vcpu->svm->vmcb->control.tsc_offset + tsc; | 1075 | *data = vcpu->svm->vmcb->control.tsc_offset + tsc; |
| 1095 | break; | 1076 | break; |
| 1096 | } | 1077 | } |
| 1097 | case MSR_EFER: | ||
| 1098 | *data = vcpu->shadow_efer; | ||
| 1099 | break; | ||
| 1100 | case MSR_IA32_APICBASE: | ||
| 1101 | *data = vcpu->apic_base; | ||
| 1102 | break; | ||
| 1103 | case MSR_K6_STAR: | 1078 | case MSR_K6_STAR: |
| 1104 | *data = vcpu->svm->vmcb->save.star; | 1079 | *data = vcpu->svm->vmcb->save.star; |
| 1105 | break; | 1080 | break; |
| @@ -1127,8 +1102,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) | |||
| 1127 | *data = vcpu->svm->vmcb->save.sysenter_esp; | 1102 | *data = vcpu->svm->vmcb->save.sysenter_esp; |
| 1128 | break; | 1103 | break; |
| 1129 | default: | 1104 | default: |
| 1130 | printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", ecx); | 1105 | return kvm_get_msr_common(vcpu, ecx, data); |
| 1131 | return 1; | ||
| 1132 | } | 1106 | } |
| 1133 | return 0; | 1107 | return 0; |
| 1134 | } | 1108 | } |
| @@ -1152,15 +1126,6 @@ static int rdmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1152 | static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) | 1126 | static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) |
| 1153 | { | 1127 | { |
| 1154 | switch (ecx) { | 1128 | switch (ecx) { |
| 1155 | #ifdef CONFIG_X86_64 | ||
| 1156 | case MSR_EFER: | ||
| 1157 | set_efer(vcpu, data); | ||
| 1158 | break; | ||
| 1159 | #endif | ||
| 1160 | case MSR_IA32_MC0_STATUS: | ||
| 1161 | printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" | ||
| 1162 | , __FUNCTION__, data); | ||
| 1163 | break; | ||
| 1164 | case MSR_IA32_TIME_STAMP_COUNTER: { | 1129 | case MSR_IA32_TIME_STAMP_COUNTER: { |
| 1165 | u64 tsc; | 1130 | u64 tsc; |
| 1166 | 1131 | ||
| @@ -1168,13 +1133,6 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) | |||
| 1168 | vcpu->svm->vmcb->control.tsc_offset = data - tsc; | 1133 | vcpu->svm->vmcb->control.tsc_offset = data - tsc; |
| 1169 | break; | 1134 | break; |
| 1170 | } | 1135 | } |
| 1171 | case MSR_IA32_UCODE_REV: | ||
| 1172 | case MSR_IA32_UCODE_WRITE: | ||
| 1173 | case 0x200 ... 0x2ff: /* MTRRs */ | ||
| 1174 | break; | ||
| 1175 | case MSR_IA32_APICBASE: | ||
| 1176 | vcpu->apic_base = data; | ||
| 1177 | break; | ||
| 1178 | case MSR_K6_STAR: | 1136 | case MSR_K6_STAR: |
| 1179 | vcpu->svm->vmcb->save.star = data; | 1137 | vcpu->svm->vmcb->save.star = data; |
| 1180 | break; | 1138 | break; |
| @@ -1202,8 +1160,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) | |||
| 1202 | vcpu->svm->vmcb->save.sysenter_esp = data; | 1160 | vcpu->svm->vmcb->save.sysenter_esp = data; |
| 1203 | break; | 1161 | break; |
| 1204 | default: | 1162 | default: |
| 1205 | printk(KERN_ERR "kvm: unhandled wrmsr: %x\n", ecx); | 1163 | return kvm_set_msr_common(vcpu, ecx, data); |
| 1206 | return 1; | ||
| 1207 | } | 1164 | } |
| 1208 | return 0; | 1165 | return 0; |
| 1209 | } | 1166 | } |
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index e5358a8b01f1..5561c5936c3d 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
| @@ -344,8 +344,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | |||
| 344 | data = vmcs_readl(GUEST_GS_BASE); | 344 | data = vmcs_readl(GUEST_GS_BASE); |
| 345 | break; | 345 | break; |
| 346 | case MSR_EFER: | 346 | case MSR_EFER: |
| 347 | data = vcpu->shadow_efer; | 347 | return kvm_get_msr_common(vcpu, msr_index, pdata); |
| 348 | break; | ||
| 349 | #endif | 348 | #endif |
| 350 | case MSR_IA32_TIME_STAMP_COUNTER: | 349 | case MSR_IA32_TIME_STAMP_COUNTER: |
| 351 | data = guest_read_tsc(); | 350 | data = guest_read_tsc(); |
| @@ -359,36 +358,13 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | |||
| 359 | case MSR_IA32_SYSENTER_ESP: | 358 | case MSR_IA32_SYSENTER_ESP: |
| 360 | data = vmcs_read32(GUEST_SYSENTER_ESP); | 359 | data = vmcs_read32(GUEST_SYSENTER_ESP); |
| 361 | break; | 360 | break; |
| 362 | case 0xc0010010: /* SYSCFG */ | ||
| 363 | case 0xc0010015: /* HWCR */ | ||
| 364 | case MSR_IA32_PLATFORM_ID: | ||
| 365 | case MSR_IA32_P5_MC_ADDR: | ||
| 366 | case MSR_IA32_P5_MC_TYPE: | ||
| 367 | case MSR_IA32_MC0_CTL: | ||
| 368 | case MSR_IA32_MCG_STATUS: | ||
| 369 | case MSR_IA32_MCG_CAP: | ||
| 370 | case MSR_IA32_MC0_MISC: | ||
| 371 | case MSR_IA32_MC0_MISC+4: | ||
| 372 | case MSR_IA32_MC0_MISC+8: | ||
| 373 | case MSR_IA32_MC0_MISC+12: | ||
| 374 | case MSR_IA32_MC0_MISC+16: | ||
| 375 | case MSR_IA32_UCODE_REV: | ||
| 376 | /* MTRR registers */ | ||
| 377 | case 0xfe: | ||
| 378 | case 0x200 ... 0x2ff: | ||
| 379 | data = 0; | ||
| 380 | break; | ||
| 381 | case MSR_IA32_APICBASE: | ||
| 382 | data = vcpu->apic_base; | ||
| 383 | break; | ||
| 384 | default: | 361 | default: |
| 385 | msr = find_msr_entry(vcpu, msr_index); | 362 | msr = find_msr_entry(vcpu, msr_index); |
| 386 | if (!msr) { | 363 | if (msr) { |
| 387 | printk(KERN_ERR "kvm: unhandled rdmsr: %x\n", msr_index); | 364 | data = msr->data; |
| 388 | return 1; | 365 | break; |
| 389 | } | 366 | } |
| 390 | data = msr->data; | 367 | return kvm_get_msr_common(vcpu, msr_index, pdata); |
| 391 | break; | ||
| 392 | } | 368 | } |
| 393 | 369 | ||
| 394 | *pdata = data; | 370 | *pdata = data; |
| @@ -405,6 +381,8 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | |||
| 405 | struct vmx_msr_entry *msr; | 381 | struct vmx_msr_entry *msr; |
| 406 | switch (msr_index) { | 382 | switch (msr_index) { |
| 407 | #ifdef CONFIG_X86_64 | 383 | #ifdef CONFIG_X86_64 |
| 384 | case MSR_EFER: | ||
| 385 | return kvm_set_msr_common(vcpu, msr_index, data); | ||
| 408 | case MSR_FS_BASE: | 386 | case MSR_FS_BASE: |
| 409 | vmcs_writel(GUEST_FS_BASE, data); | 387 | vmcs_writel(GUEST_FS_BASE, data); |
| 410 | break; | 388 | break; |
| @@ -421,32 +399,17 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | |||
| 421 | case MSR_IA32_SYSENTER_ESP: | 399 | case MSR_IA32_SYSENTER_ESP: |
| 422 | vmcs_write32(GUEST_SYSENTER_ESP, data); | 400 | vmcs_write32(GUEST_SYSENTER_ESP, data); |
| 423 | break; | 401 | break; |
| 424 | #ifdef __x86_64 | ||
| 425 | case MSR_EFER: | ||
| 426 | set_efer(vcpu, data); | ||
| 427 | break; | ||
| 428 | case MSR_IA32_MC0_STATUS: | ||
| 429 | printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" | ||
| 430 | , __FUNCTION__, data); | ||
| 431 | break; | ||
| 432 | #endif | ||
| 433 | case MSR_IA32_TIME_STAMP_COUNTER: { | 402 | case MSR_IA32_TIME_STAMP_COUNTER: { |
| 434 | guest_write_tsc(data); | 403 | guest_write_tsc(data); |
| 435 | break; | 404 | break; |
| 436 | } | 405 | } |
| 437 | case MSR_IA32_UCODE_REV: | ||
| 438 | case MSR_IA32_UCODE_WRITE: | ||
| 439 | case 0x200 ... 0x2ff: /* MTRRs */ | ||
| 440 | break; | ||
| 441 | case MSR_IA32_APICBASE: | ||
| 442 | vcpu->apic_base = data; | ||
| 443 | break; | ||
| 444 | default: | 406 | default: |
| 445 | msr = find_msr_entry(vcpu, msr_index); | 407 | msr = find_msr_entry(vcpu, msr_index); |
| 446 | if (!msr) { | 408 | if (msr) { |
| 447 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr_index); | 409 | msr->data = data; |
| 448 | return 1; | 410 | break; |
| 449 | } | 411 | } |
| 412 | return kvm_set_msr_common(vcpu, msr_index, data); | ||
| 450 | msr->data = data; | 413 | msr->data = data; |
| 451 | break; | 414 | break; |
| 452 | } | 415 | } |
