diff options
author | Avi Kivity <avi@qumranet.com> | 2006-12-29 19:49:37 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-30 13:56:44 -0500 |
commit | a9058ecd3cd72634cf548588ce79b3f225c9ca32 (patch) | |
tree | 11d1edd2dfdcec03ba6b54b3b06d41cae826b940 | |
parent | 1e885461f02259d75e7480a70d291d2d8aaa938e (diff) |
[PATCH] KVM: Simplify is_long_mode()
Instead of doing tricky stuff with the arch dependent virtualization
registers, take a peek at the guest's efer.
This simlifies some code, and fixes some confusion in the mmu branch.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/kvm/kvm.h | 10 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 4 | ||||
-rw-r--r-- | drivers/kvm/mmu.c | 2 | ||||
-rw-r--r-- | drivers/kvm/paging_tmpl.h | 4 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 6 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 6 |
6 files changed, 14 insertions, 18 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 930e04ce1af6..c2db4218d6cc 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -278,7 +278,6 @@ struct kvm_arch_ops { | |||
278 | struct kvm_segment *var, int seg); | 278 | struct kvm_segment *var, int seg); |
279 | void (*set_segment)(struct kvm_vcpu *vcpu, | 279 | void (*set_segment)(struct kvm_vcpu *vcpu, |
280 | struct kvm_segment *var, int seg); | 280 | struct kvm_segment *var, int seg); |
281 | int (*is_long_mode)(struct kvm_vcpu *vcpu); | ||
282 | void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l); | 281 | void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l); |
283 | void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0); | 282 | void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0); |
284 | void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu, | 283 | void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu, |
@@ -403,6 +402,15 @@ static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn) | |||
403 | return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL; | 402 | return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL; |
404 | } | 403 | } |
405 | 404 | ||
405 | static inline int is_long_mode(struct kvm_vcpu *vcpu) | ||
406 | { | ||
407 | #ifdef CONFIG_X86_64 | ||
408 | return vcpu->shadow_efer & EFER_LME; | ||
409 | #else | ||
410 | return 0; | ||
411 | #endif | ||
412 | } | ||
413 | |||
406 | static inline int is_pae(struct kvm_vcpu *vcpu) | 414 | static inline int is_pae(struct kvm_vcpu *vcpu) |
407 | { | 415 | { |
408 | return vcpu->cr4 & CR4_PAE_MASK; | 416 | return vcpu->cr4 & CR4_PAE_MASK; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 9f24f22e4cb2..38375e2bb703 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -398,7 +398,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
398 | return; | 398 | return; |
399 | } | 399 | } |
400 | 400 | ||
401 | if (kvm_arch_ops->is_long_mode(vcpu)) { | 401 | if (is_long_mode(vcpu)) { |
402 | if (!(cr4 & CR4_PAE_MASK)) { | 402 | if (!(cr4 & CR4_PAE_MASK)) { |
403 | printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while " | 403 | printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while " |
404 | "in long mode\n"); | 404 | "in long mode\n"); |
@@ -425,7 +425,7 @@ EXPORT_SYMBOL_GPL(set_cr4); | |||
425 | 425 | ||
426 | void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | 426 | void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) |
427 | { | 427 | { |
428 | if (kvm_arch_ops->is_long_mode(vcpu)) { | 428 | if (is_long_mode(vcpu)) { |
429 | if ( cr3 & CR3_L_MODE_RESEVED_BITS) { | 429 | if ( cr3 & CR3_L_MODE_RESEVED_BITS) { |
430 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); | 430 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); |
431 | inject_gp(vcpu); | 431 | inject_gp(vcpu); |
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index bdffe83b19e8..85887fcd584f 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
@@ -578,7 +578,7 @@ static int init_kvm_mmu(struct kvm_vcpu *vcpu) | |||
578 | 578 | ||
579 | if (!is_paging(vcpu)) | 579 | if (!is_paging(vcpu)) |
580 | return nonpaging_init_context(vcpu); | 580 | return nonpaging_init_context(vcpu); |
581 | else if (kvm_arch_ops->is_long_mode(vcpu)) | 581 | else if (is_long_mode(vcpu)) |
582 | return paging64_init_context(vcpu); | 582 | return paging64_init_context(vcpu); |
583 | else if (is_pae(vcpu)) | 583 | else if (is_pae(vcpu)) |
584 | return paging32E_init_context(vcpu); | 584 | return paging32E_init_context(vcpu); |
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index a9771b4c5bb8..09bb9b4ed12d 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h | |||
@@ -68,7 +68,7 @@ static void FNAME(init_walker)(struct guest_walker *walker, | |||
68 | hpa = safe_gpa_to_hpa(vcpu, vcpu->cr3 & PT64_BASE_ADDR_MASK); | 68 | hpa = safe_gpa_to_hpa(vcpu, vcpu->cr3 & PT64_BASE_ADDR_MASK); |
69 | walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0); | 69 | walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0); |
70 | 70 | ||
71 | ASSERT((!kvm_arch_ops->is_long_mode(vcpu) && is_pae(vcpu)) || | 71 | ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) || |
72 | (vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0); | 72 | (vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0); |
73 | 73 | ||
74 | walker->table = (pt_element_t *)( (unsigned long)walker->table | | 74 | walker->table = (pt_element_t *)( (unsigned long)walker->table | |
@@ -131,7 +131,7 @@ static pt_element_t *FNAME(fetch_guest)(struct kvm_vcpu *vcpu, | |||
131 | (walker->table[index] & PT_PAGE_SIZE_MASK) && | 131 | (walker->table[index] & PT_PAGE_SIZE_MASK) && |
132 | (PTTYPE == 64 || is_pse(vcpu)))) | 132 | (PTTYPE == 64 || is_pse(vcpu)))) |
133 | return &walker->table[index]; | 133 | return &walker->table[index]; |
134 | if (walker->level != 3 || kvm_arch_ops->is_long_mode(vcpu)) | 134 | if (walker->level != 3 || is_long_mode(vcpu)) |
135 | walker->inherited_ar &= walker->table[index]; | 135 | walker->inherited_ar &= walker->table[index]; |
136 | paddr = safe_gpa_to_hpa(vcpu, walker->table[index] & PT_BASE_ADDR_MASK); | 136 | paddr = safe_gpa_to_hpa(vcpu, walker->table[index] & PT_BASE_ADDR_MASK); |
137 | kunmap_atomic(walker->table, KM_USER0); | 137 | kunmap_atomic(walker->table, KM_USER0); |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 283024ab3ba0..68124c0bf630 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -166,11 +166,6 @@ static inline void write_dr7(unsigned long val) | |||
166 | asm volatile ("mov %0, %%dr7" :: "r" (val)); | 166 | asm volatile ("mov %0, %%dr7" :: "r" (val)); |
167 | } | 167 | } |
168 | 168 | ||
169 | static inline int svm_is_long_mode(struct kvm_vcpu *vcpu) | ||
170 | { | ||
171 | return vcpu->svm->vmcb->save.efer & KVM_EFER_LMA; | ||
172 | } | ||
173 | |||
174 | static inline void force_new_asid(struct kvm_vcpu *vcpu) | 169 | static inline void force_new_asid(struct kvm_vcpu *vcpu) |
175 | { | 170 | { |
176 | vcpu->svm->asid_generation--; | 171 | vcpu->svm->asid_generation--; |
@@ -1609,7 +1604,6 @@ static struct kvm_arch_ops svm_arch_ops = { | |||
1609 | .get_segment_base = svm_get_segment_base, | 1604 | .get_segment_base = svm_get_segment_base, |
1610 | .get_segment = svm_get_segment, | 1605 | .get_segment = svm_get_segment, |
1611 | .set_segment = svm_set_segment, | 1606 | .set_segment = svm_set_segment, |
1612 | .is_long_mode = svm_is_long_mode, | ||
1613 | .get_cs_db_l_bits = svm_get_cs_db_l_bits, | 1607 | .get_cs_db_l_bits = svm_get_cs_db_l_bits, |
1614 | .set_cr0 = svm_set_cr0, | 1608 | .set_cr0 = svm_set_cr0, |
1615 | .set_cr0_no_modeswitch = svm_set_cr0, | 1609 | .set_cr0_no_modeswitch = svm_set_cr0, |
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 983a15b1977c..603a4135de42 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -900,11 +900,6 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu, | |||
900 | vmcs_write32(sf->ar_bytes, ar); | 900 | vmcs_write32(sf->ar_bytes, ar); |
901 | } | 901 | } |
902 | 902 | ||
903 | static int vmx_is_long_mode(struct kvm_vcpu *vcpu) | ||
904 | { | ||
905 | return vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_CONTROLS_IA32E_MASK; | ||
906 | } | ||
907 | |||
908 | static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) | 903 | static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) |
909 | { | 904 | { |
910 | u32 ar = vmcs_read32(GUEST_CS_AR_BYTES); | 905 | u32 ar = vmcs_read32(GUEST_CS_AR_BYTES); |
@@ -1975,7 +1970,6 @@ static struct kvm_arch_ops vmx_arch_ops = { | |||
1975 | .get_segment_base = vmx_get_segment_base, | 1970 | .get_segment_base = vmx_get_segment_base, |
1976 | .get_segment = vmx_get_segment, | 1971 | .get_segment = vmx_get_segment, |
1977 | .set_segment = vmx_set_segment, | 1972 | .set_segment = vmx_set_segment, |
1978 | .is_long_mode = vmx_is_long_mode, | ||
1979 | .get_cs_db_l_bits = vmx_get_cs_db_l_bits, | 1973 | .get_cs_db_l_bits = vmx_get_cs_db_l_bits, |
1980 | .set_cr0 = vmx_set_cr0, | 1974 | .set_cr0 = vmx_set_cr0, |
1981 | .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch, | 1975 | .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch, |