pc_event.cc revision 76
18889Sgeoffrey.blake@arm.com/* 28889Sgeoffrey.blake@arm.com * Copyright (c) 2003 The Regents of The University of Michigan 38889Sgeoffrey.blake@arm.com * All rights reserved. 48889Sgeoffrey.blake@arm.com * 58889Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without 68889Sgeoffrey.blake@arm.com * modification, are permitted provided that the following conditions are 78889Sgeoffrey.blake@arm.com * met: redistributions of source code must retain the above copyright 88889Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer; 98889Sgeoffrey.blake@arm.com * redistributions in binary form must reproduce the above copyright 108889Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer in the 118889Sgeoffrey.blake@arm.com * documentation and/or other materials provided with the distribution; 128889Sgeoffrey.blake@arm.com * neither the name of the copyright holders nor the names of its 138889Sgeoffrey.blake@arm.com * contributors may be used to endorse or promote products derived from 148889Sgeoffrey.blake@arm.com * this software without specific prior written permission. 158889Sgeoffrey.blake@arm.com * 168889Sgeoffrey.blake@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 178889Sgeoffrey.blake@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 188889Sgeoffrey.blake@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198889Sgeoffrey.blake@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208889Sgeoffrey.blake@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 218889Sgeoffrey.blake@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228889Sgeoffrey.blake@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238889Sgeoffrey.blake@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248889Sgeoffrey.blake@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258889Sgeoffrey.blake@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 268889Sgeoffrey.blake@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278889Sgeoffrey.blake@arm.com */ 288889Sgeoffrey.blake@arm.com 298889Sgeoffrey.blake@arm.com#include <algorithm> 308889Sgeoffrey.blake@arm.com#include <map> 318889Sgeoffrey.blake@arm.com#include <string> 328889Sgeoffrey.blake@arm.com#include <utility> 338889Sgeoffrey.blake@arm.com 348889Sgeoffrey.blake@arm.com#include "sim/debug.hh" 358889Sgeoffrey.blake@arm.com#include "cpu/exec_context.hh" 368889Sgeoffrey.blake@arm.com#include "cpu/pc_event.hh" 378889Sgeoffrey.blake@arm.com#include "base/trace.hh" 388889Sgeoffrey.blake@arm.com#include "sim/universe.hh" 398889Sgeoffrey.blake@arm.com 408889Sgeoffrey.blake@arm.com#ifdef FULL_SYSTEM 418889Sgeoffrey.blake@arm.com#include "targetarch/arguments.hh" 428889Sgeoffrey.blake@arm.com#include "targetarch/pmap.h" 438889Sgeoffrey.blake@arm.com#include "mem/functional_mem/memory_control.hh" 448889Sgeoffrey.blake@arm.com#include "cpu/full_cpu/cpu.hh" 458889Sgeoffrey.blake@arm.com#include "sim/system.hh" 468889Sgeoffrey.blake@arm.com#include "cpu/full_cpu/bpred.hh" 478889Sgeoffrey.blake@arm.com#endif 488889Sgeoffrey.blake@arm.com 498889Sgeoffrey.blake@arm.comusing namespace std; 508889Sgeoffrey.blake@arm.com 518889Sgeoffrey.blake@arm.comPCEventQueue::PCEventQueue() 528889Sgeoffrey.blake@arm.com{} 538889Sgeoffrey.blake@arm.com 548889Sgeoffrey.blake@arm.comPCEventQueue::~PCEventQueue() 558889Sgeoffrey.blake@arm.com{} 568889Sgeoffrey.blake@arm.com 578889Sgeoffrey.blake@arm.combool 588889Sgeoffrey.blake@arm.comPCEventQueue::remove(PCEvent *event) 598889Sgeoffrey.blake@arm.com{ 608889Sgeoffrey.blake@arm.com int removed = 0; 618889Sgeoffrey.blake@arm.com range_t range = equal_range(event); 628889Sgeoffrey.blake@arm.com for (iterator i = range.first; i != range.second; ++i) { 638889Sgeoffrey.blake@arm.com if (*i == event) { 648889Sgeoffrey.blake@arm.com DPRINTF(PCEvent, "PC based event removed at %#x: %s\n", 658889Sgeoffrey.blake@arm.com event->pc(), event->descr()); 668889Sgeoffrey.blake@arm.com pc_map.erase(i); 678889Sgeoffrey.blake@arm.com ++removed; 688889Sgeoffrey.blake@arm.com } 698889Sgeoffrey.blake@arm.com } 708889Sgeoffrey.blake@arm.com 718889Sgeoffrey.blake@arm.com return removed > 0; 728889Sgeoffrey.blake@arm.com} 738889Sgeoffrey.blake@arm.com 748889Sgeoffrey.blake@arm.combool 758889Sgeoffrey.blake@arm.comPCEventQueue::schedule(PCEvent *event) 768889Sgeoffrey.blake@arm.com{ 778889Sgeoffrey.blake@arm.com pc_map.push_back(event); 788889Sgeoffrey.blake@arm.com sort(pc_map.begin(), pc_map.end(), MapCompare()); 798889Sgeoffrey.blake@arm.com 808889Sgeoffrey.blake@arm.com DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n", 818889Sgeoffrey.blake@arm.com event->pc(), event->descr()); 828889Sgeoffrey.blake@arm.com 838889Sgeoffrey.blake@arm.com return true; 848889Sgeoffrey.blake@arm.com} 858889Sgeoffrey.blake@arm.com 868889Sgeoffrey.blake@arm.combool 878889Sgeoffrey.blake@arm.comPCEventQueue::doService(ExecContext *xc) 888889Sgeoffrey.blake@arm.com{ 898889Sgeoffrey.blake@arm.com Addr pc = xc->regs.pc; 908889Sgeoffrey.blake@arm.com int serviced = 0; 918889Sgeoffrey.blake@arm.com range_t range = equal_range(pc); 928889Sgeoffrey.blake@arm.com for (iterator i = range.first; i != range.second; ++i) { 938889Sgeoffrey.blake@arm.com // Make sure that the pc wasn't changed as the side effect of 948889Sgeoffrey.blake@arm.com // another event. This for example, prevents two invocations 958889Sgeoffrey.blake@arm.com // of the SkipFuncEvent. Maybe we should have separate PC 968889Sgeoffrey.blake@arm.com // event queues for each processor? 978889Sgeoffrey.blake@arm.com if (pc != xc->regs.pc) 988889Sgeoffrey.blake@arm.com continue; 998889Sgeoffrey.blake@arm.com 1008889Sgeoffrey.blake@arm.com DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", 1018889Sgeoffrey.blake@arm.com (*i)->pc(), (*i)->descr()); 1028889Sgeoffrey.blake@arm.com 1038889Sgeoffrey.blake@arm.com (*i)->process(xc); 1048889Sgeoffrey.blake@arm.com ++serviced; 1058889Sgeoffrey.blake@arm.com } 1068889Sgeoffrey.blake@arm.com 1078889Sgeoffrey.blake@arm.com return serviced > 0; 1088889Sgeoffrey.blake@arm.com} 1098889Sgeoffrey.blake@arm.com 1108889Sgeoffrey.blake@arm.comvoid 1118889Sgeoffrey.blake@arm.comPCEventQueue::dump() const 1128889Sgeoffrey.blake@arm.com{ 1138889Sgeoffrey.blake@arm.com const_iterator i = pc_map.begin(); 1148889Sgeoffrey.blake@arm.com const_iterator e = pc_map.end(); 1158889Sgeoffrey.blake@arm.com 1168889Sgeoffrey.blake@arm.com for (; i != e; ++i) 1178889Sgeoffrey.blake@arm.com cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(), 1188889Sgeoffrey.blake@arm.com (*i)->descr()); 1198889Sgeoffrey.blake@arm.com} 1208889Sgeoffrey.blake@arm.com 1218889Sgeoffrey.blake@arm.comPCEventQueue::range_t 1228889Sgeoffrey.blake@arm.comPCEventQueue::equal_range(Addr pc) 1238889Sgeoffrey.blake@arm.com{ 1248889Sgeoffrey.blake@arm.com return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare()); 1258889Sgeoffrey.blake@arm.com} 1268889Sgeoffrey.blake@arm.com 1278889Sgeoffrey.blake@arm.com#ifdef FULL_SYSTEM 1288889Sgeoffrey.blake@arm.comvoid 1298889Sgeoffrey.blake@arm.comSkipFuncEvent::process(ExecContext *xc) 1308889Sgeoffrey.blake@arm.com{ 1318889Sgeoffrey.blake@arm.com Addr newpc = xc->regs.intRegFile[ReturnAddressReg]; 1328889Sgeoffrey.blake@arm.com 1338889Sgeoffrey.blake@arm.com DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description, 1348889Sgeoffrey.blake@arm.com xc->regs.pc, newpc); 1358889Sgeoffrey.blake@arm.com 136 xc->regs.pc = newpc; 137 xc->regs.npc = xc->regs.pc + sizeof(MachInst); 138 139 BranchPred *bp = xc->cpu->getBranchPred(); 140 if (bp != NULL) { 141 bp->popRAS(xc->thread_num); 142 } 143} 144 145void 146BadAddrEvent::process(ExecContext *xc) 147{ 148 // The following gross hack is the equivalent function to the 149 // annotation for vmunix::badaddr in: 150 // simos/simulation/apps/tcl/osf/tlaser.tcl 151 152 uint64_t a0 = xc->regs.intRegFile[ArgumentReg0]; 153 154 if (a0 < ALPHA_K0SEG_BASE || a0 >= ALPHA_K1SEG_BASE || 155 xc->memCtrl->badaddr(ALPHA_K0SEG_TO_PHYS(a0) & PA_IMPL_MASK)) { 156 157 DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); 158 xc->regs.intRegFile[ReturnValueReg] = 0x1; 159 SkipFuncEvent::process(xc); 160 } 161 else 162 DPRINTF(BADADDR, "badaddr arg=%#x good\n", a0); 163} 164 165void Printf(AlphaArguments args); 166void DumpMbuf(AlphaArguments args); 167 168void 169PrintfEvent::process(ExecContext *xc) 170{ 171 if (DTRACE(Printf)) { 172 DebugOut() << curTick << ": " << xc->cpu->name() << ": "; 173 174 AlphaArguments args(xc); 175 Printf(args); 176 } 177} 178 179void 180DebugPrintfEvent::process(ExecContext *xc) 181{ 182 if (DTRACE(DebugPrintf)) { 183 if (!raw) 184 DebugOut() << curTick << ": " << xc->cpu->name() << ": "; 185 186 AlphaArguments args(xc); 187 Printf(args); 188 } 189} 190 191void 192DumpMbufEvent::process(ExecContext *xc) 193{ 194 if (DTRACE(DebugPrintf)) { 195 AlphaArguments args(xc); 196 DumpMbuf(args); 197 } 198} 199#endif 200 201BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del) 202 : PCEvent(q, desc), remove(del) 203{ 204} 205 206void 207BreakPCEvent::process(ExecContext *xc) 208{ 209 debug_break(); 210 if (remove) 211 delete this; 212} 213 214#ifdef FULL_SYSTEM 215extern "C" 216void 217sched_break_pc_sys(System *sys, Addr addr) 218{ 219 PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true); 220 event->schedule(addr); 221} 222 223extern "C" 224void 225sched_break_pc(Addr addr) 226{ 227 for (vector<System *>::iterator sysi = System::systemList.begin(); 228 sysi != System::systemList.end(); ++sysi) { 229 sched_break_pc_sys(*sysi, addr); 230 } 231 232} 233#endif 234