Cleaned up and commented code. I think we are ready to merge with head.

dev/baddev.hh:
dev/pcidev.hh:
dev/tsunami.hh:
dev/tsunami_cchip.hh:
dev/tsunami_io.hh:
dev/tsunami_pchip.hh:
    Added doxygen comments
dev/pciconfigall.hh:
    Added doxygen comments. Made the hlist of devices private and provided
    members to modify the data.
dev/pcidev.cc:
    updated for change in pciconfigall
dev/tsunami_pchip.cc:
    Deleted commented out code we don't need
kern/linux/linux_syscalls.cc:
    Simplified the number -> name conversion.
kern/linux/linux_syscalls.hh:
    Removed StandardNumber and replaced with Number.
kern/linux/linux_system.cc:
kern/linux/linux_system.hh:
    LinuxSkipIdeDelay50msEvent was simply the same as the SkipFunc event,
    so I removed it. Same with with LinuxSkipFuncEvent.

--HG--
extra : convert_revision : 1508c335f87d90373f5772f3a0407ea13e858d7e
This commit is contained in:
Ali Saidi 2004-05-30 17:45:46 -04:00
parent ac27e69ef9
commit 9d0aa13991
13 changed files with 472 additions and 60 deletions

View file

@ -52,13 +52,34 @@ class BadDevice : public FunctionalMemory
public: public:
/** /**
* The default constructor. * Constructor for the Baddev Class.
* @param name name of the object
* @param a base address of the write
* @param mmu the memory controller
* @param devicename device that is not implemented
*/ */
BadDevice(const std::string &name, Addr a, MemoryController *mmu, BadDevice(const std::string &name, Addr a, MemoryController *mmu,
const std::string &devicename); const std::string &devicename);
/**
* On a read event we just panic aand hopefully print a
* meaningful error message.
* @param req Contains the address to read from.
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Fault read(MemReqPtr &req, uint8_t *data);
/**
* On a write event we just panic aand hopefully print a
* meaningful error message.
* @param req Contains the address to write to.
* @param data The data to write.
* @return The fault condition of the access.
*/
virtual Fault write(MemReqPtr &req, const uint8_t *data); virtual Fault write(MemReqPtr &req, const uint8_t *data);
/** @todo add serialize/unserialize */
}; };
#endif // __BADDEV_HH__ #endif // __BADDEV_HH__

View file

@ -37,8 +37,8 @@
#include "mem/functional_mem/functional_memory.hh" #include "mem/functional_mem/functional_memory.hh"
#include "dev/pcireg.h" #include "dev/pcireg.h"
#define MAX_PCI_DEV 32 static const uint32_t MAX_PCI_DEV = 32;
#define MAX_PCI_FUNC 8 static const uint32_t MAX_PCI_FUNC = 8;
class PciDev; class PciDev;
@ -55,22 +55,72 @@ class PciConfigAll : public FunctionalMemory
Addr addr; Addr addr;
static const Addr size = 0xffffff; static const Addr size = 0xffffff;
public:
/** /**
* Pointers to all the devices that are registered with this * Pointers to all the devices that are registered with this
* particular config space. * particular config space.
*/ */
PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC]; PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC];
public:
/** /**
* The default constructor. * Constructor for PCIConfigAll
* @param name name of the object
* @param a base address of the write
* @param mmu the memory controller
*/ */
PciConfigAll(const std::string &name, Addr a, MemoryController *mmu); PciConfigAll(const std::string &name, Addr a, MemoryController *mmu);
/**
* Check if a device exists.
* @param pcidev PCI device to check
* @param pcifunc PCI function to check
* @return true if device exists, false otherwise
*/
bool deviceExists(uint32_t pcidev, uint32_t pcifunc)
{ return devices[pcidev][pcifunc] != NULL ? true : false; }
/**
* Registers a device with the config space object.
* @param pcidev PCI device to register
* @param pcifunc PCI function to register
* @param device device to register
*/
void registerDevice(uint8_t pcidev, uint8_t pcifunc, PciDev *device)
{ devices[pcidev][pcifunc] = device; }
/**
* Read something in PCI config space. If the device does not exist
* -1 is returned, if the device does exist its PciDev::ReadConfig (or the
* virtual function that overrides) it is called.
* @param req Contains the address of the field to read.
* @param data Return the field read.
* @return The fault condition of the access.
*/
virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Fault read(MemReqPtr &req, uint8_t *data);
/**
* Write to PCI config spcae. If the device does not exit the simulator
* panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
* function that overrides it).
* @param req Contains the address to write to.
* @param data The data to write.
* @return The fault condition of the access.
*/
virtual Fault write(MemReqPtr &req, const uint8_t *data); virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };

View file

@ -64,10 +64,10 @@ PciDev::PciDev(const string &name, MemoryController *mmu, PciConfigAll *cf,
panic("NULL pointer to configuration data"); panic("NULL pointer to configuration data");
// Setup pointer in config space to point to this entry // Setup pointer in config space to point to this entry
if (cf->devices[dev][func] != NULL) if (cf->deviceExists(dev,func))
panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func); panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func);
else else
cf->devices[dev][func] = this; cf->registerDevice(dev, func, this);
} }
void void

View file

@ -39,9 +39,17 @@
class PciConfigAll; class PciConfigAll;
class MemoryController; class MemoryController;
/**
* This class encapulates the first 64 bytes of a singles PCI
* devices config space that in configured by the configuration file.
*/
class PciConfigData : public SimObject class PciConfigData : public SimObject
{ {
public: public:
/**
* Constructor to initialize the devices config space to 0.
*/
PciConfigData(const std::string &name) PciConfigData(const std::string &name)
: SimObject(name) : SimObject(name)
{ {
@ -50,8 +58,13 @@ class PciConfigData : public SimObject
memset(BARSize, 0, sizeof(BARSize)); memset(BARSize, 0, sizeof(BARSize));
} }
/** The first 64 bytes */
PCIConfig config; PCIConfig config;
/** The size of the BARs */
uint32_t BARSize[6]; uint32_t BARSize[6];
/** The addresses of the BARs */
Addr BARAddrs[6]; Addr BARAddrs[6];
}; };
@ -66,17 +79,50 @@ class PciDev : public DmaDevice
{ {
protected: protected:
MemoryController *mmu; MemoryController *mmu;
/** A pointer to the configspace all object that calls
* us when a read comes to this particular device/function.
*/
PciConfigAll *configSpace; PciConfigAll *configSpace;
/**
* A pointer to the object that contains the first 64 bytes of
* config space
*/
PciConfigData *configData; PciConfigData *configData;
/** The bus number we are on */
uint32_t busNum; uint32_t busNum;
/** The device number we have */
uint32_t deviceNum; uint32_t deviceNum;
/** The function number */
uint32_t functionNum; uint32_t functionNum;
/** The current config space. Unlike the PciConfigData this is updated
* during simulation while continues to refelect what was in the config file.
*/
PCIConfig config; PCIConfig config;
/** The size of the BARs */
uint32_t BARSize[6]; uint32_t BARSize[6];
/** The current address mapping of the BARs */
Addr BARAddrs[6]; Addr BARAddrs[6];
public: public:
/**
* Constructor for PCI Dev. This function copies data from the config file
* object PCIConfigData and registers the device with a PciConfigAll object.
* @param name name of the object
* @param mmu a pointer to the memory controller
* @param cf a pointer to the config space object that this device need to
* register with
* @param cd A pointer to the config space values specified in the conig file
* @param bus the bus this device is on
* @param dev the device id of this device
* @param func the function number of this device
*/
PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf, PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf,
PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func); PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func);
@ -87,10 +133,38 @@ class PciDev : public DmaDevice
return No_Fault; return No_Fault;
} }
/**
* Write to the PCI config space data that is stored locally. This may be
* overridden by the device but at some point it will eventually call this
* for normal operations that it does not need to override.
* @param offset the offset into config space
* @param size the size of the write
* @param data the data to write
*/
virtual void WriteConfig(int offset, int size, uint32_t data); virtual void WriteConfig(int offset, int size, uint32_t data);
/**
* Read from the PCI config space data that is stored locally. This may be
* overridden by the device but at some point it will eventually call this
* for normal operations that it does not need to override.
* @param offset the offset into config space
* @param size the size of the read
* @param data pointer to the location where the read value should be stored
*/
virtual void ReadConfig(int offset, int size, uint8_t *data); virtual void ReadConfig(int offset, int size, uint8_t *data);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };

View file

