Initial SPARC SMP support (Blue Swirl)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1694 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2005-12-05 20:31:52 +00:00
parent b9788fc4c4
commit ba3c64fb47
12 changed files with 196 additions and 54 deletions

View file

@ -53,6 +53,7 @@ typedef struct SLAVIO_INTCTLState {
#ifdef DEBUG_IRQ_COUNT
uint64_t irq_count[32];
#endif
CPUState *cpu_envs[MAX_CPUS];
} SLAVIO_INTCTLState;
#define INTCTL_MAXADDR 0xf
@ -96,6 +97,7 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint
case 2: // set softint
val &= 0xfffe0000;
s->intreg_pending[cpu] |= val;
slavio_check_interrupts(s);
DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
break;
default:
@ -216,7 +218,7 @@ static void slavio_check_interrupts(void *opaque)
CPUState *env;
SLAVIO_INTCTLState *s = opaque;
uint32_t pending = s->intregm_pending;
unsigned int i, max = 0;
unsigned int i, j, max = 0;
pending &= ~s->intregm_disabled;
@ -227,20 +229,52 @@ static void slavio_check_interrupts(void *opaque)
max = intbit_to_level[i];
}
}
env = first_cpu;
if (env->interrupt_index == 0) {
DPRINTF("Triggered pil %d\n", max);
env = s->cpu_envs[s->target_cpu];
if (!env) {
DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
}
else {
if (env->halted)
env->halted = 0;
if (env->interrupt_index == 0) {
DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
#ifdef DEBUG_IRQ_COUNT
s->irq_count[max]++;
s->irq_count[max]++;
#endif
env->interrupt_index = TT_EXTINT | max;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
env->interrupt_index = TT_EXTINT | max;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
else
DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
}
else
DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
}
else
DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
for (i = 0; i < MAX_CPUS; i++) {
max = 0;
env = s->cpu_envs[i];
if (!env)
continue;
for (j = 17; j < 32; j++) {
if (s->intreg_pending[i] & (1 << j)) {
if (max < j - 16)
max = j - 16;
}
}
if (max > 0) {
if (env->halted)
env->halted = 0;
if (env->interrupt_index == 0) {
DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
#ifdef DEBUG_IRQ_COUNT
s->irq_count[max]++;
#endif
env->interrupt_index = TT_EXTINT | max;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
}
}
}
/*
@ -251,7 +285,7 @@ void slavio_pic_set_irq(void *opaque, int irq, int level)
{
SLAVIO_INTCTLState *s = opaque;
DPRINTF("Set irq %d level %d\n", irq, level);
DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
if (irq < 32) {
uint32_t mask = 1 << irq;
uint32_t pil = intbit_to_level[irq];
@ -269,6 +303,29 @@ void slavio_pic_set_irq(void *opaque, int irq, int level)
slavio_check_interrupts(s);
}
void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
{
SLAVIO_INTCTLState *s = opaque;
DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
if (cpu == (unsigned int)-1) {
slavio_pic_set_irq(opaque, irq, level);
return;
}
if (irq < 32) {
uint32_t pil = intbit_to_level[irq];
if (pil > 0) {
if (level) {
s->intreg_pending[cpu] |= 1 << pil;
}
else {
s->intreg_pending[cpu] &= ~(1 << pil);
}
}
}
slavio_check_interrupts(s);
}
static void slavio_intctl_save(QEMUFile *f, void *opaque)
{
SLAVIO_INTCTLState *s = opaque;
@ -312,6 +369,12 @@ static void slavio_intctl_reset(void *opaque)
s->target_cpu = 0;
}
void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
{
SLAVIO_INTCTLState *s = opaque;
s->cpu_envs[cpu] = env;
}
void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
{
int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;