Revision 5fafdf24 hw/apic.c
b/hw/apic.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* APIC support |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2004-2005 Fabrice Bellard |
5 | 5 |
* |
6 | 6 |
* This library is free software; you can redistribute it and/or |
... | ... | |
182 | 182 |
}\ |
183 | 183 |
} |
184 | 184 |
|
185 |
static void apic_bus_deliver(const uint32_t *deliver_bitmask,
|
|
185 |
static void apic_bus_deliver(const uint32_t *deliver_bitmask, |
|
186 | 186 |
uint8_t delivery_mode, |
187 | 187 |
uint8_t vector_num, uint8_t polarity, |
188 | 188 |
uint8_t trigger_mode) |
... | ... | |
219 | 219 |
|
220 | 220 |
case APIC_DM_INIT: |
221 | 221 |
/* normal INIT IPI sent to processors */ |
222 |
foreach_apic(apic_iter, deliver_bitmask,
|
|
222 |
foreach_apic(apic_iter, deliver_bitmask, |
|
223 | 223 |
apic_init_ipi(apic_iter) ); |
224 | 224 |
return; |
225 |
|
|
225 |
|
|
226 | 226 |
case APIC_DM_EXTINT: |
227 | 227 |
/* handled in I/O APIC code */ |
228 | 228 |
break; |
... | ... | |
231 | 231 |
return; |
232 | 232 |
} |
233 | 233 |
|
234 |
foreach_apic(apic_iter, deliver_bitmask,
|
|
234 |
foreach_apic(apic_iter, deliver_bitmask, |
|
235 | 235 |
apic_set_irq(apic_iter, vector_num, trigger_mode) ); |
236 | 236 |
} |
237 | 237 |
|
... | ... | |
241 | 241 |
#ifdef DEBUG_APIC |
242 | 242 |
printf("cpu_set_apic_base: %016" PRIx64 "\n", val); |
243 | 243 |
#endif |
244 |
s->apicbase = (val & 0xfffff000) |
|
|
244 |
s->apicbase = (val & 0xfffff000) | |
|
245 | 245 |
(s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE)); |
246 | 246 |
/* if disabled, cannot be enabled again */ |
247 | 247 |
if (!(val & MSR_IA32_APICBASE_ENABLE)) { |
... | ... | |
407 | 407 |
if (!(env->hflags & HF_HALTED_MASK)) |
408 | 408 |
return; |
409 | 409 |
env->eip = 0; |
410 |
cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12,
|
|
410 |
cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12, |
|
411 | 411 |
0xffff, 0); |
412 | 412 |
env->hflags &= ~HF_HALTED_MASK; |
413 | 413 |
} |
... | ... | |
443 | 443 |
int trig_mode = (s->icr[0] >> 15) & 1; |
444 | 444 |
int level = (s->icr[0] >> 14) & 1; |
445 | 445 |
if (level == 0 && trig_mode == 1) { |
446 |
foreach_apic(apic_iter, deliver_bitmask,
|
|
446 |
foreach_apic(apic_iter, deliver_bitmask, |
|
447 | 447 |
apic_iter->arb_id = apic_iter->id ); |
448 | 448 |
return; |
449 | 449 |
} |
... | ... | |
451 | 451 |
break; |
452 | 452 |
|
453 | 453 |
case APIC_DM_SIPI: |
454 |
foreach_apic(apic_iter, deliver_bitmask,
|
|
454 |
foreach_apic(apic_iter, deliver_bitmask, |
|
455 | 455 |
apic_startup(apic_iter, vector_num) ); |
456 | 456 |
return; |
457 | 457 |
} |
... | ... | |
471 | 471 |
return -1; |
472 | 472 |
if (!(s->spurious_vec & APIC_SV_ENABLE)) |
473 | 473 |
return -1; |
474 |
|
|
474 |
|
|
475 | 475 |
/* XXX: spurious IRQ handling */ |
476 | 476 |
intno = get_highest_priority_int(s->irr); |
477 | 477 |
if (intno < 0) |
... | ... | |
488 | 488 |
{ |
489 | 489 |
int64_t d; |
490 | 490 |
uint32_t val; |
491 |
d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >>
|
|
491 |
d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >> |
|
492 | 492 |
s->count_shift; |
493 | 493 |
if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) { |
494 | 494 |
/* periodic */ |
... | ... | |
505 | 505 |
static void apic_timer_update(APICState *s, int64_t current_time) |
506 | 506 |
{ |
507 | 507 |
int64_t next_time, d; |
508 |
|
|
508 |
|
|
509 | 509 |
if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) { |
510 |
d = (current_time - s->initial_count_load_time) >>
|
|
510 |
d = (current_time - s->initial_count_load_time) >> |
|
511 | 511 |
s->count_shift; |
512 | 512 |
if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) { |
513 | 513 |
d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1); |
... | ... | |
818 | 818 |
s->id = last_apic_id++; |
819 | 819 |
env->cpuid_apic_id = s->id; |
820 | 820 |
s->cpu_env = env; |
821 |
s->apicbase = 0xfee00000 |
|
|
821 |
s->apicbase = 0xfee00000 | |
|
822 | 822 |
(s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE; |
823 | 823 |
|
824 | 824 |
/* XXX: mapping more APICs at the same memory location */ |
825 | 825 |
if (apic_io_memory == 0) { |
826 | 826 |
/* NOTE: the APIC is directly connected to the CPU - it is not |
827 | 827 |
on the global memory bus. */ |
828 |
apic_io_memory = cpu_register_io_memory(0, apic_mem_read,
|
|
828 |
apic_io_memory = cpu_register_io_memory(0, apic_mem_read, |
|
829 | 829 |
apic_mem_write, NULL); |
830 | 830 |
cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000, |
831 | 831 |
apic_io_memory); |
... | ... | |
834 | 834 |
|
835 | 835 |
register_savevm("apic", s->id, 2, apic_save, apic_load, s); |
836 | 836 |
qemu_register_reset(apic_reset, s); |
837 |
|
|
837 |
|
|
838 | 838 |
local_apics[s->id] = s; |
839 | 839 |
return 0; |
840 | 840 |
} |
... | ... | |
868 | 868 |
vector = pic_read_irq(isa_pic); |
869 | 869 |
else |
870 | 870 |
vector = entry & 0xff; |
871 |
|
|
871 |
|
|
872 | 872 |
apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); |
873 |
apic_bus_deliver(deliver_bitmask, delivery_mode,
|
|
873 |
apic_bus_deliver(deliver_bitmask, delivery_mode, |
|
874 | 874 |
vector, polarity, trig_mode); |
875 | 875 |
} |
876 | 876 |
} |
... | ... | |
1036 | 1036 |
ioapic_reset(s); |
1037 | 1037 |
s->id = last_apic_id++; |
1038 | 1038 |
|
1039 |
io_memory = cpu_register_io_memory(0, ioapic_mem_read,
|
|
1039 |
io_memory = cpu_register_io_memory(0, ioapic_mem_read, |
|
1040 | 1040 |
ioapic_mem_write, s); |
1041 | 1041 |
cpu_register_physical_memory(0xfec00000, 0x1000, io_memory); |
1042 | 1042 |
|
1043 | 1043 |
register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s); |
1044 | 1044 |
qemu_register_reset(ioapic_reset, s); |
1045 |
|
|
1045 |
|
|
1046 | 1046 |
return s; |
1047 | 1047 |
} |
Also available in: Unified diff