Swapnil Haria has uploaded this change for review. ( https://gem5-review.googlesource.com/5581

Change subject: patch 2613 from reviewboard for KVM
......................................................................

patch 2613 from reviewboard for KVM

Change-Id: I0bd65c592be68ca74de8ef7e11b6266f89182e1e
---
M src/arch/x86/process.cc
M src/arch/x86/regs/misc.hh
M src/arch/x86/system.cc
M src/arch/x86/system.hh
M src/arch/x86/utility.cc
M src/arch/x86/utility.hh
M src/cpu/kvm/x86_cpu.cc
7 files changed, 388 insertions(+), 317 deletions(-)



diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index d7a0571..8af5082 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -52,6 +52,7 @@
 #include "arch/x86/regs/segment.hh"
 #include "arch/x86/system.hh"
 #include "arch/x86/types.hh"
+#include "arch/x86/utility.hh"
 #include "base/loader/elf_object.hh"
 #include "base/loader/object_file.hh"
 #include "base/misc.hh"
@@ -69,6 +70,10 @@
 using namespace std;
 using namespace X86ISA;

+
+
+static int isIntel = isIntelCPU();
+
 static const int ArgumentReg[] = {
     INTREG_RDI,
     INTREG_RSI,
@@ -176,6 +181,7 @@
     return &syscallDescs[callnum];
 }

+
 void
 X86_64Process::initState()
 {
@@ -213,232 +219,224 @@
                             (uint8_t *)(&nullDescriptor), 8);
         numGDTEntries++;

-        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++;
-
+        SegDescriptor dsDesc = dataSegDesc();
         SegSelector ds = 0;
-        ds.si = numGDTEntries - 1;
-        ds.rpl = 3;
+        SegDescriptor csDesc = codeSegDesc64();
+        SegSelector cs = 0;
+        uint64_t dsDescVal;
+        uint64_t csDescVal;

-        //64 bit code segment
-        SegDescriptor csDesc = initDesc;
-        csDesc.type.codeOrData = 1;
-        csDesc.dpl = 3;
-        uint64_t csDescVal = csDesc;
+        if (isIntel){
+                // 64 bit data segment, DPL 3
+                dsDesc.dpl = 3;
+                dsDescVal = dsDesc;
+                physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                             (uint8_t *)(&dsDescVal), 8);
+
+                ds.si = numGDTEntries;
+                ds.rpl = 3;
+
+                numGDTEntries++;
+
+
+                // 64 bit code segment, DPL 3
+                csDesc.dpl = 3;
+                csDescVal = csDesc;
+                physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                                    (uint8_t *)(&csDescVal), 8);
+
+                cs.si = numGDTEntries;
+                cs.rpl = 3;
+
+                numGDTEntries++;
+        }
+
+        // 64 bit code segment
+        SegDescriptor csSysDesc = codeSegDesc64();
+        uint64_t csSysDescVal = csSysDesc;
         physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&csDescVal), 8);
+                            (uint8_t *)(&csSysDescVal), 8);
+
+        SegSelector csSys = 0;
+        csSys.si = numGDTEntries;

         numGDTEntries++;

-        SegSelector cs = 0;
-        cs.si = numGDTEntries - 1;
-        cs.rpl = 3;
+        // 64 bit data segment
+        SegDescriptor dsSysDesc = dataSegDesc();
+        uint64_t dsSysDescVal = dsSysDesc;
+        physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                            (uint8_t *)(&dsSysDescVal), 8);
+
+        SegSelector dsSys = 0;
+        dsSys.si = numGDTEntries;
+        dsSys.rpl = 0;
+        numGDTEntries++;
+
+
+
+        if (!isIntel){
+                // 64 bit data segment, DPL 3
+                dsDesc.dpl = 3;
+                dsDescVal = dsDesc;
+                physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                             (uint8_t *)(&dsDescVal), 8);
+
+                ds.si = numGDTEntries;
+                ds.rpl = 3;
+
+                numGDTEntries++;
+
+                // 64 bit code segment, DPL 3
+                csDesc.dpl = 3;
+                csDescVal = csDesc;
+                physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
+                                    (uint8_t *)(&csDescVal), 8);
+
+                cs.si = numGDTEntries;
+                cs.rpl = 3;
+
+                numGDTEntries++;
+        }

         SegSelector scall = 0;
