On Sun, Nov 27, 2011 at 10:45:35AM +0800, Liu Ping Fan wrote: > From: Liu Ping Fan <pingfank@xxxxxxxxxxxxxxxxxx> > > This device's driver in guest can get vcpu dead event and notify > qemu through the device. > This should be done through ACPI device. Look at how PCI hotplug works in hw/acpi_piix4.c. > Signed-off-by: Liu Ping Fan <pingfank@xxxxxxxxxxxxxxxxxx> > --- > Makefile.target | 1 + > hw/pc_piix.c | 1 + > hw/pci.c | 22 +++++++++++ > hw/pci.h | 1 + > hw/pci_cpustate.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 130 insertions(+), 0 deletions(-) > create mode 100644 hw/pci_cpustate.c > > diff --git a/Makefile.target b/Makefile.target > index 5607c6d..c822f9f 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -242,6 +242,7 @@ obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o > obj-i386-y += testdev.o > obj-i386-y += acpi.o acpi_piix4.o > obj-i386-y += icc_bus.o > +obj-i386-y += pci_cpustate.o > > obj-i386-y += pcspk.o i8254.o > obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o > diff --git a/hw/pc_piix.c b/hw/pc_piix.c > index 7c6f42d..090d7ba 100644 > --- a/hw/pc_piix.c > +++ b/hw/pc_piix.c > @@ -199,6 +199,7 @@ static void pc_init1(MemoryRegion *system_memory, > pci_nic_init_nofail(nd, "rtl8139", NULL); > } > > + pc_cpustate_init(NULL); > ide_drive_get(hd, MAX_IDE_BUS); > if (pci_enabled) { > PCIDevice *dev; > diff --git a/hw/pci.c b/hw/pci.c > index 5c87a62..74a8975 100644 > --- a/hw/pci.c > +++ b/hw/pci.c > @@ -1663,6 +1663,28 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, > return pci_dev; > } > > +PCIDevice *pc_cpustate_init(const char *default_devaddr) > +{ > + const char *devaddr = default_devaddr; > + PCIBus *bus; > + int devfn; > + PCIDevice *pci_dev; > + DeviceState *dev; > + bus = pci_get_bus_devfn(&devfn, devaddr); > + if (!bus) { > + error_report("Invalid PCI device address %s for device %s", > + devaddr, "pcimmstub"); > + return NULL; > + } > + > + pci_dev = pci_create(bus, devfn, "cpustate"); > + dev = &pci_dev->qdev; > + if (qdev_init(dev) < 0) { > + return NULL; > + } > + return pci_dev; > +} > + > PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, > const char *default_devaddr) > { > diff --git a/hw/pci.h b/hw/pci.h > index 071a044..bbaa013 100644 > --- a/hw/pci.h > +++ b/hw/pci.h > @@ -279,6 +279,7 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, > const char *default_devaddr); > PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, > const char *default_devaddr); > +PCIDevice *pc_cpustate_init(const char *default_devaddr); > int pci_bus_num(PCIBus *s); > void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d)); > PCIBus *pci_find_root_bus(int domain); > diff --git a/hw/pci_cpustate.c b/hw/pci_cpustate.c > new file mode 100644 > index 0000000..fd31a1f > --- /dev/null > +++ b/hw/pci_cpustate.c > @@ -0,0 +1,105 @@ > +/* pci_cpustate.c > + * emulate a pci device to get guest os CPU_DEAD event > + * > + * Copyright IBM, Corp. 2011 > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/> > + */ > +#include <zlib.h> > +#include "hw.h" > +#include "pci.h" > +#include "qemu-timer.h" > +#include "net.h" > +#include "loader.h" > +#include "sysemu.h" > +#include "iov.h" > + > +#define PCI_DEVICE_ID_CPUSTATE 0x1010 > +#define CPUSTATE_REGS_SIZE 0x1000 > + > +typedef struct VcpuState VcpuState; > + > +struct VcpuState { > + PCIDevice dev; > + MemoryRegion mmio; > + int mmio_io_addr; > + int mmio_index; > + uint32_t cpuid; > + uint32_t cpu_state; > +}; > + > +static const VMStateDescription vmstate_cpustate = { > + .name = "cpustate", > + .version_id = 1, > + .minimum_version_id = 0, > + .fields = (VMStateField[]) { > + VMSTATE_END_OF_LIST() > + }, > +}; > + > +static void > +cpustate_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val, > + unsigned size) > +{ > +} > + > +static uint64_t > +cpustate_mmio_read(void *opaque, target_phys_addr_t addr, unsigned size) > +{ > + return 0; > +} > + > +static const MemoryRegionOps cpustate_ops = { > + .read = cpustate_mmio_read, > + .write = cpustate_mmio_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > +}; > + > +static int pci_cpustate_init(PCIDevice *dev) > +{ > + uint8_t *pci_cfg = dev->config; > + VcpuState *s = DO_UPCAST(VcpuState, dev, dev); > + memory_region_init_io(&s->mmio, &cpustate_ops, s, "cpustate", > + CPUSTATE_REGS_SIZE); > + pci_cfg[PCI_INTERRUPT_PIN] = 1; > + /* I/O handler for memory-mapped I/O */ > + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); > + return 0; > +} > + > +static int pci_cpustate_exit(PCIDevice *dev) > +{ > + return 0; > +} > + > +static PCIDeviceInfo cpustate_info = { > + .qdev.name = "cpustate", > + .qdev.size = sizeof(VcpuState), > + .qdev.vmsd = &vmstate_cpustate, > + .init = pci_cpustate_init, > + .exit = pci_cpustate_exit, > + .vendor_id = PCI_VENDOR_ID_IBM, > + .device_id = PCI_DEVICE_ID_CPUSTATE, > + .revision = 0x10, > + .class_id = PCI_CLASS_SYSTEM_OTHER, > + .qdev.props = (Property[]) { > + DEFINE_PROP_END_OF_LIST(), > + } > +}; > + > +static void cpustate_register_devices(void) > +{ > + pci_qdev_register(&cpustate_info); > +} > +device_init(cpustate_register_devices) > -- > 1.7.4.4 > -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html