pc_event.cc revision 76
15643Sgblack@eecs.umich.edu/*
25643Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
35643Sgblack@eecs.umich.edu * All rights reserved.
45643Sgblack@eecs.umich.edu *
55643Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65643Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
75643Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85643Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95643Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105643Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115643Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125643Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135643Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145643Sgblack@eecs.umich.edu * this software without specific prior written permission.
155643Sgblack@eecs.umich.edu *
165643Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175643Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185643Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195643Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205643Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215643Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225643Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235643Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245643Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255643Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265643Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275643Sgblack@eecs.umich.edu */
285643Sgblack@eecs.umich.edu
295643Sgblack@eecs.umich.edu#include <algorithm>
305643Sgblack@eecs.umich.edu#include <map>
315643Sgblack@eecs.umich.edu#include <string>
325643Sgblack@eecs.umich.edu#include <utility>
335643Sgblack@eecs.umich.edu
348229Snate@binkert.org#include "sim/debug.hh"
358229Snate@binkert.org#include "cpu/exec_context.hh"
365643Sgblack@eecs.umich.edu#include "cpu/pc_event.hh"
378229Snate@binkert.org#include "base/trace.hh"
3814290Sgabeblack@google.com#include "sim/universe.hh"
395643Sgblack@eecs.umich.edu
405643Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM
415643Sgblack@eecs.umich.edu#include "targetarch/arguments.hh"
425643Sgblack@eecs.umich.edu#include "targetarch/pmap.h"
435643Sgblack@eecs.umich.edu#include "mem/functional_mem/memory_control.hh"
445643Sgblack@eecs.umich.edu#include "cpu/full_cpu/cpu.hh"
455657Sgblack@eecs.umich.edu#include "sim/system.hh"
466137Sgblack@eecs.umich.edu#include "cpu/full_cpu/bpred.hh"
475657Sgblack@eecs.umich.edu#endif
489807Sstever@gmail.com
495643Sgblack@eecs.umich.eduusing namespace std;
505643Sgblack@eecs.umich.edu
515643Sgblack@eecs.umich.eduPCEventQueue::PCEventQueue()
525643Sgblack@eecs.umich.edu{}
535643Sgblack@eecs.umich.edu
545643Sgblack@eecs.umich.eduPCEventQueue::~PCEventQueue()
555643Sgblack@eecs.umich.edu{}
565643Sgblack@eecs.umich.edu
575643Sgblack@eecs.umich.edubool
585643Sgblack@eecs.umich.eduPCEventQueue::remove(PCEvent *event)
595643Sgblack@eecs.umich.edu{
605643Sgblack@eecs.umich.edu    int removed = 0;
615643Sgblack@eecs.umich.edu    range_t range = equal_range(event);
625643Sgblack@eecs.umich.edu    for (iterator i = range.first; i != range.second; ++i) {
635643Sgblack@eecs.umich.edu        if (*i == event) {
645643Sgblack@eecs.umich.edu            DPRINTF(PCEvent, "PC based event removed at %#x: %s\n",
655643Sgblack@eecs.umich.edu                    event->pc(), event->descr());
665643Sgblack@eecs.umich.edu            pc_map.erase(i);
675643Sgblack@eecs.umich.edu            ++removed;
685657Sgblack@eecs.umich.edu        }
695657Sgblack@eecs.umich.edu    }
705643Sgblack@eecs.umich.edu
716136Sgblack@eecs.umich.edu    return removed > 0;
725643Sgblack@eecs.umich.edu}
735643Sgblack@eecs.umich.edu
745643Sgblack@eecs.umich.edubool
756139Sgblack@eecs.umich.eduPCEventQueue::schedule(PCEvent *event)
766139Sgblack@eecs.umich.edu{
775643Sgblack@eecs.umich.edu    pc_map.push_back(event);
785643Sgblack@eecs.umich.edu    sort(pc_map.begin(), pc_map.end(), MapCompare());
795643Sgblack@eecs.umich.edu
805643Sgblack@eecs.umich.edu    DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n",
815643Sgblack@eecs.umich.edu            event->pc(), event->descr());
825643Sgblack@eecs.umich.edu
835827Sgblack@eecs.umich.edu    return true;
845643Sgblack@eecs.umich.edu}
8514291Sgabeblack@google.com
8614290Sgabeblack@google.combool
875643Sgblack@eecs.umich.eduPCEventQueue::doService(ExecContext *xc)
885643Sgblack@eecs.umich.edu{
895643Sgblack@eecs.umich.edu    Addr pc = xc->regs.pc;
905643Sgblack@eecs.umich.edu    int serviced = 0;
915643Sgblack@eecs.umich.edu    range_t range = equal_range(pc);
925643Sgblack@eecs.umich.edu    for (iterator i = range.first; i != range.second; ++i) {
935643Sgblack@eecs.umich.edu        // Make sure that the pc wasn't changed as the side effect of
945643Sgblack@eecs.umich.edu        // another event.  This for example, prevents two invocations
955643Sgblack@eecs.umich.edu        // of the SkipFuncEvent.  Maybe we should have separate PC
965643Sgblack@eecs.umich.edu        // event queues for each processor?
975643Sgblack@eecs.umich.edu        if (pc != xc->regs.pc)
9811175Sandreas.hansson@arm.com            continue;
997913SBrad.Beckmann@amd.com
10011175Sandreas.hansson@arm.com        DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
10111175Sandreas.hansson@arm.com                (*i)->pc(), (*i)->descr());
1025643Sgblack@eecs.umich.edu
1035643Sgblack@eecs.umich.edu        (*i)->process(xc);
1045643Sgblack@eecs.umich.edu        ++serviced;
1055643Sgblack@eecs.umich.edu    }
10613784Sgabeblack@google.com
10713784Sgabeblack@google.com    return serviced > 0;
1085651Sgblack@eecs.umich.edu}
10914295Sgabeblack@google.com
11011144Sjthestness@gmail.comvoid
11114290Sgabeblack@google.comPCEventQueue::dump() const
11214290Sgabeblack@google.com{
11314290Sgabeblack@google.com    const_iterator i = pc_map.begin();
1147903Shestness@cs.utexas.edu    const_iterator e = pc_map.end();
11511168Sandreas.hansson@arm.com
11611168Sandreas.hansson@arm.com    for (; i != e; ++i)
1175643Sgblack@eecs.umich.edu        cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(),
1185643Sgblack@eecs.umich.edu                (*i)->descr());
1197811Ssteve.reinhardt@amd.com}
1205643Sgblack@eecs.umich.edu
1215643Sgblack@eecs.umich.eduPCEventQueue::range_t
122PCEventQueue::equal_range(Addr pc)
123{
124    return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
125}
126
127#ifdef FULL_SYSTEM
128void
129SkipFuncEvent::process(ExecContext *xc)
130{
131    Addr newpc = xc->regs.intRegFile[ReturnAddressReg];
132
133    DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
134            xc->regs.pc, newpc);
135
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