system.cc revision 2343
1/* 2 * Copyright (c) 2002-2005 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 "arch/alpha/system.hh" 30#include "arch/vtophys.hh" 31#include "base/remote_gdb.hh" 32#include "base/loader/object_file.hh" 33#include "base/loader/symtab.hh" 34#include "base/trace.hh" 35#include "mem/functional/memory_control.hh" 36#include "mem/functional/physical.hh" 37#include "sim/byteswap.hh" 38#include "sim/builder.hh" 39 40 41using namespace LittleEndianGuest; 42 43AlphaSystem::AlphaSystem(Params *p) 44 : System(p) 45{ 46 consoleSymtab = new SymbolTable; 47 palSymtab = new SymbolTable; 48 49 50 /** 51 * Load the pal, and console code into memory 52 */ 53 // Load Console Code 54 console = createObjectFile(params()->console_path); 55 if (console == NULL) 56 fatal("Could not load console file %s", params()->console_path); 57 58 // Load pal file 59 pal = createObjectFile(params()->palcode); 60 if (pal == NULL) 61 fatal("Could not load PALcode file %s", params()->palcode); 62 63 64 // Load program sections into memory 65 pal->loadSections(physmem, true); 66 console->loadSections(physmem, true); 67 68 // load symbols 69 if (!console->loadGlobalSymbols(consoleSymtab)) 70 panic("could not load console symbols\n"); 71 72 if (!pal->loadGlobalSymbols(palSymtab)) 73 panic("could not load pal symbols\n"); 74 75 if (!pal->loadLocalSymbols(palSymtab)) 76 panic("could not load pal symbols\n"); 77 78 if (!console->loadGlobalSymbols(debugSymbolTable)) 79 panic("could not load console symbols\n"); 80 81 if (!pal->loadGlobalSymbols(debugSymbolTable)) 82 panic("could not load pal symbols\n"); 83 84 if (!pal->loadLocalSymbols(debugSymbolTable)) 85 panic("could not load pal symbols\n"); 86 87 Addr addr = 0; 88#ifndef NDEBUG 89 consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic"); 90#endif 91 92 /** 93 * Copy the osflags (kernel arguments) into the consoles 94 * memory. (Presently Linux does not use the console service 95 * routine to get these command line arguments, but Tru64 and 96 * others do.) 97 */ 98 if (consoleSymtab->findAddress("env_booted_osflags", addr)) { 99 Addr paddr = vtophys(physmem, addr); 100 char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); 101 102 if (osflags) 103 strcpy(osflags, params()->boot_osflags.c_str()); 104 } 105 106 /** 107 * Set the hardware reset parameter block system type and revision 108 * information to Tsunami. 109 */ 110 if (consoleSymtab->findAddress("m5_rpb", addr)) { 111 Addr paddr = vtophys(physmem, addr); 112 char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); 113 114 if (!hwrpb) 115 panic("could not translate hwrpb addr\n"); 116 117 *(uint64_t*)(hwrpb+0x50) = htog(params()->system_type); 118 *(uint64_t*)(hwrpb+0x58) = htog(params()->system_rev); 119 } else 120 panic("could not find hwrpb\n"); 121 122} 123 124AlphaSystem::~AlphaSystem() 125{ 126 delete consoleSymtab; 127 delete console; 128 delete pal; 129#ifdef DEBUG 130 delete consolePanicEvent; 131#endif 132} 133 134/** 135 * This function fixes up addresses that are used to match PCs for 136 * hooking simulator events on to target function executions. 137 * 138 * Alpha binaries may have multiple global offset table (GOT) 139 * sections. A function that uses the GOT starts with a 140 * two-instruction prolog which sets the global pointer (gp == r29) to 141 * the appropriate GOT section. The proper gp value is calculated 142 * based on the function address, which must be passed by the caller 143 * in the procedure value register (pv aka t12 == r27). This sequence 144 * looks like the following: 145 * 146 * opcode Ra Rb offset 147 * ldah gp,X(pv) 09 29 27 X 148 * lda gp,Y(gp) 08 29 29 Y 149 * 150 * for some constant offsets X and Y. The catch is that the linker 151 * (or maybe even the compiler, I'm not sure) may recognize that the 152 * caller and callee are using the same GOT section, making this 153 * prolog redundant, and modify the call target to skip these 154 * instructions. If we check for execution of the first instruction 155 * of a function (the one the symbol points to) to detect when to skip 156 * it, we'll miss all these modified calls. It might work to 157 * unconditionally check for the third instruction, but not all 158 * functions have this prolog, and there's some chance that those 159 * first two instructions could have undesired consequences. So we do 160 * the Right Thing and pattern-match the first two instructions of the 161 * function to decide where to patch. 162 * 163 * Eventually this code should be moved into an ISA-specific file. 164 */ 165Addr 166AlphaSystem::fixFuncEventAddr(Addr addr) 167{ 168 // mask for just the opcode, Ra, and Rb fields (not the offset) 169 const uint32_t inst_mask = 0xffff0000; 170 // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27 171 const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16); 172 // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 173 const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); 174 // instruction size 175 const int sz = sizeof(uint32_t); 176 177 Addr paddr = vtophys(physmem, addr); 178 uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz); 179 uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz); 180 181 if ((i1 & inst_mask) == gp_ldah_pattern && 182 (i2 & inst_mask) == gp_lda_pattern) { 183 Addr new_addr = addr + 2*sz; 184 DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); 185 return new_addr; 186 } else { 187 return addr; 188 } 189} 190 191 192void 193AlphaSystem::setAlphaAccess(Addr access) 194{ 195 Addr addr = 0; 196 if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { 197 Addr paddr = vtophys(physmem, addr); 198 uint64_t *m5AlphaAccess = 199 (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t)); 200 201 if (!m5AlphaAccess) 202 panic("could not translate m5AlphaAccess addr\n"); 203 204 *m5AlphaAccess = htog(EV5::Phys2K0Seg(access)); 205 } else 206 panic("could not find m5AlphaAccess\n"); 207} 208 209bool 210AlphaSystem::breakpoint() 211{ 212 return remoteGDB[0]->trap(ALPHA_KENTRY_INT); 213} 214 215void 216AlphaSystem::serialize(std::ostream &os) 217{ 218 System::serialize(os); 219 consoleSymtab->serialize("console_symtab", os); 220 palSymtab->serialize("pal_symtab", os); 221} 222 223 224void 225AlphaSystem::unserialize(Checkpoint *cp, const std::string §ion) 226{ 227 System::unserialize(cp,section); 228 consoleSymtab->unserialize("console_symtab", cp, section); 229 palSymtab->unserialize("pal_symtab", cp, section); 230} 231 232 233BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) 234 235 Param<Tick> boot_cpu_frequency; 236 SimObjectParam<MemoryController *> memctrl; 237 SimObjectParam<PhysicalMemory *> physmem; 238 239 Param<std::string> kernel; 240 Param<std::string> console; 241 Param<std::string> pal; 242 243 Param<std::string> boot_osflags; 244 Param<std::string> readfile; 245 Param<unsigned int> init_param; 246 247 Param<uint64_t> system_type; 248 Param<uint64_t> system_rev; 249 250END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem) 251 252BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem) 253 254 INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), 255 INIT_PARAM(memctrl, "memory controller"), 256 INIT_PARAM(physmem, "phsyical memory"), 257 INIT_PARAM(kernel, "file that contains the kernel code"), 258 INIT_PARAM(console, "file that contains the console code"), 259 INIT_PARAM(pal, "file that contains palcode"), 260 INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", 261 "a"), 262 INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), 263 INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), 264 INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), 265 INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) 266 267END_INIT_SIM_OBJECT_PARAMS(AlphaSystem) 268 269CREATE_SIM_OBJECT(AlphaSystem) 270{ 271 AlphaSystem::Params *p = new AlphaSystem::Params; 272 p->name = getInstanceName(); 273 p->boot_cpu_frequency = boot_cpu_frequency; 274 p->memctrl = memctrl; 275 p->physmem = physmem; 276 p->kernel_path = kernel; 277 p->console_path = console; 278 p->palcode = pal; 279 p->boot_osflags = boot_osflags; 280 p->init_param = init_param; 281 p->readfile = readfile; 282 p->system_type = system_type; 283 p->system_rev = system_rev; 284 return new AlphaSystem(p); 285} 286 287REGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem) 288 289 290