Commit 0e21e12bb311c4c1095d0269dc2ef81196ccb60a

Authored by ths
1 parent aacb758b

Don't route PIC interrupts through the local APIC if the local APIC

config says so. By Ari Kivity.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3371 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 3 changed files with 38 additions and 3 deletions
hw/apic.c
... ... @@ -484,6 +484,25 @@ int apic_get_interrupt(CPUState *env)
484 484 return intno;
485 485 }
486 486  
  487 +int apic_accept_pic_intr(CPUState *env)
  488 +{
  489 + APICState *s = env->apic_state;
  490 + uint32_t lvt0;
  491 +
  492 + if (!s)
  493 + return -1;
  494 +
  495 + lvt0 = s->lvt[APIC_LVT_LINT0];
  496 +
  497 + if (s->id == 0 &&
  498 + ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
  499 + ((lvt0 & APIC_LVT_MASKED) == 0 &&
  500 + ((lvt0 >> 8) & 0x7) == APIC_DM_EXTINT)))
  501 + return 1;
  502 +
  503 + return 0;
  504 +}
  505 +
487 506 static uint32_t apic_get_current_count(APICState *s)
488 507 {
489 508 int64_t d;
... ... @@ -790,6 +809,13 @@ static void apic_reset(void *opaque)
790 809 {
791 810 APICState *s = opaque;
792 811 apic_init_ipi(s);
  812 +
  813 + /*
  814 + * LINT0 delivery mode is set to ExtInt at initialization time
  815 + * typically by BIOS, so PIC interrupt can be delivered to the
  816 + * processor when local APIC is enabled.
  817 + */
  818 + s->lvt[APIC_LVT_LINT0] = 0x700;
793 819 }
794 820  
795 821 static CPUReadMemoryFunc *apic_mem_read[3] = {
... ... @@ -821,6 +847,13 @@ int apic_init(CPUState *env)
821 847 s->apicbase = 0xfee00000 |
822 848 (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
823 849  
  850 + /*
  851 + * LINT0 delivery mode is set to ExtInt at initialization time
  852 + * typically by BIOS, so PIC interrupt can be delivered to the
  853 + * processor when local APIC is enabled.
  854 + */
  855 + s->lvt[APIC_LVT_LINT0] = 0x700;
  856 +
824 857 /* XXX: mapping more APICs at the same memory location */
825 858 if (apic_io_memory == 0) {
826 859 /* NOTE: the APIC is directly connected to the CPU - it is not
... ...
... ... @@ -93,6 +93,9 @@ int cpu_get_pic_interrupt(CPUState *env)
93 93 return intno;
94 94 }
95 95 /* read the irq from the PIC */
  96 + if (!apic_accept_pic_intr(env))
  97 + return -1;
  98 +
96 99 intno = pic_read_irq(isa_pic);
97 100 return intno;
98 101 }
... ... @@ -100,10 +103,8 @@ int cpu_get_pic_interrupt(CPUState *env)
100 103 static void pic_irq_request(void *opaque, int irq, int level)
101 104 {
102 105 CPUState *env = opaque;
103   - if (level)
  106 + if (level && apic_accept_pic_intr(env))
104 107 cpu_interrupt(env, CPU_INTERRUPT_HARD);
105   - else
106   - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
107 108 }
108 109  
109 110 /* PC cmos mappings */
... ...
... ... @@ -1139,6 +1139,7 @@ void irq_info(void);
1139 1139 typedef struct IOAPICState IOAPICState;
1140 1140  
1141 1141 int apic_init(CPUState *env);
  1142 +int apic_accept_pic_intr(CPUState *env);
1142 1143 int apic_get_interrupt(CPUState *env);
1143 1144 IOAPICState *ioapic_init(void);
1144 1145 void ioapic_set_irq(void *opaque, int vector, int level);
... ...