diff -r a0ca00815cc4 -r 4f92469f5b1d src/arch/x86/linux/process.hh --- a/src/arch/x86/linux/process.hh Fri Sep 28 09:35:25 2012 -0400 +++ b/src/arch/x86/linux/process.hh Mon Sep 24 17:15:57 2012 +0200 @@ -53,9 +53,14 @@ static SyscallDesc syscallDescs[]; static const int numSyscalls; + static const unsigned int gdt_user_cs; // Linux: GDT_ENTRY_DEFAULT_USER_CS + static const unsigned int gdt_user_ds; // Linux: GDT_ENTRY_DEFAULT_USER_DS + public: /// Constructor. X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + + void initState(); }; class I386LinuxProcess : public I386LiveProcess @@ -65,9 +70,14 @@ static SyscallDesc syscallDescs[]; static const int numSyscalls; + static const unsigned int gdt_user_cs; // Linux: GDT_ENTRY_DEFAULT_USER_CS + static const unsigned int gdt_user_ds; // Linux: GDT_ENTRY_DEFAULT_USER_DS + public: /// Constructor. I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + + void initState(); }; } // namespace X86ISA diff -r a0ca00815cc4 -r 4f92469f5b1d src/arch/x86/linux/process.cc --- a/src/arch/x86/linux/process.cc Fri Sep 28 09:35:25 2012 -0400 +++ b/src/arch/x86/linux/process.cc Mon Sep 24 17:15:57 2012 +0200 @@ -48,12 +48,98 @@ using namespace std; using namespace X86ISA; +static +void +setSegmentEntry(SETranslatingPortProxy & vmem, + Addr gdt_start, + unsigned int entry, + const SegDescriptor &sdesc) +{ + vmem.write(gdt_start + entry * sizeof(uint64_t), + static_cast(sdesc)); +} + +static +void +setDefaultSegments (SETranslatingPortProxy & vmem, + Addr gdt_start, + const unsigned int gdt_user_cs, + const unsigned int gdt_user_ds, + const bool long_mode) +{ + SegDescriptor user_cs = 0; + user_cs.baseHigh = 0; + user_cs.baseLow = 0; + user_cs.g = 1; + user_cs.d = 1; + user_cs.b = 1; + user_cs.l = long_mode ? 1 : 0; + user_cs.avl = 0; + user_cs.limitHigh = ~0; + user_cs.limitLow = ~0; + user_cs.p = 1; + user_cs.dpl = 3; + user_cs.s = 1; + user_cs.type.codeOrData = 1; + user_cs.type.c = 0; + user_cs.type.r = 1; + user_cs.type.a = 0; + setSegmentEntry(vmem, gdt_start, gdt_user_cs, user_cs); + + SegDescriptor user_ds = 0; + user_ds.baseHigh = 0; + user_ds.baseLow = 0; + user_ds.g = 1; + user_ds.d = 1; + user_ds.b = 1; + user_ds.l = 0; + user_ds.avl = 0; + user_ds.limitHigh = ~0; + user_ds.limitLow = ~0; + user_ds.p = 1; + user_ds.dpl = 3; + user_ds.s = 1; + user_ds.type.codeOrData = 0; + user_ds.type.e = 0; + user_ds.type.w = 1; + user_ds.type.a = 0; + setSegmentEntry(vmem, gdt_start, gdt_user_ds, user_ds); +} + + +// Linux: include/asm-x86/segment.h (when !defined(CONFIG_X86_32)) +const unsigned int X86_64LinuxProcess::gdt_user_cs = 6; +const unsigned int X86_64LinuxProcess::gdt_user_ds = 5; +// NOTE: We're ignoring GDT_ENTRY_DEFAULT_USER32_CS as GEM5 will use +// I386LinuxProcess instead. + + X86_64LinuxProcess::X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile) : X86_64LiveProcess(params, objFile, syscallDescs, numSyscalls) {} +void +X86_64LinuxProcess::initState() +{ + this->X86_64LiveProcess::initState(); + setDefaultSegments(initVirtMem, _gdtStart, gdt_user_cs, gdt_user_ds, true); +} + + +// Linux: include/asm-x86/segment.h (when defined(CONFIG_X86_32)) +const unsigned int I386LinuxProcess::gdt_user_cs = 14; +const unsigned int I386LinuxProcess::gdt_user_ds = 15; + + I386LinuxProcess::I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile) : I386LiveProcess(params, objFile, syscallDescs, numSyscalls) {} + +void +I386LinuxProcess::initState() +{ + this->I386LiveProcess::initState(); + setDefaultSegments(initVirtMem, _gdtStart, gdt_user_cs, gdt_user_ds, false); +} diff -r a0ca00815cc4 -r 4f92469f5b1d src/arch/x86/process.hh --- a/src/arch/x86/process.hh Fri Sep 28 09:35:25 2012 -0400 +++ b/src/arch/x86/process.hh Mon Sep 24 17:15:57 2012 +0200 @@ -100,7 +100,7 @@ public: void argsInit(int intSize, int pageSize); - void initState(); + virtual void initState(); X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i); void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); @@ -124,7 +124,7 @@ public: void argsInit(int intSize, int pageSize); - void initState(); + virtual void initState(); void syscall(int64_t callnum, ThreadContext *tc); X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i); diff -r a0ca00815cc4 -r 4f92469f5b1d src/arch/x86/process.cc --- a/src/arch/x86/process.cc Fri Sep 28 09:35:25 2012 -0400 +++ b/src/arch/x86/process.cc Mon Sep 24 17:15:57 2012 +0200 @@ -205,12 +205,14 @@ tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0); tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0); tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr); + tc->setMiscRegNoEffect(MISCREG_SEG_SEL(seg), 0xB); + tc->setMiscRegNoEffect(MISCREG_SEG_LIMIT(seg), (uint64_t)(-1)); } SegAttr csAttr = 0; csAttr.dpl = 3; csAttr.unusable = 0; - csAttr.defaultSize = 0; + csAttr.defaultSize = 1; csAttr.longMode = 1; csAttr.avl = 0; csAttr.granularity = 1; @@ -223,6 +225,13 @@ tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); + tc->setMiscRegNoEffect(MISCREG_TSG_BASE, _gdtStart); + tc->setMiscRegNoEffect(MISCREG_TSG_EFF_BASE, _gdtStart); + tc->setMiscRegNoEffect(MISCREG_TSG_LIMIT, _gdtStart + _gdtSize - 1); + + // Set the LDT selector to 0 to deactivate it. + tc->setMiscRegNoEffect(MISCREG_TSL, 0); + Efer efer = 0; efer.sce = 1; // Enable system call extensions. efer.lme = 1; // Enable long mode.