From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:48829) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXtgB-00030C-BW for qemu-devel@nongnu.org; Thu, 02 May 2013 09:36:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UXtg3-0004We-Qg for qemu-devel@nongnu.org; Thu, 02 May 2013 09:36:11 -0400 Received: from cantor2.suse.de ([195.135.220.15]:46616 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXtg3-0004VZ-Gp for qemu-devel@nongnu.org; Thu, 02 May 2013 09:36:03 -0400 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 2 May 2013 15:35:37 +0200 Message-Id: <1367501755-32272-12-git-send-email-afaerber@suse.de> In-Reply-To: <1367501755-32272-1-git-send-email-afaerber@suse.de> References: <1367501755-32272-1-git-send-email-afaerber@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 11/29] acpi_piix4: Add infrastructure to send CPU hot-plug GPE to guest List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Igor Mammedov , =?UTF-8?q?Andreas=20F=C3=A4rber?= , "Michael S. Tsirkin" From: Igor Mammedov * introduce processor status bitmask visible to guest at 0xaf00 addr, where ACPI asl code expects it * set bit corresponding to APIC ID in processor status bitmask on receiving CPU hot-plug notification * trigger CPU hot-plug SCI, to notify guest about CPU hot-plug event Signed-off-by: Igor Mammedov Signed-off-by: Andreas F=C3=A4rber --- docs/specs/acpi_cpu_hotplug.txt | 22 ++++++++++ hw/acpi/piix4.c | 90 +++++++++++++++++++++++++++++++++++= +++++- 2 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 docs/specs/acpi_cpu_hotplug.txt diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplu= g.txt new file mode 100644 index 0000000..5dec0c5 --- /dev/null +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -0,0 +1,22 @@ +QEMU<->ACPI BIOS CPU hotplug interface +-------------------------------------- + +QEMU supports CPU hotplug via ACPI. This document +describes the interface between QEMU and the ACPI BIOS. + +ACPI GPE block (IO ports 0xafe0-0xafe3, byte access): +----------------------------------------- + +Generic ACPI GPE block. Bit 2 (GPE.2) used to notify CPU +hot-add/remove event to ACPI BIOS, via SCI interrupt. + +CPU present bitmap (IO port 0xaf00-0xae1f, 1-byte access): +--------------------------------------------------------------- +One bit per CPU. Bit position reflects corresponding CPU APIC ID. +Read-only. + +CPU hot-add/remove notification: +----------------------------------------------------- +QEMU sets/clears corresponding CPU bit on hot-add/remove event. +CPU present map read by ACPI BIOS GPE.2 handler to notify OS of CPU +hot-(un)plug events. diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 88386d7..c4af1cc 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -48,19 +48,28 @@ #define PCI_EJ_BASE 0xae08 #define PCI_RMV_BASE 0xae0c =20 +#define PIIX4_PROC_BASE 0xaf00 +#define PIIX4_PROC_LEN 32 + #define PIIX4_PCI_HOTPLUG_STATUS 2 +#define PIIX4_CPU_HOTPLUG_STATUS 4 =20 struct pci_status { uint32_t up; /* deprecated, maintained for migration compatibility *= / uint32_t down; }; =20 +typedef struct CPUStatus { + uint8_t sts[PIIX4_PROC_LEN]; +} CPUStatus; + typedef struct PIIX4PMState { PCIDevice dev; =20 MemoryRegion io; MemoryRegion io_gpe; MemoryRegion io_pci; + MemoryRegion io_cpu; ACPIREGS ar; =20 APMState apm; @@ -82,6 +91,9 @@ typedef struct PIIX4PMState { uint8_t disable_s3; uint8_t disable_s4; uint8_t s4_val; + + CPUStatus gpe_cpu; + Notifier cpu_added_notifier; } PIIX4PMState; =20 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, @@ -100,8 +112,8 @@ static void pm_update_sci(PIIX4PMState *s) ACPI_BITMASK_POWER_BUTTON_ENABLE | ACPI_BITMASK_GLOBAL_LOCK_ENABLE | ACPI_BITMASK_TIMER_ENABLE)) !=3D 0) || - (((s->ar.gpe.sts[0] & s->ar.gpe.en[0]) - & PIIX4_PCI_HOTPLUG_STATUS) !=3D 0); + (((s->ar.gpe.sts[0] & s->ar.gpe.en[0]) & + (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) !=3D 0)= ; =20 qemu_set_irq(s->irq, sci_level); /* schedule a timer interruption if needed */ @@ -585,6 +597,73 @@ static const MemoryRegionOps piix4_pci_ops =3D { }, }; =20 +static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int = size) +{ + PIIX4PMState *s =3D opaque; + CPUStatus *cpus =3D &s->gpe_cpu; + uint64_t val =3D cpus->sts[addr]; + + return val; +} + +static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + /* TODO: implement VCPU removal on guest signal that CPU can be remo= ved */ +} + +static const MemoryRegionOps cpu_hotplug_ops =3D { + .read =3D cpu_status_read, + .write =3D cpu_status_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, +}; + +typedef enum { + PLUG, + UNPLUG, +} HotplugEventType; + +static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu, + HotplugEventType action) +{ + CPUStatus *g =3D &s->gpe_cpu; + ACPIGPE *gpe =3D &s->ar.gpe; + CPUClass *k =3D CPU_GET_CLASS(cpu); + int64_t cpu_id; + + assert(s !=3D NULL); + + *gpe->sts =3D *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS; + cpu_id =3D k->get_arch_id(CPU(cpu)); + if (action =3D=3D PLUG) { + g->sts[cpu_id / 8] |=3D (1 << (cpu_id % 8)); + } else { + g->sts[cpu_id / 8] &=3D ~(1 << (cpu_id % 8)); + } + pm_update_sci(s); +} + +static void piix4_cpu_added_req(Notifier *n, void *opaque) +{ + PIIX4PMState *s =3D container_of(n, PIIX4PMState, cpu_added_notifier= ); + + piix4_cpu_hotplug_req(s, CPU(opaque), PLUG); +} + +static void piix4_init_cpu_status(CPUState *cpu, void *data) +{ + CPUStatus *g =3D (CPUStatus *)data; + CPUClass *k =3D CPU_GET_CLASS(cpu); + int64_t id =3D k->get_arch_id(cpu); + + g_assert((id / 8) < PIIX4_PROC_LEN); + g->sts[id / 8] |=3D (1 << (id % 8)); +} + static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, PCIHotplugState state); =20 @@ -600,6 +679,13 @@ static void piix4_acpi_system_hot_add_init(MemoryReg= ion *parent, memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR, &s->io_pci); pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev); + + qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu); + memory_region_init_io(&s->io_cpu, &cpu_hotplug_ops, s, "apci-cpu-hot= plug", + PIIX4_PROC_LEN); + memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu); + s->cpu_added_notifier.notify =3D piix4_cpu_added_req; + qemu_register_cpu_added_notifier(&s->cpu_added_notifier); } =20 static void enable_device(PIIX4PMState *s, int slot) --=20 1.8.1.4