gem5/cpu/pc_event.cc
Ron Dreslinski d9317dd348 Some more useful debugging info for kernel panic and die events
Increase the default number of CSHR's, we should really fix this or make it a parameter

Use a setBlocked call to tell the bus it should block

New technique for sampling and switchover:
1) Sampler switchover event happens
2) All cpus in the current phase of sampling associated with this sampler are signaled to switchover
3) Each cpu drains it's pipe of things being executed (stops fetching and waits for empty pipe)
4) Once the pipe is empty the cpu calls back to the sampler to signal it has finished, and moves into the switchedout state (continues not to fetch)
5) The sampler collects all the signals, once all cpus are drained it calls the new cpu's in the next phase to takeover from the correct cpu
6) The statistics are reset and the next switchover time is calculated from this point

cpu/base_cpu.cc:
cpu/base_cpu.hh:
cpu/simple_cpu/simple_cpu.cc:
cpu/simple_cpu/simple_cpu.hh:
    Reconfigure the way the sampling switchover works
cpu/pc_event.cc:
    More debugging information on kernel panic's
kern/linux/linux_system.cc:
    More debug info for Kernel Die events
kern/linux/linux_system.hh:
    More debug info for kernel die events

--HG--
extra : convert_revision : 61cc42e43ba738705aa1f1d167b65d4d6dee51ae
2005-02-09 10:27:00 -05:00

153 lines
4.3 KiB
C++

/*
* Copyright (c) 2002-2003 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include "base/trace.hh"
#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
#include "cpu/pc_event.hh"
#include "sim/debug.hh"
#include "sim/universe.hh"
using namespace std;
PCEventQueue::PCEventQueue()
{}
PCEventQueue::~PCEventQueue()
{}
bool
PCEventQueue::remove(PCEvent *event)
{
int removed = 0;
range_t range = equal_range(event);
for (iterator i = range.first; i != range.second; ++i) {
if (*i == event) {
DPRINTF(PCEvent, "PC based event removed at %#x: %s\n",
event->pc(), event->descr());
pc_map.erase(i);
++removed;
}
}
return removed > 0;
}
bool
PCEventQueue::schedule(PCEvent *event)
{
pc_map.push_back(event);
sort(pc_map.begin(), pc_map.end(), MapCompare());
DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n",
event->pc(), event->descr());
return true;
}
bool
PCEventQueue::doService(ExecContext *xc)
{
Addr pc = xc->regs.pc & ~0x3;
int serviced = 0;
range_t range = equal_range(pc);
for (iterator i = range.first; i != range.second; ++i) {
// Make sure that the pc wasn't changed as the side effect of
// another event. This for example, prevents two invocations
// of the SkipFuncEvent. Maybe we should have separate PC
// event queues for each processor?
if (pc != (xc->regs.pc & ~0x3))
continue;
DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
(*i)->pc(), (*i)->descr());
(*i)->process(xc);
++serviced;
}
return serviced > 0;
}
void
PCEventQueue::dump() const
{
const_iterator i = pc_map.begin();
const_iterator e = pc_map.end();
for (; i != e; ++i)
cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(),
(*i)->descr());
}
PCEventQueue::range_t
PCEventQueue::equal_range(Addr pc)
{
return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
}
BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del)
: PCEvent(q, desc), remove(del)
{
}
void
BreakPCEvent::process(ExecContext *xc)
{
StringWrap name(xc->cpu->name() + ".break_event");
DPRINTFN("break event %s triggered", descr());
debug_break();
if (remove)
delete this;
}
#ifdef FULL_SYSTEM
extern "C"
void
sched_break_pc_sys(System *sys, Addr addr)
{
PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true);
event->schedule(addr);
}
extern "C"
void
sched_break_pc(Addr addr)
{
for (vector<System *>::iterator sysi = System::systemList.begin();
sysi != System::systemList.end(); ++sysi) {
sched_break_pc_sys(*sysi, addr);
}
}
#endif