changeset fe2e2f06a7c8 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=fe2e2f06a7c8
description:
        x86: Segment initialization to support KvmCPU in SE
        This patch sets up low and high privilege code and data segments and 
places them
        in the following order: cs low, ds low, ds, cs, in the GDT. 
Additionally, a
        syscall and page fault handler for KvmCPU in SE mode are defined. The 
order of
        the segment selectors in GDT is required in this manner for interrupt 
handling
        to work properly. Segment initialization is done for all the thread
        contexts.

diffstat:

 src/arch/x86/process.cc   |  473 ++++++++++++++++++++++++++++++++++++++++-----
 src/arch/x86/regs/misc.hh |   58 +++++
 src/arch/x86/system.cc    |   54 ++---
 src/arch/x86/system.hh    |    8 +
 src/sim/Process.py        |    1 +
 src/sim/process.cc        |    1 +
 src/sim/process.hh        |    3 +
 7 files changed, 504 insertions(+), 94 deletions(-)

diffs (truncated from 755 to 300 lines):

diff -r c1ad57c53a36 -r fe2e2f06a7c8 src/arch/x86/process.cc
--- a/src/arch/x86/process.cc   Sun Nov 23 18:01:08 2014 -0800
+++ b/src/arch/x86/process.cc   Sun Nov 23 18:01:08 2014 -0800
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2014 Advanced Micro Devices, Inc.
  * Copyright (c) 2007 The Hewlett-Packard Development Company
  * All rights reserved.
  *
@@ -45,6 +46,7 @@
 #include "arch/x86/regs/segment.hh"
 #include "arch/x86/isa_traits.hh"
 #include "arch/x86/process.hh"
+#include "arch/x86/system.hh"
 #include "arch/x86/types.hh"
 #include "base/loader/elf_object.hh"
 #include "base/loader/object_file.hh"
@@ -52,6 +54,7 @@
 #include "base/trace.hh"
 #include "cpu/thread_context.hh"
 #include "debug/Stack.hh"
+#include "mem/multi_level_page_table.hh"
 #include "mem/page_table.hh"
 #include "sim/process_impl.hh"
 #include "sim/syscall_emul.hh"
@@ -183,73 +186,418 @@
     initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vgettimeofdayOffset,
             vgettimeofdayBlob, sizeof(vgettimeofdayBlob));
 
-    for (int i = 0; i < contextIds.size(); i++) {
-        ThreadContext * tc = system->getThreadContext(contextIds[i]);
+    if (kvmInSE) {
+        PortProxy physProxy = system->physProxy;
 
-        SegAttr dataAttr = 0;
-        dataAttr.dpl = 3;
-        dataAttr.unusable = 0;
-        dataAttr.defaultSize = 1;
-        dataAttr.longMode = 1;
-        dataAttr.avl = 0;
-        dataAttr.granularity = 1;
-        dataAttr.present = 1;
-        dataAttr.type = 3;
-        dataAttr.writable = 1;
-        dataAttr.readable = 1;
-        dataAttr.expandDown = 0;
-        dataAttr.system = 1;
+        /*
+         * Set up the gdt.
+         */
+        uint8_t numGDTEntries = 0;
+        uint64_t nullDescriptor = 0;
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&nullDescriptor), 8);
+        numGDTEntries++;
 
