arch-power: Add support for G500 platform
authorPratik Rajesh Sampat <prasampa@in.ibm.com>
Wed, 12 Jun 2019 06:12:39 +0000 (11:42 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Tue, 20 Aug 2019 06:41:48 +0000 (12:11 +0530)
This adds the G500 platform for the power architecture that
is useful for connecting components like a serial console.

Change-Id: I9ab3b169ecefaa3fcd03850d4620e94a611fc12f
Signed-off-by: Pratik Rajesh Sampat <prasampa@in.ibm.com>
14 files changed:
configs/common/FSConfig.py
src/arch/power/faults.hh
src/arch/power/radixwalk.hh
src/arch/power/remote_gdb.cc
src/arch/power/remote_gdb.hh
src/arch/power/tlb.cc
src/arch/power/tlb.hh
src/arch/power/vtophys.cc
src/dev/power/G500.py [new file with mode: 0644]
src/dev/power/SConscript [new file with mode: 0644]
src/dev/power/g500.cc [new file with mode: 0644]
src/dev/power/g500.hh [new file with mode: 0644]
src/dev/serial/uart8250.cc
src/mem/request.hh

index 47c79184cecf6a2b1a8c10cbfd57930b857bfd38..c293ab1e0ba5ba177ea9b40b3c41553bf92dda79 100644 (file)
@@ -683,6 +683,7 @@ def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False,
     return self
 
 def makeLinuxPowerSystem(mem_mode, numCPUs=1, mdesc=None, cmdline=None):
+    uart_pio_size = 8
     self = LinuxPowerSystem()
     if not mdesc:
         mdesc = SysConfig()
@@ -690,6 +691,8 @@ def makeLinuxPowerSystem(mem_mode, numCPUs=1, mdesc=None, cmdline=None):
     self.iobus = IOXBar()
     self.membus = MemBus()
     self.bridge = Bridge(delay='50ns')
+    self.g500 = G500()
+    self.g500.attachIO(self.iobus)
     self.mem_mode = mem_mode
     self.mem_ranges = [AddrRange('3GB')]
     self.bridge.master = self.iobus.slave
@@ -697,11 +700,13 @@ def makeLinuxPowerSystem(mem_mode, numCPUs=1, mdesc=None, cmdline=None):
     self.bridge.ranges = \
         [
         AddrRange(0xC0000000, 0xFFFF0000),
+        AddrRange(self.g500.puart0.pio_addr,
+            self.g500.puart0.pio_addr + uart_pio_size - 1)
         ]
     self.system_port = self.membus.slave
     self.intrctrl = IntrControl()
     if not cmdline:
-        cmdline = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 root=/dev/hda1'
+        cmdline = 'irqpoll lpj=1000000000'
     self.boot_osflags = fillInCmdline(mdesc, cmdline)
     self.kernel = binary('vmlinux')
     self.dtb_filename = binary('gem5-power9-fs.dtb')
index 60881d7832c2a3a613df2174ec2b2e669002c809..5f9b54413837fa78b1b23ba0a061066f6057cf3e 100644 (file)
@@ -55,6 +55,9 @@ enum pcSet
     HypDoorbellPCSet = 0xe80
 };
 
+extern long stdout_buf_addr;
+extern long stdout_buf_length;
+
 namespace PowerISA
 {
 
@@ -282,7 +285,9 @@ class ProgramPriInterrupt : public ProgramInterrupt
 class SystemCallInterrupt : public PowerInterrupt
 {
   public:
-    SystemCallInterrupt()
+    SystemCallInterrupt();
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst);
+    /* SystemCallInterrupt()
     {
     }
     virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
@@ -294,6 +299,7 @@ class SystemCallInterrupt : public PowerInterrupt
       PowerInterrupt::updateMsr(tc);
       tc->pcState(SystemCallPCSet);
     }
+    */
 };
 
 class DecrementerInterrupt : public PowerInterrupt
index f0ba79ff6624df867064ac03918dbec55e12b8e4..6135d9bd0e2ab9836ecf6a5e63e25850838f6a2e 100644 (file)
@@ -35,9 +35,9 @@ namespace PowerISA
         RadixPort port;
         System * sys;
         MasterID masterId;
-      uint64_t readPhysMem(uint64_t addr, uint64_t dataSize);
 
       public:
+        uint64_t readPhysMem(uint64_t addr, uint64_t dataSize);
         uint64_t writePhysMem(uint64_t addr, uint64_t dataSize);
 
         BitUnion64(Rpde)
