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