KVM: x86 emulator: add LDS/LES/LFS/LGS/LSS instruction emulation
PATCH 1/1 KVM: x86 emulator: add LDS/LES/LFS/LGS/LSS instruction emulation
Add LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode 0xc4, 0xc5, 0x0f 0xb2, 0x0f 0xb4~0xb5)
Used by FreeDOS livecd.
--- arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 47 insertions(+), 4 deletions(-)
arch/x86/kvm/emulate.c +47 -4
@@ -1503,6 +1503,23 @@ static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,return rc; } +static int emulate_load_segment (struct x86_emulate_ctxt *ctxt, +struct x86_emulate_ops *ops,int seg) +{ +struct decode_cache *c = &ctxt->decode; +unsigned short sel; +int rc; + +memcpy (&sel, c->src.valptr + c->op_bytes,2 ); + + rc =load_segment_descriptor (ctxt, ops, sel, seg); +if (rc !=X86EMUL_CONTINUE ) +return rc; + + c->dst.val = c->src.val; +return rc; +} + static inline void setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops, struct desc_struct *cs,
@@ -2308,7 +2325,8 @@ static struct opcode opcode_table[256] = {X8 (D (DstReg | SrcImm | Mov)),/* 0xC0 - 0xC7 */ D (ByteOp | DstMem | SrcImm | ModRM),D (DstMem | SrcImmByte | ModRM), -N ,D (ImplicitOps | Stack),N ,N , +N ,D (ImplicitOps | Stack), +D (DstReg | SrcMemFAddr | ModRM),D (DstReg | SrcMemFAddr | ModRM),D (ByteOp | DstMem | SrcImm | ModRM | Mov),D (DstMem | SrcImm | ModRM | Mov),/* 0xC8 - 0xCF */ N, N, N, D(ImplicitOps | Stack),
@@ -2378,9 +2396,9 @@ static struct opcode twobyte_table[256] = {D (ModRM),N ,/* 0xB0 - 0xB7 */ D (ByteOp | DstMem | SrcReg | ModRM | Lock),D (DstMem | SrcReg | ModRM | Lock), -N ,D (DstMem | SrcReg | ModRM | BitOp | Lock), -N ,N ,D (ByteOp | DstReg | SrcMem | ModRM | Mov), -D (DstReg | SrcMem16 | ModRM | Mov), +D (DstReg | SrcMemFAddr | ModRM),D (DstMem | SrcReg | ModRM | BitOp | Lock), +D (DstReg | SrcMemFAddr | ModRM),D (DstReg | SrcMemFAddr | ModRM), +D (ByteOp | DstReg | SrcMem | ModRM | Mov),D (DstReg | SrcMem16 | ModRM | Mov),/* 0xB8 - 0xBF */ N ,N , G(BitOp, group8), D(DstMem | SrcReg | ModRM | BitOp | Lock),
@@ -3055,6 +3073,16 @@ special_insn: c->dst.addr.reg = &c->eip; c->dst.bytes = c->op_bytes; goto pop_instruction; +case 0xc4 :/* les */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_ES ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; +case 0xc5 :/* lds */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_DS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ mov: c->dst.val = c->src.val;
@@ -3483,10 +3511,25 @@ twobyte_insn: c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX ]; }break ; +case 0xb2 :/* lss */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_SS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ;case 0xb3 : btr:/* btr */ emulate_2op_SrcV_nobyte ("btr" , c->src, c->dst, ctxt->eflags);break ; +case 0xb4 :/* lfs */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_FS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; +case 0xb5 :/* lgs */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_GS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; case 0xb6 ... 0xb7: /* movzx */ c->dst.bytes = c->op_bytes; c->dst.val = (c->d & ByteOp) ? (u8) c->src.val
Signature · 1 line
1.7.0.4
PATCH v2 1/1 KVM: x86 emulator: add LDS/LES/LFS/LGS/LSS instruction emulation
Add LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode 0xc4, 0xc5, 0x0f 0xb2, 0x0f 0xb4~0xb5)
---
v1 -> v2: mask LES/LDS as No64.
--- arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 47 insertions(+), 4 deletions(-)
arch/x86/kvm/emulate.c +47 -4
@@ -1503,6 +1503,23 @@ static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,return rc; } +static int emulate_load_segment (struct x86_emulate_ctxt *ctxt, +struct x86_emulate_ops *ops,int seg) +{ +struct decode_cache *c = &ctxt->decode; +unsigned short sel; +int rc; + +memcpy (&sel, c->src.valptr + c->op_bytes,2 ); + + rc =load_segment_descriptor (ctxt, ops, sel, seg); +if (rc !=X86EMUL_CONTINUE ) +return rc; + + c->dst.val = c->src.val; +return rc; +} + static inline void setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops, struct desc_struct *cs,
@@ -2308,7 +2325,8 @@ static struct opcode opcode_table[256] = {X8 (D (DstReg | SrcImm | Mov)),/* 0xC0 - 0xC7 */ D (ByteOp | DstMem | SrcImm | ModRM),D (DstMem | SrcImmByte | ModRM), -N ,D (ImplicitOps | Stack),N ,N , +N ,D (ImplicitOps | Stack), +D (DstReg | SrcMemFAddr | ModRM | No64),D (DstReg | SrcMemFAddr | ModRM | No64),D (ByteOp | DstMem | SrcImm | ModRM | Mov),D (DstMem | SrcImm | ModRM | Mov),/* 0xC8 - 0xCF */ N, N, N, D(ImplicitOps | Stack),
@@ -2378,9 +2396,9 @@ static struct opcode twobyte_table[256] = {D (ModRM),N ,/* 0xB0 - 0xB7 */ D (ByteOp | DstMem | SrcReg | ModRM | Lock),D (DstMem | SrcReg | ModRM | Lock), -N ,D (DstMem | SrcReg | ModRM | BitOp | Lock), -N ,N ,D (ByteOp | DstReg | SrcMem | ModRM | Mov), -D (DstReg | SrcMem16 | ModRM | Mov), +D (DstReg | SrcMemFAddr | ModRM),D (DstMem | SrcReg | ModRM | BitOp | Lock), +D (DstReg | SrcMemFAddr | ModRM),D (DstReg | SrcMemFAddr | ModRM), +D (ByteOp | DstReg | SrcMem | ModRM | Mov),D (DstReg | SrcMem16 | ModRM | Mov),/* 0xB8 - 0xBF */ N ,N , G(BitOp, group8), D(DstMem | SrcReg | ModRM | BitOp | Lock),
@@ -3055,6 +3073,16 @@ special_insn: c->dst.addr.reg = &c->eip; c->dst.bytes = c->op_bytes; goto pop_instruction; +case 0xc4 :/* les */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_ES ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; +case 0xc5 :/* lds */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_DS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ mov: c->dst.val = c->src.val;
@@ -3483,10 +3511,25 @@ twobyte_insn: c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX ]; }break ; +case 0xb2 :/* lss */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_SS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ;case 0xb3 : btr:/* btr */ emulate_2op_SrcV_nobyte ("btr" , c->src, c->dst, ctxt->eflags);break ; +case 0xb4 :/* lfs */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_FS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; +case 0xb5 :/* lgs */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_GS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; case 0xb6 ... 0xb7: /* movzx */ c->dst.bytes = c->op_bytes; c->dst.val = (c->d & ByteOp) ? (u8) c->src.val
Signature · 1 line
1.7.0.4
Paolo Bonzini
maintainerQuoted 6 lines · Wei Yongjun
Add LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode0xc4,0xc5,0x0f0xb2,0x0f0xb4~0xb5)Signed-off-by Wei Yongjun<[email protected]>---
v1 -> v2: mask LES/LDS as No64.
The whole "case SrcMemFAddr" should refuse a register operand, so that "JMP FAR PTR reg" (0xff 0xeb for example) and "LDS reg, reg" (0xc4 0xc3), would raise a #UD. I'm pretty sure it is handled incorrectly right now, and I'm wondering if the resulting access to ctxt->decode->src.valptr would allow a small information leak from the kernel...
This bug is preexisting however, so I think it can be done as a follow-up patch.
Thanks!
Paolo
Quoted 3 lines · Wei Yongjun
Add LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode0xc4,0xc5,0x0f0xb2,0x0f0xb4~0xb5)
The patch looks good, but did I miss the test cases?
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 1/1 Add realmode test for LDS/LES/LFS/LGS/LSS instruction
--- x86/realmode.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
x86/realmode.c +59 -0
@@ -1184,6 +1184,64 @@ void test_cwd_cdq() outregs.eax == 0x10000000 && outregs.edx == 0); } +static struct { +void *address; +unsigned short sel; +} __attribute__((packed)) desc = { + (void *)0x1234 , +0x10 , +}; + +void test_lds_lss () +{ + inregs = (struct regs ){ .ebx = (unsigned long )&desc }; + +MK_INSN (lds,"push %ds\n\t" +"lds (%ebx), %eax\n\t" +"mov %ds, %ebx\n\t" +"pop %ds\n\t" ); +exec_in_big_real_mode (&insn_lds); +report ("lds" ,R_AX |R_BX , + outregs.eax == (unsigned long )desc.address && + outregs.ebx == desc.sel); + +MK_INSN (les,"push %es\n\t" +"les (%ebx), %eax\n\t" +"mov %es, %ebx\n\t" +"pop %es\n\t" ); +exec_in_big_real_mode (&insn_les); +report ("les" ,R_AX |R_BX , + outregs.eax == (unsigned long )desc.address && + outregs.ebx == desc.sel); + +MK_INSN (lfs,"push %fs\n\t" +"lfs (%ebx), %eax\n\t" +"mov %fs, %ebx\n\t" +"pop %fs\n\t" ); +exec_in_big_real_mode (&insn_lfs); +report ("lfs" ,R_AX |R_BX , + outregs.eax == (unsigned long )desc.address && + outregs.ebx == desc.sel); + +MK_INSN (lgs,"push %gs\n\t" +"lgs (%ebx), %eax\n\t" +"mov %gs, %ebx\n\t" +"pop %gs\n\t" ); +exec_in_big_real_mode (&insn_lgs); +report ("lgs" ,R_AX |R_BX , + outregs.eax == (unsigned long )desc.address && + outregs.ebx == desc.sel); + +MK_INSN (lss,"push %ss\n\t" +"lss (%ebx), %eax\n\t" +"mov %ss, %ebx\n\t" +"pop %ss\n\t" ); +exec_in_big_real_mode (&insn_lss); +report ("lss" ,R_AX |R_BX , + outregs.eax == (unsigned long )desc.address && + outregs.ebx == desc.sel); +} +void realmode_start (void ) {test_null ();
@@ -1215,6 +1273,7 @@ void realmode_start(void)test_cbw ();test_cwd_cdq ();test_das (); +test_lds_lss ();exit (0 ); }
Signature · 1 line
1.7.0.4
Marcelo Tosatti
AppliedRe: [PATCH] Add realmode test for LDS/LES/LFS/LGS/LSS instruction
Quoted 4 lines · Wei Yongjun
Signed-off-by Wei Yongjun <[email protected]>--- x86/realmode.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
Applied, thanks.
PATCH v3 1/1 KVM: x86 emulator: add LDS/LES/LFS/LGS/LSS instruction emulation
In reply to Wei YongjunAdd LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode 0xc4, 0xc5, 0x0f 0xb2, 0x0f 0xb4~0xb5)
---
v2 -> v3: no changes, just porting to today's git tree
--- arch/x86/kvm/emulate.c | 50 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 46 insertions(+), 4 deletions(-)
arch/x86/kvm/emulate.c +46 -4
@@ -1515,6 +1515,23 @@ static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,return rc; } +static int emulate_load_segment (struct x86_emulate_ctxt *ctxt, +struct x86_emulate_ops *ops,int seg) +{ +struct decode_cache *c = &ctxt->decode; +unsigned short sel; +int rc; + +memcpy (&sel, c->src.valptr + c->op_bytes,2 ); + + rc =load_segment_descriptor (ctxt, ops, sel, seg); +if (rc !=X86EMUL_CONTINUE ) +return rc; + + c->dst.val = c->src.val; +return rc; +} + static inline void setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops, struct desc_struct *cs,
@@ -2459,7 +2476,7 @@ static struct opcode opcode_table[256] = {D (ByteOp | DstMem | SrcImm | ModRM),D (DstMem | SrcImmByte | ModRM),I (ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),D (ImplicitOps | Stack), -N ,N , +D (DstReg | SrcMemFAddr | ModRM | No64),D (DstReg | SrcMemFAddr | ModRM | No64),D (ByteOp | DstMem | SrcImm | ModRM | Mov),D (DstMem | SrcImm | ModRM | Mov),/* 0xC8 - 0xCF */ N, N, N, D(ImplicitOps | Stack),
@@ -2530,9 +2547,9 @@ static struct opcode twobyte_table[256] = {D (ModRM),I (DstReg | SrcMem | ModRM, em_imul),/* 0xB0 - 0xB7 */ D (ByteOp | DstMem | SrcReg | ModRM | Lock),D (DstMem | SrcReg | ModRM | Lock), -N ,D (DstMem | SrcReg | ModRM | BitOp | Lock), -N ,N ,D (ByteOp | DstReg | SrcMem | ModRM | Mov), -D (DstReg | SrcMem16 | ModRM | Mov), +D (DstReg | SrcMemFAddr | ModRM),D (DstMem | SrcReg | ModRM | BitOp | Lock), +D (DstReg | SrcMemFAddr | ModRM),D (DstReg | SrcMemFAddr | ModRM), +D (ByteOp | DstReg | SrcMem | ModRM | Mov),D (DstReg | SrcMem16 | ModRM | Mov),/* 0xB8 - 0xBF */ N ,N , G(BitOp, group8), D(DstMem | SrcReg | ModRM | BitOp | Lock),
@@ -3215,6 +3232,16 @@ special_insn: c->dst.addr.reg = &c->eip; c->dst.bytes = c->op_bytes; goto pop_instruction; +case 0xc4 :/* les */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_ES ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; +case 0xc5 :/* lds */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_DS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ mov: c->dst.val = c->src.val;
@@ -3660,10 +3687,25 @@ twobyte_insn: c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX ]; }break ; +case 0xb2 :/* lss */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_SS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ;case 0xb3 : btr:/* btr */ emulate_2op_SrcV_nobyte ("btr" , c->src, c->dst, ctxt->eflags);break ; +case 0xb4 :/* lfs */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_FS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; +case 0xb5 :/* lgs */ + rc =emulate_load_segment (ctxt, ops,VCPU_SREG_GS ); +if (rc !=X86EMUL_CONTINUE ) + goto done; +break ; case 0xb6 ... 0xb7: /* movzx */ c->dst.bytes = c->op_bytes; c->dst.val = (c->d & ByteOp) ? (u8) c->src.val
Signature · 1 line
1.7.0.4
Marcelo Tosatti
AppliedQuoted 9 lines · Wei Yongjun
Add LDS/LES/LFS/LGS/LSS instruction emulation.
(opcode0xc4,0xc5,0x0f0xb2,0x0f0xb4~0xb5)Signed-off-by Wei Yongjun <[email protected]>---
v2 -> v3: no changes, just porting to today's git tree--- arch/x86/kvm/emulate.c | 50 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 46 insertions(+), 4 deletions(-)
Applied, thanks.