system.cc revision 1070
112967Smatteo.andreozzi@arm.com/* 212967Smatteo.andreozzi@arm.com * Copyright (c) 2004 The Regents of The University of Michigan 312967Smatteo.andreozzi@arm.com * All rights reserved. 412967Smatteo.andreozzi@arm.com * 512967Smatteo.andreozzi@arm.com * Redistribution and use in source and binary forms, with or without 612967Smatteo.andreozzi@arm.com * modification, are permitted provided that the following conditions are 712967Smatteo.andreozzi@arm.com * met: redistributions of source code must retain the above copyright 812967Smatteo.andreozzi@arm.com * notice, this list of conditions and the following disclaimer; 912967Smatteo.andreozzi@arm.com * redistributions in binary form must reproduce the above copyright 1012967Smatteo.andreozzi@arm.com * notice, this list of conditions and the following disclaimer in the 1112967Smatteo.andreozzi@arm.com * documentation and/or other materials provided with the distribution; 1212967Smatteo.andreozzi@arm.com * neither the name of the copyright holders nor the names of its 1312967Smatteo.andreozzi@arm.com * contributors may be used to endorse or promote products derived from 1412967Smatteo.andreozzi@arm.com * this software without specific prior written permission. 1512967Smatteo.andreozzi@arm.com * 1612967Smatteo.andreozzi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712967Smatteo.andreozzi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812967Smatteo.andreozzi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912967Smatteo.andreozzi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012967Smatteo.andreozzi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112967Smatteo.andreozzi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212967Smatteo.andreozzi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312967Smatteo.andreozzi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412967Smatteo.andreozzi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512967Smatteo.andreozzi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612967Smatteo.andreozzi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712967Smatteo.andreozzi@arm.com */ 2812967Smatteo.andreozzi@arm.com 2912967Smatteo.andreozzi@arm.com/** 3012967Smatteo.andreozzi@arm.com * @file 3112967Smatteo.andreozzi@arm.com * This code loads the linux kernel, console, pal and patches certain 3212967Smatteo.andreozzi@arm.com * functions. The symbol tables are loaded so that traces can show 3312967Smatteo.andreozzi@arm.com * the executing function and we can skip functions. Various delay 3412967Smatteo.andreozzi@arm.com * loops are skipped and their final values manually computed to speed 3512967Smatteo.andreozzi@arm.com * up boot time. 3612967Smatteo.andreozzi@arm.com */ 3712967Smatteo.andreozzi@arm.com 3812967Smatteo.andreozzi@arm.com#include "base/trace.hh" 3912967Smatteo.andreozzi@arm.com#include "cpu/exec_context.hh" 4012967Smatteo.andreozzi@arm.com#include "cpu/base_cpu.hh" 4112967Smatteo.andreozzi@arm.com#include "kern/linux/linux_events.hh" 4212967Smatteo.andreozzi@arm.com#include "kern/linux/linux_system.hh" 4312967Smatteo.andreozzi@arm.com#include "kern/system_events.hh" 4412967Smatteo.andreozzi@arm.com#include "mem/functional_mem/memory_control.hh" 4512967Smatteo.andreozzi@arm.com#include "mem/functional_mem/physical_memory.hh" 4612967Smatteo.andreozzi@arm.com#include "sim/builder.hh" 4712967Smatteo.andreozzi@arm.com#include "dev/platform.hh" 4812967Smatteo.andreozzi@arm.com#include "targetarch/isa_traits.hh" 4912967Smatteo.andreozzi@arm.com#include "targetarch/vtophys.hh" 5012967Smatteo.andreozzi@arm.com#include "sim/debug.hh" 5112967Smatteo.andreozzi@arm.com 5212967Smatteo.andreozzi@arm.comextern SymbolTable *debugSymbolTable; 5312967Smatteo.andreozzi@arm.com 5412967Smatteo.andreozzi@arm.comusing namespace std; 5512967Smatteo.andreozzi@arm.com 5612967Smatteo.andreozzi@arm.comLinuxSystem::LinuxSystem(Params *p) 5712967Smatteo.andreozzi@arm.com : System(p) 5812967Smatteo.andreozzi@arm.com{ 5912967Smatteo.andreozzi@arm.com Addr addr = 0; 6012967Smatteo.andreozzi@arm.com 6112967Smatteo.andreozzi@arm.com /** 6212967Smatteo.andreozzi@arm.com * find the address of the est_cycle_freq variable and insert it 6312967Smatteo.andreozzi@arm.com * so we don't through the lengthly process of trying to 6412967Smatteo.andreozzi@arm.com * calculated it by using the PIT, RTC, etc. 6512967Smatteo.andreozzi@arm.com */ 6612967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("est_cycle_freq", addr)) { 6712967Smatteo.andreozzi@arm.com Addr paddr = vtophys(physmem, addr); 6812967Smatteo.andreozzi@arm.com uint8_t *est_cycle_frequency = 6912967Smatteo.andreozzi@arm.com physmem->dma_addr(paddr, sizeof(uint64_t)); 7012967Smatteo.andreozzi@arm.com 7112967Smatteo.andreozzi@arm.com if (est_cycle_frequency) 7212967Smatteo.andreozzi@arm.com *(uint64_t *)est_cycle_frequency = htoa(ticksPerSecond); 7312967Smatteo.andreozzi@arm.com } 7412967Smatteo.andreozzi@arm.com 7512967Smatteo.andreozzi@arm.com 7612967Smatteo.andreozzi@arm.com /** 7712967Smatteo.andreozzi@arm.com * Since we aren't using a bootloader, we have to copy the kernel arguments 7812967Smatteo.andreozzi@arm.com * directly into the kernels memory. 7912967Smatteo.andreozzi@arm.com */ 8012967Smatteo.andreozzi@arm.com { 8112967Smatteo.andreozzi@arm.com Addr paddr = vtophys(physmem, PARAM_ADDR); 8212967Smatteo.andreozzi@arm.com char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t)); 8312967Smatteo.andreozzi@arm.com if (commandline) 8412967Smatteo.andreozzi@arm.com strcpy(commandline, params->boot_osflags.c_str()); 8512967Smatteo.andreozzi@arm.com } 8612967Smatteo.andreozzi@arm.com 8712967Smatteo.andreozzi@arm.com 8812967Smatteo.andreozzi@arm.com /** 8912967Smatteo.andreozzi@arm.com * EV5 only supports 127 ASNs so we are going to tell the kernel that the 9012967Smatteo.andreozzi@arm.com * paritiuclar EV6 we have only supports 127 asns. 9112967Smatteo.andreozzi@arm.com * @todo At some point we should change ev5.hh and the palcode to support 9212967Smatteo.andreozzi@arm.com * 255 ASNs. 9312967Smatteo.andreozzi@arm.com */ 9412967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("dp264_mv", addr)) { 9512967Smatteo.andreozzi@arm.com Addr paddr = vtophys(physmem, addr); 9612967Smatteo.andreozzi@arm.com char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); 9712967Smatteo.andreozzi@arm.com 9812967Smatteo.andreozzi@arm.com if (dp264_mv) { 9912967Smatteo.andreozzi@arm.com *(uint32_t*)(dp264_mv+0x18) = htoa((uint32_t)127); 10012967Smatteo.andreozzi@arm.com } else 10112967Smatteo.andreozzi@arm.com panic("could not translate dp264_mv addr\n"); 10212967Smatteo.andreozzi@arm.com 10312967Smatteo.andreozzi@arm.com } else 10412967Smatteo.andreozzi@arm.com panic("could not find dp264_mv\n"); 10512967Smatteo.andreozzi@arm.com 10612967Smatteo.andreozzi@arm.com#ifdef DEBUG 10712967Smatteo.andreozzi@arm.com kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); 10812967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("panic", addr)) 10912967Smatteo.andreozzi@arm.com kernelPanicEvent->schedule(addr); 11012967Smatteo.andreozzi@arm.com else 11112967Smatteo.andreozzi@arm.com panic("could not find kernel symbol \'panic\'"); 11212967Smatteo.andreozzi@arm.com#endif 11312967Smatteo.andreozzi@arm.com 11412967Smatteo.andreozzi@arm.com /** 11512967Smatteo.andreozzi@arm.com * Any time ide_delay_50ms, calibarte_delay or 11612967Smatteo.andreozzi@arm.com * determine_cpu_caches is called just skip the 11712967Smatteo.andreozzi@arm.com * function. Currently determine_cpu_caches only is used put 11812967Smatteo.andreozzi@arm.com * information in proc, however if that changes in the future we 11912967Smatteo.andreozzi@arm.com * will have to fill in the cache size variables appropriately. 12012967Smatteo.andreozzi@arm.com */ 12112967Smatteo.andreozzi@arm.com skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, "ide_delay_50ms"); 12212967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("ide_delay_50ms", addr)) 12312967Smatteo.andreozzi@arm.com skipIdeDelay50msEvent->schedule(addr+sizeof(MachInst)); 12412967Smatteo.andreozzi@arm.com 12512967Smatteo.andreozzi@arm.com skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue, 12612967Smatteo.andreozzi@arm.com "calibrate_delay"); 12712967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("calibrate_delay", addr)) 12812967Smatteo.andreozzi@arm.com skipDelayLoopEvent->schedule(addr+sizeof(MachInst)); 12912967Smatteo.andreozzi@arm.com 13012967Smatteo.andreozzi@arm.com skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue, 13112967Smatteo.andreozzi@arm.com "determine_cpu_caches"); 13212967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("determine_cpu_caches", addr)) 13312967Smatteo.andreozzi@arm.com skipCacheProbeEvent->schedule(addr+sizeof(MachInst)); 13412967Smatteo.andreozzi@arm.com 13512967Smatteo.andreozzi@arm.com debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk"); 13612967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("dprintk", addr)) 13712967Smatteo.andreozzi@arm.com debugPrintkEvent->schedule(addr+8); 13812967Smatteo.andreozzi@arm.com 13912967Smatteo.andreozzi@arm.com idleStartEvent = new IdleStartEvent(&pcEventQueue, "cpu_idle", this); 14012967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("cpu_idle", addr)) 14112967Smatteo.andreozzi@arm.com idleStartEvent->schedule(addr); 14212967Smatteo.andreozzi@arm.com 14312967Smatteo.andreozzi@arm.com printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo"); 14412967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) 14512967Smatteo.andreozzi@arm.com printThreadEvent->schedule(addr + sizeof(MachInst) * 6); 14612967Smatteo.andreozzi@arm.com} 14712967Smatteo.andreozzi@arm.com 14812967Smatteo.andreozzi@arm.comLinuxSystem::~LinuxSystem() 14912967Smatteo.andreozzi@arm.com{ 15012967Smatteo.andreozzi@arm.com#ifdef DEBUG 15112967Smatteo.andreozzi@arm.com delete kernelPanicEvent; 15212967Smatteo.andreozzi@arm.com#endif 15312967Smatteo.andreozzi@arm.com delete skipIdeDelay50msEvent; 15412967Smatteo.andreozzi@arm.com delete skipDelayLoopEvent; 15512967Smatteo.andreozzi@arm.com delete skipCacheProbeEvent; 15612967Smatteo.andreozzi@arm.com delete debugPrintkEvent; 15712967Smatteo.andreozzi@arm.com delete idleStartEvent; 15812967Smatteo.andreozzi@arm.com} 15912967Smatteo.andreozzi@arm.com 16012967Smatteo.andreozzi@arm.com 16112967Smatteo.andreozzi@arm.comvoid 16212967Smatteo.andreozzi@arm.comLinuxSystem::setDelayLoop(ExecContext *xc) 16312967Smatteo.andreozzi@arm.com{ 16412967Smatteo.andreozzi@arm.com Addr addr = 0; 16512967Smatteo.andreozzi@arm.com if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { 16612967Smatteo.andreozzi@arm.com Addr paddr = vtophys(physmem, addr); 16712967Smatteo.andreozzi@arm.com 16812967Smatteo.andreozzi@arm.com uint8_t *loops_per_jiffy = 16912967Smatteo.andreozzi@arm.com physmem->dma_addr(paddr, sizeof(uint32_t)); 17012967Smatteo.andreozzi@arm.com 17112967Smatteo.andreozzi@arm.com Tick cpuFreq = xc->cpu->getFreq(); 17212967Smatteo.andreozzi@arm.com Tick intrFreq = platform->interrupt_frequency; 17312967Smatteo.andreozzi@arm.com *(uint32_t *)loops_per_jiffy = 17412967Smatteo.andreozzi@arm.com (uint32_t)((cpuFreq / intrFreq) * 0.9988); 17512967Smatteo.andreozzi@arm.com } 17612967Smatteo.andreozzi@arm.com} 17712967Smatteo.andreozzi@arm.com 17812967Smatteo.andreozzi@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) 17912967Smatteo.andreozzi@arm.com 18012967Smatteo.andreozzi@arm.com SimObjectParam<MemoryController *> mem_ctl; 18112967Smatteo.andreozzi@arm.com SimObjectParam<PhysicalMemory *> physmem; 18212967Smatteo.andreozzi@arm.com 18312967Smatteo.andreozzi@arm.com Param<string> kernel_code; 18412967Smatteo.andreozzi@arm.com Param<string> console_code; 18512967Smatteo.andreozzi@arm.com Param<string> pal_code; 18612967Smatteo.andreozzi@arm.com 18712967Smatteo.andreozzi@arm.com Param<string> boot_osflags; 18812967Smatteo.andreozzi@arm.com Param<string> readfile; 18912967Smatteo.andreozzi@arm.com Param<unsigned int> init_param; 19012967Smatteo.andreozzi@arm.com 19112967Smatteo.andreozzi@arm.com Param<uint64_t> system_type; 19212967Smatteo.andreozzi@arm.com Param<uint64_t> system_rev; 19312967Smatteo.andreozzi@arm.com 19412967Smatteo.andreozzi@arm.com Param<bool> bin; 19512967Smatteo.andreozzi@arm.com VectorParam<string> binned_fns; 19612967Smatteo.andreozzi@arm.com 19712967Smatteo.andreozzi@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem) 19812967Smatteo.andreozzi@arm.com 19912967Smatteo.andreozzi@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 20012967Smatteo.andreozzi@arm.com 20112967Smatteo.andreozzi@arm.com INIT_PARAM(mem_ctl, "memory controller"), 20212967Smatteo.andreozzi@arm.com INIT_PARAM(physmem, "phsyical memory"), 20312967Smatteo.andreozzi@arm.com INIT_PARAM(kernel_code, "file that contains the kernel code"), 20412967Smatteo.andreozzi@arm.com INIT_PARAM(console_code, "file that contains the console code"), 20512967Smatteo.andreozzi@arm.com INIT_PARAM(pal_code, "file that contains palcode"), 20612967Smatteo.andreozzi@arm.com INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", 20712967Smatteo.andreozzi@arm.com "a"), 20812967Smatteo.andreozzi@arm.com INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), 20912967Smatteo.andreozzi@arm.com INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), 21012967Smatteo.andreozzi@arm.com INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), 21112967Smatteo.andreozzi@arm.com INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), 21212967Smatteo.andreozzi@arm.com INIT_PARAM_DFLT(bin, "is this system to be binned", false), 21312967Smatteo.andreozzi@arm.com INIT_PARAM(binned_fns, "functions to be broken down and binned") 21412967Smatteo.andreozzi@arm.com 21512967Smatteo.andreozzi@arm.comEND_INIT_SIM_OBJECT_PARAMS(LinuxSystem) 21612967Smatteo.andreozzi@arm.com 21712967Smatteo.andreozzi@arm.comCREATE_SIM_OBJECT(LinuxSystem) 21812967Smatteo.andreozzi@arm.com{ 21912967Smatteo.andreozzi@arm.com System::Params *p = new System::Params; 22012967Smatteo.andreozzi@arm.com p->name = getInstanceName(); 22112967Smatteo.andreozzi@arm.com p->memctrl = mem_ctl; 22212967Smatteo.andreozzi@arm.com p->physmem = physmem; 22312967Smatteo.andreozzi@arm.com p->kernel_path = kernel_code; 22412967Smatteo.andreozzi@arm.com p->console_path = console_code; 22512967Smatteo.andreozzi@arm.com p->palcode = pal_code; 22612967Smatteo.andreozzi@arm.com p->boot_osflags = boot_osflags; 22712967Smatteo.andreozzi@arm.com p->init_param = init_param; 22812967Smatteo.andreozzi@arm.com p->readfile = readfile; 22912967Smatteo.andreozzi@arm.com p->system_type = system_type; 23012967Smatteo.andreozzi@arm.com p->system_rev = system_rev; 23112967Smatteo.andreozzi@arm.com p->bin = bin; 23212967Smatteo.andreozzi@arm.com p->binned_fns = binned_fns; 23312967Smatteo.andreozzi@arm.com 23412967Smatteo.andreozzi@arm.com return new LinuxSystem(p); 23512967Smatteo.andreozzi@arm.com} 23612967Smatteo.andreozzi@arm.com 23712967Smatteo.andreozzi@arm.comREGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem) 23812967Smatteo.andreozzi@arm.com 23912967Smatteo.andreozzi@arm.com