diff options
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 112 |
1 files changed, 97 insertions, 15 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 0982507b962a..83756223f8aa 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #define OpDS 23ull /* DS */ | 57 | #define OpDS 23ull /* DS */ |
58 | #define OpFS 24ull /* FS */ | 58 | #define OpFS 24ull /* FS */ |
59 | #define OpGS 25ull /* GS */ | 59 | #define OpGS 25ull /* GS */ |
60 | #define OpMem8 26ull /* 8-bit zero extended memory operand */ | ||
60 | 61 | ||
61 | #define OpBits 5 /* Width of operand field */ | 62 | #define OpBits 5 /* Width of operand field */ |
62 | #define OpMask ((1ull << OpBits) - 1) | 63 | #define OpMask ((1ull << OpBits) - 1) |
@@ -101,6 +102,7 @@ | |||
101 | #define SrcAcc (OpAcc << SrcShift) | 102 | #define SrcAcc (OpAcc << SrcShift) |
102 | #define SrcImmU16 (OpImmU16 << SrcShift) | 103 | #define SrcImmU16 (OpImmU16 << SrcShift) |
103 | #define SrcDX (OpDX << SrcShift) | 104 | #define SrcDX (OpDX << SrcShift) |
105 | #define SrcMem8 (OpMem8 << SrcShift) | ||
104 | #define SrcMask (OpMask << SrcShift) | 106 | #define SrcMask (OpMask << SrcShift) |
105 | #define BitOp (1<<11) | 107 | #define BitOp (1<<11) |
106 | #define MemAbs (1<<12) /* Memory operand is absolute displacement */ | 108 | #define MemAbs (1<<12) /* Memory operand is absolute displacement */ |
@@ -858,8 +860,7 @@ static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data, | |||
858 | } | 860 | } |
859 | 861 | ||
860 | static void decode_register_operand(struct x86_emulate_ctxt *ctxt, | 862 | static void decode_register_operand(struct x86_emulate_ctxt *ctxt, |
861 | struct operand *op, | 863 | struct operand *op) |
862 | int inhibit_bytereg) | ||
863 | { | 864 | { |
864 | unsigned reg = ctxt->modrm_reg; | 865 | unsigned reg = ctxt->modrm_reg; |
865 | int highbyte_regs = ctxt->rex_prefix == 0; | 866 | int highbyte_regs = ctxt->rex_prefix == 0; |
@@ -876,7 +877,7 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt, | |||
876 | } | 877 | } |
877 | 878 | ||
878 | op->type = OP_REG; | 879 | op->type = OP_REG; |
879 | if ((ctxt->d & ByteOp) && !inhibit_bytereg) { | 880 | if (ctxt->d & ByteOp) { |
880 | op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs); | 881 | op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs); |
881 | op->bytes = 1; | 882 | op->bytes = 1; |
882 | } else { | 883 | } else { |
@@ -1151,6 +1152,22 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt, | |||
1151 | return 1; | 1152 | return 1; |
1152 | } | 1153 | } |
1153 | 1154 | ||
1155 | static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt, | ||
1156 | u16 index, struct desc_struct *desc) | ||
1157 | { | ||
1158 | struct desc_ptr dt; | ||
1159 | ulong addr; | ||
1160 | |||
1161 | ctxt->ops->get_idt(ctxt, &dt); | ||
1162 | |||
1163 | if (dt.size < index * 8 + 7) | ||
1164 | return emulate_gp(ctxt, index << 3 | 0x2); | ||
1165 | |||
1166 | addr = dt.address + index * 8; | ||
1167 | return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc, | ||
1168 | &ctxt->exception); | ||
1169 | } | ||
1170 | |||
1154 | static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt, | 1171 | static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt, |
1155 | u16 selector, struct desc_ptr *dt) | 1172 | u16 selector, struct desc_ptr *dt) |
1156 | { | 1173 | { |
@@ -1227,6 +1244,8 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt, | |||
1227 | seg_desc.type = 3; | 1244 | seg_desc.type = 3; |
1228 | seg_desc.p = 1; | 1245 | seg_desc.p = 1; |
1229 | seg_desc.s = 1; | 1246 | seg_desc.s = 1; |
1247 | if (ctxt->mode == X86EMUL_MODE_VM86) | ||
1248 | seg_desc.dpl = 3; | ||
1230 | goto load; | 1249 | goto load; |
1231 | } | 1250 | } |
1232 | 1251 | ||
@@ -1891,6 +1910,17 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, | |||
1891 | ss->p = 1; | 1910 | ss->p = 1; |
1892 | } | 1911 | } |
1893 | 1912 | ||
1913 | static bool vendor_intel(struct x86_emulate_ctxt *ctxt) | ||
1914 | { | ||
1915 | u32 eax, ebx, ecx, edx; | ||
1916 | |||
1917 | eax = ecx = 0; | ||
1918 | return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx) | ||
1919 | && ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx | ||
1920 | && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx | ||
1921 | && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx; | ||
1922 | } | ||
1923 | |||
1894 | static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) | 1924 | static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) |
1895 | { | 1925 | { |
1896 | struct x86_emulate_ops *ops = ctxt->ops; | 1926 | struct x86_emulate_ops *ops = ctxt->ops; |
@@ -2007,6 +2037,14 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) | |||
2007 | if (ctxt->mode == X86EMUL_MODE_REAL) | 2037 | if (ctxt->mode == X86EMUL_MODE_REAL) |
2008 | return emulate_gp(ctxt, 0); | 2038 | return emulate_gp(ctxt, 0); |
2009 | 2039 | ||
2040 | /* | ||
2041 | * Not recognized on AMD in compat mode (but is recognized in legacy | ||
2042 | * mode). | ||
2043 | */ | ||
2044 | if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA) | ||
2045 | && !vendor_intel(ctxt)) | ||
2046 | return emulate_ud(ctxt); | ||
2047 | |||
2010 | /* XXX sysenter/sysexit have not been tested in 64bit mode. | 2048 | /* XXX sysenter/sysexit have not been tested in 64bit mode. |
2011 | * Therefore, we inject an #UD. | 2049 | * Therefore, we inject an #UD. |
2012 | */ | 2050 | */ |
@@ -2306,6 +2344,8 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt, | |||
2306 | return emulate_gp(ctxt, 0); | 2344 | return emulate_gp(ctxt, 0); |
2307 | ctxt->_eip = tss->eip; | 2345 | ctxt->_eip = tss->eip; |
2308 | ctxt->eflags = tss->eflags | 2; | 2346 | ctxt->eflags = tss->eflags | 2; |
2347 | |||
2348 | /* General purpose registers */ | ||
2309 | ctxt->regs[VCPU_REGS_RAX] = tss->eax; | 2349 | ctxt->regs[VCPU_REGS_RAX] = tss->eax; |
2310 | ctxt->regs[VCPU_REGS_RCX] = tss->ecx; | 2350 | ctxt->regs[VCPU_REGS_RCX] = tss->ecx; |
2311 | ctxt->regs[VCPU_REGS_RDX] = tss->edx; | 2351 | ctxt->regs[VCPU_REGS_RDX] = tss->edx; |
@@ -2328,6 +2368,24 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt, | |||
2328 | set_segment_selector(ctxt, tss->gs, VCPU_SREG_GS); | 2368 | set_segment_selector(ctxt, tss->gs, VCPU_SREG_GS); |
2329 | 2369 | ||
2330 | /* | 2370 | /* |
2371 | * If we're switching between Protected Mode and VM86, we need to make | ||
2372 | * sure to update the mode before loading the segment descriptors so | ||
2373 | * that the selectors are interpreted correctly. | ||
2374 | * | ||
2375 | * Need to get rflags to the vcpu struct immediately because it | ||
2376 | * influences the CPL which is checked at least when loading the segment | ||
2377 | * descriptors and when pushing an error code to the new kernel stack. | ||
2378 | * | ||
2379 | * TODO Introduce a separate ctxt->ops->set_cpl callback | ||
2380 | */ | ||
2381 | if (ctxt->eflags & X86_EFLAGS_VM) | ||
2382 | ctxt->mode = X86EMUL_MODE_VM86; | ||
2383 | else | ||
2384 | ctxt->mode = X86EMUL_MODE_PROT32; | ||
2385 | |||
2386 | ctxt->ops->set_rflags(ctxt, ctxt->eflags); | ||
2387 | |||
2388 | /* | ||
2331 | * Now load segment descriptors. If fault happenes at this stage | 2389 | * Now load segment descriptors. If fault happenes at this stage |
2332 | * it is handled in a context of new task | 2390 | * it is handled in a context of new task |
2333 | */ | 2391 | */ |
@@ -2401,7 +2459,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt, | |||
2401 | } | 2459 | } |
2402 | 2460 | ||
2403 | static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, | 2461 | static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, |
2404 | u16 tss_selector, int reason, | 2462 | u16 tss_selector, int idt_index, int reason, |
2405 | bool has_error_code, u32 error_code) | 2463 | bool has_error_code, u32 error_code) |
2406 | { | 2464 | { |
2407 | struct x86_emulate_ops *ops = ctxt->ops; | 2465 | struct x86_emulate_ops *ops = ctxt->ops; |
@@ -2423,12 +2481,35 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, | |||
2423 | 2481 | ||
2424 | /* FIXME: check that next_tss_desc is tss */ | 2482 | /* FIXME: check that next_tss_desc is tss */ |
2425 | 2483 | ||
2426 | if (reason != TASK_SWITCH_IRET) { | 2484 | /* |
2427 | if ((tss_selector & 3) > next_tss_desc.dpl || | 2485 | * Check privileges. The three cases are task switch caused by... |
2428 | ops->cpl(ctxt) > next_tss_desc.dpl) | 2486 | * |
2429 | return emulate_gp(ctxt, 0); | 2487 | * 1. jmp/call/int to task gate: Check against DPL of the task gate |
2488 | * 2. Exception/IRQ/iret: No check is performed | ||
2489 | * 3. jmp/call to TSS: Check agains DPL of the TSS | ||
2490 | */ | ||
2491 | if (reason == TASK_SWITCH_GATE) { | ||
2492 | if (idt_index != -1) { | ||
2493 | /* Software interrupts */ | ||
2494 | struct desc_struct task_gate_desc; | ||
2495 | int dpl; | ||
2496 | |||
2497 | ret = read_interrupt_descriptor(ctxt, idt_index, | ||
2498 | &task_gate_desc); | ||
2499 | if (ret != X86EMUL_CONTINUE) | ||
2500 | return ret; | ||
2501 | |||
2502 | dpl = task_gate_desc.dpl; | ||
2503 | if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl) | ||
2504 | return emulate_gp(ctxt, (idt_index << 3) | 0x2); | ||
2505 | } | ||
2506 | } else if (reason != TASK_SWITCH_IRET) { | ||
2507 | int dpl = next_tss_desc.dpl; | ||
2508 | if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl) | ||
2509 | return emulate_gp(ctxt, tss_selector); | ||
2430 | } | 2510 | } |
2431 | 2511 | ||
2512 | |||
2432 | desc_limit = desc_limit_scaled(&next_tss_desc); | 2513 | desc_limit = desc_limit_scaled(&next_tss_desc); |
2433 | if (!next_tss_desc.p || | 2514 | if (!next_tss_desc.p || |
2434 | ((desc_limit < 0x67 && (next_tss_desc.type & 8)) || | 2515 | ((desc_limit < 0x67 && (next_tss_desc.type & 8)) || |
@@ -2481,7 +2562,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, | |||
2481 | } | 2562 | } |
2482 | 2563 | ||
2483 | int emulator_task_switch(struct x86_emulate_ctxt *ctxt, | 2564 | int emulator_task_switch(struct x86_emulate_ctxt *ctxt, |
2484 | u16 tss_selector, int reason, | 2565 | u16 tss_selector, int idt_index, int reason, |
2485 | bool has_error_code, u32 error_code) | 2566 | bool has_error_code, u32 error_code) |
2486 | { | 2567 | { |
2487 | int rc; | 2568 | int rc; |
@@ -2489,7 +2570,7 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt, | |||
2489 | ctxt->_eip = ctxt->eip; | 2570 | ctxt->_eip = ctxt->eip; |
2490 | ctxt->dst.type = OP_NONE; | 2571 | ctxt->dst.type = OP_NONE; |
2491 | 2572 | ||
2492 | rc = emulator_do_task_switch(ctxt, tss_selector, reason, | 2573 | rc = emulator_do_task_switch(ctxt, tss_selector, idt_index, reason, |
2493 | has_error_code, error_code); | 2574 | has_error_code, error_code); |
2494 | 2575 | ||
2495 | if (rc == X86EMUL_CONTINUE) | 2576 | if (rc == X86EMUL_CONTINUE) |
@@ -3514,13 +3595,13 @@ static struct opcode twobyte_table[256] = { | |||
3514 | I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr), | 3595 | I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr), |
3515 | I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg), | 3596 | I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg), |
3516 | I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg), | 3597 | I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg), |
3517 | D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), | 3598 | D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), |
3518 | /* 0xB8 - 0xBF */ | 3599 | /* 0xB8 - 0xBF */ |
3519 | N, N, | 3600 | N, N, |
3520 | G(BitOp, group8), | 3601 | G(BitOp, group8), |
3521 | I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc), | 3602 | I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc), |
3522 | I(DstReg | SrcMem | ModRM, em_bsf), I(DstReg | SrcMem | ModRM, em_bsr), | 3603 | I(DstReg | SrcMem | ModRM, em_bsf), I(DstReg | SrcMem | ModRM, em_bsr), |
3523 | D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), | 3604 | D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), |
3524 | /* 0xC0 - 0xCF */ | 3605 | /* 0xC0 - 0xCF */ |
3525 | D2bv(DstMem | SrcReg | ModRM | Lock), | 3606 | D2bv(DstMem | SrcReg | ModRM | Lock), |
3526 | N, D(DstMem | SrcReg | ModRM | Mov), | 3607 | N, D(DstMem | SrcReg | ModRM | Mov), |
@@ -3602,9 +3683,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, | |||
3602 | 3683 | ||
3603 | switch (d) { | 3684 | switch (d) { |
3604 | case OpReg: | 3685 | case OpReg: |
3605 | decode_register_operand(ctxt, op, | 3686 | decode_register_operand(ctxt, op); |
3606 | op == &ctxt->dst && | ||
3607 | ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7)); | ||
3608 | break; | 3687 | break; |
3609 | case OpImmUByte: | 3688 | case OpImmUByte: |
3610 | rc = decode_imm(ctxt, op, 1, false); | 3689 | rc = decode_imm(ctxt, op, 1, false); |
@@ -3656,6 +3735,9 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, | |||
3656 | case OpImm: | 3735 | case OpImm: |
3657 | rc = decode_imm(ctxt, op, imm_size(ctxt), true); | 3736 | rc = decode_imm(ctxt, op, imm_size(ctxt), true); |
3658 | break; | 3737 | break; |
3738 | case OpMem8: | ||
3739 | ctxt->memop.bytes = 1; | ||
3740 | goto mem_common; | ||
3659 | case OpMem16: | 3741 | case OpMem16: |
3660 | ctxt->memop.bytes = 2; | 3742 | ctxt->memop.bytes = 2; |
3661 | goto mem_common; | 3743 | goto mem_common; |