-        scall.si = csLowPL.si;
+        scall.si = csSys.si;
         scall.rpl = 0;

         SegSelector sret = 0;
-        sret.si = dsLowPL.si;
+        sret.si = dsSys.si;
         sret.rpl = 3;

+        uint64_t tss_base_addr = TSSVirtAddr;
+        uint64_t tss_limit = 0xFFFFFFFF;
+
         /* 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 = bits(TSSVirtAddr, 23, 0);
-        TSSDescLow.baseHigh = bits(TSSVirtAddr, 31, 24);
-
-        TSShigh TSSDescHigh = 0;
-        TSSDescHigh.base = bits(TSSVirtAddr, 63, 32);
-
-        struct TSSDesc {
-            uint64_t low;
-            uint64_t high;
-        } tssDescVal = {TSSDescLow, TSSDescHigh};
+        Tss64Desc tssDesc;
+        tssSegDesc64(tssDesc, tss_base_addr, tss_limit);
+        tssDesc.low.dpl = 3;

         physProxy.writeBlob(GDTPhysAddr + numGDTEntries * 8,
-                            (uint8_t *)(&tssDescVal), sizeof(tssDescVal));
-
-        numGDTEntries++;
+                            (uint8_t *)(&tssDesc), sizeof(tssDesc));

         SegSelector tssSel = 0;
-        tssSel.si = numGDTEntries - 1;
+        tssSel.si = numGDTEntries;
+        tssSel.rpl = 3;

-        uint64_t tss_base_addr = (TSSDescHigh.base << 32) |
-                                 (TSSDescLow.baseHigh << 24) |
-                                  TSSDescLow.baseLow;
- uint64_t tss_limit = TSSDescLow.limitLow | (TSSDescLow.limitHigh << 16);
+        numGDTEntries += 2;

         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.type = tssDesc.low.type;
+        tss_attr.dpl = tssDesc.low.dpl;
+        tss_attr.present = tssDesc.low.p;
+        tss_attr.granularity = tssDesc.low.g;
         tss_attr.unusable = 0;

+        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.
+
+        SegAttr tslAttr = 0;
+        tslAttr.unusable = 1;
+
+        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 = 0; // No alignment checking
+        cr0.wp = 0; // 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.
+
+        CR2 cr2 = 0;
+
+        CR3 cr3 = pageTablePhysAddr;
+
+        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
+
+        CR8 cr8 = 0;
+
+        Star star = 0;
+        if (isIntel){
+                star.syscallCsAndSs = csSys;
+                star.sysretCsAndSs = 0;
+        }
+
         for (int i = 0; i < contextIds.size(); i++) {
             ThreadContext * tc = system->getThreadContext(contextIds[i]);

-            tc->setMiscReg(MISCREG_CS, cs);
-            tc->setMiscReg(MISCREG_DS, ds);
-            tc->setMiscReg(MISCREG_ES, ds);
-            tc->setMiscReg(MISCREG_FS, ds);
-            tc->setMiscReg(MISCREG_GS, ds);
-            tc->setMiscReg(MISCREG_SS, 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_EFF_BASE, GDTVirtAddr);
             tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1);

             tc->setMiscReg(MISCREG_TR, tssSel);
             tc->setMiscReg(MISCREG_TR_BASE, tss_base_addr);
-            tc->setMiscReg(MISCREG_TR_EFF_BASE, 0);
+            tc->setMiscReg(MISCREG_TR_EFF_BASE, tss_base_addr);
             tc->setMiscReg(MISCREG_TR_LIMIT, tss_limit);
             tc->setMiscReg(MISCREG_TR_ATTR, tss_attr);

-            //Start using longmode segments.
+            // Start using longmode segments.
+            tc->setMiscReg(MISCREG_CS, cs);
             installSegDesc(tc, SEGMENT_REG_CS, csDesc, true);
+            tc->setMiscReg(MISCREG_DS, ds);
             installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true);
+            tc->setMiscReg(MISCREG_ES, ds);
             installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true);
+            tc->setMiscReg(MISCREG_FS, ds);
             installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true);
+            tc->setMiscReg(MISCREG_GS, ds);
             installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
+            tc->setMiscReg(MISCREG_SS, ds);
             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.
+            // Set up the registers that describe the operating 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_TSG_BASE, GDTVirtAddr);
-            tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);
-
             tc->setMiscReg(MISCREG_IDTR_BASE, IDTVirtAddr);
+            tc->setMiscReg(MISCREG_IDTR_EFF_BASE, IDTVirtAddr);
             tc->setMiscReg(MISCREG_IDTR_LIMIT, 0xffff);

-            /* enabling syscall and sysret */
-            MiscReg star = ((MiscReg)sret << 48) | ((MiscReg)scall << 32);
+            // Configure syscall and sysret.
+            if (!isIntel){
+                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);
+            tc->setMiscReg(MISCREG_LSTAR, syscallCodeVirtAddr);
+            tc->setMiscReg(MISCREG_SF_MASK, TFBit | DFBit);
         }

