aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/kvm.h1
-rw-r--r--drivers/kvm/kvm_main.c19
-rw-r--r--drivers/kvm/mmu.c16
-rw-r--r--drivers/kvm/paging_tmpl.h79
-rw-r--r--drivers/kvm/svm.c28
-rw-r--r--drivers/kvm/vmx.c5
-rw-r--r--drivers/kvm/x86_emulate.c98
7 files changed, 151 insertions, 95 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 91e0c75aca8f..2db1ca4c6800 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -242,6 +242,7 @@ struct kvm_vcpu {
242 u64 pdptrs[4]; /* pae */ 242 u64 pdptrs[4]; /* pae */
243 u64 shadow_efer; 243 u64 shadow_efer;
244 u64 apic_base; 244 u64 apic_base;
245 u64 ia32_misc_enable_msr;
245 int nmsrs; 246 int nmsrs;
246 struct vmx_msr_entry *guest_msrs; 247 struct vmx_msr_entry *guest_msrs;
247 struct vmx_msr_entry *host_msrs; 248 struct vmx_msr_entry *host_msrs;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 67c1154960f0..b10972ed0c9f 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -272,7 +272,9 @@ static void kvm_free_physmem(struct kvm *kvm)
272 272
273static void kvm_free_vcpu(struct kvm_vcpu *vcpu) 273static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
274{ 274{
275 vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
275 kvm_mmu_destroy(vcpu); 276 kvm_mmu_destroy(vcpu);
277 vcpu_put(vcpu);
276 kvm_arch_ops->vcpu_free(vcpu); 278 kvm_arch_ops->vcpu_free(vcpu);
277} 279}
278 280
@@ -1224,6 +1226,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
1224 case MSR_IA32_APICBASE: 1226 case MSR_IA32_APICBASE:
1225 data = vcpu->apic_base; 1227 data = vcpu->apic_base;
1226 break; 1228 break;
1229 case MSR_IA32_MISC_ENABLE:
1230 data = vcpu->ia32_misc_enable_msr;
1231 break;
1227#ifdef CONFIG_X86_64 1232#ifdef CONFIG_X86_64
1228 case MSR_EFER: 1233 case MSR_EFER:
1229 data = vcpu->shadow_efer; 1234 data = vcpu->shadow_efer;
@@ -1295,6 +1300,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
1295 case MSR_IA32_APICBASE: 1300 case MSR_IA32_APICBASE:
1296 vcpu->apic_base = data; 1301 vcpu->apic_base = data;
1297 break; 1302 break;
1303 case MSR_IA32_MISC_ENABLE:
1304 vcpu->ia32_misc_enable_msr = data;
1305 break;
1298 default: 1306 default:
1299 printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); 1307 printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr);
1300 return 1; 1308 return 1;
@@ -1598,6 +1606,10 @@ static u32 msrs_to_save[] = {
1598 1606
1599static unsigned num_msrs_to_save; 1607static unsigned num_msrs_to_save;
1600 1608
1609static u32 emulated_msrs[] = {
1610 MSR_IA32_MISC_ENABLE,
1611};
1612
1601static __init void kvm_init_msr_list(void) 1613static __init void kvm_init_msr_list(void)
1602{ 1614{
1603 u32 dummy[2]; 1615 u32 dummy[2];
@@ -1923,7 +1935,7 @@ static long kvm_dev_ioctl(struct file *filp,
1923 if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list)) 1935 if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
1924 goto out; 1936 goto out;
1925 n = msr_list.nmsrs; 1937 n = msr_list.nmsrs;
1926 msr_list.nmsrs = num_msrs_to_save; 1938 msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs);
1927 if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) 1939 if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
1928 goto out; 1940 goto out;
1929 r = -E2BIG; 1941 r = -E2BIG;
@@ -1933,6 +1945,11 @@ static long kvm_dev_ioctl(struct file *filp,
1933 if (copy_to_user(user_msr_list->indices, &msrs_to_save, 1945 if (copy_to_user(user_msr_list->indices, &msrs_to_save,
1934 num_msrs_to_save * sizeof(u32))) 1946 num_msrs_to_save * sizeof(u32)))
1935 goto out; 1947 goto out;
1948 if (copy_to_user(user_msr_list->indices
1949 + num_msrs_to_save * sizeof(u32),
1950 &emulated_msrs,
1951 ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
1952 goto out;
1936 r = 0; 1953 r = 0;
1937 break; 1954 break;
1938 } 1955 }
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index c6f972914f08..22c426cd8cb2 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -143,6 +143,7 @@ static int dbg = 1;
143#define PFERR_PRESENT_MASK (1U << 0) 143#define PFERR_PRESENT_MASK (1U << 0)
144#define PFERR_WRITE_MASK (1U << 1) 144#define PFERR_WRITE_MASK (1U << 1)
145#define PFERR_USER_MASK (1U << 2) 145#define PFERR_USER_MASK (1U << 2)
146#define PFERR_FETCH_MASK (1U << 4)
146 147
147#define PT64_ROOT_LEVEL 4 148#define PT64_ROOT_LEVEL 4
148#define PT32_ROOT_LEVEL 2 149#define PT32_ROOT_LEVEL 2
@@ -168,6 +169,11 @@ static int is_cpuid_PSE36(void)
168 return 1; 169 return 1;
169} 170}
170 171
172static int is_nx(struct kvm_vcpu *vcpu)
173{
174 return vcpu->shadow_efer & EFER_NX;
175}
176
171static int is_present_pte(unsigned long pte) 177static int is_present_pte(unsigned long pte)
172{ 178{
173 return pte & PT_PRESENT_MASK; 179 return pte & PT_PRESENT_MASK;
@@ -992,16 +998,6 @@ static inline int fix_read_pf(u64 *shadow_ent)
992 return 0; 998 return 0;
993} 999}
994 1000
995static int may_access(u64 pte, int write, int user)
996{
997
998 if (user && !(pte & PT_USER_MASK))
999 return 0;
1000 if (write && !(pte & PT_WRITABLE_MASK))
1001 return 0;
1002 return 1;
1003}
1004
1005static void paging_free(struct kvm_vcpu *vcpu) 1001static void paging_free(struct kvm_vcpu *vcpu)
1006{ 1002{
1007 nonpaging_free(vcpu); 1003 nonpaging_free(vcpu);
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 2dbf4307ed9e..149fa45fd9a5 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -63,13 +63,15 @@ struct guest_walker {
63 pt_element_t *ptep; 63 pt_element_t *ptep;
64 pt_element_t inherited_ar; 64 pt_element_t inherited_ar;
65 gfn_t gfn; 65 gfn_t gfn;
66 u32 error_code;
66}; 67};
67 68
68/* 69/*
69 * Fetch a guest pte for a guest virtual address 70 * Fetch a guest pte for a guest virtual address
70 */ 71 */
71static void FNAME(walk_addr)(struct guest_walker *walker, 72static int FNAME(walk_addr)(struct guest_walker *walker,
72 struct kvm_vcpu *vcpu, gva_t addr) 73 struct kvm_vcpu *vcpu, gva_t addr,
74 int write_fault, int user_fault, int fetch_fault)
73{ 75{
74 hpa_t hpa; 76 hpa_t hpa;
75 struct kvm_memory_slot *slot; 77 struct kvm_memory_slot *slot;
@@ -86,7 +88,7 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
86 walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3]; 88 walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3];
87 root = *walker->ptep; 89 root = *walker->ptep;
88 if (!(root & PT_PRESENT_MASK)) 90 if (!(root & PT_PRESENT_MASK))
89 return; 91 goto not_present;
90 --walker->level; 92 --walker->level;
91 } 93 }
92#endif 94#endif
@@ -111,11 +113,23 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
111 ASSERT(((unsigned long)walker->table & PAGE_MASK) == 113 ASSERT(((unsigned long)walker->table & PAGE_MASK) ==
112 ((unsigned long)ptep & PAGE_MASK)); 114 ((unsigned long)ptep & PAGE_MASK));
113 115
114 if (is_present_pte(*ptep) && !(*ptep & PT_ACCESSED_MASK))
115 *ptep |= PT_ACCESSED_MASK;
116
117 if (!is_present_pte(*ptep)) 116 if (!is_present_pte(*ptep))
118 break; 117 goto not_present;
118
119 if (write_fault && !is_writeble_pte(*ptep))
120 if (user_fault || is_write_protection(vcpu))
121 goto access_error;
122
123 if (user_fault && !(*ptep & PT_USER_MASK))
124 goto access_error;
125
126#if PTTYPE == 64
127 if (fetch_fault && is_nx(vcpu) && (*ptep & PT64_NX_MASK))
128 goto access_error;
129#endif
130
131 if (!(*ptep & PT_ACCESSED_MASK))
132 *ptep |= PT_ACCESSED_MASK; /* avoid rmw */
119 133
120 if (walker->level == PT_PAGE_TABLE_LEVEL) { 134 if (walker->level == PT_PAGE_TABLE_LEVEL) {
121 walker->gfn = (*ptep & PT_BASE_ADDR_MASK) 135 walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
@@ -146,6 +160,23 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
146 } 160 }
147 walker->ptep = ptep; 161 walker->ptep = ptep;
148 pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep); 162 pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep);
163 return 1;
164
165not_present:
166 walker->error_code = 0;
167 goto err;
168
169access_error:
170 walker->error_code = PFERR_PRESENT_MASK;
171
172err:
173 if (write_fault)
174 walker->error_code |= PFERR_WRITE_MASK;
175 if (user_fault)
176 walker->error_code |= PFERR_USER_MASK;
177 if (fetch_fault)
178 walker->error_code |= PFERR_FETCH_MASK;
179 return 0;
149} 180}
150 181
151static void FNAME(release_walker)(struct guest_walker *walker) 182static void FNAME(release_walker)(struct guest_walker *walker)
@@ -274,7 +305,7 @@ static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu,
274 struct kvm_mmu_page *page; 305 struct kvm_mmu_page *page;
275 306
276 if (is_writeble_pte(*shadow_ent)) 307 if (is_writeble_pte(*shadow_ent))
277 return 0; 308 return !user || (*shadow_ent & PT_USER_MASK);
278 309
279 writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK; 310 writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK;
280 if (user) { 311 if (user) {
@@ -347,8 +378,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
347 u32 error_code) 378 u32 error_code)
348{ 379{
349 int write_fault = error_code & PFERR_WRITE_MASK; 380 int write_fault = error_code & PFERR_WRITE_MASK;
350 int pte_present = error_code & PFERR_PRESENT_MASK;
351 int user_fault = error_code & PFERR_USER_MASK; 381 int user_fault = error_code & PFERR_USER_MASK;
382 int fetch_fault = error_code & PFERR_FETCH_MASK;
352 struct guest_walker walker; 383 struct guest_walker walker;
353 u64 *shadow_pte; 384 u64 *shadow_pte;
354 int fixed; 385 int fixed;
@@ -365,19 +396,20 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
365 /* 396 /*
366 * Look up the shadow pte for the faulting address. 397 * Look up the shadow pte for the faulting address.
367 */ 398 */
368 FNAME(walk_addr)(&walker, vcpu, addr); 399 r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault,
369 shadow_pte = FNAME(fetch)(vcpu, addr, &walker); 400 fetch_fault);
370 401
371 /* 402 /*
372 * The page is not mapped by the guest. Let the guest handle it. 403 * The page is not mapped by the guest. Let the guest handle it.
373 */ 404 */
374 if (!shadow_pte) { 405 if (!r) {
375 pgprintk("%s: not mapped\n", __FUNCTION__); 406 pgprintk("%s: guest page fault\n", __FUNCTION__);
376 inject_page_fault(vcpu, addr, error_code); 407 inject_page_fault(vcpu, addr, walker.error_code);
377 FNAME(release_walker)(&walker); 408 FNAME(release_walker)(&walker);
378 return 0; 409 return 0;
379 } 410 }
380 411
412 shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
381 pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__, 413 pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__,
382 shadow_pte, *shadow_pte); 414 shadow_pte, *shadow_pte);
383 415
@@ -399,22 +431,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
399 * mmio: emulate if accessible, otherwise its a guest fault. 431 * mmio: emulate if accessible, otherwise its a guest fault.
400 */ 432 */
401 if (is_io_pte(*shadow_pte)) { 433 if (is_io_pte(*shadow_pte)) {
402 if (may_access(*shadow_pte, write_fault, user_fault)) 434 return 1;
403 return 1;
404 pgprintk("%s: io work, no access\n", __FUNCTION__);
405 inject_page_fault(vcpu, addr,
406 error_code | PFERR_PRESENT_MASK);
407 kvm_mmu_audit(vcpu, "post page fault (io)");
408 return 0;
409 }
410
411 /*
412 * pte not present, guest page fault.
413 */
414 if (pte_present && !fixed && !write_pt) {
415 inject_page_fault(vcpu, addr, error_code);
416 kvm_mmu_audit(vcpu, "post page fault (guest)");
417 return 0;
418 } 435 }
419 436
420 ++kvm_stat.pf_fixed; 437 ++kvm_stat.pf_fixed;
@@ -429,7 +446,7 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
429 pt_element_t guest_pte; 446 pt_element_t guest_pte;
430 gpa_t gpa; 447 gpa_t gpa;
431 448
432 FNAME(walk_addr)(&walker, vcpu, vaddr); 449 FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
433 guest_pte = *walker.ptep; 450 guest_pte = *walker.ptep;
434 FNAME(release_walker)(&walker); 451 FNAME(release_walker)(&walker);
435 452
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 714f6a7841cd..c79df79307ed 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -502,6 +502,7 @@ static void init_vmcb(struct vmcb *vmcb)
502 (1ULL << INTERCEPT_IOIO_PROT) | 502 (1ULL << INTERCEPT_IOIO_PROT) |
503 (1ULL << INTERCEPT_MSR_PROT) | 503 (1ULL << INTERCEPT_MSR_PROT) |
504 (1ULL << INTERCEPT_TASK_SWITCH) | 504 (1ULL << INTERCEPT_TASK_SWITCH) |
505 (1ULL << INTERCEPT_SHUTDOWN) |
505 (1ULL << INTERCEPT_VMRUN) | 506 (1ULL << INTERCEPT_VMRUN) |
506 (1ULL << INTERCEPT_VMMCALL) | 507 (1ULL << INTERCEPT_VMMCALL) |
507 (1ULL << INTERCEPT_VMLOAD) | 508 (1ULL << INTERCEPT_VMLOAD) |
@@ -680,14 +681,14 @@ static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
680 681
681static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) 682static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
682{ 683{
683 dt->limit = vcpu->svm->vmcb->save.ldtr.limit; 684 dt->limit = vcpu->svm->vmcb->save.idtr.limit;
684 dt->base = vcpu->svm->vmcb->save.ldtr.base; 685 dt->base = vcpu->svm->vmcb->save.idtr.base;
685} 686}
686 687
687static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) 688static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
688{ 689{
689 vcpu->svm->vmcb->save.ldtr.limit = dt->limit; 690 vcpu->svm->vmcb->save.idtr.limit = dt->limit;
690 vcpu->svm->vmcb->save.ldtr.base = dt->base ; 691 vcpu->svm->vmcb->save.idtr.base = dt->base ;
691} 692}
692 693
693static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) 694static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
@@ -892,6 +893,19 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
892 return 0; 893 return 0;
893} 894}
894 895
896static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
897{
898 /*
899 * VMCB is undefined after a SHUTDOWN intercept
900 * so reinitialize it.
901 */
902 memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
903 init_vmcb(vcpu->svm->vmcb);
904
905 kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
906 return 0;
907}
908
895static int io_get_override(struct kvm_vcpu *vcpu, 909static int io_get_override(struct kvm_vcpu *vcpu,
896 struct vmcb_seg **seg, 910 struct vmcb_seg **seg,
897 int *addr_override) 911 int *addr_override)
@@ -1149,7 +1163,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
1149 case MSR_K6_STAR: 1163 case MSR_K6_STAR:
1150 vcpu->svm->vmcb->save.star = data; 1164 vcpu->svm->vmcb->save.star = data;
1151 break; 1165 break;
1152#ifdef CONFIG_X86_64_ 1166#ifdef CONFIG_X86_64
1153 case MSR_LSTAR: 1167 case MSR_LSTAR:
1154 vcpu->svm->vmcb->save.lstar = data; 1168 vcpu->svm->vmcb->save.lstar = data;
1155 break; 1169 break;
@@ -1249,6 +1263,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
1249 [SVM_EXIT_IOIO] = io_interception, 1263 [SVM_EXIT_IOIO] = io_interception,
1250 [SVM_EXIT_MSR] = msr_interception, 1264 [SVM_EXIT_MSR] = msr_interception,
1251 [SVM_EXIT_TASK_SWITCH] = task_switch_interception, 1265 [SVM_EXIT_TASK_SWITCH] = task_switch_interception,
1266 [SVM_EXIT_SHUTDOWN] = shutdown_interception,
1252 [SVM_EXIT_VMRUN] = invalid_op_interception, 1267 [SVM_EXIT_VMRUN] = invalid_op_interception,
1253 [SVM_EXIT_VMMCALL] = invalid_op_interception, 1268 [SVM_EXIT_VMMCALL] = invalid_op_interception,
1254 [SVM_EXIT_VMLOAD] = invalid_op_interception, 1269 [SVM_EXIT_VMLOAD] = invalid_op_interception,
@@ -1407,7 +1422,8 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1407 int r; 1422 int r;
1408 1423
1409again: 1424again:
1410 do_interrupt_requests(vcpu, kvm_run); 1425 if (!vcpu->mmio_read_completed)
1426 do_interrupt_requests(vcpu, kvm_run);
1411 1427
1412 clgi(); 1428 clgi();
1413 1429
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 0aa2659f6ae5..54c35c0b3181 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1116,6 +1116,8 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
1116 1116
1117 if (rdmsr_safe(index, &data_low, &data_high) < 0) 1117 if (rdmsr_safe(index, &data_low, &data_high) < 0)
1118 continue; 1118 continue;
1119 if (wrmsr_safe(index, data_low, data_high) < 0)
1120 continue;
1119 data = data_low | ((u64)data_high << 32); 1121 data = data_low | ((u64)data_high << 32);
1120 vcpu->host_msrs[j].index = index; 1122 vcpu->host_msrs[j].index = index;
1121 vcpu->host_msrs[j].reserved = 0; 1123 vcpu->host_msrs[j].reserved = 0;
@@ -1717,7 +1719,8 @@ again:
1717 vmcs_writel(HOST_GS_BASE, segment_base(gs_sel)); 1719 vmcs_writel(HOST_GS_BASE, segment_base(gs_sel));
1718#endif 1720#endif
1719 1721
1720 do_interrupt_requests(vcpu, kvm_run); 1722 if (!vcpu->mmio_read_completed)
1723 do_interrupt_requests(vcpu, kvm_run);
1721 1724
1722 if (vcpu->guest_debug.enabled) 1725 if (vcpu->guest_debug.enabled)
1723 kvm_guest_debug_pre(vcpu); 1726 kvm_guest_debug_pre(vcpu);
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index be70795b4822..7513cddb929f 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -61,6 +61,7 @@
61#define ModRM (1<<6) 61#define ModRM (1<<6)
62/* Destination is only written; never read. */ 62/* Destination is only written; never read. */
63#define Mov (1<<7) 63#define Mov (1<<7)
64#define BitOp (1<<8)
64 65
65static u8 opcode_table[256] = { 66static u8 opcode_table[256] = {
66 /* 0x00 - 0x07 */ 67 /* 0x00 - 0x07 */
@@ -148,7 +149,7 @@ static u8 opcode_table[256] = {
148 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM 149 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
149}; 150};
150 151
151static u8 twobyte_table[256] = { 152static u16 twobyte_table[256] = {
152 /* 0x00 - 0x0F */ 153 /* 0x00 - 0x0F */
153 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, 154 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
154 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 155 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
@@ -180,16 +181,16 @@ static u8 twobyte_table[256] = {
180 /* 0x90 - 0x9F */ 181 /* 0x90 - 0x9F */
181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
182 /* 0xA0 - 0xA7 */ 183 /* 0xA0 - 0xA7 */
183 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, 184 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
184 /* 0xA8 - 0xAF */ 185 /* 0xA8 - 0xAF */
185 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, 186 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
186 /* 0xB0 - 0xB7 */ 187 /* 0xB0 - 0xB7 */
187 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, 188 ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,
188 DstMem | SrcReg | ModRM, 189 DstMem | SrcReg | ModRM | BitOp,
189 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, 190 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
190 DstReg | SrcMem16 | ModRM | Mov, 191 DstReg | SrcMem16 | ModRM | Mov,
191 /* 0xB8 - 0xBF */ 192 /* 0xB8 - 0xBF */
192 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM, 193 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp,
193 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, 194 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
194 DstReg | SrcMem16 | ModRM | Mov, 195 DstReg | SrcMem16 | ModRM | Mov,
195 /* 0xC0 - 0xCF */ 196 /* 0xC0 - 0xCF */
@@ -469,7 +470,8 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,
469int 470int
470x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) 471x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
471{ 472{
472 u8 b, d, sib, twobyte = 0, rex_prefix = 0; 473 unsigned d;
474 u8 b, sib, twobyte = 0, rex_prefix = 0;
473 u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; 475 u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
474 unsigned long *override_base = NULL; 476 unsigned long *override_base = NULL;
475 unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; 477 unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
@@ -726,46 +728,6 @@ done_prefixes:
726 ; 728 ;
727 } 729 }
728 730
729 /* Decode and fetch the destination operand: register or memory. */
730 switch (d & DstMask) {
731 case ImplicitOps:
732 /* Special instructions do their own operand decoding. */
733 goto special_insn;
734 case DstReg:
735 dst.type = OP_REG;
736 if ((d & ByteOp)
737 && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
738 dst.ptr = decode_register(modrm_reg, _regs,
739 (rex_prefix == 0));
740 dst.val = *(u8 *) dst.ptr;
741 dst.bytes = 1;
742 } else {
743 dst.ptr = decode_register(modrm_reg, _regs, 0);
744 switch ((dst.bytes = op_bytes)) {
745 case 2:
746 dst.val = *(u16 *)dst.ptr;
747 break;
748 case 4:
749 dst.val = *(u32 *)dst.ptr;
750 break;
751 case 8:
752 dst.val = *(u64 *)dst.ptr;
753 break;
754 }
755 }
756 break;
757 case DstMem:
758 dst.type = OP_MEM;
759 dst.ptr = (unsigned long *)cr2;
760 dst.bytes = (d & ByteOp) ? 1 : op_bytes;
761 if (!(d & Mov) && /* optimisation - avoid slow emulated read */
762 ((rc = ops->read_emulated((unsigned long)dst.ptr,
763 &dst.val, dst.bytes, ctxt)) != 0))
764 goto done;
765 break;
766 }
767 dst.orig_val = dst.val;
768
769 /* 731 /*
770 * Decode and fetch the source operand: register, memory 732 * Decode and fetch the source operand: register, memory
771 * or immediate. 733 * or immediate.
@@ -838,6 +800,50 @@ done_prefixes:
838 break; 800 break;
839 } 801 }
840 802
803 /* Decode and fetch the destination operand: register or memory. */
804 switch (d & DstMask) {
805 case ImplicitOps:
806 /* Special instructions do their own operand decoding. */
807 goto special_insn;
808 case DstReg:
809 dst.type = OP_REG;
810 if ((d & ByteOp)
811 && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
812 dst.ptr = decode_register(modrm_reg, _regs,
813 (rex_prefix == 0));
814 dst.val = *(u8 *) dst.ptr;
815 dst.bytes = 1;
816 } else {
817 dst.ptr = decode_register(modrm_reg, _regs, 0);
818 switch ((dst.bytes = op_bytes)) {
819 case 2:
820 dst.val = *(u16 *)dst.ptr;
821 break;
822 case 4:
823 dst.val = *(u32 *)dst.ptr;
824 break;
825 case 8:
826 dst.val = *(u64 *)dst.ptr;
827 break;
828 }
829 }
830 break;
831 case DstMem:
832 dst.type = OP_MEM;
833 dst.ptr = (unsigned long *)cr2;
834 dst.bytes = (d & ByteOp) ? 1 : op_bytes;
835 if (d & BitOp) {
836 dst.ptr += src.val / BITS_PER_LONG;
837 dst.bytes = sizeof(long);
838 }
839 if (!(d & Mov) && /* optimisation - avoid slow emulated read */
840 ((rc = ops->read_emulated((unsigned long)dst.ptr,
841 &dst.val, dst.bytes, ctxt)) != 0))
842 goto done;
843 break;
844 }
845 dst.orig_val = dst.val;
846
841 if (twobyte) 847 if (twobyte)
842 goto twobyte_insn; 848 goto twobyte_insn;
843 849