system.cc revision 860
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 48//un-comment this to see the state of call stack when it changes. 49//#define SW_DEBUG 50 51using namespace std; 52 53LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, 54 MemoryController *_memCtrl, PhysicalMemory *_physmem, 55 const string &kernel_path, const string &console_path, 56 const string &palcode, const string &boot_osflags, 57 const string &bootloader_path, const bool _bin) 58 : System(_name, _init_param, _memCtrl, _physmem, _bin), bin(_bin) 59{ 60 kernelSymtab = new SymbolTable; 61 consoleSymtab = new SymbolTable; 62 bootloaderSymtab = new SymbolTable; 63 64 ObjectFile *kernel = createObjectFile(kernel_path); 65 if (kernel == NULL) 66 fatal("Could not load kernel file %s", kernel_path); 67 68 ObjectFile *console = createObjectFile(console_path); 69 if (console == NULL) 70 fatal("Could not load console file %s", console_path); 71 72 ObjectFile *bootloader = createObjectFile(bootloader_path); 73 if (bootloader == NULL) 74 fatal("Could not load bootloader file %s", bootloader_path); 75 76 if (!kernel->loadGlobalSymbols(kernelSymtab)) 77 panic("could not load kernel symbols\n"); 78 debugSymbolTable = kernelSymtab; 79 80 if (!kernel->loadLocalSymbols(kernelSymtab)) 81 panic("could not load kernel local symbols\n"); 82 83 if (!console->loadGlobalSymbols(consoleSymtab)) 84 panic("could not load console symbols\n"); 85 86 if (!bootloader->loadGlobalSymbols(bootloaderSymtab)) 87 panic("could not load bootloader symbols\n"); 88 89 // Load pal file 90 ObjectFile *pal = createObjectFile(palcode); 91 if (pal == NULL) 92 fatal("Could not load PALcode file %s", palcode); 93 pal->loadSections(physmem, true); 94 95 // Load console file 96 console->loadSections(physmem, true); 97 98 // Load kernel file 99 kernel->loadSections(physmem, true); 100 kernelStart = kernel->textBase(); 101 kernelEnd = kernel->bssBase() + kernel->bssSize(); 102 /* FIXME: entrypoint not in kernel, but in bootloader, 103 variable should be re-named appropriately */ 104 kernelEntry = kernel->entryPoint(); 105 106 107 DPRINTF(Loader, "Kernel start = %#x\n" 108 "Kernel end = %#x\n" 109 "Kernel entry = %#x\n", 110 kernelStart, kernelEnd, kernelEntry); 111 112 DPRINTF(Loader, "Kernel loaded...\n"); 113 114 // Load bootloader file 115 bootloader->loadSections(physmem, true); 116 kernelEntry = bootloader->entryPoint(); 117 kernelStart = bootloader->textBase(); 118 DPRINTF(Loader, "Bootloader entry at %#x\n", kernelEntry); 119 120#ifdef DEBUG 121 kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); 122 consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); 123#endif 124 125 badaddrEvent = new LinuxBadAddrEvent(&pcEventQueue, "badaddr"); 126 skipPowerStateEvent = new LinuxSkipFuncEvent(&pcEventQueue, 127 "tl_v48_capture_power_state"); 128 skipScavengeBootEvent = new LinuxSkipFuncEvent(&pcEventQueue, 129 "pmap_scavenge_boot"); 130 printfEvent = new LinuxPrintfEvent(&pcEventQueue, "printf"); 131 132 skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue, 133 "ide_delay_50ms"); 134 135 skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, 136 "calibrate_delay"); 137 138 skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches"); 139 140 /* debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue, 141 "debug_printf", false); 142 debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue, 143 "debug_printfr", true); 144 dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf"); 145*/ 146 147 Addr addr = 0; 148 149 if (kernelSymtab->findAddress("est_cycle_freq", addr)) { 150 Addr paddr = vtophys(physmem, addr); 151 uint8_t *est_cycle_frequency = 152 physmem->dma_addr(paddr, sizeof(uint64_t)); 153 154 if (est_cycle_frequency) 155 *(uint64_t *)est_cycle_frequency = ticksPerSecond; 156 } 157 158 if (kernelSymtab->findAddress("aic7xxx_no_reset", addr)) { 159 Addr paddr = vtophys(physmem, addr); 160 uint8_t *aic7xxx_no_reset = 161 physmem->dma_addr(paddr, sizeof(uint32_t)); 162 163 if (aic7xxx_no_reset) { 164 *(uint32_t *)aic7xxx_no_reset = 1; 165 } 166 } 167 168 if (consoleSymtab->findAddress("env_booted_osflags", addr)) { 169 Addr paddr = vtophys(physmem, addr); 170 char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); 171 172 if (osflags) 173 strcpy(osflags, boot_osflags.c_str()); 174 } 175 176 if (consoleSymtab->findAddress("xxm_rpb", addr)) { 177 Addr paddr = vtophys(physmem, addr); 178 char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); 179 180 if (hwprb) { 181 *(uint64_t*)(hwprb+0x50) = 34; // Tsunami 182 *(uint64_t*)(hwprb+0x58) = (1<<10); 183 } 184 else 185 panic("could not translate hwprb addr to set system type/variation\n"); 186 187 } else 188 panic("could not find hwprb to set system type/variation\n"); 189 190#ifdef DEBUG 191 if (kernelSymtab->findAddress("panic", addr)) 192 kernelPanicEvent->schedule(addr); 193 else 194 panic("could not find kernel symbol \'panic\'"); 195 196 if (consoleSymtab->findAddress("panic", addr)) 197 consolePanicEvent->schedule(addr); 198#endif 199 200 if (kernelSymtab->findAddress("badaddr", addr)) 201 badaddrEvent->schedule(addr); 202 // else 203 //panic("could not find kernel symbol \'badaddr\'"); 204 205 if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr)) 206 skipPowerStateEvent->schedule(addr); 207 208 if (kernelSymtab->findAddress("pmap_scavenge_boot", addr)) 209 skipScavengeBootEvent->schedule(addr); 210 211 if (kernelSymtab->findAddress("ide_delay_50ms", addr)) 212 skipIdeDelay50msEvent->schedule(addr+8); 213 214 if (kernelSymtab->findAddress("calibrate_delay", addr)) 215 skipDelayLoopEvent->schedule(addr+8); 216 217 if (kernelSymtab->findAddress("determine_cpu_caches", addr)) 218 skipCacheProbeEvent->schedule(addr+8); 219 220#if TRACING_ON 221 if (kernelSymtab->findAddress("printk", addr)) 222 printfEvent->schedule(addr); 223 224 if (kernelSymtab->findAddress("m5printf", addr)) 225 debugPrintfEvent->schedule(addr); 226 227 if (kernelSymtab->findAddress("m5printfr", addr)) 228 debugPrintfrEvent->schedule(addr); 229 230 if (kernelSymtab->findAddress("m5_dump_mbuf", addr)) 231 dumpMbufEvent->schedule(addr); 232#endif 233} 234 235LinuxSystem::~LinuxSystem() 236{ 237 delete kernel; 238 delete console; 239 240 delete kernelSymtab; 241 delete consoleSymtab; 242 delete bootloaderSymtab; 243 244 delete kernelPanicEvent; 245 delete consolePanicEvent; 246 delete badaddrEvent; 247 delete skipPowerStateEvent; 248 delete skipScavengeBootEvent; 249 delete printfEvent; 250 /*delete debugPrintfEvent; 251 delete debugPrintfrEvent; 252 delete dumpMbufEvent; 253*/ 254} 255 256void 257LinuxSystem::setDelayLoop(ExecContext *xc) 258{ 259 Addr addr = 0; 260 if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { 261 Addr paddr = vtophys(physmem, addr); 262 263 uint8_t *loops_per_jiffy = 264 physmem->dma_addr(paddr, sizeof(uint32_t)); 265 266 Tick cpuFreq = xc->cpu->getFreq(); 267 Tick intrFreq = platform->interrupt_frequency; 268 *(uint32_t *)loops_per_jiffy = 269 (uint32_t)((cpuFreq / intrFreq) * 0.9988); 270 } 271} 272 273int 274LinuxSystem::registerExecContext(ExecContext *xc) 275{ 276 int xcIndex = System::registerExecContext(xc); 277 278 if (xcIndex == 0) { 279 // activate with zero delay so that we start ticking right 280 // away on cycle 0 281 xc->activate(0); 282 } 283 284 RemoteGDB *rgdb = new RemoteGDB(this, xc); 285 GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); 286 gdbl->listen(); 287// gdbl->accept(); 288 289 if (remoteGDB.size() <= xcIndex) { 290 remoteGDB.resize(xcIndex+1); 291 } 292 293 remoteGDB[xcIndex] = rgdb; 294 295 return xcIndex; 296} 297 298 299void 300LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex) 301{ 302 System::replaceExecContext(xcIndex, xc); 303 remoteGDB[xcIndex]->replaceExecContext(xc); 304} 305 306bool 307LinuxSystem::breakpoint() 308{ 309 return remoteGDB[0]->trap(ALPHA_KENTRY_IF); 310} 311 312void 313LinuxSystem::populateMap(std::string callee, std::string caller) 314{ 315 multimap<const string, string>::const_iterator i; 316 i = callerMap.insert(make_pair(callee, caller)); 317 assert(i != callerMap.end() && "should not fail populating callerMap"); 318} 319 320bool 321LinuxSystem::findCaller(std::string callee, std::string caller) const 322{ 323 typedef multimap<const std::string, std::string>::const_iterator iter; 324 pair<iter, iter> range; 325 326 range = callerMap.equal_range(callee); 327 for (iter i = range.first; i != range.second; ++i) { 328 if ((*i).second == caller) 329 return true; 330 } 331 return false; 332} 333 334void 335LinuxSystem::dumpState(ExecContext *xc) const 336{ 337#ifndef SW_DEBUG 338 return; 339#endif 340 if (xc->swCtx) { 341 stack<fnCall *> copy(xc->swCtx->callStack); 342 if (copy.empty()) 343 return; 344 cprintf("xc->swCtx:\n"); 345 fnCall *top; 346 cprintf("|| call: %d\n",xc->swCtx->calls); 347 for (top = copy.top(); !copy.empty(); copy.pop() ) { 348 top = copy.top(); 349 cprintf("|| %13s : %s \n", top->name, top->myBin->name()); 350 } 351 } 352} 353 354BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) 355 356 Param<bool> bin; 357 SimObjectParam<MemoryController *> mem_ctl; 358 SimObjectParam<PhysicalMemory *> physmem; 359 Param<uint64_t> init_param; 360 361 Param<string> kernel_code; 362 Param<string> console_code; 363 Param<string> pal_code; 364 Param<string> boot_osflags; 365 Param<string> bootloader_code; 366 367END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) 368 369BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 370 371 372 INIT_PARAM_DFLT(bin, "is this system to be binned", false), 373 INIT_PARAM(mem_ctl, "memory controller"), 374 INIT_PARAM(physmem, "phsyical memory"), 375 INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), 376 INIT_PARAM(kernel_code, "file that contains the code"), 377 INIT_PARAM(console_code, "file that contains the console code"), 378 INIT_PARAM(pal_code, "file that contains palcode"), 379 INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", 380 "a"), 381 INIT_PARAM(bootloader_code, "file that contains the bootloader") 382 383 384END_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 385 386CREATE_SIM_OBJECT(LinuxSystem) 387{ 388 LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl, 389 physmem, kernel_code, console_code, 390 pal_code, boot_osflags, bootloader_code, bin); 391 392 return sys; 393} 394 395REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem) 396