diff options
author | Avi Kivity <avi@qumranet.com> | 2008-05-26 13:06:35 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-07-20 05:42:26 -0400 |
commit | 9ba075a664dff836fd6fb93f90fcc827f7683d91 (patch) | |
tree | a5d939aa61833525a09fa2f346964c16a80f7957 | |
parent | 81609e3e26508840a1b51414376f2541dd191483 (diff) |
KVM: MTRR support
Add emulation for the memory type range registers, needed by VMware esx 3.5,
and by pci device assignment.
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | arch/x86/kvm/x86.c | 52 | ||||
-rw-r--r-- | include/asm-x86/kvm_host.h | 3 |
2 files changed, 51 insertions, 4 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 05b54976c891..5f67a7c54e82 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -611,6 +611,38 @@ static void kvm_write_guest_time(struct kvm_vcpu *v) | |||
611 | mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); | 611 | mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); |
612 | } | 612 | } |
613 | 613 | ||
614 | static bool msr_mtrr_valid(unsigned msr) | ||
615 | { | ||
616 | switch (msr) { | ||
617 | case 0x200 ... 0x200 + 2 * KVM_NR_VAR_MTRR - 1: | ||
618 | case MSR_MTRRfix64K_00000: | ||
619 | case MSR_MTRRfix16K_80000: | ||
620 | case MSR_MTRRfix16K_A0000: | ||
621 | case MSR_MTRRfix4K_C0000: | ||
622 | case MSR_MTRRfix4K_C8000: | ||
623 | case MSR_MTRRfix4K_D0000: | ||
624 | case MSR_MTRRfix4K_D8000: | ||
625 | case MSR_MTRRfix4K_E0000: | ||
626 | case MSR_MTRRfix4K_E8000: | ||
627 | case MSR_MTRRfix4K_F0000: | ||
628 | case MSR_MTRRfix4K_F8000: | ||
629 | case MSR_MTRRdefType: | ||
630 | case MSR_IA32_CR_PAT: | ||
631 | return true; | ||
632 | case 0x2f8: | ||
633 | return true; | ||
634 | } | ||
635 | return false; | ||
636 | } | ||
637 | |||
638 | static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data) | ||
639 | { | ||
640 | if (!msr_mtrr_valid(msr)) | ||
641 | return 1; | ||
642 | |||
643 | vcpu->arch.mtrr[msr - 0x200] = data; | ||
644 | return 0; | ||
645 | } | ||
614 | 646 | ||
615 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | 647 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) |
616 | { | 648 | { |
@@ -632,8 +664,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
632 | break; | 664 | break; |
633 | case MSR_IA32_UCODE_REV: | 665 | case MSR_IA32_UCODE_REV: |
634 | case MSR_IA32_UCODE_WRITE: | 666 | case MSR_IA32_UCODE_WRITE: |
635 | case 0x200 ... 0x2ff: /* MTRRs */ | ||
636 | break; | 667 | break; |
668 | case 0x200 ... 0x2ff: | ||
669 | return set_msr_mtrr(vcpu, msr, data); | ||
637 | case MSR_IA32_APICBASE: | 670 | case MSR_IA32_APICBASE: |
638 | kvm_set_apic_base(vcpu, data); | 671 | kvm_set_apic_base(vcpu, data); |
639 | break; | 672 | break; |
@@ -691,6 +724,15 @@ int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | |||
691 | return kvm_x86_ops->get_msr(vcpu, msr_index, pdata); | 724 | return kvm_x86_ops->get_msr(vcpu, msr_index, pdata); |
692 | } | 725 | } |
693 | 726 | ||
727 | static int get_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | ||
728 | { | ||
729 | if (!msr_mtrr_valid(msr)) | ||
730 | return 1; | ||
731 | |||
732 | *pdata = vcpu->arch.mtrr[msr - 0x200]; | ||
733 | return 0; | ||
734 | } | ||
735 | |||
694 | int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | 736 | int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) |
695 | { | 737 | { |
696 | u64 data; | 738 | u64 data; |
@@ -712,11 +754,13 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
712 | case MSR_IA32_MC0_MISC+16: | 754 | case MSR_IA32_MC0_MISC+16: |
713 | case MSR_IA32_UCODE_REV: | 755 | case MSR_IA32_UCODE_REV: |
714 | case MSR_IA32_EBL_CR_POWERON: | 756 | case MSR_IA32_EBL_CR_POWERON: |
715 | /* MTRR registers */ | ||
716 | case 0xfe: | ||
717 | case 0x200 ... 0x2ff: | ||
718 | data = 0; | 757 | data = 0; |
719 | break; | 758 | break; |
759 | case MSR_MTRRcap: | ||
760 | data = 0x500 | KVM_NR_VAR_MTRR; | ||
761 | break; | ||
762 | case 0x200 ... 0x2ff: | ||
763 | return get_msr_mtrr(vcpu, msr, pdata); | ||
720 | case 0xcd: /* fsb frequency */ | 764 | case 0xcd: /* fsb frequency */ |
721 | data = 3; | 765 | data = 3; |
722 | break; | 766 | break; |
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 075598b4e3f3..fc72bad878ed 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h | |||
@@ -79,6 +79,7 @@ | |||
79 | #define KVM_MIN_FREE_MMU_PAGES 5 | 79 | #define KVM_MIN_FREE_MMU_PAGES 5 |
80 | #define KVM_REFILL_PAGES 25 | 80 | #define KVM_REFILL_PAGES 25 |
81 | #define KVM_MAX_CPUID_ENTRIES 40 | 81 | #define KVM_MAX_CPUID_ENTRIES 40 |
82 | #define KVM_NR_VAR_MTRR 8 | ||
82 | 83 | ||
83 | extern spinlock_t kvm_lock; | 84 | extern spinlock_t kvm_lock; |
84 | extern struct list_head vm_list; | 85 | extern struct list_head vm_list; |
@@ -290,6 +291,8 @@ struct kvm_vcpu_arch { | |||
290 | struct page *time_page; | 291 | struct page *time_page; |
291 | 292 | ||
292 | bool nmi_pending; | 293 | bool nmi_pending; |
294 | |||
295 | u64 mtrr[0x100]; | ||
293 | }; | 296 | }; |
294 | 297 | ||
295 | struct kvm_mem_alias { | 298 | struct kvm_mem_alias { |