@ -95,10 +95,27 @@ class Tsunami : public Platform
Tsunami(const std::string &name, System *s, IntrControl *intctrl, Tsunami(const std::string &name, System *s, IntrControl *intctrl,
PciConfigAll *pci, int intrFreq); PciConfigAll *pci, int intrFreq);
/**
* Cause the cpu to post a serial interrupt to the CPU.
*/
virtual void postConsoleInt(); virtual void postConsoleInt();
/**
* Clear a posted CPU interrupt (id=55)
*/
virtual void clearConsoleInt(); virtual void clearConsoleInt();
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };

View file

@ -42,7 +42,10 @@
class TsunamiCChip : public FunctionalMemory class TsunamiCChip : public FunctionalMemory
{ {
private: private:
/** The base address of this device */
Addr addr; Addr addr;
/** The size of mappad from the above address */
static const Addr size = 0xfff; static const Addr size = 0xfff;
protected: protected:
@ -72,23 +75,75 @@ class TsunamiCChip : public FunctionalMemory
*/ */
uint64_t drir; uint64_t drir;
/**
* The MISC register contains the CPU we are currently on
* as well as bits to ack RTC and IPI interrupts.
*/
uint64_t misc; uint64_t misc;
/** Count of the number of pending IPIs on a CPU */
uint64_t ipiInterrupting[Tsunami::Max_CPUs]; uint64_t ipiInterrupting[Tsunami::Max_CPUs];
/** Indicator of which CPUs have had an RTC interrupt */
bool RTCInterrupting[Tsunami::Max_CPUs]; bool RTCInterrupting[Tsunami::Max_CPUs];
public: public:
/**
* Initialize the Tsunami CChip by setting all of the
* device register to 0.
* @param name name of this device.
* @param t pointer back to the Tsunami object that we belong to.
* @param a address we are mapped at.
* @param mmu pointer to the memory controller that sends us events.
*/
TsunamiCChip(const std::string &name, Tsunami *t, Addr a, TsunamiCChip(const std::string &name, Tsunami *t, Addr a,
MemoryController *mmu); MemoryController *mmu);
/**
* Process a read to the CChip.
* @param req Contains the address to read from.
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Fault read(MemReqPtr &req, uint8_t *data);
/**
* Process a write to the CChip.
* @param req Contains the address to write to.
* @param data The data to write.
* @return The fault condition of the access.
*/
virtual Fault write(MemReqPtr &req, const uint8_t *data); virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
* post an RTC interrupt to the CPU
*/
void postRTC(); void postRTC();
/**
* post an interrupt to the CPU.
* @param interrupt the interrupt number to post (0-64)
*/
void postDRIR(uint32_t interrupt); void postDRIR(uint32_t interrupt);
/**
* clear an interrupt previously posted to the CPU.
* @param interrupt the interrupt number to post (0-64)
*/
void clearDRIR(uint32_t interrupt); void clearDRIR(uint32_t interrupt);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };

View file

@ -33,78 +33,145 @@
#ifndef __TSUNAMI_DMA_HH__ #ifndef __TSUNAMI_DMA_HH__
#define __TSUNAMI_DMA_HH__ #define __TSUNAMI_DMA_HH__
#define RTC_RATE 1024
#include "mem/functional_mem/functional_memory.hh" #include "mem/functional_mem/functional_memory.hh"
#include "dev/tsunami.hh" #include "dev/tsunami.hh"
/** How often the RTC interrupts */
static const int RTC_RATE = 1024;
/* /*
* Tsunami I/O device * Tsunami I/O device is a catch all for all the south bridge stuff we care
* to implement.
*/ */
class TsunamiIO : public FunctionalMemory class TsunamiIO : public FunctionalMemory
{ {
private: private:
/** The base address of this device */
Addr addr; Addr addr;
/** The size of mappad from the above address */
static const Addr size = 0xff; static const Addr size = 0xff;
struct tm tm; struct tm tm;
// In Tsunami RTC only has two i/o ports /** In Tsunami RTC only has two i/o ports one for data and one for address,
// one for data and one for address, so you * so you write the address and then read/write the data. This store the
// write the address and then read/write the data * address you are going to be reading from on a read.
*/
uint8_t RTCAddress; uint8_t RTCAddress;
protected: protected:
/**
* The ClockEvent is handles the PIT interrupts
*/
class ClockEvent : public Event class ClockEvent : public Event
{ {
protected: protected:
/** how often the PIT fires */
Tick interval; Tick interval;
/** The mode of the PIT */
uint8_t mode; uint8_t mode;
/** The status of the PIT */
uint8_t status; uint8_t status;
public: public:
/**
* Just set the mode to 0
*/
ClockEvent(); ClockEvent();
/**
* processs the timer event
*/
virtual void process(); virtual void process();
/**
* Returns a description of this event
* @return the description
*/
virtual const char *description(); virtual const char *description();
/**
* Schedule a timer interrupt to occur sometime in the future.
*/
void Program(int count); void Program(int count);
/**
* Write the mode bits of the PIT.
* @param mode the new mode
*/
void ChangeMode(uint8_t mode); void ChangeMode(uint8_t mode);
/**
* The current PIT status.
* @return the status of the PIT
*/
uint8_t Status(); uint8_t Status();
}; };
/**
* Process RTC timer events and generate interrupts appropriately.
*/
class RTCEvent : public Event class RTCEvent : public Event
{ {
protected: protected:
/** A pointer back to tsunami to create interrupt the processor. */
Tsunami* tsunami; Tsunami* tsunami;
public: public:
/** RTC Event initializes the RTC event by scheduling an event
* RTC_RATE times pre second. */
RTCEvent(Tsunami* t); RTCEvent(Tsunami* t);
/**
* Interrupth the processor and reschedule the event.
* */
virtual void process(); virtual void process();
/**
* Return a description of this event.
* @return a description
*/
virtual const char *description(); virtual const char *description();
}; };
/** uip UpdateInProgess says that the rtc is updating, but we just fake it
* by alternating it on every read of the bit since we are going to
* override the loop_per_jiffy time that it is trying to use the UIP to
* calculate.
*/
uint8_t uip; uint8_t uip;
/** Mask of the PIC1 */
uint8_t mask1; uint8_t mask1;
/** Mask of the PIC2 */
uint8_t mask2; uint8_t mask2;
/** Mode of PIC1. Not used for anything */
uint8_t mode1; uint8_t mode1;
/** Mode of PIC2. Not used for anything */
uint8_t mode2; uint8_t mode2;
uint8_t picr; //Raw PIC interrput register, before masking /** Raw PIC interrupt register before masking */
uint8_t picr; //Raw PIC interrput register
/** Is the pic interrupting right now or not. */
bool picInterrupting; bool picInterrupting;
/** A pointer to the Tsunami device which be belong to */
Tsunami *tsunami; Tsunami *tsunami;
/* /**
* This timer is initilized, but after I wrote the code * This timer is initilized, but after I wrote the code
* it doesn't seem to be used again, and best I can tell * it doesn't seem to be used again, and best I can tell
* it too is not connected to any interrupt port * it too is not connected to any interrupt port
*/ */
ClockEvent timer0; ClockEvent timer0;
/* /**
* This timer is used to control the speaker, which * This timer is used to control the speaker, which
* we normally could care less about, however it is * we normally could care less about, however it is
* also used to calculated the clockspeed and hense * also used to calculated the clockspeed and hense
@ -114,26 +181,77 @@ class TsunamiIO : public FunctionalMemory
*/ */
ClockEvent timer2; ClockEvent timer2;
/** This is the event used to interrupt the cpu like an RTC. */
RTCEvent rtc; RTCEvent rtc;
/** The interval is set via two writes to the PIT.
* This variable contains a flag as to how many writes have happened, and
* the time so far.
*/
uint32_t timerData; uint32_t timerData;
public: public:
/** Return the freqency of the RTC */
uint32_t frequency() const { return RTC_RATE; } uint32_t frequency() const { return RTC_RATE; }
/**
* Initialize all the data for devices supported by Tsunami I/O.
* @param name name of this device.
* @param t pointer back to the Tsunami object that we belong to.
* @param init_time Time (as in seconds since 1970) to set RTC to.
* @param a address we are mapped at.
* @param mmu pointer to the memory controller that sends us events.
*/
TsunamiIO(const std::string &name, Tsunami *t, time_t init_time, TsunamiIO(const std::string &name, Tsunami *t, time_t init_time,
Addr a, MemoryController *mmu); Addr a, MemoryController *mmu);
/**
* Create the tm struct from seconds since 1970
*/
void set_time(time_t t); void set_time(time_t t);
/**
* Process a read to one of the devices we are emulating.
* @param req Contains the address to read from.
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Fault read(MemReqPtr &req, uint8_t *data);
/**
* Process a write to one of the devices we emulate.
* @param req Contains the address to write to.
* @param data The data to write.
* @return The fault condition of the access.
*/
virtual Fault write(MemReqPtr &req, const uint8_t *data); virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
* Post an PIC interrupt to the CPU via the CChip
* @param bitvector interrupt to post.
*/
void postPIC(uint8_t bitvector); void postPIC(uint8_t bitvector);
/**
* Clear a posted interrupt
* @param bitvector interrupt to clear
*/
void clearPIC(uint8_t bitvector); void clearPIC(uint8_t bitvector);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };

View file

@ -47,8 +47,6 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
req->vaddr, req->size); req->vaddr, req->size);
Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
// ExecContext *xc = req->xc;
// int cpuid = xc->cpu_id;
switch (req->size) { switch (req->size) {

View file

@ -42,28 +42,75 @@
class TsunamiPChip : public FunctionalMemory class TsunamiPChip : public FunctionalMemory
{ {
private: private:
/** The base address of this device */
Addr addr; Addr addr;
/** The size of mappad from the above address */
static const Addr size = 0xfff; static const Addr size = 0xfff;
protected: protected:
/**
* pointer to the tsunami object.
* This is our access to all the other tsunami
* devices.
*/
Tsunami *tsunami; Tsunami *tsunami;
/** Window Base addresses */
uint64_t wsba[4]; uint64_t wsba[4];
/** Window masks */
uint64_t wsm[4]; uint64_t wsm[4];
/** Translated Base Addresses */
uint64_t tba[4]; uint64_t tba[4];
public: public:
/**
* Register the PChip with the mmu and init all wsba, wsm, and tba to 0
* @param name the name of thes device
* @param t a pointer to the tsunami device
* @param a the address which we respond to
* @param mmu the mmu we are to register with
*/
TsunamiPChip(const std::string &name, Tsunami *t, Addr a, TsunamiPChip(const std::string &name, Tsunami *t, Addr a,
MemoryController *mmu); MemoryController *mmu);
// @todo This hack does a quick and dirty translation of the PCI bus address to /**
// a valid DMA address. This is described in 10-10 of the Tsunami book, should be fixed * Translate a PCI bus address to a memory address for DMA.
* @todo Andrew says this needs to be fixed. What's wrong with it?
* @param busAddr PCI address to translate.
* @return memory system address
*/
Addr translatePciToDma(Addr busAddr); Addr translatePciToDma(Addr busAddr);
/**
* Process a read to the PChip.
* @param req Contains the address to read from.
* @param data A pointer to write the read data to.
* @return The fault condition of the access.
*/
virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Fault read(MemReqPtr &req, uint8_t *data);
/**
* Process a write to the PChip.
* @param req Contains the address to write to.
* @param data The data to write.
* @return The fault condition of the access.
*/
virtual Fault write(MemReqPtr &req, const uint8_t *data); virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };

View file

@ -30,7 +30,7 @@
namespace { namespace {
const char * const char *
standard_strings[SystemCalls<Linux>::StandardNumber] = { standard_strings[SystemCalls<Linux>::Number] = {
"llseek", //0 "llseek", //0
@ -367,9 +367,7 @@ namespace {
const char * const char *
SystemCalls<Linux>::name(int num) SystemCalls<Linux>::name(int num)
{ {
if (num >= StandardNumber) if ((num >= 0) && (num < Number))
return 0;
else if (num >= 0)
return standard_strings[num]; return standard_strings[num];
else else
return 0; return 0;

View file

@ -308,24 +308,15 @@ struct SystemCalls<Linux>
waitpid = 270, waitpid = 270,
write = 271, write = 271,
writev = 272, writev = 272,
StandardNumber Number
}; };
static const int Number = StandardNumber;
static const char *name(int num); static const char *name(int num);
static bool validSyscallNumber(int num) { static bool validSyscallNumber(int num) {
return num < StandardNumber; return num < Number;
} }
/* why does this exist, I don't think it is needed for linux */
static int convert(int syscall_num) {
if (!validSyscallNumber(syscall_num))
return -1;
return syscall_num ;
}
}; };
#endif // __LINUX_SYSCALLS_HH__ #endif // __LINUX_SYSCALLS_HH__

View file

@ -26,6 +26,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**
* @file
* linux_system.cc loads the linux kernel, console, pal and patches certain functions.
* The symbol tables are loaded so that traces can show the executing function and we can
* skip functions. Various delay loops are skipped and their final values manually computed to
* speed up boot time.
*/
#include "base/loader/aout_object.hh" #include "base/loader/aout_object.hh"
#include "base/loader/elf_object.hh" #include "base/loader/elf_object.hh"
#include "base/loader/object_file.hh" #include "base/loader/object_file.hh"
@ -36,6 +44,7 @@
#include "cpu/base_cpu.hh" #include "cpu/base_cpu.hh"
#include "kern/linux/linux_events.hh" #include "kern/linux/linux_events.hh"
#include "kern/linux/linux_system.hh" #include "kern/linux/linux_system.hh"
#include "kern/system_events.hh"
#include "mem/functional_mem/memory_control.hh" #include "mem/functional_mem/memory_control.hh"
#include "mem/functional_mem/physical_memory.hh" #include "mem/functional_mem/physical_memory.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
@ -58,6 +67,9 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
kernelSymtab = new SymbolTable; kernelSymtab = new SymbolTable;
consoleSymtab = new SymbolTable; consoleSymtab = new SymbolTable;
/**
* Load the kernel, pal, and console code into memory
*/
// Load kernel code // Load kernel code
ObjectFile *kernel = createObjectFile(kernel_path); ObjectFile *kernel = createObjectFile(kernel_path);
if (kernel == NULL) if (kernel == NULL)
@ -107,16 +119,22 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
#endif #endif
skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue, skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue,
"ide_delay_50ms"); "ide_delay_50ms");
skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
"calibrate_delay"); "calibrate_delay");
skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches"); skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue,
"determine_cpu_caches");
Addr addr = 0; Addr addr = 0;
/**
* find the address of the est_cycle_freq variable and insert it so we don't
* through the lengthly process of trying to calculated it by using the PIT,
* RTC, etc.
*/
if (kernelSymtab->findAddress("est_cycle_freq", addr)) { if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
Addr paddr = vtophys(physmem, addr); Addr paddr = vtophys(physmem, addr);
uint8_t *est_cycle_frequency = uint8_t *est_cycle_frequency =
@ -127,6 +145,11 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
} }
/**
* Copy the osflags (kernel arguments) into the consoles memory. Presently
* Linux does use the console service routine to get these command line
* arguments, but we might as well make them available just in case.
*/
if (consoleSymtab->findAddress("env_booted_osflags", addr)) { if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
Addr paddr = vtophys(physmem, addr); Addr paddr = vtophys(physmem, addr);
char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
@ -135,6 +158,10 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
strcpy(osflags, boot_osflags.c_str()); strcpy(osflags, boot_osflags.c_str());
} }
/**
* Since we aren't using a bootloader, we have to copy the kernel arguments
* directly into the kernels memory.
*/
{ {
Addr paddr = vtophys(physmem, PARAM_ADDR); Addr paddr = vtophys(physmem, PARAM_ADDR);
char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t)); char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t));
@ -143,13 +170,17 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
} }
/**
* Set the hardware reset parameter block system type and revision information
* to Tsunami.
*/
if (consoleSymtab->findAddress("xxm_rpb", addr)) { if (consoleSymtab->findAddress("xxm_rpb", addr)) {
Addr paddr = vtophys(physmem, addr); Addr paddr = vtophys(physmem, addr);
char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
if (hwprb) { if (hwprb) {
*(uint64_t*)(hwprb+0x50) = 34; // Tsunami *(uint64_t*)(hwprb+0x50) = 34; // Tsunami
*(uint64_t*)(hwprb+0x58) = (1<<10); *(uint64_t*)(hwprb+0x58) = (1<<10); // Plain DP264
} }
else else
panic("could not translate hwprb addr to set system type/variation\n"); panic("could not translate hwprb addr to set system type/variation\n");
@ -167,14 +198,20 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
consolePanicEvent->schedule(addr); consolePanicEvent->schedule(addr);
#endif #endif
/**
* Any time ide_delay_50ms, calibarte_delay or determine_cpu_caches is called
* just skip the function. Currently determine_cpu_caches only is used put
* information in proc, however if that changes in the future we will have to
* fill in the cache size variables appropriately.
*/
if (kernelSymtab->findAddress("ide_delay_50ms", addr)) if (kernelSymtab->findAddress("ide_delay_50ms", addr))
skipIdeDelay50msEvent->schedule(addr+8); skipIdeDelay50msEvent->schedule(addr+sizeof(MachInst));
if (kernelSymtab->findAddress("calibrate_delay", addr)) if (kernelSymtab->findAddress("calibrate_delay", addr))
skipDelayLoopEvent->schedule(addr+8); skipDelayLoopEvent->schedule(addr+sizeof(MachInst));
if (kernelSymtab->findAddress("determine_cpu_caches", addr)) if (kernelSymtab->findAddress("determine_cpu_caches", addr))
skipCacheProbeEvent->schedule(addr+8); skipCacheProbeEvent->schedule(addr+sizeof(MachInst));
} }
LinuxSystem::~LinuxSystem() LinuxSystem::~LinuxSystem()
@ -224,7 +261,11 @@ LinuxSystem::registerExecContext(ExecContext *xc)
RemoteGDB *rgdb = new RemoteGDB(this, xc); RemoteGDB *rgdb = new RemoteGDB(this, xc);
GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
gdbl->listen(); gdbl->listen();
// gdbl->accept(); /**
* Uncommenting this line waits for a remote debugger to connect
* to the simulator before continuing.
*/
//gdbl->accept();
if (remoteGDB.size() <= xcIndex) { if (remoteGDB.size() <= xcIndex) {
remoteGDB.resize(xcIndex+1); remoteGDB.resize(xcIndex+1);

View file

@ -37,6 +37,10 @@
#include <map> #include <map>
/**
* MAGIC address where the kernel arguments should go. Defined as
* PARAM in linux kernel alpha-asm.
*/
const Addr PARAM_ADDR = ULL(0xfffffc000030a000); const Addr PARAM_ADDR = ULL(0xfffffc000030a000);
class ExecContext; class ExecContext;
@ -44,15 +48,16 @@ class ElfObject;
class SymbolTable; class SymbolTable;
class BreakPCEvent; class BreakPCEvent;
class LinuxBadAddrEvent;
class LinuxSkipFuncEvent;
class LinuxSkipDelayLoopEvent; class LinuxSkipDelayLoopEvent;
class LinuxSkipIdeDelay50msEvent; class SkipFuncEvent;
class LinuxPrintfEvent;
class LinuxDebugPrintfEvent;
class FnEvent; class FnEvent;
class AlphaArguments; class AlphaArguments;
/**
* This class contains linux specific system code (Loading, Events, Binning).
* It points to objects that are the system binaries to load and patches them
* appropriately to work in simulator.
*/
class LinuxSystem : public System class LinuxSystem : public System
{ {
private: private:
@ -64,12 +69,10 @@ class LinuxSystem : public System
BreakPCEvent *kernelPanicEvent; BreakPCEvent *kernelPanicEvent;
BreakPCEvent *consolePanicEvent; BreakPCEvent *consolePanicEvent;
LinuxSkipFuncEvent *skipCacheProbeEvent; SkipFuncEvent *skipCacheProbeEvent;
LinuxSkipIdeDelay50msEvent *skipIdeDelay50msEvent; SkipFuncEvent *skipIdeDelay50msEvent;
LinuxSkipDelayLoopEvent *skipDelayLoopEvent; LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
private:
Addr kernelStart; Addr kernelStart;
Addr kernelEnd; Addr kernelEnd;
Addr kernelEntry; Addr kernelEntry;
@ -80,7 +83,6 @@ class LinuxSystem : public System
std::vector<RemoteGDB *> remoteGDB; std::vector<RemoteGDB *> remoteGDB;
std::vector<GDBListener *> gdbListen; std::vector<GDBListener *> gdbListen;
public:
LinuxSystem(const std::string _name, LinuxSystem(const std::string _name,
const uint64_t _init_param, const uint64_t _init_param,
MemoryController *_memCtrl, MemoryController *_memCtrl,