Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions hw/mips/Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ obj-y += mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-y += addr.o cputimer.o mips_int.o
obj-$(CONFIG_FULONG) += mips_fulong2e.o
obj-y += gt64xxx_pci.o
obj-y += mips_pic32mz.o mips_pic32mx7.o
obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o
obj-y += pic32_ethernet.o
55 changes: 34 additions & 21 deletions hw/mips/cputimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,13 @@
#include "qemu/timer.h"
#include "sysemu/kvm.h"

#define TIMER_FREQ 100 * 1000 * 1000

/* XXX: do not use a global */
/* Generate a random TLB index.
* Skip wired entries. */
uint32_t cpu_mips_get_random (CPUMIPSState *env)
{
static uint32_t lfsr = 1;
static uint32_t prev_idx = 0;
uint32_t idx;
/* Don't return same value twice, so get another value */
do {
lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
} while (idx == prev_idx);
prev_idx = idx;
return idx;
env->CP0_Random = env->CP0_Wired +
random() % (env->tlb->nb_tlb - env->CP0_Wired);
return env->CP0_Random;
}

/* MIPS R4K timer */
Expand All @@ -50,8 +42,8 @@ static void cpu_mips_timer_update(CPUMIPSState *env)

now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
wait = env->CP0_Compare - env->CP0_Count -
(uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
(uint32_t)muldiv64(now, env->count_freq, get_ticks_per_sec());
next = now + muldiv64(wait, get_ticks_per_sec(), env->count_freq);
timer_mod(env->timer, next);
}

Expand All @@ -62,7 +54,13 @@ static void cpu_mips_timer_expire(CPUMIPSState *env)
if (env->insn_flags & ISA_MIPS32R2) {
env->CP0_Cause |= 1 << CP0Ca_TI;
}
qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
/* External interrupt controller mode. */
env->eic_timer_irq(env, 1);
} else {
/* Legacy or vectored interrupt mode. */
qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
}

uint32_t cpu_mips_get_count (CPUMIPSState *env)
Expand All @@ -80,7 +78,7 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env)
}

return env->CP0_Count +
(uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
(uint32_t)muldiv64(now, env->count_freq, get_ticks_per_sec());
}
}

Expand All @@ -97,7 +95,7 @@ void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
/* Store new count register */
env->CP0_Count =
count - (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
TIMER_FREQ, get_ticks_per_sec());
env->count_freq, get_ticks_per_sec());
/* Update timer timer */
cpu_mips_timer_update(env);
}
Expand All @@ -110,7 +108,14 @@ void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
cpu_mips_timer_update(env);
if (env->insn_flags & ISA_MIPS32R2)
env->CP0_Cause &= ~(1 << CP0Ca_TI);
qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);

if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
/* External interrupt controller mode: nothing to do. */
env->eic_timer_irq(env, 0);
} else {
/* Legacy or vectored interrupt mode. */
qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
}

void cpu_mips_start_count(CPUMIPSState *env)
Expand All @@ -122,7 +127,7 @@ void cpu_mips_stop_count(CPUMIPSState *env)
{
/* Store the current value */
env->CP0_Count += (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
TIMER_FREQ, get_ticks_per_sec());
env->count_freq, get_ticks_per_sec());
}

static void mips_timer_cb (void *opaque)
Expand All @@ -145,13 +150,21 @@ static void mips_timer_cb (void *opaque)
env->CP0_Count--;
}

void cpu_mips_clock_init (CPUMIPSState *env)
void cpu_mips_clock_init (CPUMIPSState *env, unsigned count_freq)
{
/*
* If we're in KVM mode, don't create the periodic timer, that is handled in
* kernel.
*/
if (!kvm_enabled()) {
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
env->count_freq = count_freq;

if (qemu_loglevel_mask(CPU_LOG_INSTR)) {
/* When instruction tracing enabled,
* we need to slow down the timer to adapt
* to the decreased simulation speed. */
env->count_freq /= 10;
}
}
}
2 changes: 1 addition & 1 deletion hw/mips/mips_fulong2e.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ static void mips_fulong2e_init(MachineState *machine)

/* Init internal devices */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
cpu_mips_clock_init(env, 100*1000*1000);

/* North bridge, Bonito --> IP2 */
pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
Expand Down
11 changes: 9 additions & 2 deletions hw/mips/mips_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
CPUMIPSState *env = &cpu->env;
CPUState *cs = CPU(cpu);

if (irq < 0 || irq > 7)
if (irq < 0 || irq > 7 || (env->CP0_Config3 & (1 << CP0C3_VEIC)))
return;

if (level) {
Expand Down Expand Up @@ -74,5 +74,12 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
return;
}

qemu_set_irq(env->irq[irq], level);
if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
/* External interrupt controller mode. */
if (level > 0)
env->eic_soft_irq(env, irq);
} else {
/* Legacy or vectored interrupt mode. */
qemu_set_irq(env->irq[irq], level);
}
}
2 changes: 1 addition & 1 deletion hw/mips/mips_jazz.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ static void mips_jazz_init(MemoryRegion *address_space,

/* Init CPU internal devices */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
cpu_mips_clock_init(env, 100*1000*1000);

/* Chipset */
rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
Expand Down
4 changes: 2 additions & 2 deletions hw/mips/mips_malta.c
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ void mips_malta_init(MachineState *machine)

/* Init internal devices */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
cpu_mips_clock_init(env, 100*1000*1000);
qemu_register_reset(main_cpu_reset, cpu);
}
cpu = MIPS_CPU(first_cpu);
Expand Down Expand Up @@ -1134,7 +1134,7 @@ void mips_malta_init(MachineState *machine)

/* Init internal devices */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
cpu_mips_clock_init(env, 100*1000*1000);

/*
* We have a circular dependency problem: pci_bus depends on isa_irq,
Expand Down
2 changes: 1 addition & 1 deletion hw/mips/mips_mipssim.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ mips_mipssim_init(MachineState *machine)

/* Init CPU internal devices. */
cpu_mips_irq_init_cpu(env);
cpu_mips_clock_init(env);
cpu_mips_clock_init(env, 100*1000*1000);

/* Register 64 KB of ISA IO space at 0x1fd00000. */
memory_region_init_alias(isa, NULL, "isa_mmio",
Expand Down
Loading