diff options
author | Avi Kivity <avi@qumranet.com> | 2006-12-29 19:49:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-30 13:56:44 -0500 |
commit | 3bab1f5dda3443043cc8fe68c5ae75530339f28f (patch) | |
tree | d1b675e8f5328094c1a3d651da5e7563ad692252 /drivers | |
parent | 671d6564796e0c90398aab30f89b5e48fc5a3fbe (diff) |
[PATCH] KVM: Move common msr handling to arch independent code
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-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 | } |