Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
xen
19614-x86-emul-lldt-ltr.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 19614-x86-emul-lldt-ltr.patch of Package xen
# HG changeset patch # User Keir Fraser <keir.fraser@citrix.com> # Date 1242695376 -3600 # Node ID e421fd04e15039c4f5204a1d128af550aa9bc578 # Parent 4e7c5eb717749b043b12a3e8c43487d264276dda x86_emulate: Emulate LLDT and LTR instructions. Signed-off-by: Keir Fraser <keir.fraser@citrix.com> # HG changeset patch # User Keir Fraser <keir.fraser@citrix.com> # Date 1249635283 -3600 # Node ID 71d6d6f2ecd6e4a33b7dc1363e0dfe6b89dcc416 # Parent b9cdcf502aa35818581d41cee7e6e30ae49acb92 x86_emulate: protmode_load_seg() cannot load system segments in long mode. Signed-off-by: Keir Fraser <keir.fraser@citrix.com> --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -167,7 +167,7 @@ static uint8_t opcode_table[256] = { static uint8_t twobyte_table[256] = { /* 0x00 - 0x07 */ - 0, ImplicitOps|ModRM, 0, 0, 0, 0, ImplicitOps, 0, + SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, ImplicitOps, 0, /* 0x08 - 0x0F */ ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0, /* 0x10 - 0x17 */ @@ -276,6 +276,8 @@ struct operand { /* MSRs. */ #define MSR_TSC 0x10 +#define MSR_EFER 0xc0000080 +#define EFER_LMA (1u<<10) /* Control register flags. */ #define CR0_PE (1<<0) @@ -937,6 +939,24 @@ in_protmode( } static int +in_longmode( + struct x86_emulate_ctxt *ctxt, + struct x86_emulate_ops *ops) +{ +#ifdef __x86_64__ + uint64_t efer; + + if (ops->read_msr == NULL) + return -1; + + ops->read_msr(MSR_EFER, &efer, ctxt); + return !!(efer & EFER_LMA); +#else + return 0; +#endif +} + +static int realmode_load_seg( enum x86_segment seg, uint16_t sel, @@ -966,8 +986,8 @@ protmode_load_seg( struct { uint32_t a, b; } desc; unsigned long val; uint8_t dpl, rpl, cpl; - uint32_t new_desc_b; - int rc, fault_type = EXC_TS; + uint32_t new_desc_b, a_flag = 0x100; + int rc, fault_type = EXC_GP; /* NULL selector? */ if ( (sel & 0xfffc) == 0 ) @@ -978,8 +998,8 @@ protmode_load_seg( return ops->write_segment(seg, &segr, ctxt); } - /* LDT descriptor must be in the GDT. */ - if ( (seg == x86_seg_ldtr) && (sel & 4) ) + /* System segment descriptors must reside in the GDT. */ + if ( !is_x86_user_segment(seg) && (sel & 4) ) goto raise_exn; if ( (rc = ops->read_segment(x86_seg_ss, &ss, ctxt)) || @@ -1008,8 +1028,17 @@ protmode_load_seg( goto raise_exn; } - /* LDT descriptor is a system segment. All others are code/data. */ - if ( (desc.b & (1u<<12)) == ((seg == x86_seg_ldtr) << 12) ) + if ( !is_x86_user_segment(seg) ) + { + /* System segments must have S flag == 0. */ + if ( desc.b & (1u << 12) ) + goto raise_exn; + /* We do not support 64-bit descriptor types. */ + if ( in_longmode(ctxt, ops) ) + return X86EMUL_UNHANDLEABLE; + } + /* User segments must have S flag == 1. */ + else if ( !(desc.b & (1u << 12)) ) goto raise_exn; dpl = (desc.b >> 13) & 3; @@ -1038,6 +1067,12 @@ protmode_load_seg( if ( (desc.b & (15u<<8)) != (2u<<8) ) goto raise_exn; goto skip_accessed_flag; + case x86_seg_tr: + /* Available TSS system segment? */ + if ( (desc.b & (15u<<8)) != (9u<<8) ) + goto raise_exn; + a_flag = 0x200; /* busy flag */ + break; default: /* Readable code or data segment? */ if ( (desc.b & (5u<<9)) == (4u<<9) ) @@ -1050,8 +1085,8 @@ protmode_load_seg( } /* Ensure Accessed flag is set. */ - new_desc_b = desc.b | 0x100; - rc = ((desc.b & 0x100) ? X86EMUL_OKAY : + new_desc_b = desc.b | a_flag; + rc = ((desc.b & a_flag) ? X86EMUL_OKAY : ops->cmpxchg( x86_seg_none, desctab.base + (sel & 0xfff8) + 4, &desc.b, &new_desc_b, 4, ctxt)); @@ -1061,7 +1096,7 @@ protmode_load_seg( return rc; /* Force the Accessed flag in our local copy. */ - desc.b |= 0x100; + desc.b |= a_flag; skip_accessed_flag: segr.base = (((desc.b << 0) & 0xff000000u) | @@ -3472,6 +3507,15 @@ x86_emulate( twobyte_insn: switch ( b ) { + case 0x00: /* Grp6 */ + fail_if((modrm_reg & 6) != 2); + generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); + generate_exception_if(!mode_ring0(), EXC_GP, 0); + if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr, + src.val, ctxt, ops)) != 0 ) + goto done; + break; + case 0x40 ... 0x4f: /* cmovcc */ dst.val = src.val; if ( !test_cc(b, _regs.eflags) )
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor