B.A. Zeeb has uploaded this change for review. ( https://gem5-review.googlesource.com/6842

Change subject: arch-x86: split setting up PMAP and transition to long mode off
......................................................................

arch-x86: split setting up PMAP and transition to long mode off

Currently the (very Linux specific) code to setup the PMAP and
transition to long mode is burried in x86/system??.  Factor it
out into helper functions we can register per Operating System
and call, so that different OSes can do as they need to.
Move the Linux specific bits into x86/linux/system.??.

Change-Id: I59b7302ef1cf0ef826533f4979b90be7feb7266c
---
M src/arch/x86/linux/system.cc
M src/arch/x86/linux/system.hh
M src/arch/x86/system.cc
M src/arch/x86/system.hh
4 files changed, 124 insertions(+), 80 deletions(-)



diff --git a/src/arch/x86/linux/system.cc b/src/arch/x86/linux/system.cc
index fc5bc2d..572ac93 100644
--- a/src/arch/x86/linux/system.cc
+++ b/src/arch/x86/linux/system.cc
@@ -42,6 +42,7 @@
 #include "arch/vtophys.hh"
 #include "arch/x86/isa_traits.hh"
 #include "arch/x86/regs/int.hh"
+#include "arch/x86/system.hh"
 #include "base/trace.hh"
 #include "cpu/thread_context.hh"
 #include "mem/port_proxy.hh"
@@ -63,6 +64,8 @@
 void
 LinuxX86System::initState()
 {
+    LinuxX86SystemHelper h = LinuxX86SystemHelper();
+    X86System::setHelper(&h);
     X86System::initState();

     // The location of the real mode data structure.
@@ -139,3 +142,86 @@
 {
     return new LinuxX86System(this);
 }
+
+void
+LinuxX86SystemHelper::setupPMAP(ThreadContext *tc)
+{
+    const int PML4Bits = 9;
+    const int PDPTBits = 9;
+    const int PDTBits = 9;
+
+    PortProxy &physProxy = tc->getPhysProxy();
+
+    // Page Map Level 4
+
+    // read/write, user, not present
+    uint64_t pml4e = X86ISA::htog(0x6);
+    for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) {
+ physProxy.writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8);
+    }
+    // Point to the only PDPT
+    pml4e = X86ISA::htog(0x7 | PageDirPtrTable);
+    physProxy.writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8);
+
+    // Page Directory Pointer Table
+
+    // read/write, user, not present
+    uint64_t pdpe = X86ISA::htog(0x6);
+    for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) {
+        physProxy.writeBlob(PageDirPtrTable + offset,
+                            (uint8_t *)(&pdpe), 8);
+    }
+    // Point to the PDTs
+    for (int table = 0; table < NumPDTs; table++) {
+        pdpe = X86ISA::htog(0x7 | PageDirTable[table]);
+        physProxy.writeBlob(PageDirPtrTable + table * 8,
+                            (uint8_t *)(&pdpe), 8);
+    }
+
+    // Page Directory Tables
+
+    Addr base = 0;
+    const Addr pageSize = 2 << 20;
+    for (int table = 0; table < NumPDTs; table++) {
+        for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
+            // read/write, user, present, 4MB
+            uint64_t pdte = X86ISA::htog(0x87 | base);
+            physProxy.writeBlob(PageDirTable[table] + offset,
+                                (uint8_t *)(&pdte), 8);
+            base += pageSize;
+        }
+    }
+}
+
+void
+LinuxX86SystemHelper::transitionToLongMode(ThreadContext *tc)
+{
+
+    /*
+     * Transition from real mode all the way up to Long mode
+     */
+    CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
+    //Turn off paging.
+    cr0.pg = 0;
+    tc->setMiscReg(MISCREG_CR0, cr0);
+    //Turn on protected mode.
+    cr0.pe = 1;
+    tc->setMiscReg(MISCREG_CR0, cr0);
+
+    CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
+    //Turn on pae.
+    cr4.pae = 1;
+    tc->setMiscReg(MISCREG_CR4, cr4);
+
+    //Point to the page tables.
+    tc->setMiscReg(MISCREG_CR3, PageMapLevel4);
+
+    Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
+    //Enable long mode.
+    efer.lme = 1;
+    tc->setMiscReg(MISCREG_EFER, efer);
+
+    //Activate long mode.
+    cr0.pg = 1;
+    tc->setMiscReg(MISCREG_CR0, cr0);
+}
diff --git a/src/arch/x86/linux/system.hh b/src/arch/x86/linux/system.hh
index e8adba9..fdda86c 100644
--- a/src/arch/x86/linux/system.hh
+++ b/src/arch/x86/linux/system.hh
@@ -47,6 +47,14 @@
 #include "arch/x86/system.hh"
 #include "params/LinuxX86System.hh"

