x86: Move APIC clock divider to Python
This patch moves the 16x APIC clock divider to the Python code to avoid the post-instantiation modifications to the clock. The x86 APIC was the only object setting the clock after creation time and this required some custom functionality and configuration. With this patch, the clock multiplier is moved to the Python code and the objects are instantiated with the appropriate clock.
This commit is contained in:
parent
86a4d09269
commit
5c7ebee434
5 changed files with 23 additions and 27 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 ARM Limited
|
* Copyright (c) 2012-2013 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -410,9 +410,8 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg)
|
||||||
case APIC_CURRENT_COUNT:
|
case APIC_CURRENT_COUNT:
|
||||||
{
|
{
|
||||||
if (apicTimerEvent.scheduled()) {
|
if (apicTimerEvent.scheduled()) {
|
||||||
assert(clock);
|
|
||||||
// Compute how many m5 ticks happen per count.
|
// Compute how many m5 ticks happen per count.
|
||||||
uint64_t ticksPerCount = clock *
|
uint64_t ticksPerCount = clockPeriod() *
|
||||||
divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]);
|
divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]);
|
||||||
// Compute how many m5 ticks are left.
|
// Compute how many m5 ticks are left.
|
||||||
uint64_t val = apicTimerEvent.when() - curTick();
|
uint64_t val = apicTimerEvent.when() - curTick();
|
||||||
|
@ -587,19 +586,20 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
|
||||||
break;
|
break;
|
||||||
case APIC_INITIAL_COUNT:
|
case APIC_INITIAL_COUNT:
|
||||||
{
|
{
|
||||||
assert(clock);
|
|
||||||
newVal = bits(val, 31, 0);
|
newVal = bits(val, 31, 0);
|
||||||
// Compute how many timer ticks we're being programmed for.
|
// Compute how many timer ticks we're being programmed for.
|
||||||
uint64_t newCount = newVal *
|
uint64_t newCount = newVal *
|
||||||
(divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
|
(divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
|
||||||
// Schedule on the edge of the next tick plus the new count.
|
// Schedule on the edge of the next tick plus the new count.
|
||||||
Tick offset = curTick() % clock;
|
Tick offset = curTick() % clockPeriod();
|
||||||
if (offset) {
|
if (offset) {
|
||||||
reschedule(apicTimerEvent,
|
reschedule(apicTimerEvent,
|
||||||
curTick() + (newCount + 1) * clock - offset, true);
|
curTick() + (newCount + 1) *
|
||||||
|
clockPeriod() - offset, true);
|
||||||
} else {
|
} else {
|
||||||
reschedule(apicTimerEvent,
|
reschedule(apicTimerEvent,
|
||||||
curTick() + newCount * clock, true);
|
curTick() + newCount *
|
||||||
|
clockPeriod(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -629,8 +629,6 @@ X86ISA::Interrupts::Interrupts(Params * p) :
|
||||||
pendingIPIs(0), cpu(NULL),
|
pendingIPIs(0), cpu(NULL),
|
||||||
intSlavePort(name() + ".int_slave", this, this, latency)
|
intSlavePort(name() + ".int_slave", this, this, latency)
|
||||||
{
|
{
|
||||||
// Override the default clock
|
|
||||||
clock = 0;
|
|
||||||
pioSize = PageBytes;
|
pioSize = PageBytes;
|
||||||
memset(regs, 0, sizeof(regs));
|
memset(regs, 0, sizeof(regs));
|
||||||
//Set the local apic DFR to the flat model.
|
//Set the local apic DFR to the flat model.
|
||||||
|
@ -735,7 +733,6 @@ void
|
||||||
X86ISA::Interrupts::serialize(std::ostream &os)
|
X86ISA::Interrupts::serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
SERIALIZE_ARRAY(regs, NUM_APIC_REGS);
|
SERIALIZE_ARRAY(regs, NUM_APIC_REGS);
|
||||||
SERIALIZE_SCALAR(clock);
|
|
||||||
SERIALIZE_SCALAR(pendingSmi);
|
SERIALIZE_SCALAR(pendingSmi);
|
||||||
SERIALIZE_SCALAR(smiVector);
|
SERIALIZE_SCALAR(smiVector);
|
||||||
SERIALIZE_SCALAR(pendingNmi);
|
SERIALIZE_SCALAR(pendingNmi);
|
||||||
|
@ -761,7 +758,6 @@ void
|
||||||
X86ISA::Interrupts::unserialize(Checkpoint *cp, const std::string §ion)
|
X86ISA::Interrupts::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
{
|
{
|
||||||
UNSERIALIZE_ARRAY(regs, NUM_APIC_REGS);
|
UNSERIALIZE_ARRAY(regs, NUM_APIC_REGS);
|
||||||
UNSERIALIZE_SCALAR(clock);
|
|
||||||
UNSERIALIZE_SCALAR(pendingSmi);
|
UNSERIALIZE_SCALAR(pendingSmi);
|
||||||
UNSERIALIZE_SCALAR(smiVector);
|
UNSERIALIZE_SCALAR(smiVector);
|
||||||
UNSERIALIZE_SCALAR(pendingNmi);
|
UNSERIALIZE_SCALAR(pendingNmi);
|
||||||
|
|
|
@ -201,12 +201,6 @@ class Interrupts : public BasicPioDevice, IntDev
|
||||||
|
|
||||||
void setCPU(BaseCPU * newCPU);
|
void setCPU(BaseCPU * newCPU);
|
||||||
|
|
||||||
void
|
|
||||||
setClock(Tick newClock)
|
|
||||||
{
|
|
||||||
clock = newClock;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Params *
|
const Params *
|
||||||
params() const
|
params() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -174,10 +174,6 @@ void initCPU(ThreadContext *tc, int cpuId)
|
||||||
|
|
||||||
interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);
|
interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);
|
||||||
|
|
||||||
// @todo: Control the relative frequency, in this case 16:1, of
|
|
||||||
// the clocks in the Python code
|
|
||||||
interrupts->setClock(tc->getCpuPtr()->clockPeriod() * 16);
|
|
||||||
|
|
||||||
// TODO Set the SMRAM base address (SMBASE) to 0x00030000
|
// TODO Set the SMRAM base address (SMBASE) to 0x00030000
|
||||||
|
|
||||||
tc->setMiscReg(MISCREG_VM_CR, 0);
|
tc->setMiscReg(MISCREG_VM_CR, 0);
|
||||||
|
|
|
@ -221,8 +221,9 @@ class BaseCPU(MemObject):
|
||||||
elif buildEnv['TARGET_ISA'] == 'alpha':
|
elif buildEnv['TARGET_ISA'] == 'alpha':
|
||||||
self.interrupts = AlphaInterrupts()
|
self.interrupts = AlphaInterrupts()
|
||||||
elif buildEnv['TARGET_ISA'] == 'x86':
|
elif buildEnv['TARGET_ISA'] == 'x86':
|
||||||
_localApic = X86LocalApic(pio_addr=0x2000000000000000)
|
self.interrupts = X86LocalApic(clock = Parent.clock * 16,
|
||||||
self.interrupts = _localApic
|
pio_addr=0x2000000000000000)
|
||||||
|
_localApic = self.interrupts
|
||||||
elif buildEnv['TARGET_ISA'] == 'mips':
|
elif buildEnv['TARGET_ISA'] == 'mips':
|
||||||
self.interrupts = MipsInterrupts()
|
self.interrupts = MipsInterrupts()
|
||||||
elif buildEnv['TARGET_ISA'] == 'arm':
|
elif buildEnv['TARGET_ISA'] == 'arm':
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2012 ARM Limited
|
# Copyright (c) 2012-2013 ARM Limited
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# The license below extends only to copyright in the software and shall
|
# The license below extends only to copyright in the software and shall
|
||||||
|
@ -1207,9 +1207,10 @@ class Frequency(TickParamValue):
|
||||||
def ini_str(self):
|
def ini_str(self):
|
||||||
return '%d' % self.getValue()
|
return '%d' % self.getValue()
|
||||||
|
|
||||||
# A generic frequency and/or Latency value. Value is stored as a latency,
|
# A generic frequency and/or Latency value. Value is stored as a
|
||||||
# but to avoid ambiguity this object does not support numeric ops (* or /).
|
# latency, and any manipulation using a multiplier thus scales the
|
||||||
# An explicit conversion to a Latency or Frequency must be made first.
|
# clock period, i.e. a 2x multiplier doubles the clock period and thus
|
||||||
|
# halves the clock frequency.
|
||||||
class Clock(ParamValue):
|
class Clock(ParamValue):
|
||||||
cxx_type = 'Tick'
|
cxx_type = 'Tick'
|
||||||
|
|
||||||
|
@ -1243,6 +1244,14 @@ class Clock(ParamValue):
|
||||||
return Latency(self)
|
return Latency(self)
|
||||||
raise AttributeError, "Frequency object has no attribute '%s'" % attr
|
raise AttributeError, "Frequency object has no attribute '%s'" % attr
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
# Always treat the clock as a period when scaling
|
||||||
|
newobj = self.__class__(self)
|
||||||
|
newobj.value *= other
|
||||||
|
return newobj
|
||||||
|
|
||||||
|
__rmul__ = __mul__
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return self.period.getValue()
|
return self.period.getValue()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue