system.cc revision 2215
14166Sgblack@eecs.umich.edu/* 24166Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 34166Sgblack@eecs.umich.edu * All rights reserved. 44166Sgblack@eecs.umich.edu * 54166Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64166Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 74166Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 84166Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 94166Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 104166Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 114166Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 124166Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 134166Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 144166Sgblack@eecs.umich.edu * this software without specific prior written permission. 154166Sgblack@eecs.umich.edu * 164166Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174166Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184166Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194166Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204166Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214166Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224166Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234166Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244166Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254166Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264166Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274166Sgblack@eecs.umich.edu */ 284166Sgblack@eecs.umich.edu 294166Sgblack@eecs.umich.edu#include "arch/alpha/system.hh" 304166Sgblack@eecs.umich.edu#include "arch/vtophys.hh" 314166Sgblack@eecs.umich.edu#include "base/remote_gdb.hh" 324166Sgblack@eecs.umich.edu#include "base/loader/object_file.hh" 334166Sgblack@eecs.umich.edu#include "base/loader/symtab.hh" 344166Sgblack@eecs.umich.edu#include "base/trace.hh" 354166Sgblack@eecs.umich.edu#include "mem/functional/memory_control.hh" 364166Sgblack@eecs.umich.edu#include "mem/functional/physical.hh" 374166Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 384166Sgblack@eecs.umich.edu#include "sim/builder.hh" 394166Sgblack@eecs.umich.edu 404166Sgblack@eecs.umich.eduusing namespace LittleEndianGuest; 414166Sgblack@eecs.umich.edu 424166Sgblack@eecs.umich.eduAlphaSystem::AlphaSystem(Params *p) 434166Sgblack@eecs.umich.edu : System(p) 444166Sgblack@eecs.umich.edu{ 454166Sgblack@eecs.umich.edu consoleSymtab = new SymbolTable; 464166Sgblack@eecs.umich.edu palSymtab = new SymbolTable; 474166Sgblack@eecs.umich.edu 484166Sgblack@eecs.umich.edu 494166Sgblack@eecs.umich.edu /** 504166Sgblack@eecs.umich.edu * Load the pal, and console code into memory 514166Sgblack@eecs.umich.edu */ 524166Sgblack@eecs.umich.edu // Load Console Code 534166Sgblack@eecs.umich.edu console = createObjectFile(params()->console_path); 544166Sgblack@eecs.umich.edu if (console == NULL) 554166Sgblack@eecs.umich.edu fatal("Could not load console file %s", params()->console_path); 564166Sgblack@eecs.umich.edu 574166Sgblack@eecs.umich.edu // Load pal file 584166Sgblack@eecs.umich.edu pal = createObjectFile(params()->palcode); 594166Sgblack@eecs.umich.edu if (pal == NULL) 604166Sgblack@eecs.umich.edu fatal("Could not load PALcode file %s", params()->palcode); 614166Sgblack@eecs.umich.edu 624166Sgblack@eecs.umich.edu 634166Sgblack@eecs.umich.edu // Load program sections into memory 644166Sgblack@eecs.umich.edu pal->loadSections(physmem, true); 654166Sgblack@eecs.umich.edu console->loadSections(physmem, true); 664166Sgblack@eecs.umich.edu 674166Sgblack@eecs.umich.edu // load symbols 684166Sgblack@eecs.umich.edu if (!console->loadGlobalSymbols(consoleSymtab)) 694166Sgblack@eecs.umich.edu panic("could not load console symbols\n"); 704166Sgblack@eecs.umich.edu 714166Sgblack@eecs.umich.edu if (!pal->loadGlobalSymbols(palSymtab)) 724166Sgblack@eecs.umich.edu panic("could not load pal symbols\n"); 734166Sgblack@eecs.umich.edu 744166Sgblack@eecs.umich.edu if (!pal->loadLocalSymbols(palSymtab)) 754166Sgblack@eecs.umich.edu panic("could not load pal symbols\n"); 764166Sgblack@eecs.umich.edu 774166Sgblack@eecs.umich.edu if (!console->loadGlobalSymbols(debugSymbolTable)) 784166Sgblack@eecs.umich.edu panic("could not load console symbols\n"); 794166Sgblack@eecs.umich.edu 804166Sgblack@eecs.umich.edu if (!pal->loadGlobalSymbols(debugSymbolTable)) 814166Sgblack@eecs.umich.edu panic("could not load pal symbols\n"); 824166Sgblack@eecs.umich.edu 834166Sgblack@eecs.umich.edu if (!pal->loadLocalSymbols(debugSymbolTable)) 844166Sgblack@eecs.umich.edu panic("could not load pal symbols\n"); 854166Sgblack@eecs.umich.edu 864166Sgblack@eecs.umich.edu Addr addr = 0; 874166Sgblack@eecs.umich.edu#ifndef NDEBUG 884166Sgblack@eecs.umich.edu consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic"); 894166Sgblack@eecs.umich.edu#endif 904166Sgblack@eecs.umich.edu 914863Sgblack@eecs.umich.edu /** 924166Sgblack@eecs.umich.edu * Copy the osflags (kernel arguments) into the consoles 934166Sgblack@eecs.umich.edu * memory. (Presently Linux does not use the console service 944166Sgblack@eecs.umich.edu * routine to get these command line arguments, but Tru64 and 954166Sgblack@eecs.umich.edu * others do.) 964166Sgblack@eecs.umich.edu */ 974166Sgblack@eecs.umich.edu if (consoleSymtab->findAddress("env_booted_osflags", addr)) { 984166Sgblack@eecs.umich.edu Addr paddr = vtophys(physmem, addr); 994434Ssaidi@eecs.umich.edu char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); 1004166Sgblack@eecs.umich.edu 1014166Sgblack@eecs.umich.edu if (osflags) 1024166Sgblack@eecs.umich.edu strcpy(osflags, params()->boot_osflags.c_str()); 1034166Sgblack@eecs.umich.edu } 1044166Sgblack@eecs.umich.edu 1054166Sgblack@eecs.umich.edu /** 1064166Sgblack@eecs.umich.edu * Set the hardware reset parameter block system type and revision 1074166Sgblack@eecs.umich.edu * information to Tsunami. 1084166Sgblack@eecs.umich.edu */ 1094166Sgblack@eecs.umich.edu if (consoleSymtab->findAddress("m5_rpb", addr)) { 1104166Sgblack@eecs.umich.edu Addr paddr = vtophys(physmem, addr); 1114166Sgblack@eecs.umich.edu char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); 1124166Sgblack@eecs.umich.edu 1134166Sgblack@eecs.umich.edu if (!hwrpb) 1144166Sgblack@eecs.umich.edu panic("could not translate hwrpb addr\n"); 1154166Sgblack@eecs.umich.edu 1164166Sgblack@eecs.umich.edu *(uint64_t*)(hwrpb+0x50) = htog(params()->system_type); 1174166Sgblack@eecs.umich.edu *(uint64_t*)(hwrpb+0x58) = htog(params()->system_rev); 1184166Sgblack@eecs.umich.edu } else 1194166Sgblack@eecs.umich.edu panic("could not find hwrpb\n"); 1204166Sgblack@eecs.umich.edu 1214166Sgblack@eecs.umich.edu} 1224166Sgblack@eecs.umich.edu 1234166Sgblack@eecs.umich.eduAlphaSystem::~AlphaSystem() 1244166Sgblack@eecs.umich.edu{ 1254166Sgblack@eecs.umich.edu delete consoleSymtab; 1264786Sgblack@eecs.umich.edu delete console; 1274786Sgblack@eecs.umich.edu delete pal; 1284786Sgblack@eecs.umich.edu#ifdef DEBUG 1294793Sgblack@eecs.umich.edu delete consolePanicEvent; 1304166Sgblack@eecs.umich.edu#endif 1314820Sgblack@eecs.umich.edu} 1324820Sgblack@eecs.umich.edu 1334820Sgblack@eecs.umich.edu/** 1344166Sgblack@eecs.umich.edu * This function fixes up addresses that are used to match PCs for 1354166Sgblack@eecs.umich.edu * hooking simulator events on to target function executions. 1364166Sgblack@eecs.umich.edu * 1374166Sgblack@eecs.umich.edu * Alpha binaries may have multiple global offset table (GOT) 1384166Sgblack@eecs.umich.edu * sections. A function that uses the GOT starts with a 1394166Sgblack@eecs.umich.edu * two-instruction prolog which sets the global pointer (gp == r29) to 1404166Sgblack@eecs.umich.edu * the appropriate GOT section. The proper gp value is calculated 1414166Sgblack@eecs.umich.edu * based on the function address, which must be passed by the caller 1424166Sgblack@eecs.umich.edu * in the procedure value register (pv aka t12 == r27). This sequence 1434166Sgblack@eecs.umich.edu * looks like the following: 1444166Sgblack@eecs.umich.edu * 1454166Sgblack@eecs.umich.edu * opcode Ra Rb offset 1464166Sgblack@eecs.umich.edu * ldah gp,X(pv) 09 29 27 X 1474166Sgblack@eecs.umich.edu * lda gp,Y(gp) 08 29 29 Y 1484166Sgblack@eecs.umich.edu * 1494863Sgblack@eecs.umich.edu * for some constant offsets X and Y. The catch is that the linker 1504863Sgblack@eecs.umich.edu * (or maybe even the compiler, I'm not sure) may recognize that the 1514166Sgblack@eecs.umich.edu * caller and callee are using the same GOT section, making this 1524166Sgblack@eecs.umich.edu * prolog redundant, and modify the call target to skip these 1534166Sgblack@eecs.umich.edu * instructions. If we check for execution of the first instruction 1544166Sgblack@eecs.umich.edu * of a function (the one the symbol points to) to detect when to skip 1554166Sgblack@eecs.umich.edu * it, we'll miss all these modified calls. It might work to 1564166Sgblack@eecs.umich.edu * unconditionally check for the third instruction, but not all 1574166Sgblack@eecs.umich.edu * functions have this prolog, and there's some chance that those 1584166Sgblack@eecs.umich.edu * first two instructions could have undesired consequences. So we do 1594166Sgblack@eecs.umich.edu * the Right Thing and pattern-match the first two instructions of the 1604166Sgblack@eecs.umich.edu * function to decide where to patch. 1614166Sgblack@eecs.umich.edu * 1624166Sgblack@eecs.umich.edu * Eventually this code should be moved into an ISA-specific file. 1634166Sgblack@eecs.umich.edu */ 1644166Sgblack@eecs.umich.eduAddr 1654793Sgblack@eecs.umich.eduAlphaSystem::fixFuncEventAddr(Addr addr) 1664849Sgblack@eecs.umich.edu{ 1674166Sgblack@eecs.umich.edu // mask for just the opcode, Ra, and Rb fields (not the offset) 1684166Sgblack@eecs.umich.edu const uint32_t inst_mask = 0xffff0000; 1694166Sgblack@eecs.umich.edu // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27 1704166Sgblack@eecs.umich.edu const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16); 1714793Sgblack@eecs.umich.edu // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 1724793Sgblack@eecs.umich.edu const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); 1734793Sgblack@eecs.umich.edu // instruction size 1744793Sgblack@eecs.umich.edu const int sz = sizeof(uint32_t); 1754793Sgblack@eecs.umich.edu 1764777Sgblack@eecs.umich.edu Addr paddr = vtophys(physmem, addr); 1774793Sgblack@eecs.umich.edu uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz); 1784793Sgblack@eecs.umich.edu uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz); 1794793Sgblack@eecs.umich.edu 1804793Sgblack@eecs.umich.edu if ((i1 & inst_mask) == gp_ldah_pattern && 1814777Sgblack@eecs.umich.edu (i2 & inst_mask) == gp_lda_pattern) { 1824793Sgblack@eecs.umich.edu Addr new_addr = addr + 2*sz; 1834793Sgblack@eecs.umich.edu DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); 1844793Sgblack@eecs.umich.edu return new_addr; 1854793Sgblack@eecs.umich.edu } else { 1864793Sgblack@eecs.umich.edu return addr; 1874793Sgblack@eecs.umich.edu } 1884793Sgblack@eecs.umich.edu} 1894793Sgblack@eecs.umich.edu 1904793Sgblack@eecs.umich.edu 1914793Sgblack@eecs.umich.eduvoid 1924793Sgblack@eecs.umich.eduAlphaSystem::setAlphaAccess(Addr access) 1934793Sgblack@eecs.umich.edu{ 1944793Sgblack@eecs.umich.edu Addr addr = 0; 1954793Sgblack@eecs.umich.edu if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { 1964793Sgblack@eecs.umich.edu Addr paddr = vtophys(physmem, addr); 1974793Sgblack@eecs.umich.edu uint64_t *m5AlphaAccess = 1984793Sgblack@eecs.umich.edu (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t)); 1994793Sgblack@eecs.umich.edu 2004793Sgblack@eecs.umich.edu if (!m5AlphaAccess) 2014793Sgblack@eecs.umich.edu panic("could not translate m5AlphaAccess addr\n"); 2024793Sgblack@eecs.umich.edu 2034793Sgblack@eecs.umich.edu *m5AlphaAccess = htog(EV5::Phys2K0Seg(access)); 2044793Sgblack@eecs.umich.edu } else 2054793Sgblack@eecs.umich.edu panic("could not find m5AlphaAccess\n"); 2064793Sgblack@eecs.umich.edu} 2074793Sgblack@eecs.umich.edu 2084166Sgblack@eecs.umich.edubool 2094166Sgblack@eecs.umich.eduAlphaSystem::breakpoint() 2104166Sgblack@eecs.umich.edu{ 2114166Sgblack@eecs.umich.edu return remoteGDB[0]->trap(ALPHA_KENTRY_INT); 2124166Sgblack@eecs.umich.edu} 2134166Sgblack@eecs.umich.edu 2144166Sgblack@eecs.umich.eduvoid 2154793Sgblack@eecs.umich.eduAlphaSystem::serialize(std::ostream &os) 2164793Sgblack@eecs.umich.edu{ 2174793Sgblack@eecs.umich.edu System::serialize(os); 2184793Sgblack@eecs.umich.edu consoleSymtab->serialize("console_symtab", os); 2194793Sgblack@eecs.umich.edu palSymtab->serialize("pal_symtab", os); 2204793Sgblack@eecs.umich.edu} 2214793Sgblack@eecs.umich.edu 2224793Sgblack@eecs.umich.edu 2234793Sgblack@eecs.umich.eduvoid 2244793Sgblack@eecs.umich.eduAlphaSystem::unserialize(Checkpoint *cp, const std::string §ion) 2254793Sgblack@eecs.umich.edu{ 2264793Sgblack@eecs.umich.edu System::unserialize(cp,section); 2274793Sgblack@eecs.umich.edu consoleSymtab->unserialize("console_symtab", cp, section); 2284793Sgblack@eecs.umich.edu palSymtab->unserialize("pal_symtab", cp, section); 2294793Sgblack@eecs.umich.edu} 2304793Sgblack@eecs.umich.edu 2314793Sgblack@eecs.umich.edu 2324793Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) 2334793Sgblack@eecs.umich.edu 2344793Sgblack@eecs.umich.edu Param<Tick> boot_cpu_frequency; 2354793Sgblack@eecs.umich.edu SimObjectParam<MemoryController *> memctrl; 2364793Sgblack@eecs.umich.edu SimObjectParam<PhysicalMemory *> physmem; 2374793Sgblack@eecs.umich.edu 2384793Sgblack@eecs.umich.edu Param<std::string> kernel; 2394793Sgblack@eecs.umich.edu Param<std::string> console; 2404793Sgblack@eecs.umich.edu Param<std::string> pal; 2414793Sgblack@eecs.umich.edu 2424793Sgblack@eecs.umich.edu Param<std::string> boot_osflags; 2434793Sgblack@eecs.umich.edu Param<std::string> readfile; 2444793Sgblack@eecs.umich.edu Param<unsigned int> init_param; 2454793Sgblack@eecs.umich.edu 2464793Sgblack@eecs.umich.edu Param<uint64_t> system_type; 2474166Sgblack@eecs.umich.edu Param<uint64_t> system_rev; 2484777Sgblack@eecs.umich.edu 2494793Sgblack@eecs.umich.edu Param<bool> bin; 2504166Sgblack@eecs.umich.edu VectorParam<std::string> binned_fns; 2514793Sgblack@eecs.umich.edu Param<bool> bin_int; 2524166Sgblack@eecs.umich.edu 2534793Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) 2544166Sgblack@eecs.umich.edu 2554166Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) 2564793Sgblack@eecs.umich.edu 2574166Sgblack@eecs.umich.edu INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), 2584793Sgblack@eecs.umich.edu INIT_PARAM(memctrl, "memory controller"), 2594166Sgblack@eecs.umich.edu INIT_PARAM(physmem, "phsyical memory"), 2604793Sgblack@eecs.umich.edu INIT_PARAM(kernel, "file that contains the kernel code"), 2614777Sgblack@eecs.umich.edu INIT_PARAM(console, "file that contains the console code"), 2624166Sgblack@eecs.umich.edu INIT_PARAM(pal, "file that contains palcode"), 2634166Sgblack@eecs.umich.edu INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", 2644166Sgblack@eecs.umich.edu "a"), 2654793Sgblack@eecs.umich.edu INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), 2664777Sgblack@eecs.umich.edu INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), 2674777Sgblack@eecs.umich.edu INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), 2684793Sgblack@eecs.umich.edu INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), 2694166Sgblack@eecs.umich.edu INIT_PARAM_DFLT(bin, "is this system to be binned", false), 2704793Sgblack@eecs.umich.edu INIT_PARAM(binned_fns, "functions to be broken down and binned"), 2714166Sgblack@eecs.umich.edu INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true) 2724793Sgblack@eecs.umich.edu 2734793Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(AlphaSystem) 2744793Sgblack@eecs.umich.edu 2754793Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(AlphaSystem) 2764166Sgblack@eecs.umich.edu{ 2774793Sgblack@eecs.umich.edu AlphaSystem::Params *p = new AlphaSystem::Params; 2784777Sgblack@eecs.umich.edu p->name = getInstanceName(); 2794793Sgblack@eecs.umich.edu p->boot_cpu_frequency = boot_cpu_frequency; 2804166Sgblack@eecs.umich.edu p->memctrl = memctrl; 2814166Sgblack@eecs.umich.edu p->physmem = physmem; 2824166Sgblack@eecs.umich.edu p->kernel_path = kernel; 2834166Sgblack@eecs.umich.edu p->console_path = console; 2844849Sgblack@eecs.umich.edu p->palcode = pal; 2854849Sgblack@eecs.umich.edu p->boot_osflags = boot_osflags; 2864166Sgblack@eecs.umich.edu p->init_param = init_param; 2874166Sgblack@eecs.umich.edu p->readfile = readfile; 2884166Sgblack@eecs.umich.edu p->system_type = system_type; 2894847Sgblack@eecs.umich.edu p->system_rev = system_rev; 2904793Sgblack@eecs.umich.edu p->bin = bin; 2914793Sgblack@eecs.umich.edu p->binned_fns = binned_fns; 2924793Sgblack@eecs.umich.edu p->bin_int = bin_int; 2934166Sgblack@eecs.umich.edu return new AlphaSystem(p); 2944166Sgblack@eecs.umich.edu} 2954166Sgblack@eecs.umich.edu 2964847Sgblack@eecs.umich.eduREGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem) 2974166Sgblack@eecs.umich.edu 2984166Sgblack@eecs.umich.edu 2994166Sgblack@eecs.umich.edu