It's backport of acpi related cpu-hotplug code from qemu-kvm. Provides means to communicate cpu hot-plug events to guest OS and that works with current seabios.
Signed-off-by: Igor Mammedov <imamm...@redhat.com> --- hw/acpi_piix4.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++- hw/pc.h | 1 + 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index bdc55a1..5a83d73 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -43,9 +43,15 @@ #define PCI_BASE 0xae00 #define PCI_EJ_BASE 0xae08 #define PCI_RMV_BASE 0xae0c +#define PROC_BASE 0xaf00 +#define PIIX4_CPU_HOTPLUG_STATUS 4 #define PIIX4_PCI_HOTPLUG_STATUS 2 +struct gpe_regs { + uint8_t cpus_sts[32]; +}; + struct pci_status { uint32_t up; uint32_t down; @@ -71,6 +77,7 @@ typedef struct PIIX4PMState { /* for pci hotplug */ ACPIGPE gpe; + struct gpe_regs gpe_cpu; struct pci_status pci0_status; uint32_t pci0_hotplug_enable; } PIIX4PMState; @@ -90,7 +97,8 @@ static void pm_update_sci(PIIX4PMState *s) ACPI_BITMASK_POWER_BUTTON_ENABLE | ACPI_BITMASK_GLOBAL_LOCK_ENABLE | ACPI_BITMASK_TIMER_ENABLE)) != 0) || - (((s->gpe.sts[0] & s->gpe.en[0]) & PIIX4_PCI_HOTPLUG_STATUS) != 0); + (((s->gpe.sts[0] & s->gpe.en[0]) & + (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) != 0); qemu_set_irq(s->irq, sci_level); /* schedule a timer interruption if needed */ @@ -329,11 +337,16 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) } +static PIIX4PMState *global_piix4_pm_state; /* cpu hotadd */ + static int piix4_pm_initfn(PCIDevice *dev) { PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev); uint8_t *pci_conf; + /* for cpu hotadd */ + global_piix4_pm_state = s; + pci_conf = s->dev.config; pci_conf[0x06] = 0x80; pci_conf[0x07] = 0x02; @@ -425,8 +438,17 @@ device_init(piix4_pm_register); static uint32_t gpe_readb(void *opaque, uint32_t addr) { PIIX4PMState *s = opaque; - uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr); + uint32_t val = 0; + struct gpe_regs *g = &s->gpe_cpu; + switch (addr) { + case PROC_BASE ... PROC_BASE+31: + val = g->cpus_sts[addr - PROC_BASE]; + break; + default: + val = acpi_gpe_ioport_readb(&s->gpe, addr); + } + PIIX4_DPRINTF("gpe read %x == %x\n", addr, val); return val; } @@ -519,11 +541,20 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) { struct pci_status *pci0_status = &s->pci0_status; + int i = 0, cpus = smp_cpus; + while (cpus > 0) { + s->gpe_cpu.cpus_sts[i++] = (cpus < 8) ? (1 << cpus) - 1 : 0xff; + cpus -= 8; + } + register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s); register_ioport_read(GPE_BASE, GPE_LEN, 1, gpe_readb, s); acpi_gpe_blk(&s->gpe, GPE_BASE); + register_ioport_write(PROC_BASE, 32, 1, gpe_writeb, s); + register_ioport_read(PROC_BASE, 32, 1, gpe_readb, s); + register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status); register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, pci0_status); @@ -536,6 +567,36 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev); } +static void enable_processor(PIIX4PMState *s, int cpu) +{ + struct gpe_regs *g = &s->gpe_cpu; + ACPIGPE *gpe = &s->gpe; + + *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS; + g->cpus_sts[cpu / 8] |= (1 << (cpu % 8)); +} + +static void disable_processor(PIIX4PMState *s, int cpu) +{ + struct gpe_regs *g = &s->gpe_cpu; + ACPIGPE *gpe = &s->gpe; + + *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS; + g->cpus_sts[cpu / 8] &= ~(1 << (cpu % 8)); +} + +void acpi_cpu_hot_plug(int cpu, int state) +{ + PIIX4PMState *s = global_piix4_pm_state; + + if (state) { + enable_processor(s, cpu); + } else { + disable_processor(s, cpu); + } + pm_update_sci(s); +} + static void enable_device(PIIX4PMState *s, int slot) { s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; diff --git a/hw/pc.h b/hw/pc.h index 13e41f1..fd1e09c 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -163,6 +163,7 @@ extern size_t acpi_tables_len; void acpi_bios_init(void); int acpi_table_add(const char *table_desc); +void acpi_cpu_hot_plug(int cpu, int state); /* acpi_piix.c */ -- 1.7.7.6