diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2007-03-30 10:02:14 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-05-03 03:52:28 -0400 |
commit | 80b7706e4cbaa51d65bd6fea83bd0e59856f50e9 (patch) | |
tree | c688c8b9cd07c2555facd657e8e8e3ed508b93be | |
parent | b8836737d92c139be770eae3d6574e33d1224caf (diff) |
KVM: SVM: enable LBRV virtualization if available
This patch enables the virtualization of the last branch record MSRs on
SVM if this feature is available in hardware. It also introduces a small
and simple check feature for specific SVM extensions.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | drivers/kvm/svm.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 303e95957e7b..b7e1410e4007 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -44,6 +44,10 @@ MODULE_LICENSE("GPL"); | |||
44 | #define KVM_EFER_LMA (1 << 10) | 44 | #define KVM_EFER_LMA (1 << 10) |
45 | #define KVM_EFER_LME (1 << 8) | 45 | #define KVM_EFER_LME (1 << 8) |
46 | 46 | ||
47 | #define SVM_FEATURE_NPT (1 << 0) | ||
48 | #define SVM_FEATURE_LBRV (1 << 1) | ||
49 | #define SVM_DEATURE_SVML (1 << 2) | ||
50 | |||
47 | unsigned long iopm_base; | 51 | unsigned long iopm_base; |
48 | unsigned long msrpm_base; | 52 | unsigned long msrpm_base; |
49 | 53 | ||
@@ -68,6 +72,7 @@ struct svm_cpu_data { | |||
68 | }; | 72 | }; |
69 | 73 | ||
70 | static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); | 74 | static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); |
75 | static uint32_t svm_features; | ||
71 | 76 | ||
72 | struct svm_init_data { | 77 | struct svm_init_data { |
73 | int cpu; | 78 | int cpu; |
@@ -82,6 +87,11 @@ static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000}; | |||
82 | 87 | ||
83 | #define MAX_INST_SIZE 15 | 88 | #define MAX_INST_SIZE 15 |
84 | 89 | ||
90 | static inline u32 svm_has(u32 feat) | ||
91 | { | ||
92 | return svm_features & feat; | ||
93 | } | ||
94 | |||
85 | static unsigned get_addr_size(struct kvm_vcpu *vcpu) | 95 | static unsigned get_addr_size(struct kvm_vcpu *vcpu) |
86 | { | 96 | { |
87 | struct vmcb_save_area *sa = &vcpu->svm->vmcb->save; | 97 | struct vmcb_save_area *sa = &vcpu->svm->vmcb->save; |
@@ -302,6 +312,7 @@ static void svm_hardware_enable(void *garbage) | |||
302 | svm_data->asid_generation = 1; | 312 | svm_data->asid_generation = 1; |
303 | svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; | 313 | svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; |
304 | svm_data->next_asid = svm_data->max_asid + 1; | 314 | svm_data->next_asid = svm_data->max_asid + 1; |
315 | svm_features = cpuid_edx(SVM_CPUID_FUNC); | ||
305 | 316 | ||
306 | asm volatile ( "sgdt %0" : "=m"(gdt_descr) ); | 317 | asm volatile ( "sgdt %0" : "=m"(gdt_descr) ); |
307 | gdt = (struct desc_struct *)gdt_descr.address; | 318 | gdt = (struct desc_struct *)gdt_descr.address; |
@@ -511,6 +522,8 @@ static void init_vmcb(struct vmcb *vmcb) | |||
511 | control->msrpm_base_pa = msrpm_base; | 522 | control->msrpm_base_pa = msrpm_base; |
512 | control->tsc_offset = 0; | 523 | control->tsc_offset = 0; |
513 | control->int_ctl = V_INTR_MASKING_MASK; | 524 | control->int_ctl = V_INTR_MASKING_MASK; |
525 | if (svm_has(SVM_FEATURE_LBRV)) | ||
526 | control->lbr_ctl = 1ULL; | ||
514 | 527 | ||
515 | init_seg(&save->es); | 528 | init_seg(&save->es); |
516 | init_seg(&save->ss); | 529 | init_seg(&save->ss); |