diff options
Diffstat (limited to 'hw/sparc')
-rw-r--r-- | hw/sparc/leon3.c | 37 | ||||
-rw-r--r-- | hw/sparc/trace-events | 2 |
2 files changed, 38 insertions, 1 deletions
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 7e16eea..98e3789 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -137,7 +137,36 @@ static void main_cpu_reset(void *opaque) env->regbase[6] = s->sp; } -void leon3_irq_ack(void *irq_manager, int intno) +static void leon3_cache_control_int(CPUSPARCState *env) +{ + uint32_t state = 0; + + if (env->cache_control & CACHE_CTRL_IF) { + /* Instruction cache state */ + state = env->cache_control & CACHE_STATE_MASK; + if (state == CACHE_ENABLED) { + state = CACHE_FROZEN; + trace_int_helper_icache_freeze(); + } + + env->cache_control &= ~CACHE_STATE_MASK; + env->cache_control |= state; + } + + if (env->cache_control & CACHE_CTRL_DF) { + /* Data cache state */ + state = (env->cache_control >> 2) & CACHE_STATE_MASK; + if (state == CACHE_ENABLED) { + state = CACHE_FROZEN; + trace_int_helper_dcache_freeze(); + } + + env->cache_control &= ~(CACHE_STATE_MASK << 2); + env->cache_control |= (state << 2); + } +} + +static void leon3_irq_ack(void *irq_manager, int intno) { grlib_irqmp_ack((DeviceState *)irq_manager, intno); } @@ -181,6 +210,12 @@ static void leon3_set_pil_in(void *opaque, int n, int level) } } +static void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno) +{ + leon3_irq_ack(irq_manager, intno); + leon3_cache_control_int(env); +} + static void leon3_generic_hw_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; diff --git a/hw/sparc/trace-events b/hw/sparc/trace-events index 355b07a..dfb53dc 100644 --- a/hw/sparc/trace-events +++ b/hw/sparc/trace-events @@ -19,3 +19,5 @@ sun4m_iommu_bad_addr(uint64_t addr) "bad addr 0x%"PRIx64 # leon3.c leon3_set_irq(int intno) "Set CPU IRQ %d" leon3_reset_irq(int intno) "Reset CPU IRQ %d" +int_helper_icache_freeze(void) "Instruction cache: freeze" +int_helper_dcache_freeze(void) "Data cache: freeze" |