Now skips the calibrate_delay loop in the kernel boot

dev/tsunami.cc:
    Changed so Tsunami has a pointer to the System to which it belongs.
    Now it is derived from generic base class Platform so platform stuff
    can be accessed based on the system
dev/tsunami_io.cc:
dev/tsunami_io.hh:
    Cleanup and added copyright
kern/linux/linux_system.cc:
kern/linux/linux_system.hh:
    Added event to skip the "calibrate_delay" function, now calculate
    loops_per_jiffy based on frequency, interrupt frequency, and constant
sim/system.hh:
    Added pointer to generic Platform base class

--HG--
extra : convert_revision : 5bd925eec220a2ca48eb6164d2ecfdec96922c2c
This commit is contained in:
Andrew Schultz 2004-02-05 18:23:16 -05:00
parent 77a30ed48d
commit c76675be58
6 changed files with 242 additions and 177 deletions

View file

@ -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);
}

View file

@ -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");
}
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_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);
}

View file

@ -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);

View file

@ -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)
{

View file

@ -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);

View file

@ -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;