system.cc revision 882
1/* 2 * Copyright (c) 2003 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "base/loader/aout_object.hh" 30#include "base/loader/elf_object.hh" 31#include "base/loader/object_file.hh" 32#include "base/loader/symtab.hh" 33#include "base/remote_gdb.hh" 34#include "base/trace.hh" 35#include "cpu/exec_context.hh" 36#include "cpu/base_cpu.hh" 37#include "kern/linux/linux_events.hh" 38#include "kern/linux/linux_system.hh" 39#include "mem/functional_mem/memory_control.hh" 40#include "mem/functional_mem/physical_memory.hh" 41#include "sim/builder.hh" 42#include "dev/platform.hh" 43#include "targetarch/isa_traits.hh" 44#include "targetarch/vtophys.hh" 45 46extern SymbolTable *debugSymbolTable; 47 48using namespace std; 49 50LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, 51 MemoryController *_memCtrl, PhysicalMemory *_physmem, 52 const string &kernel_path, const string &console_path, 53 const string &palcode, const string &boot_osflags, 54 const bool _bin, const vector<string> &_binned_fns) 55 : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns), 56 bin(_bin), binned_fns(_binned_fns) 57{ 58 kernelSymtab = new SymbolTable; 59 consoleSymtab = new SymbolTable; 60 61 // Load kernel code 62 ObjectFile *kernel = createObjectFile(kernel_path); 63 if (kernel == NULL) 64 fatal("Could not load kernel file %s", kernel_path); 65 66 // Load Console Code 67 ObjectFile *console = createObjectFile(console_path); 68 if (console == NULL) 69 fatal("Could not load console file %s", console_path); 70 71 // Load pal file 72 ObjectFile *pal = createObjectFile(palcode); 73 if (pal == NULL) 74 fatal("Could not load PALcode file %s", palcode); 75 pal->loadSections(physmem, true); 76 77 // Load console file 78 console->loadSections(physmem, true); 79 80 // Load kernel file 81 kernel->loadSections(physmem, true); 82 kernelStart = kernel->textBase(); 83 kernelEnd = kernel->bssBase() + kernel->bssSize(); 84 kernelEntry = kernel->entryPoint(); 85 86 // load symbols 87 if (!kernel->loadGlobalSymbols(kernelSymtab)) 88 panic("could not load kernel symbols\n"); 89 debugSymbolTable = kernelSymtab; 90 91 if (!kernel->loadLocalSymbols(kernelSymtab)) 92 panic("could not load kernel local symbols\n"); 93 94 if (!console->loadGlobalSymbols(consoleSymtab)) 95 panic("could not load console symbols\n"); 96 97 DPRINTF(Loader, "Kernel start = %#x\n" 98 "Kernel end = %#x\n" 99 "Kernel entry = %#x\n", 100 kernelStart, kernelEnd, kernelEntry); 101 102 DPRINTF(Loader, "Kernel loaded...\n"); 103 104 105#ifdef DEBUG 106 kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); 107 consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); 108#endif 109 110 skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue, 111 "ide_delay_50ms"); 112 113 skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, 114 "calibrate_delay"); 115 116 skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches"); 117 118 Addr addr = 0; 119 120 if (kernelSymtab->findAddress("est_cycle_freq", addr)) { 121 Addr paddr = vtophys(physmem, addr); 122 uint8_t *est_cycle_frequency = 123 physmem->dma_addr(paddr, sizeof(uint64_t)); 124 125 if (est_cycle_frequency) 126 *(uint64_t *)est_cycle_frequency = ticksPerSecond; 127 } 128 129 130 if (consoleSymtab->findAddress("env_booted_osflags", addr)) { 131 Addr paddr = vtophys(physmem, addr); 132 char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); 133 134 if (osflags) 135 strcpy(osflags, boot_osflags.c_str()); 136 } 137 138 { 139 Addr paddr = vtophys(physmem, PARAM_ADDR); 140 char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t)); 141 if (commandline) 142 strcpy(commandline, boot_osflags.c_str()); 143 } 144 145 146 if (consoleSymtab->findAddress("xxm_rpb", addr)) { 147 Addr paddr = vtophys(physmem, addr); 148 char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); 149 150 if (hwprb) { 151 *(uint64_t*)(hwprb+0x50) = 34; // Tsunami 152 *(uint64_t*)(hwprb+0x58) = (1<<10); 153 } 154 else 155 panic("could not translate hwprb addr to set system type/variation\n"); 156 157 } else 158 panic("could not find hwprb to set system type/variation\n"); 159 160#ifdef DEBUG 161 if (kernelSymtab->findAddress("panic", addr)) 162 kernelPanicEvent->schedule(addr); 163 else 164 panic("could not find kernel symbol \'panic\'"); 165 166 if (consoleSymtab->findAddress("panic", addr)) 167 consolePanicEvent->schedule(addr); 168#endif 169 170 if (kernelSymtab->findAddress("ide_delay_50ms", addr)) 171 skipIdeDelay50msEvent->schedule(addr+8); 172 173 if (kernelSymtab->findAddress("calibrate_delay", addr)) 174 skipDelayLoopEvent->schedule(addr+8); 175 176 if (kernelSymtab->findAddress("determine_cpu_caches", addr)) 177 skipCacheProbeEvent->schedule(addr+8); 178} 179 180LinuxSystem::~LinuxSystem() 181{ 182 delete kernel; 183 delete console; 184 185 delete kernelSymtab; 186 delete consoleSymtab; 187 188 delete kernelPanicEvent; 189 delete consolePanicEvent; 190 delete skipIdeDelay50msEvent; 191 delete skipDelayLoopEvent; 192 delete skipCacheProbeEvent; 193} 194 195 196void 197LinuxSystem::setDelayLoop(ExecContext *xc) 198{ 199 Addr addr = 0; 200 if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { 201 Addr paddr = vtophys(physmem, addr); 202 203 uint8_t *loops_per_jiffy = 204 physmem->dma_addr(paddr, sizeof(uint32_t)); 205 206 Tick cpuFreq = xc->cpu->getFreq(); 207 Tick intrFreq = platform->interrupt_frequency; 208 *(uint32_t *)loops_per_jiffy = 209 (uint32_t)((cpuFreq / intrFreq) * 0.9988); 210 } 211} 212 213int 214LinuxSystem::registerExecContext(ExecContext *xc) 215{ 216 int xcIndex = System::registerExecContext(xc); 217 218 if (xcIndex == 0) { 219 // activate with zero delay so that we start ticking right 220 // away on cycle 0 221 xc->activate(0); 222 } 223 224 RemoteGDB *rgdb = new RemoteGDB(this, xc); 225 GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); 226 gdbl->listen(); 227// gdbl->accept(); 228 229 if (remoteGDB.size() <= xcIndex) { 230 remoteGDB.resize(xcIndex+1); 231 } 232 233 remoteGDB[xcIndex] = rgdb; 234 235 return xcIndex; 236} 237 238 239void 240LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex) 241{ 242 System::replaceExecContext(xcIndex, xc); 243 remoteGDB[xcIndex]->replaceExecContext(xc); 244} 245 246bool 247LinuxSystem::breakpoint() 248{ 249 return remoteGDB[0]->trap(ALPHA_KENTRY_IF); 250} 251 252BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) 253 254 Param<bool> bin; 255 SimObjectParam<MemoryController *> mem_ctl; 256 SimObjectParam<PhysicalMemory *> physmem; 257 Param<uint64_t> init_param; 258 259 Param<string> kernel_code; 260 Param<string> console_code; 261 Param<string> pal_code; 262 Param<string> boot_osflags; 263 VectorParam<string> binned_fns; 264 265END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) 266 267BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 268 269 270 INIT_PARAM_DFLT(bin, "is this system to be binned", false), 271 INIT_PARAM(mem_ctl, "memory controller"), 272 INIT_PARAM(physmem, "phsyical memory"), 273 INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), 274 INIT_PARAM(kernel_code, "file that contains the code"), 275 INIT_PARAM(console_code, "file that contains the console code"), 276 INIT_PARAM(pal_code, "file that contains palcode"), 277 INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", 278 "a"), 279 INIT_PARAM(binned_fns, "functions to be broken down and binned") 280 281 282END_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 283 284CREATE_SIM_OBJECT(LinuxSystem) 285{ 286 LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl, 287 physmem, kernel_code, console_code, 288 pal_code, boot_osflags, bin, binned_fns); 289 290 return sys; 291} 292 293REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem) 294