return self
def makeLinuxPowerSystem(mem_mode, numCPUs=1, mdesc=None, cmdline=None):
+ uart_pio_size = 8
self = LinuxPowerSystem()
if not mdesc:
mdesc = SysConfig()
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
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')
HypDoorbellPCSet = 0xe80
};
+extern long stdout_buf_addr;
+extern long stdout_buf_length;
+
namespace PowerISA
{
class SystemCallInterrupt : public PowerInterrupt
{
public:
- SystemCallInterrupt()
+ SystemCallInterrupt();
+ virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst);
+ /* SystemCallInterrupt()
{
}
virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
PowerInterrupt::updateMsr(tc);
tc->pcState(SystemCallPCSet);
}
+ */
};
class DecrementerInterrupt : public PowerInterrupt
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)
// 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;
}
{
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
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*
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); }
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
#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()
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{
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{
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()
{
*/
#include "arch/power/vtophys.hh"
+#include "arch/power/radixwalk.hh"
using namespace std;
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();
}
--- /dev/null
+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
--- /dev/null
+Import('*')
+
+if env['TARGET_ISA'] == 'power':
+ SimObject('G500.py')
+
+ Source('g500.cc')
\ No newline at end of file
--- /dev/null
+#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
--- /dev/null
+ /**
+ * @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
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();
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) {
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) {
STICKY_PRIVATE_FLAGS = VALID_CONTEXT_ID
};
- private:
-
+ //private:
+ public:
/**
* Set up a physical (e.g. device) request in a previously
* allocated Request object.