/* Set up the content of the TSS and write it to physical memory. */
@@ -489,7 +487,7 @@
         GateDescriptorLow PFGateLow = 0;
         PFGateLow.offsetHigh = bits(PFHandlerVirtAddr, 31, 16);
         PFGateLow.offsetLow = bits(PFHandlerVirtAddr, 15, 0);
-        PFGateLow.selector = csLowPL;
+        PFGateLow.selector = csSys;
         PFGateLow.p = 1;
         PFGateLow.dpl = 0;
         PFGateLow.type = 0xe;      // gate interrupt type
diff --git a/src/arch/x86/regs/misc.hh b/src/arch/x86/regs/misc.hh
index 48f7d97..4be4110 100644
--- a/src/arch/x86/regs/misc.hh
+++ b/src/arch/x86/regs/misc.hh
@@ -897,43 +897,15 @@
         EndSubBitUnion(type)
     EndBitUnion(SegDescriptor)

-    /**
-     * TSS Descriptor (long mode - 128 bits)
-     * the lower 64 bits
-     */
-    BitUnion64(TSSlow)
-        Bitfield<63, 56> baseHigh;
-        Bitfield<39, 16> baseLow;
-        Bitfield<55> g; // Granularity
-        Bitfield<52> avl; // Available To Software
-        Bitfield<51, 48> limitHigh;
-        Bitfield<15, 0> limitLow;
-        Bitfield<47> p; // Present
-        Bitfield<46, 45> dpl; // Descriptor Privilege-Level
-        SubBitUnion(type, 43, 40)
-            // Specifies whether this descriptor is for code or data.
-            Bitfield<43> codeOrData;
+    struct Tss64Desc
+    {
+        SegDescriptor low;

-            // These bit fields are for code segments
-            Bitfield<42> c; // Conforming
-            Bitfield<41> r; // Readable
-
-            // These bit fields are for data segments
-            Bitfield<42> e; // Expand-Down
-            Bitfield<41> w; // Writable
-
-            // This is used for both code and data segments.
-            Bitfield<40> a; // Accessed
-        EndSubBitUnion(type)
-    EndBitUnion(TSSlow)
-
-    /**
-     * TSS Descriptor (long mode - 128 bits)
-     * the upper 64 bits
-     */
-    BitUnion64(TSShigh)
-        Bitfield<31, 0> base;
-    EndBitUnion(TSShigh)
+        BitUnion64(TSSHigh)
+            Bitfield<32, 0> base;
+        EndBitUnion(TSSHigh)
+        TSSHigh high;
+    };

     BitUnion64(SegAttr)
         Bitfield<1, 0> dpl;
diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc
index ecde836..5127f96 100644
--- a/src/arch/x86/system.cc
+++ b/src/arch/x86/system.cc
@@ -42,6 +42,7 @@
 #include "arch/x86/bios/intelmp.hh"
 #include "arch/x86/bios/smbios.hh"
 #include "arch/x86/isa_traits.hh"
+#include "arch/x86/utility.hh"
 #include "base/loader/object_file.hh"
 #include "cpu/thread_context.hh"
 #include "params/X86System.hh"
@@ -58,52 +59,6 @@
 }

 void
-X86ISA::installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
-        SegDescriptor desc, bool longmode)
-{
-    uint64_t base = desc.baseLow + (desc.baseHigh << 24);
-    bool honorBase = !longmode || seg == SEGMENT_REG_FS ||
-                                  seg == SEGMENT_REG_GS ||
-                                  seg == SEGMENT_REG_TSL ||
-                                  seg == SYS_SEGMENT_REG_TR;
-    uint64_t limit = desc.limitLow | (desc.limitHigh << 16);
-
-    SegAttr attr = 0;
-
-    attr.dpl = desc.dpl;
-    attr.unusable = 0;
-    attr.defaultSize = desc.d;
-    attr.longMode = desc.l;
-    attr.avl = desc.avl;
-    attr.granularity = desc.g;
-    attr.present = desc.p;
-    attr.system = desc.s;
-    attr.type = desc.type;
-    if (desc.s) {
-        if (desc.type.codeOrData) {
-            // Code segment
-            attr.expandDown = 0;
-            attr.readable = desc.type.r;
-            attr.writable = 0;
-        } else {
-            // Data segment
-            attr.expandDown = desc.type.e;
-            attr.readable = 1;
-            attr.writable = desc.type.w;
-        }
-    } else {
-        attr.readable = 1;
-        attr.writable = 1;
-        attr.expandDown = 0;
-    }
-
-    tc->setMiscReg(MISCREG_SEG_BASE(seg), base);
-    tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? base : 0);
-    tc->setMiscReg(MISCREG_SEG_LIMIT(seg), limit);
-    tc->setMiscReg(MISCREG_SEG_ATTR(seg), (MiscReg)attr);
-}
-
-void
 X86System::initState()
 {
     System::initState();
@@ -145,73 +100,59 @@
                         (uint8_t *)(&nullDescriptor), 8);
     numGDTEntries++;

-    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 csDesc = initDesc;
-    csDesc.type.codeOrData = 1;
-    csDesc.dpl = 0;
-    //Because we're dealing with a pointer and I don't think it's
-    //guaranteed that there isn't anything in a nonvirtual class between
-    //it's beginning in memory and it's actual data, we'll use an
-    //intermediary.
+    // 64 bit code segment.
+    SegDescriptor csDesc = codeSegDesc64();
+    // Because we're dealing with a pointer and I don't think it's
+    // guaranteed that there isn't anything in a nonvirtual class between
+    // it's beginning in memory and it's actual data, we'll use an
+    // intermediary.
     uint64_t csDescVal = csDesc;
     physProxy.writeBlob(GDTBase + numGDTEntries * 8,
                         (uint8_t *)(&csDescVal), 8);

+    SegSelector cs = 0;
+    cs.si = numGDTEntries;
+
     numGDTEntries++;

-    SegSelector cs = 0;
-    cs.si = numGDTEntries - 1;
+    tc->setMiscReg(MISCREG_CS, cs);

-    tc->setMiscReg(MISCREG_CS, (MiscReg)cs);
-
-    //32 bit data segment
-    SegDescriptor dsDesc = initDesc;
+    // 32 bit data segment.
+    SegDescriptor dsDesc = dataSegDesc();
     uint64_t dsDescVal = dsDesc;
     physProxy.writeBlob(GDTBase + numGDTEntries * 8,
                         (uint8_t *)(&dsDescVal), 8);

