On Thu, 19 Dec 2013 16:14:03 +0200 "Michael S. Tsirkin" <m...@redhat.com> wrote:
> 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. sure > > > > --- > > 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