diff options
-rw-r--r-- | base/loader/elf_object.cc | 8 | ||||
-rw-r--r-- | cpu/exetrace.cc | 14 | ||||
-rw-r--r-- | dev/alpha_console.cc | 16 | ||||
-rw-r--r-- | dev/alpha_console.hh | 8 | ||||
-rw-r--r-- | dev/baddev.cc | 67 | ||||
-rw-r--r-- | dev/baddev.hh | 64 | ||||
-rw-r--r-- | dev/console.cc | 4 | ||||
-rw-r--r-- | dev/pciconfigall.cc | 192 | ||||
-rw-r--r-- | dev/pciconfigall.hh | 93 | ||||
-rw-r--r-- | dev/pcidev.cc | 387 | ||||
-rw-r--r-- | dev/pcidev.hh | 98 | ||||
-rw-r--r-- | dev/platform.hh | 59 | ||||
-rw-r--r-- | dev/tsunami.cc | 93 | ||||
-rw-r--r-- | dev/tsunami.hh | 108 | ||||
-rw-r--r-- | dev/tsunami_cchip.cc | 322 | ||||
-rw-r--r-- | dev/tsunami_cchip.hh | 92 | ||||
-rw-r--r-- | dev/tsunami_io.cc | 404 | ||||
-rw-r--r-- | dev/tsunami_io.hh | 140 | ||||
-rw-r--r-- | dev/tsunami_pchip.cc | 284 | ||||
-rw-r--r-- | dev/tsunami_pchip.hh | 76 | ||||
-rw-r--r-- | dev/tsunami_uart.cc | 220 | ||||
-rw-r--r-- | dev/tsunami_uart.hh | 68 | ||||
-rw-r--r-- | dev/tsunamireg.h | 110 | ||||
-rw-r--r-- | kern/linux/linux.hh | 34 | ||||
-rw-r--r-- | kern/linux/linux_syscalls.cc | 376 | ||||
-rw-r--r-- | kern/linux/linux_syscalls.hh | 329 | ||||
-rw-r--r-- | kern/linux/linux_system.cc | 732 | ||||
-rw-r--r-- | kern/linux/linux_system.hh | 198 | ||||
-rw-r--r-- | sim/system.hh | 2 |
29 files changed, 4580 insertions, 18 deletions
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc index f2a67f22e..9889b9d4c 100644 --- a/base/loader/elf_object.cc +++ b/base/loader/elf_object.cc @@ -190,7 +190,7 @@ bool ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding) { Elf *elf; - int secidx = 1; // there is a 0 but it is nothing, go figure + int sec_idx = 1; // there is a 0 but it is nothing, go figure Elf_Scn *section; GElf_Shdr shdr; Elf_Data *data; @@ -210,7 +210,7 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding) assert(elf != NULL); // Get the first section - section = elf_getscn(elf, secidx); + section = elf_getscn(elf, sec_idx); // While there are no more sections while (section != NULL) { @@ -231,8 +231,8 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding) } } } - ++secidx; - section = elf_getscn(elf, secidx); + ++sec_idx; + section = elf_getscn(elf, sec_idx); } elf_end(elf); diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc index 3e8877e93..4d3a70f37 100644 --- a/cpu/exetrace.cc +++ b/cpu/exetrace.cc @@ -48,11 +48,12 @@ using namespace std; // -const SymbolTable *debugSymbolTable = NULL; +SymbolTable *debugSymbolTable = NULL; void Trace::InstRecord::dump(ostream &outs) { + if (flags[PRINT_CYCLE]) ccprintf(outs, "%7d: ", cycle); @@ -64,7 +65,16 @@ Trace::InstRecord::dump(ostream &outs) if (flags[PRINT_THREAD_NUM]) outs << "T" << thread << " : "; - outs << "0x" << hex << PC << " : "; + + std::string str; + if(debugSymbolTable->findSymbol(PC, str)) + outs << "@" << setw(17) << str << " : "; + else if(debugSymbolTable->findSymbol(PC - 4, str)) + outs << "@" << setw(15) << str << "+4 : "; + else if(debugSymbolTable->findSymbol(PC - 8, str)) + outs << "@" << setw(15) << str << "+8 : "; + else + outs << "0x" << hex << PC << " : "; // // Print decoded instruction diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index 2dc939b97..ad9d0a239 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -46,12 +46,14 @@ #include "mem/functional_mem/memory_control.hh" #include "sim/builder.hh" #include "sim/system.hh" +#include "dev/tsunami_io.hh" using namespace std; -AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d, - System *system, BaseCPU *cpu, TlaserClock *clock, - int num_cpus, MemoryController *mmu, Addr a) +AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, + SimpleDisk *d, System *system, + BaseCPU *cpu, TsunamiIO *clock, int num_cpus, + Addr a, MemoryController *mmu) : FunctionalMemory(name), disk(d), console(cons), addr(a) { mmu->add_child(this, Range<Addr>(addr, addr + size)); @@ -79,7 +81,7 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data) memset(data, 0, req->size); uint64_t val; - Addr daddr = req->paddr - addr; + Addr daddr = req->paddr - (addr & PA_IMPL_MASK); switch (daddr) { case offsetof(AlphaAccess, inputChar): @@ -127,7 +129,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data) return Machine_Check_Fault; } - Addr daddr = req->paddr - addr; + Addr daddr = req->paddr - (addr & PA_IMPL_MASK); ExecContext *other_xc; switch (daddr) { @@ -250,7 +252,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) Param<Addr> addr; SimObjectParam<System *> system; SimObjectParam<BaseCPU *> cpu; - SimObjectParam<TlaserClock *> clock; + SimObjectParam<TsunamiIO *> clock; END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) @@ -270,7 +272,7 @@ END_INIT_SIM_OBJECT_PARAMS(AlphaConsole) CREATE_SIM_OBJECT(AlphaConsole) { return new AlphaConsole(getInstanceName(), sim_console, disk, - system, cpu, clock, num_cpus, mmu, addr); + system, cpu, clock, num_cpus, addr, mmu); } REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole) diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh index 54a2af6d5..d0fa552af 100644 --- a/dev/alpha_console.hh +++ b/dev/alpha_console.hh @@ -37,6 +37,7 @@ #include "dev/alpha_access.h" #include "mem/functional_mem/functional_memory.hh" #include "sim/host.hh" +#include "dev/tsunami_io.hh" class BaseCPU; class SimConsole; @@ -88,9 +89,10 @@ class AlphaConsole : public FunctionalMemory public: /** Standard Constructor */ - AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d, - System *system, BaseCPU *cpu, TlaserClock *clock, - int num_cpus, MemoryController *mmu, Addr addr); + AlphaConsole(const std::string &name, SimConsole *cons, + SimpleDisk *d, System *system, BaseCPU *cpu, + TsunamiIO *clock, int num_cpus, + Addr a, MemoryController *mmu); /** * memory mapped reads and writes diff --git a/dev/baddev.cc b/dev/baddev.cc new file mode 100644 index 000000000..8a5d68533 --- /dev/null +++ b/dev/baddev.cc @@ -0,0 +1,67 @@ +/* $Id$ */ + +/* @file + * BadDevice implemenation + */ + +#include <deque> +#include <string> +#include <vector> + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "dev/scsi_ctrl.hh" +#include "dev/baddev.hh" +#include "dev/tsunamireg.h" +#include "dev/tsunami.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "sim/system.hh" + +using namespace std; + +BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu, + const string &devicename) + : FunctionalMemory(name), addr(a), devname(devicename) +{ + mmu->add_child(this, Range<Addr>(addr, addr + size)); +} + +Fault +BadDevice::read(MemReqPtr &req, uint8_t *data) +{ + + panic("Device %s not imlpmented\n", devname); + return No_Fault; +} + +Fault +BadDevice::write(MemReqPtr &req, const uint8_t *data) +{ + panic("Device %s not imlpmented\n", devname); + return No_Fault; +} + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice) + + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + Param<string> devicename; + +END_DECLARE_SIM_OBJECT_PARAMS(BadDevice) + +BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice) + + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address"), + INIT_PARAM(devicename, "Name of device to error on") + +END_INIT_SIM_OBJECT_PARAMS(BadDevice) + +CREATE_SIM_OBJECT(BadDevice) +{ + return new BadDevice(getInstanceName(), addr, mmu, devicename); +} + +REGISTER_SIM_OBJECT("BadDevice", BadDevice) diff --git a/dev/baddev.hh b/dev/baddev.hh new file mode 100644 index 000000000..ed896d792 --- /dev/null +++ b/dev/baddev.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * This devices just panics when touched. For example if you have a + * kernel that touches the frame buffer which isn't allowed. + */ + +#ifndef __BADDEV_HH__ +#define __BADDEV_HH__ + +#include "mem/functional_mem/functional_memory.hh" + +/** + * BadDevice + * This device just panics when accessed. It is supposed to warn + * the user that the kernel they are running has unsupported + * options (i.e. frame buffer) + */ +class BadDevice : public FunctionalMemory +{ + private: + Addr addr; + static const Addr size = 0xf; + + std::string devname; + + public: + /** + * The default constructor. + */ + BadDevice(const std::string &name, Addr a, MemoryController *mmu, + const std::string &devicename); + + virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Fault write(MemReqPtr &req, const uint8_t *data); +}; + +#endif // __BADDEV_HH__ diff --git a/dev/console.cc b/dev/console.cc index 5e7b0abf6..fb74c388a 100644 --- a/dev/console.cc +++ b/dev/console.cc @@ -413,8 +413,8 @@ CREATE_SIM_OBJECT(SimConsole) SimConsole *console = new SimConsole(getInstanceName(), filename, number); ((ConsoleListener *)listener)->add(console); ((SimConsole *)console)->initInt(intr_control); - ((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt | - SimConsole::ReceiveInterrupt); +// ((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt | +// SimConsole::ReceiveInterrupt); return console; } diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc new file mode 100644 index 000000000..63943c7be --- /dev/null +++ b/dev/pciconfigall.cc @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * PCI Configspace implementation + */ + +#include <deque> +#include <string> +#include <vector> + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "dev/scsi_ctrl.hh" +#include "dev/pciconfigall.hh" +#include "dev/pcidev.hh" +#include "dev/tsunamireg.h" +#include "dev/tsunami.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "sim/system.hh" + +using namespace std; + +PCIConfigAll::PCIConfigAll(const string &name, Tsunami *t, Addr a, + MemoryController *mmu) + : FunctionalMemory(name), addr(a), tsunami(t) +{ + mmu->add_child(this, Range<Addr>(addr, addr + size)); + + // Put back pointer in tsunami + tsunami->pciconfig = this; + + // Make all the pointers to devices null + for(int x=0; x < MAX_PCI_DEV; x++) + for(int y=0; y < MAX_PCI_FUNC; y++) + devices[x][y] = NULL; +} + +Fault +PCIConfigAll::read(MemReqPtr &req, uint8_t *data) +{ + DPRINTF(PCIConfigAll, "read va=%#x size=%d\n", + req->vaddr, req->size); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + + int device = (daddr >> 11) & 0x1F; + int func = (daddr >> 8) & 0x7; + int reg = daddr & 0xFF; + + if (devices[device][func] == NULL) { + switch (req->size) { + // case sizeof(uint64_t): + // *(uint64_t*)data = 0xFFFFFFFFFFFFFFFF; + // return No_Fault; + case sizeof(uint32_t): + *(uint32_t*)data = 0xFFFFFFFF; + return No_Fault; + case sizeof(uint16_t): + *(uint16_t*)data = 0xFFFF; + return No_Fault; + case sizeof(uint8_t): + *(uint8_t*)data = 0xFF; + return No_Fault; + default: + panic("invalid access size(?) for PCI configspace!\n"); + } + } else { + switch (req->size) { + case sizeof(uint32_t): + case sizeof(uint16_t): + case sizeof(uint8_t): + devices[device][func]->ReadConfig(reg, req->size, data); + return No_Fault; + default: + panic("invalid access size(?) for PCI configspace!\n"); + } + } + + DPRINTFN("Tsunami PCI Configspace ERROR: read daddr=%#x size=%d\n", + daddr, req->size); + + return No_Fault; +} + +Fault +PCIConfigAll::write(MemReqPtr &req, const uint8_t *data) +{ + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + + int device = (daddr >> 11) & 0x1F; + int func = (daddr >> 8) & 0x7; + int reg = daddr & 0xFF; + + union { + uint8_t byte_value; + uint16_t half_value; + uint32_t word_value; + }; + + if (devices[device][func] == NULL) + panic("Attempting to write to config space on non-existant device\n"); + else { + switch (req->size) { + case sizeof(uint8_t): + byte_value = *(uint8_t*)data; + break; + case sizeof(uint16_t): + half_value = *(uint16_t*)data; + break; + case sizeof(uint32_t): + word_value = *(uint32_t*)data; + break; + default: + panic("invalid access size(?) for PCI configspace!\n"); + } + } + + DPRINTF(PCIConfigAll, "write - va=%#x size=%d data=%#x\n", + req->vaddr, req->size, word_value); + + devices[device][func]->WriteConfig(reg, req->size, word_value); + + return No_Fault; +} + +void +PCIConfigAll::serialize(std::ostream &os) +{ + // code should be written +} + +void +PCIConfigAll::unserialize(Checkpoint *cp, const std::string §ion) +{ + //code should be written +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(PCIConfigAll) + + SimObjectParam<Tsunami *> tsunami; + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + Param<Addr> mask; + +END_DECLARE_SIM_OBJECT_PARAMS(PCIConfigAll) + +BEGIN_INIT_SIM_OBJECT_PARAMS(PCIConfigAll) + + INIT_PARAM(tsunami, "Tsunami"), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address"), + INIT_PARAM(mask, "Address Mask") + +END_INIT_SIM_OBJECT_PARAMS(PCIConfigAll) + +CREATE_SIM_OBJECT(PCIConfigAll) +{ + return new PCIConfigAll(getInstanceName(), tsunami, addr, mmu); +} + +REGISTER_SIM_OBJECT("PCIConfigAll", PCIConfigAll) + +#endif // DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh new file mode 100644 index 000000000..95a171c53 --- /dev/null +++ b/dev/pciconfigall.hh @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @todo + * Should derive Tsunami from common platform class so PCI will work with + * multiple platforms + * + * @file + * PCI Config space implementation. + */ + +#ifndef __PCICONFIGALL_HH__ +#define __PCICONFIGALL_HH__ + +#include "mem/functional_mem/functional_memory.hh" +#include "dev/tsunami.hh" +#include "dev/pcireg.h" + +#define MAX_PCI_DEV 32 +#define MAX_PCI_FUNC 8 + +class PciDev; + +/** + * PCI Config Space + * All of PCI config space needs to return -1 on Tsunami, except + * the devices that exist. This device maps the entire bus config + * space and passes the requests on to TsunamiPCIDev devices as + * appropriate. + */ +class PCIConfigAll : public FunctionalMemory +{ + private: + Addr addr; + static const Addr size = 0xffffff; + + protected: + + /** + * Pointer to the Tsunmi Object so we can communicate + * to other Tsunami devices in need be. + * @todo Make this more generic for multiple platforms + */ + Tsunami *tsunami; + + public: + /** + * Pointers to all the devices that are registered with this + * particular config space. + */ + PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC]; + + /** + * The default constructor. + */ + PCIConfigAll(const std::string &name, Tsunami *t, Addr a, + MemoryController *mmu); + + virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Fault write(MemReqPtr &req, const uint8_t *data); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +}; + +#endif // __PCICONFIGALL_HH__ diff --git a/dev/pcidev.cc b/dev/pcidev.cc new file mode 100644 index 000000000..c0358cd5a --- /dev/null +++ b/dev/pcidev.cc @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * A single PCI device configuration space entry. + */ + +#include <list> +#include <sstream> +#include <string> +#include <vector> + +#include "base/inifile.hh" +#include "base/misc.hh" +#include "base/str.hh" // for to_number +#include "base/trace.hh" +#include "dev/pciareg.h" +#include "dev/scsi_ctrl.hh" +#include "dev/pcidev.hh" +#include "dev/pciconfigall.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "sim/param.hh" +#include "sim/universe.hh" +#include "dev/tsunamireg.h" + +using namespace std; + +PciDev::PciDev(const string &name, MemoryController *mmu, PCIConfigAll *cf, + PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func) + : FunctionalMemory(name), MMU(mmu), ConfigSpace(cf), ConfigData(cd), + Bus(bus), Device(dev), Function(func) +{ + // copy the config data from the PciConfigData object + if (cd) { + memcpy(config.data, cd->config.data, sizeof(config.data)); + memcpy(BARSize, cd->BARSize, sizeof(BARSize)); + memcpy(BARAddrs, cd->BARAddrs, sizeof(BARAddrs)); + } else + panic("NULL pointer to configuration data"); + + // Setup pointer in config space to point to this entry + if (cf->devices[dev][func] != NULL) + panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func); + else + cf->devices[dev][func] = this; +} + +void +PciDev::ReadConfig(int offset, int size, uint8_t *data) +{ + switch(size) { + case sizeof(uint32_t): + memcpy((uint32_t*)data, config.data + offset, sizeof(uint32_t)); + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x data: %#x\n", + Device, Function, offset, *(uint32_t*)(config.data + offset)); + break; + + case sizeof(uint16_t): + memcpy((uint16_t*)data, config.data + offset, sizeof(uint16_t)); + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x data: %#x\n", + Device, Function, offset, *(uint16_t*)(config.data + offset)); + break; + + case sizeof(uint8_t): + memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t)); + printf("data: %#x\n", *(uint8_t*)(config.data + offset)); + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x data: %#x\n", + Device, Function, offset, *(uint8_t*)(config.data + offset)); + break; + + default: + panic("Invalid Read Size"); + } +} + +void +PciDev::WriteConfig(int offset, int size, uint32_t data) +{ + uint32_t barnum; + + union { + uint8_t byte_value; + uint16_t half_value; + uint32_t word_value; + }; + word_value = data; + + DPRINTF(PCIDEV, + "write device: %#x function: %#x reg: %#x size: %#x data: %#x\n", + Device, Function, offset, size, word_value); + + barnum = (offset - PCI0_BASE_ADDR0) >> 2; + + switch (size) { + case sizeof(uint8_t): // 1-byte access + switch (offset) { + case PCI0_INTERRUPT_LINE: + case PCI_CACHE_LINE_SIZE: + case PCI_LATENCY_TIMER: + *(uint8_t *)&config.data[offset] = byte_value; + break; + + default: + panic("writing to a read only register"); + } + break; + + case sizeof(uint16_t): // 2-byte access + switch (offset) { + case PCI_COMMAND: + case PCI_STATUS: + case PCI_CACHE_LINE_SIZE: + *(uint16_t *)&config.data[offset] = half_value; + break; + + default: + panic("writing to a read only register"); + } + break; + + case sizeof(uint16_t)+1: // 3-byte access + panic("invalid access size"); + + case sizeof(uint32_t): // 4-byte access + switch (offset) { + case PCI0_BASE_ADDR0: + case PCI0_BASE_ADDR1: + case PCI0_BASE_ADDR2: + case PCI0_BASE_ADDR3: + case PCI0_BASE_ADDR4: + case PCI0_BASE_ADDR5: + // Writing 0xffffffff to a BAR tells the card to set the + // value of the bar + // to size of memory it needs + if (word_value == 0xffffffff) { + // This is I/O Space, bottom two bits are read only + if (config.data[offset] & 0x1) { + *(uint32_t *)&config.data[offset] = + ~(BARSize[barnum] - 1) | + (config.data[offset] & 0x3); + } else { + // This is memory space, bottom four bits are read only + *(uint32_t *)&config.data[offset] = + ~(BARSize[barnum] - 1) | + (config.data[offset] & 0xF); + } + } else { + // This is I/O Space, bottom two bits are read only + if(config.data[offset] & 0x1) { + *(uint32_t *)&config.data[offset] = (word_value & ~0x3) | + (config.data[offset] & 0x3); + + if (word_value & ~0x1) { + Addr base_addr = (word_value & ~0x1) + TSUNAMI_PCI0_IO; + Addr base_size = BARSize[barnum]-1; + + // It's never been set + if (BARAddrs[barnum] == 0) + MMU->add_child(this, + Range<Addr>(base_addr, + base_addr + base_size)); + else + MMU->update_child(this, + Range<Addr>(BARAddrs[barnum], + BARAddrs[barnum] + + base_size), + Range<Addr>(base_addr, + base_addr + + base_size)); + + BARAddrs[barnum] = base_addr; + } + + } else { + // This is memory space, bottom four bits are read only + *(uint32_t *)&config.data[offset] = (word_value & ~0xF) | + (config.data[offset] & 0xF); + + if (word_value & ~0x3) { + Addr base_addr = (word_value & ~0x3) + + TSUNAMI_PCI0_MEMORY; + + Addr base_size = BARSize[barnum]-1; + + // It's never been set + if (BARAddrs[barnum] == 0) + MMU->add_child(this, + Range<Addr>(base_addr, + base_addr + base_size)); + else + MMU->update_child(this, + Range<Addr>(BARAddrs[barnum], + BARAddrs[barnum] + + base_size), + Range<Addr>(base_addr, + base_addr + + base_size)); + + BARAddrs[barnum] = base_addr; + } + } + } + break; + + case PCI0_ROM_BASE_ADDR: + if (word_value == 0xfffffffe) + *(uint32_t *)&config.data[offset] = 0xffffffff; + else + *(uint32_t *)&config.data[offset] = word_value; + break; + + case PCI_COMMAND: + // This could also clear some of the error bits in the Status + // register. However they should never get set, so lets ignore + // it for now + *(uint16_t *)&config.data[offset] = half_value; + break; + + default: + panic("writing to a read only register"); + } + break; + } +} + +void +PciDev::serialize(ostream &os) +{ + SERIALIZE_ARRAY(config.data, 64); +} + +void +PciDev::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(config.data, 64); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) + + Param<int> VendorID; + Param<int> DeviceID; + Param<int> Command; + Param<int> Status; + Param<int> Revision; + Param<int> ProgIF; + Param<int> SubClassCode; + Param<int> ClassCode; + Param<int> CacheLineSize; + Param<int> LatencyTimer; + Param<int> HeaderType; + Param<int> BIST; + Param<uint32_t> BAR0; + Param<uint32_t> BAR1; + Param<uint32_t> BAR2; + Param<uint32_t> BAR3; + Param<uint32_t> BAR4; + Param<uint32_t> BAR5; + Param<uint32_t> CardbusCIS; + Param<int> SubsystemVendorID; + Param<int> SubsystemID; + Param<uint32_t> ExpansionROM; + Param<int> InterruptLine; + Param<int> InterruptPin; + Param<int> MinimumGrant; + Param<int> MaximumLatency; + Param<uint32_t> BAR0Size; + Param<uint32_t> BAR1Size; + Param<uint32_t> BAR2Size; + Param<uint32_t> BAR3Size; + Param<uint32_t> BAR4Size; + Param<uint32_t> BAR5Size; + +END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) + +BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData) + + INIT_PARAM(VendorID, "Vendor ID"), + INIT_PARAM(DeviceID, "Device ID"), + INIT_PARAM_DFLT(Command, "Command Register", 0x00), + INIT_PARAM_DFLT(Status, "Status Register", 0x00), + INIT_PARAM_DFLT(Revision, "Device Revision", 0x00), + INIT_PARAM_DFLT(ProgIF, "Programming Interface", 0x00), + INIT_PARAM(SubClassCode, "Sub-Class Code"), + INIT_PARAM(ClassCode, "Class Code"), + INIT_PARAM_DFLT(CacheLineSize, "System Cacheline Size", 0x00), + INIT_PARAM_DFLT(LatencyTimer, "PCI Latency Timer", 0x00), + INIT_PARAM_DFLT(HeaderType, "PCI Header Type", 0x00), + INIT_PARAM_DFLT(BIST, "Built In Self Test", 0x00), + INIT_PARAM_DFLT(BAR0, "Base Address Register 0", 0x00), + INIT_PARAM_DFLT(BAR1, "Base Address Register 1", 0x00), + INIT_PARAM_DFLT(BAR2, "Base Address Register 2", 0x00), + INIT_PARAM_DFLT(BAR3, "Base Address Register 3", 0x00), + INIT_PARAM_DFLT(BAR4, "Base Address Register 4", 0x00), + INIT_PARAM_DFLT(BAR5, "Base Address Register 5", 0x00), + INIT_PARAM_DFLT(CardbusCIS, "Cardbus Card Information Structure", 0x00), + INIT_PARAM_DFLT(SubsystemVendorID, "Subsystem Vendor ID", 0x00), + INIT_PARAM_DFLT(SubsystemID, "Subsystem ID", 0x00), + INIT_PARAM_DFLT(ExpansionROM, "Expansion ROM Base Address Register", 0x00), + INIT_PARAM(InterruptLine, "Interrupt Line Register"), + INIT_PARAM(InterruptPin, "Interrupt Pin Register"), + INIT_PARAM_DFLT(MinimumGrant, "Minimum Grant", 0x00), + INIT_PARAM_DFLT(MaximumLatency, "Maximum Latency", 0x00), + INIT_PARAM_DFLT(BAR0Size, "Base Address Register 0 Size", 0x00), + INIT_PARAM_DFLT(BAR1Size, "Base Address Register 1 Size", 0x00), + INIT_PARAM_DFLT(BAR2Size, "Base Address Register 2 Size", 0x00), + INIT_PARAM_DFLT(BAR3Size, "Base Address Register 3 Size", 0x00), + INIT_PARAM_DFLT(BAR4Size, "Base Address Register 4 Size", 0x00), + INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00) + +END_INIT_SIM_OBJECT_PARAMS(PciConfigData) + +CREATE_SIM_OBJECT(PciConfigData) +{ + PciConfigData *data = new PciConfigData(getInstanceName()); + + data->config.hdr.vendor = VendorID; + data->config.hdr.device = DeviceID; + data->config.hdr.command = Command; + data->config.hdr.status = Status; + data->config.hdr.revision = Revision; + data->config.hdr.progIF = ProgIF; + data->config.hdr.subClassCode = SubClassCode; + data->config.hdr.classCode = ClassCode; + data->config.hdr.cacheLineSize = CacheLineSize; + data->config.hdr.latencyTimer = LatencyTimer; + data->config.hdr.headerType = HeaderType; + data->config.hdr.bist = BIST; + + data->config.hdr.pci0.baseAddr0 = BAR0; + data->config.hdr.pci0.baseAddr1 = BAR1; + data->config.hdr.pci0.baseAddr2 = BAR2; + data->config.hdr.pci0.baseAddr3 = BAR3; + data->config.hdr.pci0.baseAddr4 = BAR4; + data->config.hdr.pci0.baseAddr5 = BAR5; + data->config.hdr.pci0.cardbusCIS = CardbusCIS; + data->config.hdr.pci0.subsystemVendorID = SubsystemVendorID; + data->config.hdr.pci0.subsystemID = SubsystemVendorID; + data->config.hdr.pci0.expansionROM = ExpansionROM; + data->config.hdr.pci0.interruptLine = InterruptLine; + data->config.hdr.pci0.interruptPin = InterruptPin; + data->config.hdr.pci0.minimumGrant = MinimumGrant; + data->config.hdr.pci0.maximumLatency = MaximumLatency; + + data->BARSize[0] = BAR0Size; + data->BARSize[1] = BAR1Size; + data->BARSize[2] = BAR2Size; + data->BARSize[3] = BAR3Size; + data->BARSize[4] = BAR4Size; + data->BARSize[5] = BAR5Size; + + return data; +} + +REGISTER_SIM_OBJECT("PciConfigData", PciConfigData) + +#endif // DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pcidev.hh b/dev/pcidev.hh new file mode 100644 index 000000000..dcd3d1b8a --- /dev/null +++ b/dev/pcidev.hh @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * PCI configspace devices + */ + +#ifndef __PCI_DEV_HH__ +#define __PCI_DEV_HH__ + +#include "dev/pcireg.h" +#include "sim/sim_object.hh" +#include "mem/functional_mem/functional_memory.hh" + +class PCIConfigAll; +class MemoryController; + +class PciConfigData : public SimObject +{ + public: + PciConfigData(const std::string &name) + : SimObject(name) + { + memset(config.data, 0, sizeof(config.data)); + memset(BARAddrs, 0, sizeof(BARAddrs)); + memset(BARSize, 0, sizeof(BARSize)); + } + + PCIConfig config; + uint32_t BARSize[6]; + Addr BARAddrs[6]; +}; + +/** + * PCI device, base implemnation is only config space. + * Each device is connected to a PCIConfigSpace device + * which returns -1 for everything but the pcidevs that + * register with it. This object registers with the PCIConfig space + * object. + */ +class PciDev : public FunctionalMemory +{ + protected: + MemoryController *MMU; + PCIConfigAll *ConfigSpace; + PciConfigData *ConfigData; + uint32_t Bus; + uint32_t Device; + uint32_t Function; + + PCIConfig config; + uint32_t BARSize[6]; + Addr BARAddrs[6]; + + public: + PciDev(const std::string &name, MemoryController *mmu, PCIConfigAll *cf, + PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func); + + virtual Fault read(MemReqPtr &req, uint8_t *data) { + return No_Fault; + } + virtual Fault write(MemReqPtr &req, const uint8_t *data) { + return No_Fault; + } + + virtual void WriteConfig(int offset, int size, uint32_t data); + virtual void ReadConfig(int offset, int size, uint8_t *data); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __PCI_DEV_HH__ diff --git a/dev/platform.hh b/dev/platform.hh new file mode 100644 index 000000000..4425570f2 --- /dev/null +++ b/dev/platform.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Generic interface for platforms + */ + +#ifndef __PLATFORM_HH_ +#define __PLATFORM_HH_ + +#include "sim/sim_object.hh" + +class IntrControl; +class SimConsole; + +class Platform : public SimObject +{ + public: + /** Pointer to the interrupt controller */ + IntrControl *intrctrl; + /** Pointer to the simulation console */ + SimConsole *cons; + + int interrupt_frequency; + + public: + Platform(const std::string &name, SimConsole *con, IntrControl *intctrl, + int intrFreq) + : SimObject(name), intrctrl(intctrl), cons(con), + interrupt_frequency(intrFreq) {} +}; + +#endif // __PLATFORM_HH_ diff --git a/dev/tsunami.cc b/dev/tsunami.cc new file mode 100644 index 000000000..04ab922b9 --- /dev/null +++ b/dev/tsunami.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <deque> +#include <string> +#include <vector> + +#include "cpu/intr_control.hh" +#include "dev/console.hh" +#include "dev/etherdev.hh" +#include "dev/adaptec_ctrl.hh" +#include "dev/tlaser_clock.hh" +#include "dev/tsunami_cchip.hh" +#include "dev/tsunami_pchip.hh" +#include "dev/tsunami.hh" +#include "sim/builder.hh" +#include "sim/system.hh" + +using namespace std; + +Tsunami::Tsunami(const string &name, System *s, SimConsole *con, + IntrControl *ic, int intr_freq) + : Platform(name, con, ic, intr_freq), system(s) +{ + // set the back pointer from the system to myself + system->platform = this; + + for (int i = 0; i < Tsunami::Max_CPUs; i++) + intr_sum_type[i] = 0; +} + +void +Tsunami::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs); +} + +void +Tsunami::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs); +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami) + + SimObjectParam<System *> system; + SimObjectParam<SimConsole *> cons; + SimObjectParam<IntrControl *> intrctrl; + Param<int> interrupt_frequency; + +END_DECLARE_SIM_OBJECT_PARAMS(Tsunami) + +BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami) + + INIT_PARAM(system, "system"), + INIT_PARAM(cons, "system console"), + INIT_PARAM(intrctrl, "interrupt controller"), + INIT_PARAM_DFLT(interrupt_frequency, "frequency of interrupts", 1024) + +END_INIT_SIM_OBJECT_PARAMS(Tsunami) + +CREATE_SIM_OBJECT(Tsunami) +{ + return new Tsunami(getInstanceName(), system, cons, intrctrl, + interrupt_frequency); +} + +REGISTER_SIM_OBJECT("Tsunami", Tsunami) diff --git a/dev/tsunami.hh b/dev/tsunami.hh new file mode 100644 index 000000000..ef27ff18e --- /dev/null +++ b/dev/tsunami.hh @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Declaration of top level class for the Tsunami chipset. This class just + * retains pointers to all its children so the children can communicate. + */ + +#ifndef __TSUNAMI_HH__ +#define __TSUNAMI_HH__ + +#include "dev/platform.hh" + +class AdaptecController; +class TlaserClock; +class EtherDev; +class TsunamiCChip; +class TsunamiPChip; +class TsunamiIO; +class PCIConfigAll; +class System; + +/** + * Top level class for Tsunami Chipset emulation. + * This structure just contains pointers to all the + * children so the children can commnicate to do the + * read work + */ + +class Tsunami : public Platform +{ + public: + + /** Max number of CPUs in a Tsunami */ + static const int Max_CPUs = 4; + + /** Pointer to the system */ + System *system; + /** Pointer to the TsunamiIO device which has the RTC */ + TsunamiIO *io; + /** Pointer to the SCSI controller device */ + AdaptecController *scsi; + /** Pointer to the ethernet controller device */ + EtherDev *ethernet; + + /** Pointer to the Tsunami CChip. + * The chip contains some configuration information and + * all the interrupt mask and status registers + */ + TsunamiCChip *cchip; + + /** Pointer to the Tsunami PChip. + * The pchip is the interface to the PCI bus, in our case + * it does not have to do much. + */ + TsunamiPChip *pchip; + + /** Pointer to the PCI Config Space + * The config space in Tsunami all needs to return + * -1 if a device is not there. + */ + PCIConfigAll *pciconfig; + + int intr_sum_type[Tsunami::Max_CPUs]; + int ipi_pending[Tsunami::Max_CPUs]; + + public: + /** + * Constructor for the Tsunami Class. + * @param name name of the object + * @param con pointer to the console + * @param intrcontrol pointer to the interrupt controller + * @param intrFreq frequency that interrupts happen + */ + Tsunami(const std::string &name, System *s, SimConsole *con, + IntrControl *intctrl, int intrFreq); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __TSUNAMI_HH__ diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc new file mode 100644 index 000000000..2d8113491 --- /dev/null +++ b/dev/tsunami_cchip.cc @@ -0,0 +1,322 @@ +/* $Id$ */ + +/* @file + * Emulation of the Tsunami CChip CSRs + */ + +#include <deque> +#include <string> +#include <vector> + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "dev/console.hh" +#include "dev/tsunami_cchip.hh" +#include "dev/tsunamireg.h" +#include "dev/tsunami.hh" +#include "cpu/intr_control.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "sim/system.hh" + +using namespace std; + +TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a, + MemoryController *mmu) + : FunctionalMemory(name), addr(a), tsunami(t) +{ + mmu->add_child(this, Range<Addr>(addr, addr + size)); + + for(int i=0; i < Tsunami::Max_CPUs; i++) { + dim[i] = 0; + dir[i] = 0; + dirInterrupting[i] = false; + } + + drir = 0; + misc = 0; + RTCInterrupting = false; + + //Put back pointer in tsunami + tsunami->cchip = this; +} + +Fault +TsunamiCChip::read(MemReqPtr &req, uint8_t *data) +{ + DPRINTF(Tsunami, "read va=%#x size=%d\n", + req->vaddr, req->size); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + ExecContext *xc = req->xc; + + switch (req->size) { + + case sizeof(uint64_t): + switch(daddr) { + case TSDEV_CC_CSR: + *(uint64_t*)data = 0x0; + return No_Fault; + case TSDEV_CC_MTR: + panic("TSDEV_CC_MTR not implemeted\n"); + return No_Fault; + case TSDEV_CC_MISC: + *(uint64_t*)data = misc | (xc->cpu_id & 0x3); + return No_Fault; + case TSDEV_CC_AAR0: + case TSDEV_CC_AAR1: + case TSDEV_CC_AAR2: + case TSDEV_CC_AAR3: + panic("TSDEV_CC_AARx not implemeted\n"); + return No_Fault; + case TSDEV_CC_DIM0: + *(uint64_t*)data = dim[0]; + return No_Fault; + case TSDEV_CC_DIM1: + *(uint64_t*)data = dim[1]; + return No_Fault; + case TSDEV_CC_DIM2: + *(uint64_t*)data = dim[2]; + return No_Fault; + case TSDEV_CC_DIM3: + *(uint64_t*)data = dim[3]; + return No_Fault; + case TSDEV_CC_DIR0: + *(uint64_t*)data = dir[0]; + return No_Fault; + case TSDEV_CC_DIR1: + *(uint64_t*)data = dir[1]; + return No_Fault; + case TSDEV_CC_DIR2: + *(uint64_t*)data = dir[2]; + return No_Fault; + case TSDEV_CC_DIR3: + *(uint64_t*)data = dir[3]; + return No_Fault; + case TSDEV_CC_DRIR: + *(uint64_t*)data = drir; + return No_Fault; + case TSDEV_CC_PRBEN: + panic("TSDEV_CC_PRBEN not implemented\n"); + return No_Fault; + case TSDEV_CC_IIC0: + case TSDEV_CC_IIC1: + case TSDEV_CC_IIC2: + case TSDEV_CC_IIC3: + panic("TSDEV_CC_IICx not implemented\n"); + return No_Fault; + case TSDEV_CC_MPR0: + case TSDEV_CC_MPR1: + case TSDEV_CC_MPR2: + case TSDEV_CC_MPR3: + panic("TSDEV_CC_MPRx not implemented\n"); + return No_Fault; + default: + panic("default in cchip read reached, accessing 0x%x\n"); + } // uint64_t + + break; + case sizeof(uint32_t): + case sizeof(uint16_t): + case sizeof(uint8_t): + default: + panic("invalid access size(?) for tsunami register!\n"); + } + DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); + + return No_Fault; +} + +Fault +TsunamiCChip::write(MemReqPtr &req, const uint8_t *data) +{ + DPRINTF(Tsunami, "write - va=%#x size=%d \n", + req->vaddr, req->size); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + + switch (req->size) { + + case sizeof(uint64_t): + switch(daddr) { + case TSDEV_CC_CSR: + panic("TSDEV_CC_CSR write\n"); + return No_Fault; + case TSDEV_CC_MTR: + panic("TSDEV_CC_MTR write not implemented\n"); + return No_Fault; + case TSDEV_CC_MISC: + //If it is the seventh bit, clear the RTC interrupt + if ((*(uint64_t*) data) & (1<<4)) { + RTCInterrupting = false; + tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0); + DPRINTF(Tsunami, "clearing rtc interrupt\n"); + misc &= ~(1<<4); + } else panic("TSDEV_CC_MISC write not implemented\n"); + return No_Fault; + case TSDEV_CC_AAR0: + case TSDEV_CC_AAR1: + case TSDEV_CC_AAR2: + case TSDEV_CC_AAR3: + panic("TSDEV_CC_AARx write not implemeted\n"); + return No_Fault; + case TSDEV_CC_DIM0: + dim[0] = *(uint64_t*)data; + if (dim[0] & drir) { + dir[0] = dim[0] & drir; + if (!dirInterrupting[0]) { + dirInterrupting[0] = true; + tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ1, 0); + DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n"); + } + } + return No_Fault; + case TSDEV_CC_DIM1: + dim[1] = *(uint64_t*)data; + if (dim[1] & drir) { + dir[1] = dim[1] & drir; + if (!dirInterrupting[1]) { + dirInterrupting[1] = true; + tsunami->intrctrl->post(1, TheISA::INTLEVEL_IRQ1, 0); + DPRINTF(Tsunami, "posting dir interrupt to cpu 1\n"); + } + } + return No_Fault; + case TSDEV_CC_DIM2: + dim[2] = *(uint64_t*)data; + if (dim[2] & drir) { + dir[2] = dim[2] & drir; + if (!dirInterrupting[2]) { + dirInterrupting[2] = true; + tsunami->intrctrl->post(2, TheISA::INTLEVEL_IRQ1, 0); + DPRINTF(Tsunami, "posting dir interrupt to cpu 2\n"); + } + } + return No_Fault; + case TSDEV_CC_DIM3: + dim[3] = *(uint64_t*)data; + if ((dim[3] & drir) /*And Not Already Int*/) { + dir[3] = dim[3] & drir; + if (!dirInterrupting[3]) { + dirInterrupting[3] = true; + tsunami->intrctrl->post(3, TheISA::INTLEVEL_IRQ1, 0); + DPRINTF(Tsunami, "posting dir interrupt to cpu 3\n"); + } + } + return No_Fault; + case TSDEV_CC_DIR0: + case TSDEV_CC_DIR1: + case TSDEV_CC_DIR2: + case TSDEV_CC_DIR3: + panic("TSDEV_CC_DIR write not implemented\n"); + return No_Fault; + case TSDEV_CC_DRIR: + panic("TSDEV_CC_DRIR write not implemented\n"); + return No_Fault; + case TSDEV_CC_PRBEN: + panic("TSDEV_CC_PRBEN write not implemented\n"); + return No_Fault; + case TSDEV_CC_IIC0: + case TSDEV_CC_IIC1: + case TSDEV_CC_IIC2: + case TSDEV_CC_IIC3: + panic("TSDEV_CC_IICx write not implemented\n"); + return No_Fault; + case TSDEV_CC_MPR0: + case TSDEV_CC_MPR1: + case TSDEV_CC_MPR2: + case TSDEV_CC_MPR3: + panic("TSDEV_CC_MPRx write not implemented\n"); + return No_Fault; + default: + panic("default in cchip read reached, accessing 0x%x\n"); + } + + break; + case sizeof(uint32_t): + case sizeof(uint16_t): + case sizeof(uint8_t): + default: + panic("invalid access size(?) for tsunami register!\n"); + } + + DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); + + return No_Fault; +} + +void +TsunamiCChip::postDRIR(uint64_t bitvector) +{ + drir |= bitvector; + for(int i=0; i < Tsunami::Max_CPUs; i++) { + if (bitvector & dim[i]) { + dir[i] |= bitvector; + if (!dirInterrupting[i]) { + dirInterrupting[i] = true; + tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, 0); + DPRINTF(Tsunami, "posting dir interrupt to cpu %d\n",i); + } + } + } +} + +void +TsunamiCChip::clearDRIR(uint64_t bitvector) +{ + drir &= ~bitvector; + for(int i=0; i < Tsunami::Max_CPUs; i++) { + dir[i] &= ~bitvector; + if (!dir[i]) { + dirInterrupting[i] = false; + tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, 0); + DPRINTF(Tsunami, "clearing dir interrupt to cpu %d\n", i); + + } + } +} + +void +TsunamiCChip::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); + SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); + SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); + SERIALIZE_SCALAR(drir); + SERIALIZE_SCALAR(misc); + SERIALIZE_SCALAR(RTCInterrupting); +} + +void +TsunamiCChip::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs); + UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs); + UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs); + UNSERIALIZE_SCALAR(drir); + UNSERIALIZE_SCALAR(misc); + UNSERIALIZE_SCALAR(RTCInterrupting); +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) + + SimObjectParam<Tsunami *> tsunami; + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + +END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip) + +BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) + + INIT_PARAM(tsunami, "Tsunami"), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address") + +END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip) + +CREATE_SIM_OBJECT(TsunamiCChip) +{ + return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu); +} + +REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip) diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh new file mode 100644 index 000000000..8c8ed4d20 --- /dev/null +++ b/dev/tsunami_cchip.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * Emulation of the Tsunami CChip CSRs + */ + +#ifndef __TSUNAMI_CCHIP_HH__ +#define __TSUNAMI_CCHIP_HH__ + +#include "mem/functional_mem/functional_memory.hh" +#include "dev/tsunami.hh" + +/* + * Tsunami CChip + */ +class TsunamiCChip : public FunctionalMemory +{ + private: + Addr addr; + static const Addr size = 0xfff; + + protected: + /** + * pointer to the tsunami object. + * This is our access to all the other tsunami + * devices. + */ + Tsunami *tsunami; + + /** + * The dims are device interrupt mask registers. + * One exists for each CPU, the DRIR X DIM = DIR + */ + uint64_t dim[Tsunami::Max_CPUs]; + + /** + * The dirs are device interrupt registers. + * One exists for each CPU, the DRIR X DIM = DIR + */ + uint64_t dir[Tsunami::Max_CPUs]; + bool dirInterrupting[Tsunami::Max_CPUs]; + + /** + * This register contains bits for each PCI interrupt + * that can occur. + */ + uint64_t drir; + + public: + TsunamiCChip(const std::string &name, Tsunami *t, Addr a, + MemoryController *mmu); + + virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Fault write(MemReqPtr &req, const uint8_t *data); + + void postDRIR(uint64_t bitvector); + void clearDRIR(uint64_t bitvector); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + uint64_t misc; + bool RTCInterrupting; +}; + +#endif // __TSUNAMI_CCHIP_HH__ diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc new file mode 100644 index 000000000..ccf0bc2da --- /dev/null +++ b/dev/tsunami_io.cc @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * Tsunami I/O including PIC, PIT, RTC, DMA + */ + +#include <sys/time.h> + +#include <deque> +#include <string> +#include <vector> + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "dev/console.hh" +#include "dev/tlaser_clock.hh" +#include "dev/tsunami_io.hh" +#include "dev/tsunamireg.h" +#include "dev/tsunami.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "dev/tsunami_cchip.hh" + +using namespace std; + +#define UNIX_YEAR_OFFSET 52 + +// Timer Event for Periodic interrupt of RTC +TsunamiIO::RTCEvent::RTCEvent(Tsunami* t) + : Event(&mainEventQueue), tsunami(t) +{ + DPRINTF(MC146818, "RTC Event Initilizing\n"); + schedule(curTick + ticksPerSecond/RTC_RATE); +} + +void +TsunamiIO::RTCEvent::process() +{ + DPRINTF(MC146818, "RTC Timer Interrupt\n"); + schedule(curTick + ticksPerSecond/RTC_RATE); + //Actually interrupt the processor here + if (!tsunami->cchip->RTCInterrupting) { + tsunami->cchip->misc |= 1 << 7; + tsunami->cchip->RTCInterrupting = true; + tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ2, 0); + } +} + +const char * +TsunamiIO::RTCEvent::description() +{ + return "tsunami RTC 1024Hz interrupt"; +} + +// Timer Event for PIT Timers +TsunamiIO::ClockEvent::ClockEvent() + : Event(&mainEventQueue) +{ + DPRINTF(Tsunami, "Clock Event Initilizing\n"); + mode = 0; +} + +void +TsunamiIO::ClockEvent::process() +{ + DPRINTF(Tsunami, "Timer Interrupt\n"); + if (mode == 0) + status = 0x20; // set bit that linux is looking for + else + schedule(curTick + interval); +} + +void +TsunamiIO::ClockEvent::Program(int count) +{ + DPRINTF(Tsunami, "Timer set to curTick + %d\n", count); + // should be count * (cpufreq/pitfreq) + interval = count * ticksPerSecond/1193180UL; + schedule(curTick + interval); + status = 0; +} + +const char * +TsunamiIO::ClockEvent::description() +{ + return "tsunami 8254 Interval timer"; +} + +void +TsunamiIO::ClockEvent::ChangeMode(uint8_t md) +{ + mode = md; +} + +uint8_t +TsunamiIO::ClockEvent::Status() +{ + return status; +} + +TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time, + Addr a, MemoryController *mmu) + : FunctionalMemory(name), addr(a), tsunami(t), rtc(t) +{ + mmu->add_child(this, Range<Addr>(addr, addr + size)); + + // set the back pointer from tsunami to myself + tsunami->io = this; + + timerData = 0; + set_time(init_time == 0 ? time(NULL) : init_time); + uip = 1; + picr = 0; + picInterrupting = false; +} + +void +TsunamiIO::set_time(time_t t) +{ + gmtime_r(&t, &tm); + DPRINTFN("Real-time clock set to %s", asctime(&tm)); +} + +Fault +TsunamiIO::read(MemReqPtr &req, uint8_t *data) +{ + DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", + req->vaddr, req->size, req->vaddr & 0xfff); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); +// ExecContext *xc = req->xc; +// int cpuid = xc->cpu_id; + + switch(req->size) { + case sizeof(uint8_t): + switch(daddr) { + case TSDEV_TMR_CTL: + *(uint8_t*)data = timer2.Status(); + return No_Fault; + case TSDEV_RTC_DATA: + switch(RTCAddress) { + case RTC_CONTROL_REGISTERA: + *(uint8_t*)data = uip << 7 | 0x26; + uip = !uip; + return No_Fault; + case RTC_CONTROL_REGISTERB: + // DM and 24/12 and UIE + *(uint8_t*)data = 0x46; + return No_Fault; + case RTC_CONTROL_REGISTERC: + // If we want to support RTC user access in linux + // This won't work, but for now it's fine + *(uint8_t*)data = 0x00; + return No_Fault; + case RTC_CONTROL_REGISTERD: + panic("RTC Control Register D not implemented"); + case RTC_SECOND: + *(uint8_t *)data = tm.tm_sec; + return No_Fault; + case RTC_MINUTE: + *(uint8_t *)data = tm.tm_min; + return No_Fault; + case RTC_HOUR: + *(uint8_t *)data = tm.tm_hour; + return No_Fault; + case RTC_DAY_OF_WEEK: + *(uint8_t *)data = tm.tm_wday; + return No_Fault; + case RTC_DAY_OF_MONTH: + *(uint8_t *)data = tm.tm_mday; + case RTC_MONTH: + *(uint8_t *)data = tm.tm_mon + 1; + return No_Fault; + case RTC_YEAR: + *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET; + return No_Fault; + default: + panic("Unknown RTC Address\n"); + } + + default: + panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); + } + case sizeof(uint16_t): + case sizeof(uint32_t): + case sizeof(uint64_t): + default: + panic("I/O Read - invalid size - va %#x size %d\n", + req->vaddr, req->size); + } + panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); + + return No_Fault; +} + +Fault +TsunamiIO::write(MemReqPtr &req, const uint8_t *data) +{ + uint8_t dt = *(uint8_t*)data; + uint64_t dt64 = dt; + + DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n", + req->vaddr, req->size, req->vaddr & 0xfff, dt64); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)); + + switch(req->size) { + case sizeof(uint8_t): + switch(daddr) { + case TSDEV_PIC1_MASK: + mask1 = *(uint8_t*)data; + if ((picr & mask1) && !picInterrupting) { + picInterrupting = true; + tsunami->cchip->postDRIR(uint64_t(1) << 55); + DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); + } + return No_Fault; + case TSDEV_PIC2_MASK: + mask2 = *(uint8_t*)data; + //PIC2 Not implemented to interrupt + return No_Fault; + case TSDEV_DMA1_RESET: + return No_Fault; + case TSDEV_DMA2_RESET: + return No_Fault; + case TSDEV_DMA1_MODE: + mode1 = *(uint8_t*)data; + return No_Fault; + case TSDEV_DMA2_MODE: + mode2 = *(uint8_t*)data; + return No_Fault; + case TSDEV_DMA1_MASK: + case TSDEV_DMA2_MASK: + return No_Fault; + case TSDEV_TMR_CTL: + return No_Fault; + case TSDEV_TMR2_CTL: + if ((*(uint8_t*)data & 0x30) != 0x30) + panic("Only L/M write supported\n"); + + switch(*(uint8_t*)data >> 6) { + case 0: + timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1); + break; + case 2: + timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1); + break; + default: + panic("Read Back Command not implemented\n"); + } + return No_Fault; + case TSDEV_TMR2_DATA: + /* two writes before we actually start the Timer + so I set a flag in the timerData */ + if(timerData & 0x1000) { + timerData &= 0x1000; + timerData += *(uint8_t*)data << 8; + timer2.Program(timerData); + } else { + timerData = *(uint8_t*)data; + timerData |= 0x1000; + } + return No_Fault; + case TSDEV_TMR0_DATA: + /* two writes before we actually start the Timer + so I set a flag in the timerData */ + if(timerData & 0x1000) { + timerData &= 0x1000; + timerData += *(uint8_t*)data << 8; + timer0.Program(timerData); + } else { + timerData = *(uint8_t*)data; + timerData |= 0x1000; + } + return No_Fault; + case TSDEV_RTC_ADDR: + RTCAddress = *(uint8_t*)data; + return No_Fault; + case TSDEV_RTC_DATA: + panic("RTC Write not implmented (rtc.o won't work)\n"); + default: + panic("I/O Write - va%#x size %d\n", req->vaddr, req->size); + } + case sizeof(uint16_t): + case sizeof(uint32_t): + case sizeof(uint64_t): + default: + panic("I/O Write - invalid size - va %#x size %d\n", + req->vaddr, req->size); + } + + + return No_Fault; +} + +void +TsunamiIO::postPIC(uint8_t bitvector) +{ + //PIC2 Is not implemented, because nothing of interest there + picr |= bitvector; + if ((picr & mask1) && !picInterrupting) { + picInterrupting = true; + tsunami->cchip->postDRIR(uint64_t(1) << 55); + DPRINTF(Tsunami, "posting pic interrupt to cchip\n"); + } +} + +void +TsunamiIO::clearPIC(uint8_t bitvector) +{ + //PIC2 Is not implemented, because nothing of interest there + picr &= ~bitvector; + if (!(picr & mask1)) { + picInterrupting = false; + tsunami->cchip->clearDRIR(uint64_t(1) << 55); + DPRINTF(Tsunami, "clearing pic interrupt to cchip\n"); + } +} + +void +TsunamiIO::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(timerData); + SERIALIZE_SCALAR(uip); + SERIALIZE_SCALAR(picr); + SERIALIZE_SCALAR(picInterrupting); + Tick time0when = timer0.when(); + Tick time2when = timer2.when(); + Tick rtcwhen = rtc.when(); + SERIALIZE_SCALAR(time0when); + SERIALIZE_SCALAR(time2when); + SERIALIZE_SCALAR(rtcwhen); + +} + +void +TsunamiIO::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(timerData); + UNSERIALIZE_SCALAR(uip); + UNSERIALIZE_SCALAR(picr); + UNSERIALIZE_SCALAR(picInterrupting); + Tick time0when; + Tick time2when; + Tick rtcwhen; + UNSERIALIZE_SCALAR(time0when); + UNSERIALIZE_SCALAR(time2when); + UNSERIALIZE_SCALAR(rtcwhen); + timer0.reschedule(time0when); + timer2.reschedule(time2when); + rtc.reschedule(rtcwhen); +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) + + SimObjectParam<Tsunami *> tsunami; + Param<time_t> time; + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + +END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO) + +BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO) + + INIT_PARAM(tsunami, "Tsunami"), + INIT_PARAM_DFLT(time, "System time to use " + "(0 for actual time, default is 1/1/06", ULL(1136073600)), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address") + +END_INIT_SIM_OBJECT_PARAMS(TsunamiIO) + +CREATE_SIM_OBJECT(TsunamiIO) +{ + return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu); +} + +REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO) diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh new file mode 100644 index 000000000..90bef2b86 --- /dev/null +++ b/dev/tsunami_io.hh @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * Tsunami Fake I/O Space mapping including RTC/timer interrupts + */ + +#ifndef __TSUNAMI_DMA_HH__ +#define __TSUNAMI_DMA_HH__ + +#define RTC_RATE 1024 + +#include "mem/functional_mem/functional_memory.hh" +#include "dev/tsunami.hh" + +/* + * Tsunami I/O device + */ +class TsunamiIO : public FunctionalMemory +{ + private: + Addr addr; + static const Addr size = 0xff; + + struct tm tm; + + // In Tsunami RTC only has two i/o ports + // one for data and one for address, so you + // write the address and then read/write the data + uint8_t RTCAddress; + + protected: + + class ClockEvent : public Event + { + protected: + Tick interval; + uint8_t mode; + uint8_t status; + + public: + ClockEvent(); + + virtual void process(); + virtual const char *description(); + void Program(int count); + void ChangeMode(uint8_t mode); + uint8_t Status(); + + }; + + class RTCEvent : public Event + { + protected: + Tsunami* tsunami; + public: + RTCEvent(Tsunami* t); + + virtual void process(); + virtual const char *description(); + }; + + uint8_t uip; + + uint8_t mask1; + uint8_t mask2; + uint8_t mode1; + uint8_t mode2; + + uint8_t picr; //Raw PIC interrput register, before masking + bool picInterrupting; + + Tsunami *tsunami; + + /* + * This timer is initilized, but after I wrote the code + * it doesn't seem to be used again, and best I can tell + * it too is not connected to any interrupt port + */ + ClockEvent timer0; + + /* + * This timer is used to control the speaker, which + * we normally could care less about, however it is + * also used to calculated the clockspeed and hense + * bogomips which is kinda important to the scheduler + * so we need to implemnt it although after boot I can't + * imagine we would be playing with the PC speaker much + */ + ClockEvent timer2; + + RTCEvent rtc; + + uint32_t timerData; + + + public: + uint32_t frequency() const { return RTC_RATE; } + + TsunamiIO(const std::string &name, Tsunami *t, time_t init_time, + Addr a, MemoryController *mmu); + + void set_time(time_t t); + + virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Fault write(MemReqPtr &req, const uint8_t *data); + + void postPIC(uint8_t bitvector); + void clearPIC(uint8_t bitvector); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __TSUNAMI_IO_HH__ diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc new file mode 100644 index 000000000..b0a4c4d95 --- /dev/null +++ b/dev/tsunami_pchip.cc @@ -0,0 +1,284 @@ +/* $Id$ */ + +/* @file + * Tsunami PChip (pci) + */ + +#include <deque> +#include <string> +#include <vector> + +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "dev/console.hh" +#include "dev/etherdev.hh" +#include "dev/scsi_ctrl.hh" +#include "dev/tlaser_clock.hh" +#include "dev/tsunami_pchip.hh" +#include "dev/tsunamireg.h" +#include "dev/tsunami.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "sim/system.hh" + +using namespace std; + +TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, + MemoryController *mmu) + : FunctionalMemory(name), addr(a), tsunami(t) +{ + mmu->add_child(this, Range<Addr>(addr, addr + size)); + + wsba0 = 0; + wsba1 = 0; + wsba2 = 0; + wsba3 = 0; + wsm0 = 0; + wsm1 = 0; + wsm2 = 0; + wsm3 = 0; + tba0 = 0; + tba1 = 0; + tba2 = 0; + tba3 = 0; + + //Set back pointer in tsunami + tsunami->pchip = this; +} + +Fault +TsunamiPChip::read(MemReqPtr &req, uint8_t *data) +{ + DPRINTF(Tsunami, "read va=%#x size=%d\n", + req->vaddr, req->size); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; +// ExecContext *xc = req->xc; +// int cpuid = xc->cpu_id; + + switch (req->size) { + + case sizeof(uint64_t): + switch(daddr) { + case TSDEV_PC_WSBA0: + *(uint64_t*)data = wsba0; + return No_Fault; + case TSDEV_PC_WSBA1: + *(uint64_t*)data = wsba1; + return No_Fault; + case TSDEV_PC_WSBA2: + *(uint64_t*)data = wsba2; + return No_Fault; + case TSDEV_PC_WSBA3: + *(uint64_t*)data = wsba3; + return No_Fault; + case TSDEV_PC_WSM0: + *(uint64_t*)data = wsm0; + return No_Fault; + case TSDEV_PC_WSM1: + *(uint64_t*)data = wsm1; + return No_Fault; + case TSDEV_PC_WSM2: + *(uint64_t*)data = wsm2; + return No_Fault; + case TSDEV_PC_WSM3: + *(uint64_t*)data = wsm3; + return No_Fault; + case TSDEV_PC_TBA0: + *(uint64_t*)data = tba0; + return No_Fault; + case TSDEV_PC_TBA1: + *(uint64_t*)data = tba1; + return No_Fault; + case TSDEV_PC_TBA2: + *(uint64_t*)data = tba2; + return No_Fault; + case TSDEV_PC_TBA3: + *(uint64_t*)data = tba3; + return No_Fault; + case TSDEV_PC_PCTL: + // might want to change the clock?? + *(uint64_t*)data = 0x00; // try this + return No_Fault; + case TSDEV_PC_PLAT: + panic("PC_PLAT not implemented\n"); + case TSDEV_PC_RES: + panic("PC_RES not implemented\n"); + case TSDEV_PC_PERROR: + panic("PC_PERROR not implemented\n"); + case TSDEV_PC_PERRMASK: + panic("PC_PERRMASK not implemented\n"); + case TSDEV_PC_PERRSET: + panic("PC_PERRSET not implemented\n"); + case TSDEV_PC_TLBIV: + panic("PC_TLBIV not implemented\n"); + case TSDEV_PC_TLBIA: + *(uint64_t*)data = 0x00; // shouldn't be readable, but linux + return No_Fault; + case TSDEV_PC_PMONCTL: + panic("PC_PMONCTL not implemented\n"); + case TSDEV_PC_PMONCNT: + panic("PC_PMONCTN not implemented\n"); + default: + panic("Default in PChip Read reached reading 0x%x\n", daddr); + + } // uint64_t + + break; + case sizeof(uint32_t): + case sizeof(uint16_t): + case sizeof(uint8_t): + default: + panic("invalid access size(?) for tsunami register!\n\n"); + } + DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); + + return No_Fault; +} + +Fault +TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) +{ + DPRINTF(Tsunami, "write - va=%#x size=%d \n", + req->vaddr, req->size); + + Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; + + switch (req->size) { + + case sizeof(uint64_t): + switch(daddr) { + case TSDEV_PC_WSBA0: + wsba0 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSBA1: + wsba1 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSBA2: + wsba2 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSBA3: + wsba3 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSM0: + wsm0 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSM1: + wsm1 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSM2: + wsm2 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_WSM3: + wsm3 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_TBA0: + tba0 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_TBA1: + tba1 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_TBA2: + tba2 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_TBA3: + tba3 = *(uint64_t*)data; + return No_Fault; + case TSDEV_PC_PCTL: + // might want to change the clock?? + //*(uint64_t*)data; // try this + return No_Fault; + case TSDEV_PC_PLAT: + panic("PC_PLAT not implemented\n"); + case TSDEV_PC_RES: + panic("PC_RES not implemented\n"); + case TSDEV_PC_PERROR: + panic("PC_PERROR not implemented\n"); + case TSDEV_PC_PERRMASK: + panic("PC_PERRMASK not implemented\n"); + case TSDEV_PC_PERRSET: + panic("PC_PERRSET not implemented\n"); + case TSDEV_PC_TLBIV: + panic("PC_TLBIV not implemented\n"); + case TSDEV_PC_TLBIA: + return No_Fault; // value ignored, supposted to invalidate SG TLB + case TSDEV_PC_PMONCTL: + panic("PC_PMONCTL not implemented\n"); + case TSDEV_PC_PMONCNT: + panic("PC_PMONCTN not implemented\n"); + default: + panic("Default in PChip Read reached reading 0x%x\n", daddr); + + } // uint64_t + + break; + case sizeof(uint32_t): + case sizeof(uint16_t): + case sizeof(uint8_t): + default: + panic("invalid access size(?) for tsunami register!\n\n"); + } + + DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); + + return No_Fault; +} + +void +TsunamiPChip::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(wsba0); + SERIALIZE_SCALAR(wsba1); + SERIALIZE_SCALAR(wsba2); + SERIALIZE_SCALAR(wsba3); + SERIALIZE_SCALAR(wsm0); + SERIALIZE_SCALAR(wsm1); + SERIALIZE_SCALAR(wsm2); + SERIALIZE_SCALAR(wsm3); + SERIALIZE_SCALAR(tba0); + SERIALIZE_SCALAR(tba1); + SERIALIZE_SCALAR(tba2); + SERIALIZE_SCALAR(tba3); + +} + +void +TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(wsba0); + UNSERIALIZE_SCALAR(wsba1); + UNSERIALIZE_SCALAR(wsba2); + UNSERIALIZE_SCALAR(wsba3); + UNSERIALIZE_SCALAR(wsm0); + UNSERIALIZE_SCALAR(wsm1); + UNSERIALIZE_SCALAR(wsm2); + UNSERIALIZE_SCALAR(wsm3); + UNSERIALIZE_SCALAR(tba0); + UNSERIALIZE_SCALAR(tba1); + UNSERIALIZE_SCALAR(tba2); + UNSERIALIZE_SCALAR(tba3); + +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) + + SimObjectParam<Tsunami *> tsunami; + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + +END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) + +BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) + + INIT_PARAM(tsunami, "Tsunami"), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address") + +END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) + +CREATE_SIM_OBJECT(TsunamiPChip) +{ + return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu); +} + +REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh new file mode 100644 index 000000000..99530ddc0 --- /dev/null +++ b/dev/tsunami_pchip.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * Tsunami PChip + */ + +#ifndef __TSUNAMI_PCHIP_HH__ +#define __TSUNAMI_PCHIP_HH__ + +#include "mem/functional_mem/functional_memory.hh" +#include "dev/tsunami.hh" + +/* + * Tsunami PChip + */ +class TsunamiPChip : public FunctionalMemory +{ + private: + Addr addr; + static const Addr size = 0xfff; + + protected: + Tsunami *tsunami; + + uint64_t wsba0; + uint64_t wsba1; + uint64_t wsba2; + uint64_t wsba3; + uint64_t wsm0; + uint64_t wsm1; + uint64_t wsm2; + uint64_t wsm3; + uint64_t tba0; + uint64_t tba1; + uint64_t tba2; + uint64_t tba3; + + + public: + TsunamiPChip(const std::string &name, Tsunami *t, Addr a, + MemoryController *mmu); + + virtual Fault read(MemReqPtr &req, uint8_t *data); + virtual Fault write(MemReqPtr &req, const uint8_t *data); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __TSUNAMI_PCHIP_HH__ diff --git a/dev/tsunami_uart.cc b/dev/tsunami_uart.cc new file mode 100644 index 000000000..6f15c5ee0 --- /dev/null +++ b/dev/tsunami_uart.cc @@ -0,0 +1,220 @@ +/* $Id$ */ + +/* @file + * Tsunami UART + */ + +/* + * Copyright (C) 1998 by the Board of Trustees + * of Leland Stanford Junior University. + * Copyright (C) 1998 Digital Equipment Corporation + * + * This file is part of the SimOS distribution. + * See LICENSE file for terms of the license. + * + */ + +#include <string> +#include <vector> + +#include "base/inifile.hh" +#include "base/str.hh" // for to_number +#include "base/trace.hh" +#include "dev/console.hh" +#include "dev/tsunami_uart.hh" +#include "mem/functional_mem/memory_control.hh" +#include "sim/builder.hh" +#include "targetarch/ev5.hh" + +using namespace std; + +#define CONS_INT_TX 0x01 // interrupt enable / state bits +#define CONS_INT_RX 0x02 + +TsunamiUart::TsunamiUart(const string &name, SimConsole *c, Addr a, + MemoryController *mmu) + : FunctionalMemory(name), addr(a), cons(c), status_store(0), + valid_char(false) +{ + mmu->add_child(this, Range<Addr>(addr, addr + size)); + + IER = 0; +} + +Fault +TsunamiUart::read(MemReqPtr &req, uint8_t *data) +{ + Addr daddr = req->paddr - (addr & PA_IMPL_MASK); + DPRINTF(TsunamiUart, " read register %#x\n", daddr); + + switch (req->size) { + case sizeof(uint64_t): + *(uint64_t *)data = 0; + break; + case sizeof(uint32_t): + *(uint32_t *)data = 0; + break; + case sizeof(uint16_t): + *(uint16_t *)data = 0; + break; + case sizeof(uint8_t): + *(uint8_t *)data = 0; + break; + } + + switch (daddr) { + case 0x5: // Status Register + { + int status = cons->intStatus(); + if (!valid_char) { + valid_char = cons->in(next_char); + if (!valid_char) + status &= ~CONS_INT_RX; + } else { + status |= CONS_INT_RX; + } + + if (status_store == 3) { + // RR3 stuff? Don't really understand it, btw + status_store = 0; + if (status & CONS_INT_TX) { + *data = (1 << 4); + return No_Fault; + } else if (status & CONS_INT_RX) { + *data = (1 << 5); + return No_Fault; + } else { + DPRINTF(TsunamiUart, "spurious read\n"); + return No_Fault; + } + } else { + int reg = (1 << 2) | (1 << 5) | (1 << 6); + if (status & CONS_INT_RX) + reg |= (1 << 0); + *data = reg; + return No_Fault; + } + break; + } + + case 0x0: // Data register (RX) +// if (!valid_char) +// panic("Invalid character"); + + DPRINTF(TsunamiUart, "read data register \'%c\' %#02x\n", + isprint(next_char) ? next_char : ' ', next_char); + + *data = next_char; + valid_char = false; + return No_Fault; + + case 0x1: // Interrupt Enable Register + // This is the lovely way linux checks there is actually a serial + // port at the desired address + if (IER == 0) + *data = 0; + else if (IER == 0x0F) + *data = 0x0F; + else + *data = 0; + return No_Fault; + case 0x2: + *data = 0; // This means a 8250 serial port, do we want a 16550? + return No_Fault; + } + *data = 0; + // panic("%s: read daddr=%#x type=read *data=%#x\n", name(), daddr, *data); + + return No_Fault; +} + +Fault +TsunamiUart::write(MemReqPtr &req, const uint8_t *data) +{ + Addr daddr = req->paddr - (addr & PA_IMPL_MASK); + + DPRINTF(TsunamiUart, " write register %#x value %#x\n", daddr, *(uint8_t*)data); + switch (daddr) { + case 0x3: + status_store = *data; + switch (*data) { + case 0x03: // going to read RR3 + return No_Fault; + + case 0x28: // Ack of TX + { + if ((cons->intStatus() & CONS_INT_TX) == 0) + panic("Ack of transmit, though there was no interrupt"); + + cons->clearInt(CONS_INT_TX); + return No_Fault; + } + + case 0x00: + case 0x01: + case 0x12: + // going to write data??? + return No_Fault; + + default: + DPRINTF(TsunamiUart, "writing status register %#x \n", + *(uint8_t *)data); + return No_Fault; + } + + case 0x0: // Data register (TX) + cons->out(*(uint64_t *)data); + return No_Fault; + case 0x1: // DLM + DPRINTF(TsunamiUart, "writing to DLM/IER %#x\n", *(uint8_t*)data); + IER = *(uint8_t*)data; + return No_Fault; + case 0x4: // MCR + DPRINTF(TsunamiUart, "writing to MCR %#x\n", *(uint8_t*)data); + return No_Fault; + + } + + return No_Fault; +} + +void +TsunamiUart::serialize(ostream &os) +{ + SERIALIZE_SCALAR(status_store); + SERIALIZE_SCALAR(next_char); + SERIALIZE_SCALAR(valid_char); + SERIALIZE_SCALAR(IER); +} + +void +TsunamiUart::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(status_store); + UNSERIALIZE_SCALAR(next_char); + UNSERIALIZE_SCALAR(valid_char); + UNSERIALIZE_SCALAR(IER); +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart) + + SimObjectParam<SimConsole *> console; + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + +END_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart) + +BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiUart) + + INIT_PARAM(console, "The console"), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address") + +END_INIT_SIM_OBJECT_PARAMS(TsunamiUart) + +CREATE_SIM_OBJECT(TsunamiUart) +{ + return new TsunamiUart(getInstanceName(), console, addr, mmu); +} + +REGISTER_SIM_OBJECT("TsunamiUart", TsunamiUart) diff --git a/dev/tsunami_uart.hh b/dev/tsunami_uart.hh new file mode 100644 index 000000000..f0a9b644b --- /dev/null +++ b/dev/tsunami_uart.hh @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * Tsunami UART + */ + +#ifndef __TSUNAMI_UART_HH__ +#define __TSUNAMI_UART_HH__ + +#include "mem/functional_mem/functional_memory.hh" + +class SimConsole; + +/* + * Tsunami UART + */ +class TsunamiUart : public FunctionalMemory +{ + private: + Addr addr; + static const Addr size = 0x8; + + protected: + SimConsole *cons; + int status_store; + uint8_t next_char; + bool valid_char; + uint8_t IER; + + public: + TsunamiUart(const std::string &name, SimConsole *c, Addr a, + MemoryController *mmu); + + Fault read(MemReqPtr &req, uint8_t *data); + Fault write(MemReqPtr &req, const uint8_t *data); + + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __TSUNAMI_UART_HH__ diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h new file mode 100644 index 000000000..c74279ecf --- /dev/null +++ b/dev/tsunamireg.h @@ -0,0 +1,110 @@ + +#ifndef __TSUNAMIREG_H__ +#define __TSUNAMIREG_H__ + +#define ALPHA_K0SEG_BASE 0xfffffc0000000000 + +// CChip Registers +#define TSDEV_CC_CSR 0x00 +#define TSDEV_CC_MTR 0x01 +#define TSDEV_CC_MISC 0x02 + +#define TSDEV_CC_AAR0 0x04 +#define TSDEV_CC_AAR1 0x05 +#define TSDEV_CC_AAR2 0x06 +#define TSDEV_CC_AAR3 0x07 +#define TSDEV_CC_DIM0 0x08 +#define TSDEV_CC_DIM1 0x09 +#define TSDEV_CC_DIR0 0x0A +#define TSDEV_CC_DIR1 0x0B +#define TSDEV_CC_DRIR 0x0C +#define TSDEV_CC_PRBEN 0x0D +#define TSDEV_CC_IIC0 0x0E +#define TSDEV_CC_IIC1 0x0F +#define TSDEV_CC_MPR0 0x10 +#define TSDEV_CC_MPR1 0x11 +#define TSDEV_CC_MPR2 0x12 +#define TSDEV_CC_MPR3 0x13 + +#define TSDEV_CC_DIM2 0x18 +#define TSDEV_CC_DIM3 0x19 +#define TSDEV_CC_DIR2 0x1A +#define TSDEV_CC_DIR3 0x1B +#define TSDEV_CC_IIC2 0x1C +#define TSDEV_CC_IIC3 0x1D + + +// PChip Registers +#define TSDEV_PC_WSBA0 0x00 +#define TSDEV_PC_WSBA1 0x01 +#define TSDEV_PC_WSBA2 0x02 +#define TSDEV_PC_WSBA3 0x03 +#define TSDEV_PC_WSM0 0x04 +#define TSDEV_PC_WSM1 0x05 +#define TSDEV_PC_WSM2 0x06 +#define TSDEV_PC_WSM3 0x07 +#define TSDEV_PC_TBA0 0x08 +#define TSDEV_PC_TBA1 0x09 +#define TSDEV_PC_TBA2 0x0A +#define TSDEV_PC_TBA3 0x0B +#define TSDEV_PC_PCTL 0x0C +#define TSDEV_PC_PLAT 0x0D +#define TSDEV_PC_RES 0x0E +#define TSDEV_PC_PERROR 0x0F +#define TSDEV_PC_PERRMASK 0x10 +#define TSDEV_PC_PERRSET 0x11 +#define TSDEV_PC_TLBIV 0x12 +#define TSDEV_PC_TLBIA 0x13 +#define TSDEV_PC_PMONCTL 0x14 +#define TSDEV_PC_PMONCNT 0x15 + +#define TSDEV_PC_SPST 0x20 + + +// DChip Registers +#define TSDEV_DC_DSC 0x20 +#define TSDEV_DC_STR 0x21 +#define TSDEV_DC_DREV 0x22 +#define TSDEV_DC_DSC2 0x23 + +// I/O Ports +#define TSDEV_PIC1_MASK 0x21 +#define TSDEV_PIC2_MASK 0xA1 +#define TSDEV_DMA1_RESET 0x0D +#define TSDEV_DMA2_RESET 0xDA +#define TSDEV_DMA1_MODE 0x0B +#define TSDEV_DMA2_MODE 0xD6 +#define TSDEV_DMA1_MASK 0x0A +#define TSDEV_DMA2_MASK 0xD4 +#define TSDEV_TMR_CTL 0x61 +#define TSDEV_TMR2_CTL 0x43 +#define TSDEV_TMR2_DATA 0x42 +#define TSDEV_TMR0_DATA 0x40 + +#define TSDEV_RTC_ADDR 0x70 +#define TSDEV_RTC_DATA 0x71 + +// RTC defines +#define RTC_SECOND 0 // second of minute [0..59] +#define RTC_SECOND_ALARM 1 // seconds to alarm +#define RTC_MINUTE 2 // minute of hour [0..59] +#define RTC_MINUTE_ALARM 3 // minutes to alarm +#define RTC_HOUR 4 // hour of day [0..23] +#define RTC_HOUR_ALARM 5 // hours to alarm +#define RTC_DAY_OF_WEEK 6 // day of week [1..7] +#define RTC_DAY_OF_MONTH 7 // day of month [1..31] +#define RTC_MONTH 8 // month of year [1..12] +#define RTC_YEAR 9 // year [00..99] +#define RTC_CONTROL_REGISTERA 10 // control register A +#define RTC_CONTROL_REGISTERB 11 // control register B +#define RTC_CONTROL_REGISTERC 12 // control register C +#define RTC_CONTROL_REGISTERD 13 // control register D +#define RTC_REGNUMBER_RTC_CR1 0x6A // control register 1 + +#define PCHIP_PCI0_MEMORY 0x10000000000 +#define PCHIP_PCI0_IO 0x101FC000000 +#define TSUNAMI_PCI0_MEMORY ALPHA_K0SEG_BASE + PCHIP_PCI0_MEMORY +#define TSUNAMI_PCI0_IO ALPHA_K0SEG_BASE + PCHIP_PCI0_IO + + +#endif // __TSUNAMIREG_H__ diff --git a/kern/linux/linux.hh b/kern/linux/linux.hh new file mode 100644 index 000000000..a3cb94e91 --- /dev/null +++ b/kern/linux/linux.hh @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINUX_HH__ +#define __LINUX_HH__ + +class Linux {}; + +#endif // __LINUX_HH__ diff --git a/kern/linux/linux_syscalls.cc b/kern/linux/linux_syscalls.cc new file mode 100644 index 000000000..d259499a2 --- /dev/null +++ b/kern/linux/linux_syscalls.cc @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "kern/linux/linux_syscalls.hh" + +namespace { + const char * + standard_strings[SystemCalls<Linux>::StandardNumber] = { + + + "llseek", //0 + "newselect", //1 + "sysctl", //2 + "access", //3 + "acct", //4 + "adjtimex", //5 + "afs_syscall", //6 + "alarm", //7 + "bdflush", //8 + "break", //9 + + + "brk", //10 + "capget", //11 + "capset", //12 + "chdir", //13 + "chmod", //14 + "chown", //15 + "chown32", //16 + "chroot", //17 + "clock_getres", //18 + "clock_gettime", //19 + + + "clock_nanosleep", //20 + "clock_settime", //21 + "clone", //22 + "close", //23 + "creat", //24 + "create_module", //25 + "delete_module", //26 + "dup", //27 + "dup2", //28 + "epoll_create", //29 + + + "epoll_ctl", //30 + "epoll_wait", //31 + "execve", //32 + "exit", //33 + "exit_group", //34 + "fadvise64", //35 + "fadvise64_64", //36 + "fchdir", //37 + "fchmod", //38 + "fchown", //39 + + + "fchown32", //40 + "fcntl", //41 + "fcntl64", //42 + "fdatasync", //43 + "fgetxattr", //44 + "flistxattr", //45 + "flock", //46 + "fork", //47 + "fremovexattr", //48 + "fsetxattr", //49 + + + "fstat", //50 + "fstat64", //51 + "fstatfs", //52 + "fstatfs64", //53 + "fsync", //54 + "ftime", //55 + "ftruncate", //56 + "ftruncate64", //57 + "futex", //58 + "get_kernel_syms", //59 + + + "get_thread_area", //60 + "getcwd", //61 + "getdents", //62 + "getdents64", //63 + "getegid", //64 + "getegid32", //65 + "geteuid", //66 + "geteuid32", //67 + "getgid", //68 + "getgid32", //69 + + + "getgroups", //70 + "getgroups32", //71 + "getitimer", //72 + "getpgid", //73 + "getpgrp", //74 + "getpid", //75 + "getpmsg", //76 + "getppid", //77 + "getpriority", //78 + "getresgid", //79 + + + "getresgid32", //80 + "getresuid", //81 + "getresuid32", //82 + "getrlimit", //83 + "getrusage", //84 + "getsid", //85 + "gettid", //86 + "gettimeofday", //87 + "getuid", //88 + "getuid32", //89 + + + "getxattr", //90 + "gtty", //91 + "idle", //92 + "init_module", //93 + "io_cancel", //94 + "io_destroy", //95 + "io_getevents", //96 + "io_setup", //97 + "io_submit", //98 + "ioctl", //99 + + + "ioperm", //100 + "iopl", //101 + "ipc", //102 + "kill", //103 + "lchown", //104 + "lchown32", //105 + "lgetxattr", //106 + "link", //107 + "listxattr", //108 + "llistxattr", //109 + + + "lock", //110 + "lookup_dcookie", //111 + "lremovexattr", //112 + "lseek", //113 + "lsetxattr", //114 + "lstat", //115 + "lstat64", //116 + "madvise", //117 + "madvise1", //118 + "mincore", //119 + + + "mkdir", //120 + "mknod", //121 + "mlock", //122 + "mlockall", //123 + "mmap", //124 + "mmap2", //125 + "modify_ldt", //126 + "mount", //127 + "mprotect", //128 + "mpx", //129 + + + "mremap", //130 + "msync", //131 + "munlock", //132 + "munlockall", //133 + "munmap", //134 + "nanosleep", //135 + "nfsservctl", //136 + "nice", //137 + "oldfstat", //138 + "oldlstat", //139 + + + "oldolduname", //140 + "oldstat", //141 + "olduname", //142 + "open", //143 + "pause", //144 + "personality", //145 + "pipe", //146 + "pivot_root", //147 + "poll", //148 + "prctl", //149 + + + "pread64", //150 + "prof", //151 + "profil", //152 + "ptrace", //153 + "putpmsg", //154 + "pwrite64", //155 + "query_module", //156 + "quotactl", //157 + "read", //158 + "readahead", //159 + + + "readdir", //160 + "readlink", //161 + "readv", //162 + "reboot", //163 + "remap_file_pages", //164 + "removexattr", //165 + "rename", //166 + "restart_syscall", //167 + "rmdir", //168 + "rt_sigaction", //169 + + + "rt_sigpending", //170 + "rt_sigprocmask", //171 + "rt_sigqueueinfo", //172 + "rt_sigreturn", //173 + "rt_sigsuspend", //174 + "rt_sigtimedwait", //175 + "sched_get_priority_max", //176 + "sched_get_priority_min", //177 + "sched_getaffinity", //178 + "sched_getparam", //179 + + + "sched_getscheduler", //180 + "sched_rr_get_interval", //181 + "sched_setaffinity", //182 + "sched_setparam", //183 + "sched_setscheduler", //184 + "sched_yield", //185 + "select", //186 + "sendfile", //187 + "sendfile64", //188 + "set_thread_area", //189 + + + "set_tid_address", //190 + "setdomainname", //191 + "setfsgid", //192 + "setfsgid32", //193 + "setfsuid", //194 + "setfsuid32", //195 + "setgid", //196 + "setgid32", //197 + "setgroups", //198 + "setgroups32", //199 + + + "sethostname", //200 + "setitimer", //201 + "setpgid", //202 + "setpriority", //203 + "setregid", //204 + "setregid32", //205 + "setresgid", //206 + "setresgid32", //207 + "setresuid", //208 + "setresuid32", //209 + + + "setreuid", //210 + "setreuid32", //211 + "setrlimit", //212 + "setsid", //213 + "settimeofday", //214 + "setuid", //215 + "setuid32", //216 + "setxattr", //217 + "sgetmask", //218 + "sigaction", //219 + + + "sigaltstack", //220 + "signal", //221 + "sigpending", //222 + "sigprocmask", //223 + "sigreturn", //224 + "sigsuspend", //225 + "socketcall", //226 + "ssetmask", //227 + "stat", //228 + "stat64", //229 + + + "statfs", //230 + "statfs64", //231 + "stime", //232 + "stty", //233 + "swapoff", //234 + "swapon", //235 + "symlink", //236 + "sync", //237 + "sysfs", //238 + "sysinfo", //239 + + + "syslog", //240 + "tgkill", //241 + "time", //242 + "timer_create", //243 + "timer_delete", //244 + "timer_getoverrun", //245 + "timer_gettime", //246 + "timer_settime", //247 + "times", //248 + "tkill", //249 + + + "truncate", //250 + "truncate64", //251 + "ugetrlimit", //252 + "ulimit", //253 + "umask", //254 + "umount", //255 + "umount2", //256 + "uname", //257 + "unlink", //258 + "uselib", //259 + + + "ustat", //260 + "utime", //261 + "utimes", //262 + "vfork", //263 + "vhangup", //264 + "vm86", //265 + "vm86old", //266 + "vserver", //267 + "wait4", //268 + "waitpid", //269 + + + "write", //270 + "writev", //271 + }; + + +} + +const char * +SystemCalls<Linux>::name(int num) +{ + if (num >= StandardNumber) + return 0; + else if (num >= 0) + return standard_strings[num]; + else + return 0; +} diff --git a/kern/linux/linux_syscalls.hh b/kern/linux/linux_syscalls.hh new file mode 100644 index 000000000..54d2391a8 --- /dev/null +++ b/kern/linux/linux_syscalls.hh @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINUX_SYSCALLS_HH__ +#define __LINUX_SYSCALLS_HH__ + +#include "targetarch/syscalls.hh" +#include "kern/linux/linux.hh" + +struct SystemCalls<Linux> +{ + enum { + syscall = 0, + llseek = 1, + newselect = 2, + sysctl = 3, + access = 4, + acct = 5, + adjtimex = 6, + afs_syscall = 7, + alarm = 8, + bdflush = 9, + _break = 10, /*renamed from break*/ + brk = 11, + capget = 12, + capset = 13, + chdir = 14, + chmod = 15, + chown = 16, + chown32 = 17, + chroot = 18, + clock_getres = 19, + clock_gettime = 20, + clock_nanosleep = 21, + clock_settime = 22, + clone = 23, + close = 24, + creat = 25, + create_module = 26, + delete_module = 27, + dup = 28, + dup2 = 29, + epoll_create = 30, + epoll_ctl = 31, + epoll_wait = 32, + execve = 33, + exit = 34, + exit_group = 35, + fadvise64 = 36, + fadvise64_64 = 37, + fchdir = 38, + fchmod = 39, + fchown = 40, + fchown32 = 41, + fcntl = 42, + fcntl64 = 43, + fdatasync = 44, + fgetxattr = 45, + flistxattr = 46, + flock = 47, + fork = 48, + fremovexattr = 49, + fsetxattr = 50, + fstat = 51, + fstat64 = 52, + fstatfs = 53, + fstatfs64 = 54, + fsync = 55, + ftime = 56, + ftruncate = 57, + ftruncate64 = 58, + futex = 59, + get_kernel_syms = 60, + get_thread_area = 61, + getcwd = 62, + getdents = 63, + getdents64 = 64, + getegid = 65, + getegid32 = 66, + geteuid = 67, + geteuid32 = 68, + getgid = 69, + getgid32 = 70, + getgroups = 71, + getgroups32 = 72, + getitimer = 73, + getpgid = 74, + getpgrp = 75, + getpid = 76, + getpmsg = 77, + getppid = 78, + getpriority = 79, + getresgid = 80, + getresgid32 = 81, + getresuid = 82, + getresuid32 = 83, + getrlimit = 84, + getrusage = 85, + getsid = 86, + gettid = 87, + gettimeofday = 88, + getuid = 89, + getuid32 = 90, + getxattr = 91, + gtty = 92, + idle = 93, + init_module = 94, + io_cancel = 95, + io_destroy = 96, + io_getevents = 97, + io_setup = 98, + io_submit = 99, + ioctl = 100, + ioperm = 101, + iopl = 102, + ipc = 103, + kill = 104, + lchown = 105, + lchown32 = 106, + lgetxattr = 107, + link = 108, + listxattr = 109, + llistxattr = 110, + lock = 111, + lookup_dcookie = 112, + lremovexattr = 113, + lseek = 114, + lsetxattr = 115, + lstat = 116, + lstat64 = 117, + madvise = 118, + madvise1 = 119, + mincore = 120, + mkdir = 121, + mknod = 122, + mlock = 123, + mlockall = 124, + mmap = 125, + mmap2 = 126, + modify_ldt = 127, + mount = 128, + mprotect = 129, + mpx = 130, + mremap = 131, + msync = 132, + munlock = 133, + munlockall = 134, + munmap = 135, + nanosleep = 136, + nfsservctl = 137, + nice = 138, + oldfstat = 139, + oldlstat = 140, + oldolduname = 141, + oldstat = 142, + olduname = 143, + open = 144, + pause = 145, + personality = 146, + pipe = 147, + pivot_root = 148, + poll = 149, + prctl = 150, + pread64 = 151, + prof = 152, + profil = 153, + ptrace = 154, + putpmsg = 155, + pwrite64 = 156, + query_module = 157, + quotactl = 158, + read = 159, + readahead = 160, + readdir = 161, + readlink = 162, + readv = 163, + reboot = 164, + remap_file_pages = 165, + removexattr = 166, + rename = 167, + restart_syscall = 168, + rmdir = 169, + rt_sigaction = 170, + rt_sigpending = 171, + rt_sigprocmask = 172, + rt_sigqueueinfo = 173, + rt_sigreturn = 174, + rt_sigsuspend = 175, + rt_sigtimedwait = 176, + sched_get_priority_max = 177, + sched_get_priority_min = 178, + sched_getaffinity = 179, + sched_getparam = 180, + sched_getscheduler = 181, + sched_rr_get_interval = 182, + sched_setaffinity = 183, + sched_setparam = 184, + sched_setscheduler = 185, + sched_yield = 186, + select = 187, + sendfile = 188, + sendfile64 = 189, + set_thread_area = 190, + set_tid_address = 191, + setdomainname = 192, + setfsgid = 193, + setfsgid32 = 194, + setfsuid = 195, + setfsuid32 = 196, + setgid = 197, + setgid32 = 198, + setgroups = 199, + setgroups32 = 200, + sethostname = 201, + setitimer = 202, + setpgid = 203, + setpriority = 204, + setregid = 205, + setregid32 = 206, + setresgid = 207, + setresgid32 = 208, + setresuid = 209, + setresuid32 = 210, + setreuid = 211, + setreuid32 = 212, + setrlimit = 213, + setsid = 214, + settimeofday = 215, + setuid = 216, + setuid32 = 217, + setxattr = 218, + sgetmask = 219, + sigaction = 220, + sigaltstack = 221, + signal = 222, + sigpending = 223, + sigprocmask = 224, + sigreturn = 225, + sigsuspend = 226, + socketcall = 227, + ssetmask = 228, + stat = 229, + stat64 = 230, + statfs = 231, + statfs64 = 232, + stime = 233, + stty = 234, + swapoff = 235, + swapon = 236, + symlink = 237, + sync = 238, + sysfs = 239, + sysinfo = 240, + syslog = 241, + tgkill = 242, + time = 243, + timer_create = 244, + timer_delete = 245, + timer_getoverrun = 246, + timer_gettime = 247, + timer_settime = 248, + times = 249, + tkill = 250, + truncate = 251, + truncate64 = 252, + ugetrlimit = 253, + ulimit = 254, + umask = 255, + umount = 256, + umount2 = 257, + uname = 258, + unlink = 259, + uselib = 260, + ustat = 261, + utime = 262, + utimes = 263, + vfork = 264, + vhangup = 265, + vm86 = 266, + vm86old = 267, + vserver = 268, + wait4 = 269, + waitpid = 270, + write = 271, + writev = 272, + StandardNumber + }; + + static const char *name(int num); + + static bool validSyscallNumber(int num) { + return num < StandardNumber; + } + + /* 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__ diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc new file mode 100644 index 000000000..798577ba5 --- /dev/null +++ b/kern/linux/linux_system.cc @@ -0,0 +1,732 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "base/loader/aout_object.hh" +#include "base/loader/elf_object.hh" +#include "base/loader/object_file.hh" +#include "base/loader/symtab.hh" +#include "base/remote_gdb.hh" +#include "base/trace.hh" +#include "cpu/exec_context.hh" +#include "cpu/base_cpu.hh" +#include "kern/linux/linux_events.hh" +#include "kern/linux/linux_system.hh" +#include "mem/functional_mem/memory_control.hh" +#include "mem/functional_mem/physical_memory.hh" +#include "sim/builder.hh" +#include "dev/platform.hh" +#include "targetarch/isa_traits.hh" +#include "targetarch/vtophys.hh" + +extern SymbolTable *debugSymbolTable; + +//un-comment this to see the state of call stack when it changes. +//#define SW_DEBUG + +using namespace std; + +LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, + MemoryController *_memCtrl, PhysicalMemory *_physmem, + const string &kernel_path, const string &console_path, + const string &palcode, const string &boot_osflags, + const string &bootloader_path, const bool _bin) + : System(_name, _init_param, _memCtrl, _physmem, _bin), bin(_bin) +{ + kernelSymtab = new SymbolTable; + consoleSymtab = new SymbolTable; + bootloaderSymtab = new SymbolTable; + + ObjectFile *kernel = createObjectFile(kernel_path); + if (kernel == NULL) + fatal("Could not load kernel file %s", kernel_path); + + ObjectFile *console = createObjectFile(console_path); + if (console == NULL) + fatal("Could not load console file %s", console_path); + + ObjectFile *bootloader = createObjectFile(bootloader_path); + if (bootloader == NULL) + fatal("Could not load bootloader file %s", bootloader_path); + + if (!kernel->loadGlobalSymbols(kernelSymtab)) + panic("could not load kernel symbols\n"); + debugSymbolTable = kernelSymtab; + + if (!console->loadGlobalSymbols(consoleSymtab)) + panic("could not load console symbols\n"); + + if (!bootloader->loadGlobalSymbols(bootloaderSymtab)) + panic("could not load bootloader symbols\n"); + + // Load pal file + ObjectFile *pal = createObjectFile(palcode); + if (pal == NULL) + fatal("Could not load PALcode file %s", palcode); + pal->loadSections(physmem, true); + + // Load console file + console->loadSections(physmem, true); + + // Load kernel file + kernel->loadSections(physmem, true); + kernelStart = kernel->textBase(); + kernelEnd = kernel->bssBase() + kernel->bssSize(); + /* FIXME: entrypoint not in kernel, but in bootloader, + variable should be re-named appropriately */ + kernelEntry = kernel->entryPoint(); + + + DPRINTF(Loader, "Kernel start = %#x\n" + "Kernel end = %#x\n" + "Kernel entry = %#x\n", + kernelStart, kernelEnd, kernelEntry); + + DPRINTF(Loader, "Kernel loaded...\n"); + + // Load bootloader file + bootloader->loadSections(physmem, true); + kernelEntry = bootloader->entryPoint(); + kernelStart = bootloader->textBase(); + DPRINTF(Loader, "Bootloader entry at %#x\n", kernelEntry); + +#ifdef FS_MEASURE + //INSTRUMENTATION CODEGEN BEGIN ONE + if (bin == true) { + esIntrBin = new Statistics::MainBin(name() + " es_intr"); + fnBins.insert(make_pair("es_intr", esIntrBin)); + + esRxeofBin = new Statistics::MainBin(name() + " es_rxeof"); + fnBins.insert(make_pair("es_rxeof", esRxeofBin)); + + esNewbufBin = new Statistics::MainBin(name() + " es_newbuf"); + fnBins.insert(make_pair("es_newbuf", esNewbufBin)); + + esDmaLoadBin = new Statistics::MainBin(name() + " es_dma_load"); + fnBins.insert(make_pair("es_dma_load", esDmaLoadBin)); + + dmaMapLoadBin = new Statistics::MainBin(name() + " dma_map_load"); + fnBins.insert(make_pair("dma_map_load", dmaMapLoadBin)); + + etherInputBin = new Statistics::MainBin(name() + " ether_input"); + fnBins.insert(make_pair("ether_input", etherInputBin)); + + netisrInputBin = new Statistics::MainBin(name() + " netisr_input"); + fnBins.insert(make_pair("netisr_input", netisrInputBin)); + + schednetisrIsrBin = new Statistics::MainBin(name() + " schednetisr_isr"); + fnBins.insert(make_pair("schednetisr_isr", schednetisrIsrBin)); + + ipintrBin = new Statistics::MainBin(name() + " ipintr"); + fnBins.insert(make_pair("ipintr", ipintrBin)); + + ipDooptionsBin = new Statistics::MainBin(name() + " ip_dooptions"); + fnBins.insert(make_pair("ip_dooptions", ipDooptionsBin)); + + ipReassBin = new Statistics::MainBin(name() + " ip_reass"); + fnBins.insert(make_pair("ip_reass", ipReassBin)); + + tcpInputBin = new Statistics::MainBin(name() + " tcp_input"); + fnBins.insert(make_pair("tcp_input", tcpInputBin)); + + sbappendBin = new Statistics::MainBin(name() + " sbappend"); + fnBins.insert(make_pair("sbappend", sbappendBin)); + + readBin = new Statistics::MainBin(name() + " read"); + fnBins.insert(make_pair("read", readBin)); + + sooReadBin = new Statistics::MainBin(name() + " soo_read"); + fnBins.insert(make_pair("soo_read", sooReadBin)); + + orecvBin = new Statistics::MainBin(name() + " orecv"); + fnBins.insert(make_pair("orecv", orecvBin)); + + recvitBin = new Statistics::MainBin(name() + " recvit"); + fnBins.insert(make_pair("recvit", recvitBin)); + + soreceiveBin = new Statistics::MainBin(name() + " soreceive"); + fnBins.insert(make_pair("soreceive", soreceiveBin)); + + osendBin = new Statistics::MainBin(name() + " osend"); + fnBins.insert(make_pair("osend", osendBin)); + + writeBin = new Statistics::MainBin(name() + " write"); + fnBins.insert(make_pair("write", writeBin)); + + sooWriteBin = new Statistics::MainBin(name() + " soo_write"); + fnBins.insert(make_pair("soo_write", sooWriteBin)); + + senditBin = new Statistics::MainBin(name() + " sendit"); + fnBins.insert(make_pair("sendit", senditBin)); + + sosendBin = new Statistics::MainBin(name() + " sosend"); + fnBins.insert(make_pair("sosend", sosendBin)); + + tcpSosendBin = new Statistics::MainBin(name() + " tcp_sosend"); + fnBins.insert(make_pair("tcp_sosend", tcpSosendBin)); + + tcpOutputBin = new Statistics::MainBin(name() + " tcp_output"); + fnBins.insert(make_pair("tcp_output", tcpOutputBin)); + + ipOutputBin = new Statistics::MainBin(name() + " ip_output"); + fnBins.insert(make_pair("ip_output", ipOutputBin)); + + etherOutputBin = new Statistics::MainBin(name() + " ether_output"); + fnBins.insert(make_pair("ether_output", etherOutputBin)); + + esStartBin = new Statistics::MainBin(name() + " es_start"); + fnBins.insert(make_pair("es_start", esStartBin)); + + esTransmitBin = new Statistics::MainBin(name() + " es_transmit"); + fnBins.insert(make_pair("es_transmit", esTransmitBin)); + + esTxeofBin = new Statistics::MainBin(name() + " es_txeof"); + fnBins.insert(make_pair("es_txeof", esTxeofBin)); + + idleThreadBin = new Statistics::MainBin(name() + " idle_thread"); + fnBins.insert(make_pair("idle_thread", idleThreadBin)); + + } + //INSTRUMENTATION CODEGEN END +#endif //FS_MEASURE + + kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); + consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); + badaddrEvent = new LinuxBadAddrEvent(&pcEventQueue, "badaddr"); + skipPowerStateEvent = new LinuxSkipFuncEvent(&pcEventQueue, + "tl_v48_capture_power_state"); + skipScavengeBootEvent = new LinuxSkipFuncEvent(&pcEventQueue, + "pmap_scavenge_boot"); + printfEvent = new LinuxPrintfEvent(&pcEventQueue, "printf"); + + skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, + "calibrate_delay"); + + /* debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue, + "debug_printf", false); + debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue, + "debug_printfr", true); + dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf"); +*/ +#ifdef FS_MEASURE + //INSTRUMENTATION CODEGEN BEGIN TWO + if (bin == true) { + esIntrEvent = new FnEvent(&pcEventQueue, "es_intr", this); + esRxeofEvent = new FnEvent(&pcEventQueue, "es_rxeof", this); + esNewbufEvent = new FnEvent(&pcEventQueue, "es_newbuf", this); + esDmaLoadEvent = new FnEvent(&pcEventQueue, "es_dma_load", this); + dmaMapLoadEvent = new FnEvent(&pcEventQueue, "dma_map_load", this); + etherInputEvent = new FnEvent(&pcEventQueue, "ether_input", this); + netisrInputEvent = new FnEvent(&pcEventQueue, "netisr_input", this); + schednetisrIsrEvent = new FnEvent(&pcEventQueue, "schednetisr_isr", this); + ipintrEvent = new FnEvent(&pcEventQueue, "ipintr", this); + ipDooptionsEvent = new FnEvent(&pcEventQueue, "ip_dooptions", this); + ipReassEvent = new FnEvent(&pcEventQueue, "ip_reass", this); + tcpInputEvent = new FnEvent(&pcEventQueue, "tcp_input", this); + sbappendEvent = new FnEvent(&pcEventQueue, "sbappend", this); + readEvent = new FnEvent(&pcEventQueue, "read", this); + sooReadEvent = new FnEvent(&pcEventQueue, "soo_read", this); + orecvEvent = new FnEvent(&pcEventQueue, "orecv", this); + recvitEvent = new FnEvent(&pcEventQueue, "recvit", this); + soreceiveEvent = new FnEvent(&pcEventQueue, "soreceive", this); + osendEvent = new FnEvent(&pcEventQueue, "osend", this); + writeEvent = new FnEvent(&pcEventQueue, "write", this); + sooWriteEvent = new FnEvent(&pcEventQueue, "soo_write", this); + senditEvent = new FnEvent(&pcEventQueue, "sendit", this); + sosendEvent = new FnEvent(&pcEventQueue, "sosend", this); + tcpSosendEvent = new FnEvent(&pcEventQueue, "tcp_sosend", this); + tcpOutputEvent = new FnEvent(&pcEventQueue, "tcp_output", this); + ipOutputEvent = new FnEvent(&pcEventQueue, "ip_output", this); + etherOutputEvent = new FnEvent(&pcEventQueue, "ether_output", this); + esStartEvent = new FnEvent(&pcEventQueue, "es_start", this); + esTransmitEvent = new FnEvent(&pcEventQueue, "es_transmit", this); + esTxeofEvent = new FnEvent(&pcEventQueue, "es_txeof", this); + idleThreadEvent = new FnEvent(&pcEventQueue, "idle_thread", this); + } + //INSTRUMENTATION CODEGEN END +#endif //FS_MEASURE + + Addr addr = 0; + if (kernelSymtab->findAddress("est_cycle_freq", addr)) { + Addr paddr = vtophys(physmem, addr); + uint8_t *est_cycle_frequency = + physmem->dma_addr(paddr, sizeof(uint64_t)); + + if (est_cycle_frequency) + *(uint64_t *)est_cycle_frequency = ticksPerSecond; + } + + if (consoleSymtab->findAddress("env_booted_osflags", addr)) { + Addr paddr = vtophys(physmem, addr); + char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); + + if (osflags) + strcpy(osflags, boot_osflags.c_str()); + } + + if (kernelSymtab->findAddress("panic", addr)) + kernelPanicEvent->schedule(addr); + else + panic("could not find kernel symbol \'panic\'"); + + if (consoleSymtab->findAddress("panic", addr)) + consolePanicEvent->schedule(addr); + + if (kernelSymtab->findAddress("badaddr", addr)) + badaddrEvent->schedule(addr); + // else + //panic("could not find kernel symbol \'badaddr\'"); + + if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr)) + skipPowerStateEvent->schedule(addr); + + if (kernelSymtab->findAddress("pmap_scavenge_boot", addr)) + skipScavengeBootEvent->schedule(addr); + + if (kernelSymtab->findAddress("calibrate_delay", addr)) + skipDelayLoopEvent->schedule(addr+8); + +#if TRACING_ON + if (kernelSymtab->findAddress("printk", addr)) + printfEvent->schedule(addr); + + if (kernelSymtab->findAddress("m5printf", addr)) + debugPrintfEvent->schedule(addr); + + if (kernelSymtab->findAddress("m5printfr", addr)) + debugPrintfrEvent->schedule(addr); + + if (kernelSymtab->findAddress("m5_dump_mbuf", addr)) + dumpMbufEvent->schedule(addr); +#endif + +#ifdef FS_MEASURE + //INSTRUMENTATION CODEGEN BEGIN THREE + if (bin == true) { + if (kernelSymtab->findAddress("es_intr", addr)) + esIntrEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_intr\'"); + + if (kernelSymtab->findAddress("es_rxeof", addr)) + esRxeofEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_rxeof\'"); + + if (kernelSymtab->findAddress("es_newbuf", addr)) + esNewbufEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_newbuf\'"); + + if (kernelSymtab->findAddress("es_dma_load", addr)) + esDmaLoadEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_dma_load\'"); + + if (kernelSymtab->findAddress("dma_map_load", addr)) + dmaMapLoadEvent->schedule(addr); + else + panic("could not find kernel symbol \'dma_map_load\'"); + + if (kernelSymtab->findAddress("ether_input", addr)) + etherInputEvent->schedule(addr); + else + panic("could not find kernel symbol \'ether_input\'"); + + if (kernelSymtab->findAddress("netisr_input", addr)) + netisrInputEvent->schedule(addr); + else + panic("could not find kernel symbol \'netisr_input\'"); + + if (kernelSymtab->findAddress("schednetisr_isr", addr)) + schednetisrIsrEvent->schedule(addr); + else + panic("could not find kernel symbol \'schednetisr_isr\'"); + + if (kernelSymtab->findAddress("ipintr", addr)) + ipintrEvent->schedule(addr); + else + panic("could not find kernel symbol \'ipintr\'"); + + if (kernelSymtab->findAddress("ip_dooptions", addr)) + ipDooptionsEvent->schedule(addr); + else + panic("could not find kernel symbol \'ip_dooptions\'"); + + if (kernelSymtab->findAddress("ip_reass", addr)) + ipReassEvent->schedule(addr); + else + panic("could not find kernel symbol \'ip_reass\'"); + + if (kernelSymtab->findAddress("tcp_input", addr)) + tcpInputEvent->schedule(addr); + else + panic("could not find kernel symbol \'tcp_input\'"); + + if (kernelSymtab->findAddress("sbappend", addr)) + sbappendEvent->schedule(addr); + else + panic("could not find kernel symbol \'sbappend\'"); + + if (kernelSymtab->findAddress("read", addr)) + readEvent->schedule(addr); + else + panic("could not find kernel symbol \'read\'"); + + if (kernelSymtab->findAddress("soo_read", addr)) + sooReadEvent->schedule(addr); + else + panic("could not find kernel symbol \'soo_read\'"); + + if (kernelSymtab->findAddress("orecv", addr)) + orecvEvent->schedule(addr); + else + panic("could not find kernel symbol \'orecv\'"); + + if (kernelSymtab->findAddress("recvit", addr)) + recvitEvent->schedule(addr); + else + panic("could not find kernel symbol \'recvit\'"); + + if (kernelSymtab->findAddress("soreceive", addr)) + soreceiveEvent->schedule(addr); + else + panic("could not find kernel symbol \'soreceive\'"); + + if (kernelSymtab->findAddress("osend", addr)) + osendEvent->schedule(addr); + else + panic("could not find kernel symbol \'osend\'"); + + if (kernelSymtab->findAddress("write", addr)) + writeEvent->schedule(addr); + else + panic("could not find kernel symbol \'write\'"); + + if (kernelSymtab->findAddress("soo_write", addr)) + sooWriteEvent->schedule(addr); + else + panic("could not find kernel symbol \'soo_write\'"); + + if (kernelSymtab->findAddress("sendit", addr)) + senditEvent->schedule(addr); + else + panic("could not find kernel symbol \'sendit\'"); + + if (kernelSymtab->findAddress("sosend", addr)) + sosendEvent->schedule(addr); + else + panic("could not find kernel symbol \'sosend\'"); + + if (kernelSymtab->findAddress("tcp_sosend", addr)) + tcpSosendEvent->schedule(addr); + else + panic("could not find kernel symbol \'tcp_sosend\'"); + + if (kernelSymtab->findAddress("tcp_output", addr)) + tcpOutputEvent->schedule(addr); + else + panic("could not find kernel symbol \'tcp_output\'"); + + if (kernelSymtab->findAddress("ip_output", addr)) + ipOutputEvent->schedule(addr); + else + panic("could not find kernel symbol \'ip_output\'"); + + if (kernelSymtab->findAddress("ether_output", addr)) + etherOutputEvent->schedule(addr); + else + panic("could not find kernel symbol \'ether_output\'"); + + if (kernelSymtab->findAddress("es_start", addr)) + esStartEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_start\'"); + + if (kernelSymtab->findAddress("es_transmit", addr)) + esTransmitEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_transmit\'"); + + if (kernelSymtab->findAddress("es_txeof", addr)) + esTxeofEvent->schedule(addr); + else + panic("could not find kernel symbol \'es_txeof\'"); + + if (kernelSymtab->findAddress("idle_thread", addr)) + idleThreadEvent->schedule(addr); + else + panic("could not find kernel symbol \'idle_thread\'"); + + } + //INSTRUMENTATION CODEGEN END + if (bin == true) { + fnCalls + .name(name() + ":fnCalls") + .desc("all fn calls being tracked") + ; + + populateMap("es_intr", ""); + populateMap("es_rxeof", "es_intr"); + populateMap("es_newbuf", "es_rxeof"); + populateMap("es_dma_load", "es_newbuf"); + populateMap("dma_map_load", "es_dma_load"); + populateMap("ether_input", "es_rxeof"); + populateMap("netisr_input", "ether_input"); + populateMap("schednetisr_isr", "netisr_input"); + + populateMap("ipintr", ""); + populateMap("ip_dooptions", "ipintr"); + populateMap("ip_reass", "ipintr"); + populateMap("tcp_input", "ipintr"); + populateMap("sbappend", "tcp_input"); + + populateMap("read", ""); + populateMap("orecv", ""); + populateMap("soo_read", "read"); + populateMap("recvit", "orecv"); + populateMap("soreceive", "recvit"); + populateMap("soreceive", "soo_read"); + + populateMap("write", ""); + populateMap("osend", ""); + populateMap("soo_write", "write"); + populateMap("sendit", "osend"); + populateMap("sosend", "sendit"); + populateMap("sosend", "soo_write"); + populateMap("tcp_sosend", "sosend"); + populateMap("tcp_output", "tcp_sosend"); + populateMap("ip_output", "tcp_output"); + populateMap("ether_output", "ip_output"); + populateMap("es_start", "ether_output"); + populateMap("es_transmit", "es_start"); + + populateMap("es_txeof", "es_intr"); + + populateMap("idle_thread", ""); + } +#endif //FS_MEASURE +} + +LinuxSystem::~LinuxSystem() +{ + delete kernel; + delete console; + + delete kernelSymtab; + delete consoleSymtab; + delete bootloaderSymtab; + + delete kernelPanicEvent; + delete consolePanicEvent; + delete badaddrEvent; + delete skipPowerStateEvent; + delete skipScavengeBootEvent; + delete printfEvent; + /*delete debugPrintfEvent; + delete debugPrintfrEvent; + delete dumpMbufEvent; +*/ +#ifdef FS_MEASURE + //INSTRUMENTATION CODEGEN BEGIN FOUR + if (bin == true) { + delete esIntrEvent; + delete esRxeofEvent; + delete esNewbufEvent; + delete esDmaLoadEvent; + delete dmaMapLoadEvent; + delete etherInputEvent; + delete netisrInputEvent; + delete schednetisrIsrEvent; + delete ipintrEvent; + delete ipDooptionsEvent; + delete ipReassEvent; + delete tcpInputEvent; + delete sbappendEvent; + delete readEvent; + delete sooReadEvent; + delete orecvEvent; + delete recvitEvent; + delete soreceiveEvent; + delete osendEvent; + delete writeEvent; + delete sooWriteEvent; + delete senditEvent; + delete sosendEvent; + delete tcpSosendEvent; + delete tcpOutputEvent; + delete ipOutputEvent; + delete etherOutputEvent; + delete esStartEvent; + delete esTransmitEvent; + delete esTxeofEvent; + delete idleThreadEvent; + } + //INSTRUMENTATION CODEGEN END +#endif //FS_MEASURE +} + +void +LinuxSystem::setDelayLoop(ExecContext *xc) +{ + Addr addr = 0; + if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { + Addr paddr = vtophys(physmem, addr); + + uint8_t *loops_per_jiffy = + physmem->dma_addr(paddr, sizeof(uint32_t)); + + Tick cpuFreq = xc->cpu->getFreq(); + Tick intrFreq = platform->interrupt_frequency; + *(uint32_t *)loops_per_jiffy = + (uint32_t)((cpuFreq / intrFreq) * 0.9988); + } +} + +int +LinuxSystem::registerExecContext(ExecContext *xc) +{ + int xcIndex = System::registerExecContext(xc); + + if (xcIndex == 0) { + // activate with zero delay so that we start ticking right + // away on cycle 0 + xc->activate(0); + } + + RemoteGDB *rgdb = new RemoteGDB(this, xc); + GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); + gdbl->listen(); + + if (remoteGDB.size() <= xcIndex) { + remoteGDB.resize(xcIndex+1); + } + + remoteGDB[xcIndex] = rgdb; + + return xcIndex; +} + + +void +LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex) +{ + System::replaceExecContext(xcIndex, xc); + remoteGDB[xcIndex]->replaceExecContext(xc); +} + +bool +LinuxSystem::breakpoint() +{ + return remoteGDB[0]->trap(ALPHA_KENTRY_IF); +} + +#ifdef FS_MEASURE +void +LinuxSystem::populateMap(std::string callee, std::string caller) +{ + multimap<const string, string>::const_iterator i; + i = callerMap.insert(make_pair(callee, caller)); + assert(i != callerMap.end() && "should not fail populating callerMap"); +} + +bool +LinuxSystem::findCaller(std::string callee, std::string caller) const +{ + typedef multimap<const std::string, std::string>::const_iterator iter; + pair<iter, iter> range; + + range = callerMap.equal_range(callee); + for (iter i = range.first; i != range.second; ++i) { + if ((*i).second == caller) + return true; + } + return false; +} + +void +LinuxSystem::dumpState(ExecContext *xc) const +{ +#ifndef SW_DEBUG + return; +#endif + if (xc->swCtx) { + stack<fnCall *> copy(xc->swCtx->callStack); + if (copy.empty()) + return; + cprintf("xc->swCtx:\n"); + fnCall *top; + cprintf("|| call: %d\n",xc->swCtx->calls); + for (top = copy.top(); !copy.empty(); copy.pop() ) { + top = copy.top(); + cprintf("|| %13s : %s \n", top->name, top->myBin->name()); + } + } +} +#endif //FS_MEASURE + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) + + Param<bool> bin; + SimObjectParam<MemoryController *> mem_ctl; + SimObjectParam<PhysicalMemory *> physmem; + Param<uint64_t> init_param; + + Param<string> kernel_code; + Param<string> console_code; + Param<string> pal_code; + Param<string> boot_osflags; + Param<string> bootloader_code; + +END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) + +BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem) + + INIT_PARAM_DFLT(bin, "is this system to be binned", false), + INIT_PARAM(mem_ctl, "memory controller"), + INIT_PARAM(physmem, "phsyical memory"), + INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), + INIT_PARAM(kernel_code, "file that contains the kernel code"), + INIT_PARAM(console_code, "file that contains the console code"), + INIT_PARAM(pal_code, "file that contains palcode"), + INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", + "a"), + INIT_PARAM(bootloader_code, "file that contains the bootloader") + + +END_INIT_SIM_OBJECT_PARAMS(LinuxSystem) + +CREATE_SIM_OBJECT(LinuxSystem) +{ + LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl, + physmem, kernel_code, console_code, + pal_code, boot_osflags, bootloader_code, bin); + + return sys; +} + +REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem) diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh new file mode 100644 index 000000000..6aa29249a --- /dev/null +++ b/kern/linux/linux_system.hh @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINUX_SYSTEM_HH__ +#define __LINUX_SYSTEM_HH__ + +#include <vector> + +#include "sim/system.hh" +#include "targetarch/isa_traits.hh" + +#ifdef FS_MEASURE +#include <map> +#endif + +class ExecContext; +class ElfObject; +class SymbolTable; + +class BreakPCEvent; +class LinuxBadAddrEvent; +class LinuxSkipFuncEvent; +class LinuxSkipDelayLoopEvent; +class LinuxPrintfEvent; +class LinuxDebugPrintfEvent; +class LinuxDumpMbufEvent; +#ifdef FS_MEASURE +class FnEvent; +#endif +class AlphaArguments; + +class LinuxSystem : public System +{ + private: + ElfObject *kernel; + ElfObject *console; + ElfObject *bootloader; + + SymbolTable *kernelSymtab; + SymbolTable *bootloaderSymtab; + SymbolTable *consoleSymtab; + +#ifdef FS_MEASURE + //INSTRUMENTATION CODEGEN BEGIN ONE + Statistics::MainBin *esIntrBin; + Statistics::MainBin *esRxeofBin; + Statistics::MainBin *esNewbufBin; + Statistics::MainBin *esDmaLoadBin; + Statistics::MainBin *dmaMapLoadBin; + Statistics::MainBin *etherInputBin; + Statistics::MainBin *netisrInputBin; + Statistics::MainBin *schednetisrIsrBin; + Statistics::MainBin *ipintrBin; + Statistics::MainBin *ipDooptionsBin; + Statistics::MainBin *ipReassBin; + Statistics::MainBin *tcpInputBin; + Statistics::MainBin *sbappendBin; + Statistics::MainBin *readBin; + Statistics::MainBin *sooReadBin; + Statistics::MainBin *orecvBin; + Statistics::MainBin *recvitBin; + Statistics::MainBin *soreceiveBin; + Statistics::MainBin *osendBin; + Statistics::MainBin *writeBin; + Statistics::MainBin *sooWriteBin; + Statistics::MainBin *senditBin; + Statistics::MainBin *sosendBin; + Statistics::MainBin *tcpSosendBin; + Statistics::MainBin *tcpOutputBin; + Statistics::MainBin *ipOutputBin; + Statistics::MainBin *etherOutputBin; + Statistics::MainBin *esStartBin; + Statistics::MainBin *esTransmitBin; + Statistics::MainBin *esTxeofBin; + Statistics::MainBin *idleThreadBin; + //INSTRUMENTATION CODEGEN END +#endif //FS_MEASURE + + BreakPCEvent *kernelPanicEvent; + BreakPCEvent *consolePanicEvent; + LinuxBadAddrEvent *badaddrEvent; + LinuxSkipFuncEvent *skipPowerStateEvent; + LinuxSkipFuncEvent *skipScavengeBootEvent; + LinuxSkipDelayLoopEvent *skipDelayLoopEvent; + LinuxPrintfEvent *printfEvent; + LinuxDebugPrintfEvent *debugPrintfEvent; + LinuxDebugPrintfEvent *debugPrintfrEvent; + LinuxDumpMbufEvent *dumpMbufEvent; +#ifdef FS_MEASURE + //INSTRUMENTATION CODEGEN BEGIN TWO + FnEvent *esIntrEvent; + FnEvent *esRxeofEvent; + FnEvent *esNewbufEvent; + FnEvent *esDmaLoadEvent; + FnEvent *dmaMapLoadEvent; + FnEvent *etherInputEvent; + FnEvent *netisrInputEvent; + FnEvent *schednetisrIsrEvent; + FnEvent *ipintrEvent; + FnEvent *ipDooptionsEvent; + FnEvent *ipReassEvent; + FnEvent *tcpInputEvent; + FnEvent *sbappendEvent; + FnEvent *readEvent; + FnEvent *sooReadEvent; + FnEvent *orecvEvent; + FnEvent *recvitEvent; + FnEvent *soreceiveEvent; + FnEvent *osendEvent; + FnEvent *writeEvent; + FnEvent *sooWriteEvent; + FnEvent *senditEvent; + FnEvent *sosendEvent; + FnEvent *tcpSosendEvent; + FnEvent *tcpOutputEvent; + FnEvent *ipOutputEvent; + FnEvent *etherOutputEvent; + FnEvent *esStartEvent; + FnEvent *esTransmitEvent; + FnEvent *esTxeofEvent; + FnEvent *idleThreadEvent; + //INSTRUMENTATION CODEGEN END +#endif //FS_MEASURE + + private: + + Addr kernelStart; + Addr kernelEnd; + Addr kernelEntry; + bool bin; + +#ifdef FS_MEASURE + std::multimap<const std::string, std::string> callerMap; + void populateMap(std::string caller, std::string callee); +#endif + + public: + std::vector<RemoteGDB *> remoteGDB; + std::vector<GDBListener *> gdbListen; + + public: + LinuxSystem(const std::string _name, + const uint64_t _init_param, + MemoryController *_memCtrl, + PhysicalMemory *_physmem, + const std::string &kernel_path, + const std::string &console_path, + const std::string &palcode, + const std::string &boot_osflags, + const std::string &bootloader_path, + const bool _bin); + ~LinuxSystem(); + + void setDelayLoop(ExecContext *xc); + + int registerExecContext(ExecContext *xc); + void replaceExecContext(ExecContext *xc, int xcIndex); + + Addr getKernelStart() const { return kernelStart; } + Addr getKernelEnd() const { return kernelEnd; } + Addr getKernelEntry() const { return kernelEntry; } + bool breakpoint(); + + static void Printf(AlphaArguments args); + static void DumpMbuf(AlphaArguments args); + +#ifdef FS_MEASURE + bool findCaller(std::string callee, std::string caller) const; + void dumpState(ExecContext *xc) const; +#endif //FS_MEASURE +}; + +#endif // __LINUX_SYSTEM_HH__ diff --git a/sim/system.hh b/sim/system.hh index 8348a144e..e5d990e86 100644 --- a/sim/system.hh +++ b/sim/system.hh @@ -43,6 +43,7 @@ class MemoryController; class PhysicalMemory; +class Platform; class RemoteGDB; class GDBListener; @@ -60,6 +61,7 @@ class System : public SimObject const uint64_t init_param; MemoryController *memCtrl; PhysicalMemory *physmem; + Platform *platform; bool bin; PCEventQueue pcEventQueue; |