diff options
Diffstat (limited to 'kern/linux/linux_system.cc')
-rw-r--r-- | kern/linux/linux_system.cc | 125 |
1 files changed, 74 insertions, 51 deletions
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc index a0000fe33..6287ce470 100644 --- a/kern/linux/linux_system.cc +++ b/kern/linux/linux_system.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 The Regents of The University of Michigan + * Copyright (c) 2004 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +26,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * @file + * linux_system.cc loads the linux kernel, console, pal and patches certain functions. + * The symbol tables are loaded so that traces can show the executing function and we can + * skip functions. Various delay loops are skipped and their final values manually computed to + * speed up boot time. + */ + #include "base/loader/aout_object.hh" #include "base/loader/elf_object.hh" #include "base/loader/object_file.hh" @@ -36,6 +44,7 @@ #include "cpu/base_cpu.hh" #include "kern/linux/linux_events.hh" #include "kern/linux/linux_system.hh" +#include "kern/system_events.hh" #include "mem/functional_mem/memory_control.hh" #include "mem/functional_mem/physical_memory.hh" #include "sim/builder.hh" @@ -51,40 +60,26 @@ 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, - const vector<string> &_binned_fns) + const bool _bin, const vector<string> &_binned_fns) : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns), bin(_bin), binned_fns(_binned_fns) { kernelSymtab = new SymbolTable; consoleSymtab = new SymbolTable; - bootloaderSymtab = new SymbolTable; + /** + * Load the kernel, pal, and console code into memory + */ + // Load kernel code ObjectFile *kernel = createObjectFile(kernel_path); if (kernel == NULL) fatal("Could not load kernel file %s", kernel_path); + // Load Console Code 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 (!kernel->loadLocalSymbols(kernelSymtab)) - panic("could not load kernel local symbols\n"); - - 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) @@ -98,10 +93,18 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, 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(); + // load symbols + if (!kernel->loadGlobalSymbols(kernelSymtab)) + panic("could not load kernel symbols\n"); + debugSymbolTable = kernelSymtab; + + if (!kernel->loadLocalSymbols(kernelSymtab)) + panic("could not load kernel local symbols\n"); + + if (!console->loadGlobalSymbols(consoleSymtab)) + panic("could not load console symbols\n"); DPRINTF(Loader, "Kernel start = %#x\n" "Kernel end = %#x\n" @@ -110,27 +113,28 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, 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 DEBUG kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); #endif - skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue, - "ide_delay_50ms"); + skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, + "ide_delay_50ms"); skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, "calibrate_delay"); - skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches"); + skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue, + "determine_cpu_caches"); Addr addr = 0; + /** + * find the address of the est_cycle_freq variable and insert it so we don't + * through the lengthly process of trying to calculated it by using the PIT, + * RTC, etc. + */ if (kernelSymtab->findAddress("est_cycle_freq", addr)) { Addr paddr = vtophys(physmem, addr); uint8_t *est_cycle_frequency = @@ -140,31 +144,43 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, *(uint64_t *)est_cycle_frequency = ticksPerSecond; } - if (kernelSymtab->findAddress("aic7xxx_no_reset", addr)) { - Addr paddr = vtophys(physmem, addr); - uint8_t *aic7xxx_no_reset = - physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (aic7xxx_no_reset) { - *(uint32_t *)aic7xxx_no_reset = 1; - } - } + /** + * Copy the osflags (kernel arguments) into the consoles memory. Presently + * Linux does use the console service routine to get these command line + * arguments, but we might as well make them available just in case. + */ 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()); + strcpy(osflags, boot_osflags.c_str()); } + /** + * Since we aren't using a bootloader, we have to copy the kernel arguments + * directly into the kernels memory. + */ + { + Addr paddr = vtophys(physmem, PARAM_ADDR); + char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t)); + if (commandline) + strcpy(commandline, boot_osflags.c_str()); + } + + + /** + * Set the hardware reset parameter block system type and revision information + * to Tsunami. + */ if (consoleSymtab->findAddress("xxm_rpb", addr)) { Addr paddr = vtophys(physmem, addr); char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); if (hwprb) { *(uint64_t*)(hwprb+0x50) = 34; // Tsunami - *(uint64_t*)(hwprb+0x58) = (1<<10); + *(uint64_t*)(hwprb+0x58) = (1<<10); // Plain DP264 } else panic("could not translate hwprb addr to set system type/variation\n"); @@ -182,14 +198,20 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param, consolePanicEvent->schedule(addr); #endif + /** + * Any time ide_delay_50ms, calibarte_delay or determine_cpu_caches is called + * just skip the function. Currently determine_cpu_caches only is used put + * information in proc, however if that changes in the future we will have to + * fill in the cache size variables appropriately. + */ if (kernelSymtab->findAddress("ide_delay_50ms", addr)) - skipIdeDelay50msEvent->schedule(addr+8); + skipIdeDelay50msEvent->schedule(addr+sizeof(MachInst)); if (kernelSymtab->findAddress("calibrate_delay", addr)) - skipDelayLoopEvent->schedule(addr+8); + skipDelayLoopEvent->schedule(addr+sizeof(MachInst)); if (kernelSymtab->findAddress("determine_cpu_caches", addr)) - skipCacheProbeEvent->schedule(addr+8); + skipCacheProbeEvent->schedule(addr+sizeof(MachInst)); } LinuxSystem::~LinuxSystem() @@ -199,7 +221,6 @@ LinuxSystem::~LinuxSystem() delete kernelSymtab; delete consoleSymtab; - delete bootloaderSymtab; delete kernelPanicEvent; delete consolePanicEvent; @@ -208,6 +229,7 @@ LinuxSystem::~LinuxSystem() delete skipCacheProbeEvent; } + void LinuxSystem::setDelayLoop(ExecContext *xc) { @@ -239,7 +261,11 @@ LinuxSystem::registerExecContext(ExecContext *xc) RemoteGDB *rgdb = new RemoteGDB(this, xc); GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex); gdbl->listen(); -// gdbl->accept(); + /** + * Uncommenting this line waits for a remote debugger to connect + * to the simulator before continuing. + */ + //gdbl->accept(); if (remoteGDB.size() <= xcIndex) { remoteGDB.resize(xcIndex+1); @@ -275,7 +301,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) Param<string> console_code; Param<string> pal_code; Param<string> boot_osflags; - Param<string> bootloader_code; VectorParam<string> binned_fns; END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) @@ -292,7 +317,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 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"), INIT_PARAM(binned_fns, "functions to be broken down and binned") @@ -302,8 +326,7 @@ 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, binned_fns); + pal_code, boot_osflags, bin, binned_fns); return sys; } |