On Fri, Dec 13, 2013 at 05:22:08PM +0100, Igor Mammedov wrote: > .. so it could be used for adding CPU hotplug to Q35 machine > > Signed-off-by: Igor Mammedov <imamm...@redhat.com>
Sounds good but please call this file cpu_hotplug.c/.h or cpu-hotplug.c/h and make all prefixes acpi_cpu_hotplug and AcpiCpuHotplug. > --- > hw/acpi/Makefile.objs | 2 +- > hw/acpi/hotplug.c | 65 +++++++++++++++++++++++++++++++++++++++ > hw/acpi/piix4.c | 78 > +++++------------------------------------------ > include/hw/acpi/hotplug.h | 31 +++++++++++++++++++ > 4 files changed, 104 insertions(+), 72 deletions(-) > create mode 100644 hw/acpi/hotplug.c > create mode 100644 include/hw/acpi/hotplug.h > > diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs > index a0b63b5..41dec06 100644 > --- a/hw/acpi/Makefile.objs > +++ b/hw/acpi/Makefile.objs > @@ -1,2 +1,2 @@ > -common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o > +common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o hotplug.o > > diff --git a/hw/acpi/hotplug.c b/hw/acpi/hotplug.c > new file mode 100644 > index 0000000..fcc0988 > --- /dev/null > +++ b/hw/acpi/hotplug.c > @@ -0,0 +1,65 @@ > +/* > + * QEMU ACPI hotplug utilities > + * > + * Copyright (C) 2013 Red Hat Inc > + * > + * Authors: > + * Igor Mammedov <imamm...@redhat.com> > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + */ > +#include "hw/hw.h" > +#include "hw/acpi/hotplug.h" > + > +static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size) > +{ > + AcpiCPUHotplug *cpus = opaque; > + uint64_t val = 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 removed > */ > +} > + > +static const MemoryRegionOps acpi_cpu_hotplug_ops = { > + .read = cpu_status_read, > + .write = cpu_status_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 1, > + .max_access_size = 1, > + }, > +}; > + > +void acpi_hotplug_cpu_add(ACPIGPE *gpe, AcpiCPUHotplug *g, CPUState *cpu) > +{ > + CPUClass *k = CPU_GET_CLASS(cpu); > + int64_t cpu_id; > + > + *gpe->sts = *gpe->sts | ACPI_CPU_HOTPLUG_STATUS; > + cpu_id = k->get_arch_id(CPU(cpu)); > + g->sts[cpu_id / 8] |= (1 << (cpu_id % 8)); > +} > + > +void acpi_hotplug_cpu_init(MemoryRegion *parent, Object *owner, > + AcpiCPUHotplug *gpe_cpu, uint16_t base) > +{ > + CPUState *cpu; > + > + CPU_FOREACH(cpu) { > + CPUClass *cc = CPU_GET_CLASS(cpu); > + int64_t id = cc->get_arch_id(cpu); > + > + g_assert((id / 8) < ACPI_GPE_PROC_LEN); > + gpe_cpu->sts[id / 8] |= (1 << (id % 8)); > + } > + gpe_cpu->io_base = base; > + memory_region_init_io(&gpe_cpu->io, owner, &acpi_cpu_hotplug_ops, > + gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN); > + memory_region_add_subregion(parent, gpe_cpu->io_base, &gpe_cpu->io); > +} > diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c > index b6b97ce..8ab85b2 100644 > --- a/hw/acpi/piix4.c > +++ b/hw/acpi/piix4.c > @@ -30,6 +30,7 @@ > #include "hw/nvram/fw_cfg.h" > #include "exec/address-spaces.h" > #include "hw/acpi/piix4.h" > +#include "hw/acpi/hotplug.h" > > //#define DEBUG > > @@ -50,20 +51,14 @@ > #define PCI_RMV_BASE 0xae0c > > #define PIIX4_PROC_BASE 0xaf00 > -#define PIIX4_PROC_LEN 32 > > #define PIIX4_PCI_HOTPLUG_STATUS 2 > -#define PIIX4_CPU_HOTPLUG_STATUS 4 > > struct pci_status { > uint32_t up; /* deprecated, maintained for migration compatibility */ > uint32_t down; > }; > > -typedef struct CPUStatus { > - uint8_t sts[PIIX4_PROC_LEN]; > -} CPUStatus; > - > typedef struct PIIX4PMState { > /*< private >*/ > PCIDevice parent_obj; > @@ -74,7 +69,6 @@ typedef struct PIIX4PMState { > > MemoryRegion io_gpe; > MemoryRegion io_pci; > - MemoryRegion io_cpu; > ACPIREGS ar; > > APMState apm; > @@ -97,7 +91,7 @@ typedef struct PIIX4PMState { > uint8_t disable_s4; > uint8_t s4_val; > > - CPUStatus gpe_cpu; > + AcpiCPUHotplug gpe_cpu; > Notifier cpu_added_notifier; > } PIIX4PMState; > > @@ -628,61 +622,13 @@ static const MemoryRegionOps piix4_pci_ops = { > }, > }; > > -static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size) > -{ > - PIIX4PMState *s = opaque; > - CPUStatus *cpus = &s->gpe_cpu; > - uint64_t val = 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 removed > */ > -} > - > -static const MemoryRegionOps cpu_hotplug_ops = { > - .read = cpu_status_read, > - .write = cpu_status_write, > - .endianness = DEVICE_LITTLE_ENDIAN, > - .valid = { > - .min_access_size = 1, > - .max_access_size = 1, > - }, > -}; > - > -typedef enum { > - PLUG, > - UNPLUG, > -} HotplugEventType; > - > -static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu, > - HotplugEventType action) > -{ > - CPUStatus *g = &s->gpe_cpu; > - ACPIGPE *gpe = &s->ar.gpe; > - CPUClass *k = CPU_GET_CLASS(cpu); > - int64_t cpu_id; > - > - assert(s != NULL); > - > - *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS; > - cpu_id = k->get_arch_id(CPU(cpu)); > - if (action == PLUG) { > - g->sts[cpu_id / 8] |= (1 << (cpu_id % 8)); > - } else { > - g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8)); > - } > - acpi_update_sci(&s->ar, s->irq); > -} > - > static void piix4_cpu_added_req(Notifier *n, void *opaque) > { > PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier); > > - piix4_cpu_hotplug_req(s, CPU(opaque), PLUG); > + assert(s != NULL); > + acpi_hotplug_cpu_add(&s->ar.gpe, &s->gpe_cpu, CPU(opaque)); > + acpi_update_sci(&s->ar, s->irq); > } > > static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, > @@ -691,8 +637,6 @@ static int piix4_device_hotplug(DeviceState *qdev, > PCIDevice *dev, > static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, > PCIBus *bus, PIIX4PMState *s) > { > - CPUState *cpu; > - > memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s, > "acpi-gpe0", GPE_LEN); > memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); > @@ -703,16 +647,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion > *parent, > &s->io_pci); > pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s)); > > - CPU_FOREACH(cpu) { > - CPUClass *cc = CPU_GET_CLASS(cpu); > - int64_t id = cc->get_arch_id(cpu); > - > - g_assert((id / 8) < PIIX4_PROC_LEN); > - s->gpe_cpu.sts[id / 8] |= (1 << (id % 8)); > - } > - memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s, > - "acpi-cpu-hotplug", PIIX4_PROC_LEN); > - memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu); > + acpi_hotplug_cpu_init(parent, OBJECT(s), &s->gpe_cpu, > + PIIX4_PROC_BASE); > s->cpu_added_notifier.notify = piix4_cpu_added_req; > qemu_register_cpu_added_notifier(&s->cpu_added_notifier); > } > diff --git a/include/hw/acpi/hotplug.h b/include/hw/acpi/hotplug.h > new file mode 100644 > index 0000000..8bc176b > --- /dev/null > +++ b/include/hw/acpi/hotplug.h > @@ -0,0 +1,31 @@ > +/* > + * QEMU ACPI hotplug utilities > + * > + * Copyright (C) 2013 Red Hat Inc > + * > + * Authors: > + * Igor Mammedov <imamm...@redhat.com> > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + */ > +#ifndef ACPI_HOTPLUG_H > +#define ACPI_HOTPLUG_H > + > +#include "hw/acpi/acpi.h" > + > +#define ACPI_CPU_HOTPLUG_STATUS 4 > + > +#define ACPI_GPE_PROC_LEN 32 > + > +typedef struct AcpiCPUHotplug { > + MemoryRegion io; > + uint16_t io_base; > + uint8_t sts[ACPI_GPE_PROC_LEN]; > +} AcpiCPUHotplug; > + > +void acpi_hotplug_cpu_add(ACPIGPE *gpe, AcpiCPUHotplug *g, CPUState *cpu); > + > +void acpi_hotplug_cpu_init(MemoryRegion *parent, Object *owner, > + AcpiCPUHotplug *gpe_cpu, uint16_t base); > +#endif > -- > 1.8.3.1