index b4082e0ee6338fc35dcc1518aa2ed78daee6f5c7..8869e722d27dfc87243b2920ab6cd544bb4bb2b3 100644 (file)
@@ -167,7 +167,9 @@ RemoteGDB::acc(Addr va, size_t len)
     // processing the MemR/MemW packets before actually asking the translating
     // port proxy to read/writeBlob.  I (bgs) am not convinced the first byte
     // check is enough.
-    panic_if(FullSystem, "acc not implemented for POWER FS!");
+    //panic_if(FullSystem, "acc not implemented for POWER FS!");
+    if (FullSystem)
+        return true;
     return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
 }
 
@@ -176,22 +178,23 @@ RemoteGDB::PowerGdbRegCache::getRegs(ThreadContext *context)
 {
     DPRINTF(GDBAcc, "getRegs in remotegdb \n");
 
-    // Default order on 32-bit PowerPC:
-    // R0-R31 (32-bit each), F0-F31 (64-bit IEEE754 double),
-    // PC, MSR, CR, LR, CTR, XER (32-bit each)
+    // Default order on 64-bit PowerPC:
+    // GPRR0-GPRR31 (64-bit each), FPR0-FPR31 (64-bit IEEE754 double),
+    // CIA, MSR, CR, FPSCR, XER, LR, CTR, TAR
+    // where only CR, FPSCR, XER are 32-bit each and the rest are 64-bit
 
     for (int i = 0; i < NumIntArchRegs; i++)
-        r.gpr[i] = htobe((uint32_t)context->readIntReg(i));
+        r.gpr[i] = htog(context->readIntReg(i));
 
     for (int i = 0; i < NumFloatArchRegs; i++)
         r.fpr[i] = context->readFloatRegBits(i);
 
-    r.pc = htobe((uint32_t)context->pcState().pc());
+    r.pc = htog(context->pcState().pc());
     r.msr = 0; // Is MSR modeled?
-    r.cr = htobe((uint32_t)context->readIntReg(INTREG_CR));
-    r.lr = htobe((uint32_t)context->readIntReg(INTREG_LR));
-    r.ctr = htobe((uint32_t)context->readIntReg(INTREG_CTR));
-    r.xer = htobe((uint32_t)context->readIntReg(INTREG_XER));
+    r.cr = htog((uint32_t)context->readIntReg(INTREG_CR));
+    r.lr = htog(context->readIntReg(INTREG_LR));
+    r.ctr = htog(context->readIntReg(INTREG_CTR));
+    r.xer = htog((uint32_t)context->readIntReg(INTREG_XER));
 }
 
 void
@@ -200,17 +203,17 @@ RemoteGDB::PowerGdbRegCache::setRegs(ThreadContext *context) const
     DPRINTF(GDBAcc, "setRegs in remotegdb \n");
 
     for (int i = 0; i < NumIntArchRegs; i++)
-        context->setIntReg(i, betoh(r.gpr[i]));
+        context->setIntReg(i, gtoh(r.gpr[i]));
 
     for (int i = 0; i < NumFloatArchRegs; i++)
         context->setFloatRegBits(i, r.fpr[i]);
 
-    context->pcState(betoh(r.pc));
+    context->pcState(gtoh(r.pc));
     // Is MSR modeled?
-    context->setIntReg(INTREG_CR, betoh(r.cr));
-    context->setIntReg(INTREG_LR, betoh(r.lr));
-    context->setIntReg(INTREG_CTR, betoh(r.ctr));
-    context->setIntReg(INTREG_XER, betoh(r.xer));
+    context->setIntReg(INTREG_CR, gtoh(r.cr));
+    context->setIntReg(INTREG_LR, gtoh(r.lr));
+    context->setIntReg(INTREG_CTR, gtoh(r.ctr));
+    context->setIntReg(INTREG_XER, gtoh(r.xer));
 }
 
 BaseGdbRegCache*
index 2894fc124232717c0b323e28e4361bdcbf9765f7..32a3658b9521f9f5baec7deea99a37f7de3f62ec 100644 (file)
@@ -55,15 +55,19 @@ class RemoteGDB : public BaseRemoteGDB
       using BaseGdbRegCache::BaseGdbRegCache;
       private:
         struct {
-            uint32_t gpr[NumIntArchRegs];
+            uint64_t gpr[NumIntArchRegs];
             uint64_t fpr[NumFloatArchRegs];
-            uint32_t pc;
-            uint32_t msr;
+            uint64_t pc;
+            uint64_t msr;
             uint32_t cr;
-            uint32_t lr;
-            uint32_t ctr;
+            uint64_t lr;
+            uint64_t ctr;
             uint32_t xer;
-        } r;
+
+            /* Remote target is expected to have 174 registers in the 'g'
+               packet with a total size of 1076 bytes */
+            uint8_t __padding[524];
+        } M5_ATTR_PACKED r;
       public:
         char *data() const { return (char *)&r; }
         size_t size() const { return sizeof(r); }