+class LinuxX86SystemHelper : public X86SystemHelper
+{
+
+  public:
+    virtual void setupPMAP(ThreadContext *);
+    virtual void transitionToLongMode(ThreadContext *);
+};
+
 class LinuxX86System : public X86System
 {
   protected:
diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc
index ecde836..fd84977 100644
--- a/src/arch/x86/system.cc
+++ b/src/arch/x86/system.cc
@@ -123,21 +123,10 @@
     // while allowing consistency checks and the underlying mechansims
     // just to be safe.

-    const int NumPDTs = 4;
-
-    const Addr PageMapLevel4 = 0x70000;
-    const Addr PageDirPtrTable = 0x71000;
-    const Addr PageDirTable[NumPDTs] =
-        {0x72000, 0x73000, 0x74000, 0x75000};
-    const Addr GDTBase = 0x76000;
-
-    const int PML4Bits = 9;
-    const int PDPTBits = 9;
-    const int PDTBits = 9;
-
     /*
      * Set up the gdt.
      */
+    const Addr GDTBase = 0x76000;
     uint8_t numGDTEntries = 0;
     // Place holder at selector 0
     uint64_t nullDescriptor = 0;
@@ -226,70 +215,12 @@
     // Put valid values in all of the various table entries which indicate
     // that those entries don't point to further tables or pages. Then
     // set the values of those entries which are needed.
-
-    // Page Map Level 4
-
-    // read/write, user, not present
-    uint64_t pml4e = X86ISA::htog(0x6);
-    for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) {
- physProxy.writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8);
-    }
-    // Point to the only PDPT
-    pml4e = X86ISA::htog(0x7 | PageDirPtrTable);
-    physProxy.writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8);
-
-    // Page Directory Pointer Table
-
-    // read/write, user, not present
-    uint64_t pdpe = X86ISA::htog(0x6);
-    for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) {
-        physProxy.writeBlob(PageDirPtrTable + offset,
-                            (uint8_t *)(&pdpe), 8);
-    }
-    // Point to the PDTs
-    for (int table = 0; table < NumPDTs; table++) {
-        pdpe = X86ISA::htog(0x7 | PageDirTable[table]);
-        physProxy.writeBlob(PageDirPtrTable + table * 8,
-                            (uint8_t *)(&pdpe), 8);
-    }
-
-    // Page Directory Tables
-
-    Addr base = 0;
-    const Addr pageSize = 2 << 20;
-    for (int table = 0; table < NumPDTs; table++) {
-        for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
-            // read/write, user, present, 4MB
-            uint64_t pdte = X86ISA::htog(0x87 | base);
-            physProxy.writeBlob(PageDirTable[table] + offset,
-                                (uint8_t *)(&pdte), 8);
-            base += pageSize;
-        }
-    }
-
-    /*
-     * Transition from real mode all the way up to Long mode
-     */
-    CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0);
-    //Turn off paging.
-    cr0.pg = 0;
-    tc->setMiscReg(MISCREG_CR0, cr0);
-    //Turn on protected mode.
-    cr0.pe = 1;
-    tc->setMiscReg(MISCREG_CR0, cr0);
-
-    CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
-    //Turn on pae.
-    cr4.pae = 1;
-    tc->setMiscReg(MISCREG_CR4, cr4);
-
-    //Point to the page tables.
-    tc->setMiscReg(MISCREG_CR3, PageMapLevel4);
-
-    Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER);
-    //Enable long mode.
-    efer.lme = 1;
-    tc->setMiscReg(MISCREG_EFER, efer);
+    if (_helper) {
+       _helper->setupPMAP(tc);
+       // Transition from real mode all the way up to Long mode.
+       _helper->transitionToLongMode(tc);
+    } else
+       fatal("%s: _helper not set; check derived classes.\n", __func__);

     //Start using longmode segments.
     installSegDesc(tc, SEGMENT_REG_CS, csDesc, true);
@@ -299,10 +230,6 @@
     installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true);
     installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true);

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

     // We should now be in long mode. Yay!
diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh
index 45bc965..497ad33 100644
--- a/src/arch/x86/system.hh
+++ b/src/arch/x86/system.hh
@@ -81,6 +81,27 @@
     const uint64_t pageTablePhysAddr = 0x70000;
 }

+class X86SystemHelper
+{
+
+  public:
+    inline X86SystemHelper() { }
+    inline ~X86SystemHelper() { }
+
+  public:
+    virtual void setupPMAP(ThreadContext *) = 0;
+    virtual void transitionToLongMode(ThreadContext *) = 0;
+
+  protected:
+    static const int NumPDTs = 4;
+
+    const Addr PageMapLevel4 = 0x70000;
+    const Addr PageDirPtrTable = 0x71000;
+    const Addr PageDirTable[NumPDTs] =
+        {0x72000, 0x73000, 0x74000, 0x75000};
+
+};
+
 class X86System : public System
 {
   public:
@@ -93,6 +114,7 @@
  */
   public:

+    void setHelper(X86SystemHelper *h) { _helper = h; }
     void initState();

   protected:
@@ -101,6 +123,7 @@
     X86ISA::IntelMP::FloatingPointer * mpFloatingPointer;
     X86ISA::IntelMP::ConfigTable * mpConfigTable;
     X86ISA::ACPI::RSDP * rsdp;
+    X86SystemHelper * _helper;

     void writeOutSMBiosTable(Addr header,
             Addr &headerSize, Addr &tableSize, Addr table = 0);

--
To view, visit https://gem5-review.googlesource.com/6842
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: I59b7302ef1cf0ef826533f4979b90be7feb7266c
Gerrit-Change-Number: 6842
Gerrit-PatchSet: 1
Gerrit-Owner: B.A. Zeeb <[email protected]>
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to