121 |
/* normal INIT IPI sent to processors */ |
/* normal INIT IPI sent to processors */ |
122 |
for (apic_iter = first_local_apic; apic_iter != NULL; |
for (apic_iter = first_local_apic; apic_iter != NULL; |
123 |
apic_iter = apic_iter->next_apic) { |
apic_iter = apic_iter->next_apic) { |
124 |
apic_init_ipi(apic_iter); |
if (deliver_bitmask & (1 << apic_iter->id)) |
125 |
|
apic_init_ipi(apic_iter); |
126 |
} |
} |
127 |
return; |
return; |
128 |
|
|
318 |
s->tpr = 0; |
s->tpr = 0; |
319 |
s->spurious_vec = 0xff; |
s->spurious_vec = 0xff; |
320 |
s->log_dest = 0; |
s->log_dest = 0; |
321 |
s->dest_mode = 0; |
s->dest_mode = 0xf; |
322 |
memset(s->isr, 0, sizeof(s->isr)); |
memset(s->isr, 0, sizeof(s->isr)); |
323 |
memset(s->tmr, 0, sizeof(s->tmr)); |
memset(s->tmr, 0, sizeof(s->tmr)); |
324 |
memset(s->irr, 0, sizeof(s->irr)); |
memset(s->irr, 0, sizeof(s->irr)); |
332 |
s->next_time = 0; |
s->next_time = 0; |
333 |
} |
} |
334 |
|
|
335 |
|
/* send a SIPI message to the CPU to start it */ |
336 |
|
static void apic_startup(APICState *s, int vector_num) |
337 |
|
{ |
338 |
|
CPUState *env = s->cpu_env; |
339 |
|
if (!env->cpu_halted) |
340 |
|
return; |
341 |
|
env->eip = 0; |
342 |
|
cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12, |
343 |
|
0xffff, 0); |
344 |
|
env->cpu_halted = 0; |
345 |
|
} |
346 |
|
|
347 |
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, |
348 |
uint8_t delivery_mode, uint8_t vector_num, |
uint8_t delivery_mode, uint8_t vector_num, |
349 |
uint8_t polarity, uint8_t trigger_mode) |
uint8_t polarity, uint8_t trigger_mode) |
352 |
int dest_shorthand = (s->icr[0] >> 18) & 3; |
int dest_shorthand = (s->icr[0] >> 18) & 3; |
353 |
APICState *apic_iter; |
APICState *apic_iter; |
354 |
|
|
355 |
|
switch (dest_shorthand) { |
356 |
|
case 0: |
357 |
|
deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode); |
358 |
|
break; |
359 |
|
case 1: |
360 |
|
deliver_bitmask = (1 << s->id); |
361 |
|
break; |
362 |
|
case 2: |
363 |
|
deliver_bitmask = 0xffffffff; |
364 |
|
break; |
365 |
|
case 3: |
366 |
|
deliver_bitmask = 0xffffffff & ~(1 << s->id); |
367 |
|
break; |
368 |
|
} |
369 |
|
|
370 |
switch (delivery_mode) { |
switch (delivery_mode) { |
371 |
case APIC_DM_LOWPRI: |
case APIC_DM_LOWPRI: |
372 |
/* XXX: serch for focus processor, arbitration */ |
/* XXX: search for focus processor, arbitration */ |
373 |
dest = s->id; |
dest = s->id; |
374 |
|
break; |
375 |
|
|
376 |
case APIC_DM_INIT: |
case APIC_DM_INIT: |
377 |
{ |
{ |
393 |
for (apic_iter = first_local_apic; apic_iter != NULL; |
for (apic_iter = first_local_apic; apic_iter != NULL; |
394 |
apic_iter = apic_iter->next_apic) { |
apic_iter = apic_iter->next_apic) { |
395 |
if (deliver_bitmask & (1 << apic_iter->id)) { |
if (deliver_bitmask & (1 << apic_iter->id)) { |
396 |
/* XXX: SMP support */ |
apic_startup(apic_iter, vector_num); |
|
/* apic_startup(apic_iter); */ |
|
397 |
} |
} |
398 |
} |
} |
399 |
return; |
return; |
400 |
} |
} |
401 |
|
|
|
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; |
|
|
} |
|
|
|
|
402 |
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, |
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, |
403 |
trigger_mode); |
trigger_mode); |
404 |
} |
} |
547 |
case 0x28: |
case 0x28: |
548 |
val = s->esr; |
val = s->esr; |
549 |
break; |
break; |
|
case 0x32 ... 0x37: |
|
|
val = s->lvt[index - 0x32]; |
|
|
break; |
|
550 |
case 0x30: |
case 0x30: |
551 |
case 0x31: |
case 0x31: |
552 |
val = s->icr[index & 1]; |
val = s->icr[index & 1]; |
553 |
break; |
break; |
554 |
|
case 0x32 ... 0x37: |
555 |
|
val = s->lvt[index - 0x32]; |
556 |
|
break; |
557 |
case 0x38: |
case 0x38: |
558 |
val = s->initial_count; |
val = s->initial_count; |
559 |
break; |
break; |
594 |
case 0x02: |
case 0x02: |
595 |
s->id = (val >> 24); |
s->id = (val >> 24); |
596 |
break; |
break; |
597 |
|
case 0x03: |
598 |
|
break; |
599 |
case 0x08: |
case 0x08: |
600 |
s->tpr = val; |
s->tpr = val; |
601 |
apic_update_irq(s); |
apic_update_irq(s); |
602 |
break; |
break; |
603 |
|
case 0x09: |
604 |
|
case 0x0a: |
605 |
|
break; |
606 |
case 0x0b: /* EOI */ |
case 0x0b: /* EOI */ |
607 |
apic_eoi(s); |
apic_eoi(s); |
608 |
break; |
break; |
616 |
s->spurious_vec = val & 0x1ff; |
s->spurious_vec = val & 0x1ff; |
617 |
apic_update_irq(s); |
apic_update_irq(s); |
618 |
break; |
break; |
619 |
|
case 0x10 ... 0x17: |
620 |
|
case 0x18 ... 0x1f: |
621 |
|
case 0x20 ... 0x27: |
622 |
|
case 0x28: |
623 |
|
break; |
624 |
case 0x30: |
case 0x30: |
625 |
s->icr[0] = val; |
s->icr[0] = val; |
626 |
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, |
643 |
s->initial_count_load_time = qemu_get_clock(vm_clock); |
s->initial_count_load_time = qemu_get_clock(vm_clock); |
644 |
apic_timer_update(s, s->initial_count_load_time); |
apic_timer_update(s, s->initial_count_load_time); |
645 |
break; |
break; |
646 |
|
case 0x39: |
647 |
|
break; |
648 |
case 0x3e: |
case 0x3e: |
649 |
{ |
{ |
650 |
int v; |
int v; |