-        //Initialize the segment registers.
-        for(int seg = 0; seg < NUM_SEGMENTREGS; seg++) {
-            tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0);
-            tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0);
-            tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr);
+        SegDescriptor initDesc = 0;
+        initDesc.type.codeOrData = 0; // code or data type
+        initDesc.type.c = 0;          // conforming
+        initDesc.type.r = 1;          // readable
+        initDesc.dpl = 0;             // privilege
+        initDesc.p = 1;               // present
+        initDesc.l = 1;               // longmode - 64 bit
+        initDesc.d = 0;               // operand size
+        initDesc.g = 1;               // granularity
+        initDesc.s = 1;               // system segment
+        initDesc.limitHigh = 0xFFFF;
+        initDesc.limitLow = 0xF;
+        initDesc.baseHigh = 0x0;
+        initDesc.baseLow = 0x0;
+
+        //64 bit code segment
+        SegDescriptor csLowPLDesc = initDesc;
+        csLowPLDesc.type.codeOrData = 1;
+        csLowPLDesc.dpl = 0;
+        uint64_t csLowPLDescVal = csLowPLDesc;
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&csLowPLDescVal), 8);
+
+        numGDTEntries++;
+
+        SegSelector csLowPL = 0;
+        csLowPL.si = numGDTEntries - 1;
+        csLowPL.rpl = 0;
+
+        //64 bit data segment
+        SegDescriptor dsLowPLDesc = initDesc;
+        dsLowPLDesc.type.codeOrData = 0;
+        dsLowPLDesc.dpl = 0;
+        uint64_t dsLowPLDescVal = dsLowPLDesc;
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&dsLowPLDescVal), 8);
+
+        numGDTEntries++;
+
+        SegSelector dsLowPL = 0;
+        dsLowPL.si = numGDTEntries - 1;
+        dsLowPL.rpl = 0;
+
+        //64 bit data segment
+        SegDescriptor dsDesc = initDesc;
+        dsDesc.type.codeOrData = 0;
+        dsDesc.dpl = 3;
+        uint64_t dsDescVal = dsDesc;
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&dsDescVal), 8);
+
+        numGDTEntries++;
+
+        SegSelector ds = 0;
+        ds.si = numGDTEntries - 1;
+        ds.rpl = 3;
+
+        //64 bit code segment
+        SegDescriptor csDesc = initDesc;
+        csDesc.type.codeOrData = 1;
+        csDesc.dpl = 3;
+        uint64_t csDescVal = csDesc;
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&csDescVal), 8);
+
+        numGDTEntries++;
+
+        SegSelector cs = 0;
+        cs.si = numGDTEntries - 1;
+        cs.rpl = 3;
+
+        SegSelector scall = 0;
+        scall.si = csLowPL.si;
+        scall.rpl = 0;
+
+        SegSelector sret = 0;
+        sret.si = dsLowPL.si;
+        sret.rpl = 3;
+
+        /* In long mode the TSS has been extended to 16 Bytes */
+        TSSlow TSSDescLow = 0;
+        TSSDescLow.type = 0xB;
+        TSSDescLow.dpl = 0; // Privelege level 0
+        TSSDescLow.p = 1; // Present
+        TSSDescLow.g = 1; // Page granularity
+        TSSDescLow.limitHigh = 0xF;
+        TSSDescLow.limitLow = 0xFFFF;
+        TSSDescLow.baseLow = (((uint32_t)TSSVirtAddr) << 8) >> 8;
+        TSSDescLow.baseHigh = (uint8_t)(((uint32_t)TSSVirtAddr) >> 24);
+
+        TSShigh TSSDescHigh = 0;
+        TSSDescHigh.base = (uint32_t)(TSSVirtAddr >> 32);
+
+        struct TSSDesc {
+            uint64_t low;
+            uint64_t high;
+        } tssDescVal = {TSSDescLow, TSSDescHigh};
+
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&tssDescVal), sizeof(tssDescVal));
+
+        numGDTEntries++;
+
+        SegSelector tssSel = 0;
+        tssSel.si = numGDTEntries - 1;
+
+        uint64_t tss_base_addr = (TSSDescHigh.base << 32) | 
((TSSDescLow.baseHigh << 24) | TSSDescLow.baseLow);
+        uint64_t tss_limit = TSSDescLow.limitLow | (TSSDescLow.limitHigh << 
16);
+
+        SegAttr tss_attr = 0;
+
+        tss_attr.type = TSSDescLow.type;
+        tss_attr.dpl = TSSDescLow.dpl;
+        tss_attr.present = TSSDescLow.p;
+        tss_attr.granularity = TSSDescLow.g;
+        tss_attr.unusable = 0;
+
+        for (int i = 0; i < contextIds.size(); i++) {
+            ThreadContext * tc = system->getThreadContext(contextIds[i]);
+
+            tc->setMiscReg(MISCREG_CS, (MiscReg)cs);
+            tc->setMiscReg(MISCREG_DS, (MiscReg)ds);
+            tc->setMiscReg(MISCREG_ES, (MiscReg)ds);
+            tc->setMiscReg(MISCREG_FS, (MiscReg)ds);
+            tc->setMiscReg(MISCREG_GS, (MiscReg)ds);
+            tc->setMiscReg(MISCREG_SS, (MiscReg)ds);
+
+            // LDT
+            tc->setMiscReg(MISCREG_TSL, 0);
+            SegAttr tslAttr = 0;
+            tslAttr.present = 1;
+            tslAttr.type = 2;
+            tc->setMiscReg(MISCREG_TSL_ATTR, tslAttr);
+
+            tc->setMiscReg(MISCREG_TSG_BASE, GDTVirtAddr);
+            tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1);
+
+            tc->setMiscReg(MISCREG_TR, (MiscReg)tssSel);
+            tc->setMiscReg(MISCREG_SEG_BASE(SYS_SEGMENT_REG_TR), 
tss_base_addr);
+            tc->setMiscReg(MISCREG_SEG_EFF_BASE(SYS_SEGMENT_REG_TR), 0);
+            tc->setMiscReg(MISCREG_SEG_LIMIT(SYS_SEGMENT_REG_TR), tss_limit);
+            tc->setMiscReg(MISCREG_SEG_ATTR(SYS_SEGMENT_REG_TR), 
(MiscReg)tss_attr);
+
+            //Start using longmode segments.
+            installSegDesc(tc, SEGMENT_REG_CS, csDesc, true);
+            installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true);
+            installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true);
+            installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true);
+            installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
+            installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true);
+
+            Efer efer = 0;
+            efer.sce = 1; // Enable system call extensions.
+            efer.lme = 1; // Enable long mode.
+            efer.lma = 1; // Activate long mode.
+            efer.nxe = 0; // Enable nx support.
+            efer.svme = 1; // Enable svm support for now.
+            efer.ffxsr = 0; // Turn on fast fxsave and fxrstor.
+            tc->setMiscReg(MISCREG_EFER, efer);
+
+            //Set up the registers that describe the operating mode.
+            CR0 cr0 = 0;
+            cr0.pg = 1; // Turn on paging.
+            cr0.cd = 0; // Don't disable caching.
+            cr0.nw = 0; // This is bit is defined to be ignored.
+            cr0.am = 1; // No alignment checking
+            cr0.wp = 1; // Supervisor mode can write read only pages
+            cr0.ne = 1;
+            cr0.et = 1; // This should always be 1
+            cr0.ts = 0; // We don't do task switching, so causing fp exceptions
+                        // would be pointless.
+            cr0.em = 0; // Allow x87 instructions to execute natively.
+            cr0.mp = 1; // This doesn't really matter, but the manual suggests
+                        // setting it to one.
+            cr0.pe = 1; // We're definitely in protected mode.
+            tc->setMiscReg(MISCREG_CR0, cr0);
+
+            CR0 cr2 = 0;
+            tc->setMiscReg(MISCREG_CR2, cr2);
+
+            CR3 cr3 = pageTablePhysAddr;
+            tc->setMiscReg(MISCREG_CR3, cr3);
+
+            CR4 cr4 = 0;
+            //Turn on pae.
+            cr4.osxsave = 1; // Enable XSAVE and Proc Extended States
+            cr4.osxmmexcpt = 1; // Operating System Unmasked Exception
+            cr4.osfxsr = 1; // Operating System FXSave/FSRSTOR Support
+            cr4.pce = 0; // Performance-Monitoring Counter Enable
+            cr4.pge = 0; // Page-Global Enable
+            cr4.mce = 0; // Machine Check Enable
+            cr4.pae = 1; // Physical-Address Extension
+            cr4.pse = 0; // Page Size Extensions
+            cr4.de = 0; // Debugging Extensions
+            cr4.tsd = 0; // Time Stamp Disable
+            cr4.pvi = 0; // Protected-Mode Virtual Interrupts
+            cr4.vme = 0; // Virtual-8086 Mode Extensions
+
+            tc->setMiscReg(MISCREG_CR4, cr4);
+
+            CR4 cr8 = 0;
+            tc->setMiscReg(MISCREG_CR8, cr8);
+
+            const Addr PageMapLevel4 = pageTablePhysAddr;
+            //Point to the page tables.
+            tc->setMiscReg(MISCREG_CR3, PageMapLevel4);
+
+            tc->setMiscReg(MISCREG_MXCSR, 0x1f80);
+
+            tc->setMiscReg(MISCREG_APIC_BASE, 0xfee00900);
+
+            tc->setMiscReg(MISCREG_SEG_BASE(MISCREG_TSG - 
MISCREG_SEG_SEL_BASE), GDTVirtAddr);
+            tc->setMiscReg(MISCREG_SEG_LIMIT(MISCREG_TSG - 
MISCREG_SEG_SEL_BASE), 0xffff);
+
+            tc->setMiscReg(MISCREG_SEG_BASE(MISCREG_IDTR - 
MISCREG_SEG_SEL_BASE), IDTVirtAddr);
+            tc->setMiscReg(MISCREG_SEG_LIMIT(MISCREG_IDTR - 
MISCREG_SEG_SEL_BASE), 0xffff);
+
+            /* enabling syscall and sysret */
+            MiscReg star = ((MiscReg)sret << 48) | ((MiscReg)scall << 32);
+            tc->setMiscReg(MISCREG_STAR, star);
+            MiscReg lstar = (MiscReg) syscallCodeVirtAddr;
+            tc->setMiscReg(MISCREG_LSTAR, lstar);
+            MiscReg sfmask = (1<<8) | (1<<10); // TF | DF
+            tc->setMiscReg(MISCREG_SF_MASK, sfmask);
         }
 
-        SegAttr csAttr = 0;
-        csAttr.dpl = 3;
-        csAttr.unusable = 0;
-        csAttr.defaultSize = 0;
-        csAttr.longMode = 1;
-        csAttr.avl = 0;
-        csAttr.granularity = 1;
-        csAttr.present = 1;
-        csAttr.type = 10;
-        csAttr.writable = 0;
-        csAttr.readable = 1;
-        csAttr.expandDown = 0;
-        csAttr.system = 1;
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to