diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 59930dd9d09d..701a0821705b 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -50,6 +50,7 @@ #include "qom/cpu.h" #include "hw/nvram/fw_cfg.h" #include "qemu/cutils.h" +#include "trace.h" /*****************************************************************************/ /* ICH9 LPC PCI to ISA bridge */ @@ -423,6 +424,29 @@ void ich9_lpc_pm_init(PCIDevice *lpc_pci, bool smm_enabled) /* APM */ +static void ich9_apm_broadcast_smi(void) +{ + CPUState *cs; + + pause_all_vcpus(); + cpu_synchronize_all_states(); + CPU_FOREACH(cs) { + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; + + if (env->smbase == 0x30000 && env->eip == 0xfff0) { + CPUClass *k = CPU_GET_CLASS(cs); + uint64_t cpu_arch_id = k->get_arch_id(cs); + + trace_ich9_apm_broadcast_smi_skip(cpu_arch_id); + continue; + } + + cpu_interrupt(cs, CPU_INTERRUPT_SMI); + } + resume_all_vcpus(); +} + static void ich9_apm_ctrl_changed(uint32_t val, void *arg) { ICH9LPCState *lpc = arg; @@ -439,10 +463,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg) if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) { if (lpc->smi_negotiated_features & (UINT64_C(1) << ICH9_LPC_SMI_F_BROADCAST_BIT)) { - CPUState *cs; - CPU_FOREACH(cs) { - cpu_interrupt(cs, CPU_INTERRUPT_SMI); - } + ich9_apm_broadcast_smi(); } else { cpu_interrupt(current_cpu, CPU_INTERRUPT_SMI); } diff --git a/hw/isa/trace-events b/hw/isa/trace-events index 9faca41a975d..a0df525d042a 100644 --- a/hw/isa/trace-events +++ b/hw/isa/trace-events @@ -7,3 +7,6 @@ pc87312_info_floppy(uint32_t base) "base 0x%x" pc87312_info_ide(uint32_t base) "base 0x%x" pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u" pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u" + +# hw/isa/lpc_ich9.c +ich9_apm_broadcast_smi_skip(uint64_t cpu_arch_id) "cpu_arch_id=0x%"PRIx64