summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dev/tsunami.cc14
-rw-r--r--dev/tsunami_io.cc309
-rw-r--r--dev/tsunami_io.hh64
-rw-r--r--kern/linux/linux_system.cc26
-rw-r--r--kern/linux/linux_system.hh4
-rw-r--r--sim/system.hh2
6 files changed, 242 insertions, 177 deletions
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index 42281c507..04ab922b9 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -43,11 +43,13 @@
using namespace std;
-Tsunami::Tsunami(const string &name, EtherDev *e, SimConsole *con,
+Tsunami::Tsunami(const string &name, System *s, SimConsole *con,
IntrControl *ic, int intr_freq)
- : SimObject(name), intrctrl(ic), cons(con), ethernet(e),
- interrupt_frequency(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;
}
@@ -66,7 +68,7 @@ Tsunami::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
- SimObjectParam<EtherDev *> ethernet;
+ SimObjectParam<System *> system;
SimObjectParam<SimConsole *> cons;
SimObjectParam<IntrControl *> intrctrl;
Param<int> interrupt_frequency;
@@ -75,7 +77,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami)
- INIT_PARAM(ethernet, "ethernet controller"),
+ INIT_PARAM(system, "system"),
INIT_PARAM(cons, "system console"),
INIT_PARAM(intrctrl, "interrupt controller"),
INIT_PARAM_DFLT(interrupt_frequency, "frequency of interrupts", 1024)
@@ -84,7 +86,7 @@ END_INIT_SIM_OBJECT_PARAMS(Tsunami)
CREATE_SIM_OBJECT(Tsunami)
{
- return new Tsunami(getInstanceName(), ethernet, cons, intrctrl,
+ return new Tsunami(getInstanceName(), system, cons, intrctrl,
interrupt_frequency);
}
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 79fc4cb51..25323ee14 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -1,4 +1,30 @@
-/* $Id$ */
+/*
+ * 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
@@ -25,7 +51,6 @@ using namespace std;
#define UNIX_YEAR_OFFSET 52
-
// Timer Event for Periodic interrupt of RTC
TsunamiIO::RTCEvent::RTCEvent(Tsunami* t)
: Event(&mainEventQueue), tsunami(t)
@@ -66,7 +91,7 @@ TsunamiIO::ClockEvent::process()
{
DPRINTF(Tsunami, "Timer Interrupt\n");
if (mode == 0)
- status = 0x20; // set bit that linux is looking for
+ status = 0x20; // set bit that linux is looking for
else
schedule(curTick + interval);
}
@@ -99,13 +124,13 @@ TsunamiIO::ClockEvent::Status()
return status;
}
-
-
-
TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
- Addr addr, Addr mask, MemoryController *mmu)
+ Addr addr, Addr mask, MemoryController *mmu)
: MmapDevice(name, addr, mask, mmu), tsunami(t), rtc(t)
{
+ // set the back pointer from tsunami to myself
+ tsunami->io = this;
+
timerData = 0;
set_time(init_time == 0 ? time(NULL) : init_time);
uip = 1;
@@ -131,62 +156,63 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
// 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(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");
}
- 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);
+
+ 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);
+ panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
return No_Fault;
}
@@ -203,87 +229,88 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
Addr daddr = (req->paddr & addr_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(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;
}
- 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;
+ 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);
}
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index 9ebf61481..aa77645f3 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -56,19 +56,19 @@ class TsunamiIO : public MmapDevice
class ClockEvent : public Event
{
- protected:
- Tick interval;
- uint8_t mode;
- uint8_t status;
+ protected:
+ Tick interval;
+ uint8_t mode;
+ uint8_t status;
- public:
- ClockEvent();
+ public:
+ ClockEvent();
- virtual void process();
- virtual const char *description();
- void Program(int count);
- void ChangeMode(uint8_t mode);
- uint8_t Status();
+ virtual void process();
+ virtual const char *description();
+ void Program(int count);
+ void ChangeMode(uint8_t mode);
+ uint8_t Status();
};
@@ -83,41 +83,45 @@ class TsunamiIO : public MmapDevice
virtual const char *description();
};
- uint8_t uip;
+ uint8_t uip;
- uint8_t mask1;
- uint8_t mask2;
- uint8_t mode1;
- uint8_t mode2;
+ 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 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;
+ /*
+ * 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;
+ RTCEvent rtc;
- uint32_t timerData;
+ uint32_t timerData;
public:
uint32_t frequency() const { return RTC_RATE; }
TsunamiIO(const std::string &name, Tsunami *t, time_t init_time,
- Addr addr, Addr mask, MemoryController *mmu);
+ Addr addr, Addr mask, MemoryController *mmu);
void set_time(time_t t);
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc
index db67c5619..798577ba5 100644
--- a/kern/linux/linux_system.cc
+++ b/kern/linux/linux_system.cc
@@ -33,11 +33,13 @@
#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"
@@ -220,6 +222,10 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
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,
@@ -301,6 +307,9 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
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);
@@ -581,6 +590,23 @@ LinuxSystem::~LinuxSystem()
#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)
{
diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh
index cfb20f6dc..6aa29249a 100644
--- a/kern/linux/linux_system.hh
+++ b/kern/linux/linux_system.hh
@@ -45,6 +45,7 @@ class SymbolTable;
class BreakPCEvent;
class LinuxBadAddrEvent;
class LinuxSkipFuncEvent;
+class LinuxSkipDelayLoopEvent;
class LinuxPrintfEvent;
class LinuxDebugPrintfEvent;
class LinuxDumpMbufEvent;
@@ -105,6 +106,7 @@ class LinuxSystem : public System
LinuxBadAddrEvent *badaddrEvent;
LinuxSkipFuncEvent *skipPowerStateEvent;
LinuxSkipFuncEvent *skipScavengeBootEvent;
+ LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
LinuxPrintfEvent *printfEvent;
LinuxDebugPrintfEvent *debugPrintfEvent;
LinuxDebugPrintfEvent *debugPrintfrEvent;
@@ -174,6 +176,8 @@ class LinuxSystem : public System
const bool _bin);
~LinuxSystem();
+ void setDelayLoop(ExecContext *xc);
+
int registerExecContext(ExecContext *xc);
void replaceExecContext(ExecContext *xc, int xcIndex);
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;