diff options
Diffstat (limited to 'hw/apic.c')
-rw-r--r-- | hw/apic.c | 37 |
1 files changed, 26 insertions, 11 deletions
@@ -85,6 +85,8 @@ typedef struct APICState { int64_t initial_count_load_time, next_time; uint32_t idx; QEMUTimer *timer; + int sipi_vector; + int wait_for_sipi; } APICState; static int apic_io_memory; @@ -93,7 +95,6 @@ static int last_apic_idx = 0; static int apic_irq_delivered; -static void apic_init_ipi(APICState *s); static void apic_set_irq(APICState *s, int vector_num, int trigger_mode); static void apic_update_irq(APICState *s); static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, @@ -249,7 +250,7 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, case APIC_DM_INIT: /* normal INIT IPI sent to processors */ foreach_apic(apic_iter, deliver_bitmask, - apic_init_ipi(apic_iter) ); + cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) ); return; case APIC_DM_EXTINT: @@ -454,10 +455,14 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, } -static void apic_init_ipi(APICState *s) +void apic_init_reset(CPUState *env) { + APICState *s = env->apic_state; int i; + if (!s) + return; + s->tpr = 0; s->spurious_vec = 0xff; s->log_dest = 0; @@ -474,22 +479,31 @@ static void apic_init_ipi(APICState *s) s->initial_count = 0; s->initial_count_load_time = 0; s->next_time = 0; + s->wait_for_sipi = 1; - cpu_reset(s->cpu_env); - - s->cpu_env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP); + env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP); } -/* 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->halted) + s->sipi_vector = vector_num; + cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI); +} + +void apic_sipi(CPUState *env) +{ + APICState *s = env->apic_state; + + cpu_reset_interrupt(env, CPU_INTERRUPT_SIPI); + + if (!s->wait_for_sipi) return; + env->eip = 0; - cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12, + cpu_x86_load_seg_cache(env, R_CS, s->sipi_vector << 8, s->sipi_vector << 12, 0xffff, 0); env->halted = 0; + s->wait_for_sipi = 0; } static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, @@ -894,7 +908,8 @@ static void apic_reset(void *opaque) s->apicbase = 0xfee00000 | (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; - apic_init_ipi(s); + cpu_reset(s->cpu_env); + apic_init_reset(s->cpu_env); if (bsp) { /* |