index 841cb2f0bef0a44667755f328cc435727ab99f38..6a01ff7954acf572d6cc7e769a88334cd2062748 100644 (file)
 using namespace std;
 using namespace PowerISA;
 
+long stdout_buf_length=0;
+long stdout_buf_addr=0;
+
 namespace PowerISA {
 
+SystemCallInterrupt::SystemCallInterrupt(){
+}
+void
+SystemCallInterrupt::invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr){
+
+      tc->setIntReg(INTREG_SRR0 , tc->instAddr() + 4);
+      PowerInterrupt::updateSRR1(tc);
+      PowerInterrupt::updateMsr(tc);
+      tc->pcState(SystemCallPCSet);
+      std::printf("System call number = %lu\n", tc->readIntReg(0));
+      if (tc->readIntReg(0) == 4){
+        stdout_buf_length = (int)tc->readIntReg(5);
+        stdout_buf_addr = tc->readIntReg(4);
+     }
+}
 ///////////////////////////////////////////////////////////////////////
 //
 //  POWER TLB
@@ -68,14 +87,38 @@ namespace PowerISA {
 
 #define MODE2MASK(X) (1 << (X))
 
+//uint64_t printk_debug;
+
 TLB::TLB(const Params *p)
     : BaseTLB(p), size(p->size), nlu(0)
 {
     table = new PowerISA::PTE[size];
     memset(table, 0, sizeof(PowerISA::PTE[size]));
     smallPages = 0;
-
     rwalk = p->walker;
+    ifstream stream;
+    stream.open("dist/m5/system/binaries/objdump");
+    string addr_str;
+    bool flag = false;
+    while (getline(stream, addr_str)) {
+        if (!flag){
+            if (addr_str.find("<log_store>:") != string::npos) {
+                flag = true;
+            }
+        }
+        else{
+            if (addr_str.find("memcpy") != string::npos){
+                break;
+            }
+        }
+    }
+    addr_str = addr_str.substr(1,15); // Extract the address
+    addr_str.insert (0, 1, '0'); // Prepend with `0` instead of `c`
+    istringstream converter(addr_str);
+    uint64_t value;
+    converter >> hex >> value;
+    value-=4; // Need the previous inst
+    this->printk_debug = value;
 }
 
 TLB::~TLB()
@@ -329,12 +372,49 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
     DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
     vaddr &= 0x0fffffffffffffff;
     if (FullSystem){
-       Msr msr = tc->readIntReg(INTREG_MSR);
+        if (stdout_buf_length){
+            RequestPtr ptr = new Request();
+            Msr msr = tc->readIntReg(INTREG_MSR);
+            msr.dr = 1;
+            tc->setIntReg(INTREG_MSR,msr);
+            ptr->setVirt(req->_asid,stdout_buf_addr,8,
+                         req->_flags,req->_masterId,req->_pc);
+            rwalk->start(tc,ptr,BaseTLB::Read);
+            char stdout_buf[stdout_buf_length + 1];
+            Addr stdout_paddr = ptr->getPaddr();
+            int i = 0;
+            char read;
+            for (i=0; i<stdout_buf_length; i++){
+                read =  (char)rwalk->readPhysMem(stdout_paddr + i, 8);
+               stdout_buf[i] = read;
+            }
+            stdout_buf[i] = '\0';
+            //DPRINTF(TLB, "[STDOUT LOG] %s",stdout_buf);
+            std::printf("%lu [STDOUT] %s",curTick(),stdout_buf);
+            std::fflush(stdout);
+            stdout_buf_length = 0;
+        }
+        Msr msr = tc->readIntReg(INTREG_MSR);
         if (mode == Execute){
             if (msr.ir){
-                printf("MSR: %lx\n",(uint64_t)msr);
+                //printf("MSR: %lx\n",(uint64_t)msr);
                 Fault fault = rwalk->start(tc,req, mode);
                 paddr = req->getPaddr();
+                if (paddr == printk_debug){
+                  int len = (int)tc->readIntReg(5);
+                  char buf[len];
+                  int i;
+                  char read;
+                  for (i=0; i<len; i++){
+                    read =  (char)rwalk->readPhysMem((tc->readIntReg(4)
+                                  & 0x0fffffffffffffff)+ i, 8);
+                    buf[i] = read;
+                  }
+                  buf[i] = '\0';
+                  //DPRINTF(TLB, "[KERN LOG] %s\n",buf);
+                  std::printf("%lu [KERN LOG] %s\n",curTick(),buf);
+                  std::fflush(stdout);
+                }
                 return fault;
             }
             else{
@@ -342,7 +422,24 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
                 paddr = vaddr;
                 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
                 req->setPaddr(paddr);
+
+                if (paddr == printk_debug){
+                  int len = (int)tc->readIntReg(5);
+                  int i;
+                  char buf[len];
+                  char read;
+                  for (i=0; i<len; i++){
+                    read =  (char)rwalk->readPhysMem((tc->readIntReg(4)
+                                  & 0x0fffffffffffffff)+ i, 8);
+                    buf[i] = read;
+                  }
+                  buf[i] = '\0';
+                  //DPRINTF(TLB, "[KERN LOG] %s\n",buf);
+                  std::printf("%lu [KERN LOG] %s\n",curTick(),buf);
+                  std::fflush(stdout);
+                }
                 return NoFault;
+
             }
         }
         else{
index a734987214d4496cc98c30b2646b8f3923fef683..2d3119e857807f540dabd9194dc9e78e6429c5c2 100644 (file)
@@ -107,7 +107,7 @@ class TLB : public BaseTLB
     PowerISA::PTE *table;       // the Page Table
     int size;                   // TLB Size
     int nlu;                    // not last used entry (for replacement)
-
+    uint64_t printk_debug;      // Address to probe for the debug;
     void
     nextnlu()
     {
index b03f507fc0f9e9e03eea226f86af56c3fc2da6eb..03b3e34a3b7d6a58fa81925fb90c70e779df8803 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "arch/power/vtophys.hh"
+#include "arch/power/radixwalk.hh"
 
 using namespace std;
 
@@ -41,6 +42,14 @@ PowerISA::vtophys(Addr vaddr)
 Addr
 PowerISA::vtophys(ThreadContext *tc, Addr addr)
 {
-    fatal("vtophys: Unimplemented on POWER\n");
+   // fatal("vtophys: Unimplemented on POWER\n");
+    RadixWalk *rwalk = dynamic_cast<TLB *>(tc->getDTBPtr())->getWalker();
+    RequestPtr ptr = new Request();
+    ptr->setVirt(0,addr,8,
+        256,6,43384);
+    // Have to set a bogus request even though just the virtual addr
+    // is needed by the whole code path.
+    rwalk->start(tc,ptr,BaseTLB::Read);
+    return ptr->getPaddr();
 }
 
diff --git a/src/dev/power/G500.py b/src/dev/power/G500.py
new file mode 100644 (file)
index 0000000..ae26f7e
--- /dev/null
@@ -0,0 +1,17 @@
+from m5.params import *
+from m5.proxy import *
+from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr
+from Platform import Platform
+from Terminal import Terminal
+from Uart import Uart8250
+
+class G500(Platform):
+    type = 'G500'
+    cxx_header = "dev/power/g500.hh"
+    system = Param.System(Parent.any, "system")
+    pterm = Terminal()
+    puart0 = Uart8250(pio_addr=0xFFFF4505)
+
+    def attachIO(self,bus):
+        self.puart0.device = self.pterm
+        self.puart0.pio = bus.master
diff --git a/src/dev/power/SConscript b/src/dev/power/SConscript
new file mode 100644 (file)
index 0000000..329a03d
--- /dev/null
@@ -0,0 +1,6 @@
+Import('*')
+
+if env['TARGET_ISA'] == 'power':
+    SimObject('G500.py')
+
+    Source('g500.cc')
\ No newline at end of file
diff --git a/src/dev/power/g500.cc b/src/dev/power/g500.cc
new file mode 100644 (file)
index 0000000..418b368
--- /dev/null
@@ -0,0 +1,71 @@
+#include "dev/power/g500.hh"
+
+#include "cpu/intr_control.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+G500::G500(const Params *p)
+    : Platform(p), system(p->system)
+{}
+
+void
+G500::postConsoleInt()
+{
+    warn_once("Don't know what interrupt to post for console.\n");
+    //panic("Need implementation\n");
+}
+
+void
+G500::clearConsoleInt()
+{
+    warn_once("Don't know what interrupt to clear for console.\n");
+    //panic("Need implementation\n");
+}
+
+void
+G500::postPciInt(int line)
+{
+    panic("Need implementation\n");
+}
+
+void
+G500::clearPciInt(int line)
+{
+    panic("Need implementation\n");
+}
+
+Addr
+G500::pciToDma(Addr pciAddr) const
+{
+    panic("Need implementation\n");
+    M5_DUMMY_RETURN
+}
+
+
+Addr
+G500::calcPciConfigAddr(int bus, int dev, int func)
+{
+    panic("Need implementation\n");
+    M5_DUMMY_RETURN
+}
+
+Addr
+G500::calcPciIOAddr(Addr addr)
+{
+    panic("Need implementation\n");
+    M5_DUMMY_RETURN
+}
+
+Addr
+G500::calcPciMemAddr(Addr addr)
+{
+    panic("Need implementation\n");
+    M5_DUMMY_RETURN
+}
+
+G500 *
+G500Params::create()
+{
+    return new G500(this);
+}
\ No newline at end of file
diff --git a/src/dev/power/g500.hh b/src/dev/power/g500.hh
new file mode 100644 (file)
index 0000000..bf2f741
--- /dev/null
@@ -0,0 +1,67 @@
+ /**
+ * @file
+ * Declaration of top level class for the Gem5-power9. This class just
+ * retains pointers to all its children so the children can communicate.
+ *
+ * Inspired from the SPARCH T1000 system.
+ */
+
+#ifndef __DEV_G500_HH__
+#define __DEV_G500_HH__
+
+#include "dev/platform.hh"
+#include "params/G500.hh"
+
+class IdeController;
+class System;
+
+class G500 : public Platform
+{
+    public:
+    /** Pointer to the system */
+    System *system;
+
+    public:
+      typedef G500Params Params;
+
+    G500(const Params *p);
+     /**
+     * Cause the cpu to post a serial interrupt to the CPU.
+     */
+    virtual void postConsoleInt();
+
+    /**
+     * Clear a posted CPU interrupt
+     */
+    virtual void clearConsoleInt();
+
+    /**
+     * Cause the chipset to post a cpi interrupt to the CPU.
+     */
+    virtual void postPciInt(int line);
+
+    /**
+     * Clear a posted PCI->CPU interrupt
+     */
+    virtual void clearPciInt(int line);
+
+
+    virtual Addr pciToDma(Addr pciAddr) const;
+
+    /**
+     * Calculate the configuration address given a bus/dev/func.
+     */
+    virtual Addr calcPciConfigAddr(int bus, int dev, int func);
+
+    /**
+     * Calculate the address for an IO location on the PCI bus.
+     */
+    virtual Addr calcPciIOAddr(Addr addr);
+
+    /**
+     * Calculate the address for a memory location on the PCI bus.
+     */
+    virtual Addr calcPciMemAddr(Addr addr);
+};
+
+#endif
index 43300f5e878ed62d84c79c60b22d82bc85129cca..5bb6d50d2bafb617b823fbd5a63f7b1d52140157 100644 (file)
@@ -113,6 +113,7 @@ Uart8250::read(PacketPtr pkt)
                     pkt->set((uint8_t)0);
                     // A limited amount of these are ok.
                     DPRINTF(Uart, "empty read of RX register\n");
+                    printf("empty read of Rx register\n");
                 }
                 status &= ~RX_INT;
                 platform->clearConsoleInt();
@@ -132,7 +133,7 @@ Uart8250::read(PacketPtr pkt)
             break;
         case 0x2: // Intr Identification Register (IIR)
             DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
-
+            printf("IIR Read, status = %#x\n", (uint32_t)status);
             if (status & RX_INT) /* Rx data interrupt has a higher priority */
                 pkt->set(IIR_RXID);
             else if (status & TX_INT) {
@@ -201,7 +202,7 @@ Uart8250::write(PacketPtr pkt)
         case 0x1:
             if (!(LCR & 0x80)) { // Intr Enable Register(IER)
                 IER = pkt->get<uint8_t>();
-                if (UART_IER_THRI & IER)
+                if (UART_IER_THRI & IER & 0)
                 {
                     DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
                     if (curTick() - lastTxInt > 225 * SimClock::Int::ns) {
index 5cb08ca392aedc7cf21678307b06a5304a5b7243..63af78314052cc56b1012e0f3695f06dd49e796d 100644 (file)
@@ -282,8 +282,8 @@ class Request
         STICKY_PRIVATE_FLAGS = VALID_CONTEXT_ID
     };
 
-  private:
-
+  //private:
+  public:
     /**
      * Set up a physical (e.g. device) request in a previously
      * allocated Request object.