APIC fixes - SIPI support

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1641 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2005-11-21 23:26:26 +00:00
parent 6a00d60127
commit e0fd87812f

View file

@ -121,7 +121,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode,
/* normal INIT IPI sent to processors */ /* normal INIT IPI sent to processors */
for (apic_iter = first_local_apic; apic_iter != NULL; for (apic_iter = first_local_apic; apic_iter != NULL;
apic_iter = apic_iter->next_apic) { apic_iter = apic_iter->next_apic) {
apic_init_ipi(apic_iter); if (deliver_bitmask & (1 << apic_iter->id))
apic_init_ipi(apic_iter);
} }
return; return;
@ -317,7 +318,7 @@ static void apic_init_ipi(APICState *s)
s->tpr = 0; s->tpr = 0;
s->spurious_vec = 0xff; s->spurious_vec = 0xff;
s->log_dest = 0; s->log_dest = 0;
s->dest_mode = 0; s->dest_mode = 0xf;
memset(s->isr, 0, sizeof(s->isr)); memset(s->isr, 0, sizeof(s->isr));
memset(s->tmr, 0, sizeof(s->tmr)); memset(s->tmr, 0, sizeof(s->tmr));
memset(s->irr, 0, sizeof(s->irr)); memset(s->irr, 0, sizeof(s->irr));
@ -331,6 +332,18 @@ static void apic_init_ipi(APICState *s)
s->next_time = 0; s->next_time = 0;
} }
/* send a SIPI message to the CPU to start it */
static void apic_startup(APICState *s, int vector_num)
{
CPUState *env = s->cpu_env;
if (!env->cpu_halted)
return;
env->eip = 0;
cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12,
0xffff, 0);
env->cpu_halted = 0;
}
static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
uint8_t delivery_mode, uint8_t vector_num, uint8_t delivery_mode, uint8_t vector_num,
uint8_t polarity, uint8_t trigger_mode) uint8_t polarity, uint8_t trigger_mode)
@ -339,10 +352,26 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
int dest_shorthand = (s->icr[0] >> 18) & 3; int dest_shorthand = (s->icr[0] >> 18) & 3;
APICState *apic_iter; APICState *apic_iter;
switch (dest_shorthand) {
case 0:
deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode);
break;
case 1:
deliver_bitmask = (1 << s->id);
break;
case 2:
deliver_bitmask = 0xffffffff;
break;
case 3:
deliver_bitmask = 0xffffffff & ~(1 << s->id);
break;
}
switch (delivery_mode) { switch (delivery_mode) {
case APIC_DM_LOWPRI: case APIC_DM_LOWPRI:
/* XXX: serch for focus processor, arbitration */ /* XXX: search for focus processor, arbitration */
dest = s->id; dest = s->id;
break;
case APIC_DM_INIT: case APIC_DM_INIT:
{ {
@ -364,28 +393,12 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
for (apic_iter = first_local_apic; apic_iter != NULL; for (apic_iter = first_local_apic; apic_iter != NULL;
apic_iter = apic_iter->next_apic) { apic_iter = apic_iter->next_apic) {
if (deliver_bitmask & (1 << apic_iter->id)) { if (deliver_bitmask & (1 << apic_iter->id)) {
/* XXX: SMP support */ apic_startup(apic_iter, vector_num);
/* apic_startup(apic_iter); */
} }
} }
return; return;
} }
switch (dest_shorthand) {
case 0:
deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode);
break;
case 1:
deliver_bitmask = (1 << s->id);
break;
case 2:
deliver_bitmask = 0xffffffff;
break;
case 3:
deliver_bitmask = 0xffffffff & ~(1 << s->id);
break;
}
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
trigger_mode); trigger_mode);
} }
@ -534,13 +547,13 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
case 0x28: case 0x28:
val = s->esr; val = s->esr;
break; break;
case 0x32 ... 0x37:
val = s->lvt[index - 0x32];
break;
case 0x30: case 0x30:
case 0x31: case 0x31:
val = s->icr[index & 1]; val = s->icr[index & 1];
break; break;
case 0x32 ... 0x37:
val = s->lvt[index - 0x32];
break;
case 0x38: case 0x38:
val = s->initial_count; val = s->initial_count;
break; break;
@ -581,10 +594,15 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
case 0x02: case 0x02:
s->id = (val >> 24); s->id = (val >> 24);
break; break;
case 0x03:
break;
case 0x08: case 0x08:
s->tpr = val; s->tpr = val;
apic_update_irq(s); apic_update_irq(s);
break; break;
case 0x09:
case 0x0a:
break;
case 0x0b: /* EOI */ case 0x0b: /* EOI */
apic_eoi(s); apic_eoi(s);
break; break;
@ -598,6 +616,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
s->spurious_vec = val & 0x1ff; s->spurious_vec = val & 0x1ff;
apic_update_irq(s); apic_update_irq(s);
break; break;
case 0x10 ... 0x17:
case 0x18 ... 0x1f:
case 0x20 ... 0x27:
case 0x28:
break;
case 0x30: case 0x30:
s->icr[0] = val; s->icr[0] = val;
apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1, apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
@ -620,6 +643,8 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
s->initial_count_load_time = qemu_get_clock(vm_clock); s->initial_count_load_time = qemu_get_clock(vm_clock);
apic_timer_update(s, s->initial_count_load_time); apic_timer_update(s, s->initial_count_load_time);
break; break;
case 0x39:
break;
case 0x3e: case 0x3e:
{ {
int v; int v;