+    SegSelector ds = 0;
+    ds.si = numGDTEntries;
+
     numGDTEntries++;

-    SegSelector ds = 0;
-    ds.si = numGDTEntries - 1;
+    tc->setMiscReg(MISCREG_DS, ds);
+    tc->setMiscReg(MISCREG_ES, ds);
+    tc->setMiscReg(MISCREG_FS, ds);
+    tc->setMiscReg(MISCREG_GS, ds);
+    tc->setMiscReg(MISCREG_SS, ds);

-    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);
+    Tss64Desc tssDesc;
+    tssSegDesc64(tssDesc, 0x0, 0xFFFFFFFF);
+    physProxy.writeBlob(GDTBase + numGDTEntries * 8,
+                        (uint8_t *)(&tssDesc), 16);
+
+    SegSelector tss = 0;
+    tss.si = numGDTEntries;
+
+    numGDTEntries += 2;

     tc->setMiscReg(MISCREG_TSL, 0);
+    SegAttr ldtAttr = 0;
+    ldtAttr.unusable = 1;
+    tc->setMiscReg(MISCREG_TSL_ATTR, ldtAttr);
     tc->setMiscReg(MISCREG_TSG_BASE, GDTBase);
     tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1);

-    SegDescriptor tssDesc = initDesc;
-    uint64_t tssDescVal = tssDesc;
-    physProxy.writeBlob(GDTBase + numGDTEntries * 8,
-                        (uint8_t *)(&tssDescVal), 8);
-
-    numGDTEntries++;
-
-    SegSelector tss = 0;
-    tss.si = numGDTEntries - 1;
-
-    tc->setMiscReg(MISCREG_TR, (MiscReg)tss);
-    installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc, true);
+    tc->setMiscReg(MISCREG_TR, tss);
+    installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc.low, true);

     /*
      * Identity map the first 4GB of memory. In order to map this region
@@ -271,27 +212,27 @@
      * Transition from real mode all the way up to Long mode
      */
     CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
-    //Turn off paging.
+    // Turn off paging.
     cr0.pg = 0;
     tc->setMiscReg(MISCREG_CR0, cr0);
-    //Turn on protected mode.
+    // Turn on protected mode.
     cr0.pe = 1;
     tc->setMiscReg(MISCREG_CR0, cr0);

     CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
-    //Turn on pae.
+    // Turn on pae.
     cr4.pae = 1;
     tc->setMiscReg(MISCREG_CR4, cr4);

-    //Point to the page tables.
+    // Point to the page tables.
     tc->setMiscReg(MISCREG_CR3, PageMapLevel4);

     Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
-    //Enable long mode.
+    // Enable long mode.
     efer.lme = 1;
     tc->setMiscReg(MISCREG_EFER, efer);

-    //Start using longmode segments.
+    // 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);
@@ -299,7 +240,7 @@
     installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
     installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true);

-    //Activate long mode.
+    // Activate long mode.
     cr0.pg = 1;
     tc->setMiscReg(MISCREG_CR0, cr0);

@@ -310,12 +251,12 @@
     Addr ebdaPos = 0xF0000;
     Addr fixed, table;

-    //Write out the SMBios/DMI table
+    // Write out the SMBios/DMI table
     writeOutSMBiosTable(ebdaPos, fixed, table);
     ebdaPos += (fixed + table);
     ebdaPos = roundUp(ebdaPos, 16);

-    //Write out the Intel MP Specification configuration table
+    // Write out the Intel MP Specification configuration table
     writeOutMPTable(ebdaPos, fixed, table);
     ebdaPos += (fixed + table);
 }
diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh
index 45bc965..e1b2637 100644
--- a/src/arch/x86/system.hh
+++ b/src/arch/x86/system.hh
@@ -59,9 +59,6 @@
         class ConfigTable;
     }

-    void installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
-                        SegDescriptor desc, bool longmode);
-
     /* memory mappings for KVMCpu in SE mode */
     const uint64_t syscallCodeVirtAddr = 0xffff800000000000;
     const uint64_t syscallCodePhysAddr = 0x60000;
diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc
index 33b53ca..4aa5d53 100644
--- a/src/arch/x86/utility.cc
+++ b/src/arch/x86/utility.cc
@@ -40,6 +40,8 @@

 #include "arch/x86/utility.hh"

+#include <fstream>
+
 #include "arch/x86/interrupts.hh"
 #include "arch/x86/registers.hh"
 #include "arch/x86/x86_traits.hh"
@@ -367,4 +369,89 @@
     memcpy(_mem, fp80.bits, 10);
 }

+void
+installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
+               SegDescriptor desc, bool longmode)
+{
+    uint64_t base = desc.baseLow + (desc.baseHigh << 24);
+    bool honorBase = !longmode || seg == SEGMENT_REG_FS ||
+                                  seg == SEGMENT_REG_GS ||
+                                  seg == SEGMENT_REG_TSL ||
+                                  seg == SYS_SEGMENT_REG_TR;
+    uint64_t limit = desc.limitLow | (desc.limitHigh << 16);
+    if (desc.g)
+        limit = limit * PageBytes + PageBytes - 1;
+
+    SegAttr attr = 0;
+
+    attr.dpl = desc.dpl;
+    attr.unusable = 0;
+    attr.defaultSize = desc.d;
+    attr.longMode = desc.l;
+    attr.avl = desc.avl;
+    attr.granularity = desc.g;
+    attr.present = desc.p;
+    attr.system = desc.s;
+    attr.type = desc.type;
+    if (desc.s) {
+        if (desc.type.codeOrData) {
+            // Code segment
+            attr.expandDown = 0;
+            attr.readable = desc.type.r;
+            attr.writable = 0;
+        } else {
+            // Data segment
+            attr.expandDown = desc.type.e;
+            attr.readable = 1;
+            attr.writable = desc.type.w;
+        }
+    } else {
+        attr.readable = 1;
+        attr.writable = 1;
+        attr.expandDown = 0;
+    }
+
+    tc->setMiscReg(MISCREG_SEG_BASE(seg), base);
+    tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? base : 0);
+    tc->setMiscReg(MISCREG_SEG_LIMIT(seg), limit);
+    tc->setMiscReg(MISCREG_SEG_ATTR(seg), (MiscReg)attr);
+}
+
+
+int
+isIntelCPU()
+{
+    static int checked=0;
+    static int isIntel=0;
+
+    if (checked){
+        return(isIntel);
+    } else{
+        checked = 1;
+        std::string vendor("vendor_id");
+        std::string check("GenuineIntel");
+        std::ifstream inFile("/proc/cpuinfo");
+        for (std::string line; getline( inFile, line); ) {
+            std::stringstream stream(line);
+            std::string oneWord;
+            int count=0;
+            while (stream >> oneWord){ count++; }
+            if (count == 3){
+                std::stringstream stream(line);
+                std::string type_string, value_string;
+                stream >> type_string;
+                stream >> oneWord;
+                stream >> value_string;
+                if (!type_string.compare(vendor)) {
+                    inFile.close();
+                    isIntel = !value_string.compare(check);
+                    std::cout << "running on " << value_string << "\n";
+                    return isIntel;
+                }
+            }
+        }
+    }
+    return isIntel;
+}
+
 } // namespace X86_ISA
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index 87d5cbb..8282453 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -196,6 +196,87 @@
      * @param value Double precision float to store.
      */
     void storeFloat80(void *mem, double value);
+
+    /**
+     * Build a standard 64 bit code segment descriptor.
+     */
+    static inline SegDescriptor
+    codeSegDesc64()
+    {
+        SegDescriptor desc = 0;
+        desc.type.codeOrData = 1;
+        desc.type.c = 0; // Not conforming
+        desc.type.r = 1; // Readable
+        desc.dpl = 0; // Privelege level 0
+        desc.p = 1; // Present
+        desc.l = 1; // 64 bit
+        desc.d = 0; // default operand size
+        desc.g = 1; // Page granularity
+        desc.s = 1; // Not a system segment
+        desc.limitHigh = 0xF;
+        desc.limitLow = 0xFFFF;
+        return desc;
+    }
+
+    /**
+     * Build a standard 32/64 bit data segment descriptor.
+     */
+    static inline SegDescriptor
+    dataSegDesc()
+    {
+        SegDescriptor desc = 0;
+        desc.type.codeOrData = 0;
+        desc.type.e = 0; // Not expand down
+        desc.type.w = 1; // Writable
+        desc.dpl = 0; // Privelege level 0
+        desc.p = 1; // Present
+        desc.d = 1; // Default operand size
+        desc.g = 1; // Page granularity
+        desc.s = 1; // Not a system segment
+        desc.limitHigh = 0xF;
+        desc.limitLow = 0xFFFF;
+        return desc;
+    }
+
+    /**
+     * Build a 64 bit tss segment descriptor.
+     *
+     * @param desc The descriptor structure to fill in.
+     * @param base The base address of the TSS.
+     * @param limit The limit of the TSS.
+     */
+    static inline void
+    tssSegDesc64(Tss64Desc &desc, Addr base, Addr limit)
+    {
+        desc.low = 0;
+        desc.high = 0;
+
+        desc.low.type = 0xB;
+        desc.low.dpl = 0; // Privelege level 0
+        desc.low.p = 1; // Present
+        desc.low.d = 1; // Default operand size
+        desc.low.s = 0;
+
+        if (limit > mask(20)) {
+            if ((limit & mask(12)) != mask(12)) {
+                panic("Limit %#x doesn't fit in a segment descriptor.\n",
+                      limit);
+            }
+            limit = limit >> 12;
+            desc.low.g = 1;
+        }
+        desc.low.limitHigh = bits(limit, 19, 16);
+        desc.low.limitLow = bits(limit, 15, 0);
+
+        desc.low.baseHigh = bits(base, 31, 24);
+        desc.low.baseLow = bits(base, 23, 0);
+        desc.high.base = bits(base, 63, 32);
+    }
+
+    void installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
+                        SegDescriptor desc, bool longmode);
+
+    int isIntelCPU();
 }

 #endif // __ARCH_X86_UTILITY_HH__
diff --git a/src/cpu/kvm/x86_cpu.cc b/src/cpu/kvm/x86_cpu.cc
index 467e1ba..6ac11d0 100644
--- a/src/cpu/kvm/x86_cpu.cc
+++ b/src/cpu/kvm/x86_cpu.cc
@@ -505,9 +505,9 @@
         if (!seg.present)
             warn("%s: P flag not set\n", name);

-        if (((seg.limit & 0xFFF) == 0 && seg.g) ||
-            ((seg.limit & 0xFFF00000) != 0 && !seg.g)) {
-            warn("%s limit (0x%x) and g (%i) combination is illegal.\n",
+        if ((seg.g && bits(seg.limit, 11, 0) != mask(12)) ||
+            (bits(seg.limit, 31, 20) && !seg.g)) {
+            warn("%s limit (%#x) and g (%i) combination is illegal.\n",
                  name, seg.limit, seg.g);
         }
         break;
@@ -719,12 +719,7 @@
     kvm_seg.l = attr.longMode;
     kvm_seg.g = attr.granularity;
     kvm_seg.avl = attr.avl;
-
-    // A segment is normally unusable when the selector is zero. There
-    // is a attr.unusable flag in gem5, but it seems unused. qemu
-    // seems to set this to 0 all the time, so we just do the same and
-    // hope for the best.
-    kvm_seg.unusable = 0;
+    kvm_seg.unusable = attr.unusable;
 }

 static inline void

--
To view, visit https://gem5-review.googlesource.com/5581
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0bd65c592be68ca74de8ef7e11b6266f89182e1e
Gerrit-Change-Number: 5581
Gerrit-PatchSet: 1
Gerrit-Owner: Swapnil Haria <[email protected]>
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to