All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: Igor Mammedov <imammedo@redhat.com>
Cc: "pingfank@linux.vnet.ibm.com" <pingfank@linux.vnet.ibm.com>,
	"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
	"gleb@redhat.com" <gleb@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 1/3] Introduce a new bus "ICC" to connect APIC
Date: Tue, 17 Jan 2012 14:57:14 +0100	[thread overview]
Message-ID: <4F157E3A.2060203@siemens.com> (raw)
In-Reply-To: <1326806230-2734-2-git-send-email-imammedo@redhat.com>

On 2012-01-17 14:17, Igor Mammedov wrote:
> Introduce a new structure CPUS as the controller of ICC (INTERRUPT
> CONTROLLER COMMUNICATIONS), and new bus "ICC" to hold APIC,instead
> of sysbus. So we can support APIC hot-plug feature.
> 
> This is repost of original patch for qemu-kvm rebased on current qemu:
> http://lists.nongnu.org/archive/html/qemu-devel/2011-11/msg01478.html
> All credits to Liu Ping Fan for writing it.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  Makefile.objs       |    2 +-
>  hw/apic.c           |   24 +++++++++----
>  hw/apic.h           |    1 +
>  hw/icc_bus.c        |   92 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/icc_bus.h        |   61 +++++++++++++++++++++++++++++++++
>  hw/pc.c             |   14 +++++--
>  target-i386/cpu.h   |    1 +
>  target-i386/cpuid.c |   16 +++++++++
>  8 files changed, 199 insertions(+), 12 deletions(-)
>  create mode 100644 hw/icc_bus.c
>  create mode 100644 hw/icc_bus.h
> 
> diff --git a/Makefile.objs b/Makefile.objs
> index 4f6d26c..45df666 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -212,7 +212,7 @@ hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
>  hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
>  hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
>  hw-obj-$(CONFIG_FDC) += fdc.o
> -hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
> +hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o icc_bus.o
>  hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
>  hw-obj-$(CONFIG_DMA) += dma.o
>  hw-obj-$(CONFIG_HPET) += hpet.o
> diff --git a/hw/apic.c b/hw/apic.c
> index 9d0f460..e666b4c 100644
> --- a/hw/apic.c
> +++ b/hw/apic.c
> @@ -21,9 +21,10 @@
>  #include "ioapic.h"
>  #include "qemu-timer.h"
>  #include "host-utils.h"
> -#include "sysbus.h"
> +#include "icc_bus.h"
>  #include "trace.h"
>  #include "pc.h"
> +#include "exec-memory.h"
>  
>  /* APIC Local Vector Table */
>  #define APIC_LVT_TIMER   0
> @@ -80,7 +81,7 @@
>  typedef struct APICState APICState;
>  
>  struct APICState {
> -    SysBusDevice busdev;
> +    ICCBusDevice busdev;
>      MemoryRegion io_memory;
>      void *cpu_env;
>      uint32_t apicbase;
> @@ -988,9 +989,19 @@ static const MemoryRegionOps apic_io_ops = {
>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static int apic_init1(SysBusDevice *dev)
> +int apic_mmio_map(DeviceState *dev, target_phys_addr_t base)
>  {
> -    APICState *s = FROM_SYSBUS(APICState, dev);
> +    APICState *s = DO_UPCAST(APICState, busdev.qdev, dev);
> +
> +    memory_region_add_subregion(get_system_memory(),
> +                                base,
> +                                &s->io_memory);
> +    return 0;
> +}
> +
> +static int apic_init1(ICCBusDevice *dev)
> +{
> +    APICState *s = DO_UPCAST(APICState, busdev, dev);
>      static int last_apic_idx;
>  
>      if (last_apic_idx >= MAX_APICS) {
> @@ -998,7 +1009,6 @@ static int apic_init1(SysBusDevice *dev)
>      }
>      memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic",
>                            MSI_ADDR_SIZE);
> -    sysbus_init_mmio(dev, &s->io_memory);
>  
>      s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
>      s->idx = last_apic_idx++;
> @@ -1006,7 +1016,7 @@ static int apic_init1(SysBusDevice *dev)
>      return 0;
>  }
>  
> -static SysBusDeviceInfo apic_info = {
> +static ICCBusDeviceInfo apic_info = {
>      .init = apic_init1,
>      .qdev.name = "apic",
>      .qdev.size = sizeof(APICState),
> @@ -1022,7 +1032,7 @@ static SysBusDeviceInfo apic_info = {
>  
>  static void apic_register_devices(void)
>  {
> -    sysbus_register_withprop(&apic_info);
> +    iccbus_register_devinfo(&apic_info);
>  }
>  
>  device_init(apic_register_devices)
> diff --git a/hw/apic.h b/hw/apic.h
> index a5c910f..d42081e 100644
> --- a/hw/apic.h
> +++ b/hw/apic.h
> @@ -17,6 +17,7 @@ void cpu_set_apic_tpr(DeviceState *s, uint8_t val);
>  uint8_t cpu_get_apic_tpr(DeviceState *s);
>  void apic_init_reset(DeviceState *s);
>  void apic_sipi(DeviceState *s);
> +int apic_mmio_map(DeviceState *dev, target_phys_addr_t base);
>  
>  /* pc.c */
>  int cpu_is_bsp(CPUState *env);
> diff --git a/hw/icc_bus.c b/hw/icc_bus.c
> new file mode 100644
> index 0000000..ac88f2e
> --- /dev/null
> +++ b/hw/icc_bus.c
> @@ -0,0 +1,92 @@
> +/* icc_bus.c
> + * emulate x86 ICC(INTERRUPT CONTROLLER COMMUNICATIONS) bus
> + *
> + * 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 "icc_bus.h"
> +
> +static CPUSockets *cpu_sockets;
> +
> +static ICCBusInfo icc_bus_info = {
> +    .qinfo.name = "icc",
> +    .qinfo.size = sizeof(ICCBus),
> +    .qinfo.props = (Property[]) {
> +        DEFINE_PROP_END_OF_LIST(),
> +    }
> +};
> +
> +static int iccbus_device_init(DeviceState *dev, DeviceInfo *base)
> +{
> +    ICCBusDeviceInfo *info = container_of(base, ICCBusDeviceInfo, qdev);
> +    ICCBusDevice *idev = DO_UPCAST(ICCBusDevice, qdev, dev);
> +
> +    return info->init(idev);
> +}
> +
> +void iccbus_register_devinfo(ICCBusDeviceInfo *info)
> +{
> +    info->qdev.init = iccbus_device_init;
> +    info->qdev.bus_info = &icc_bus_info.qinfo;
> +    assert(info->qdev.size >= sizeof(ICCBusDevice));
> +    qdev_register(&info->qdev);
> +}
> +
> +BusState *get_icc_bus(void)
> +{
> +    return &cpu_sockets->icc_bus->qbus;
> +}
> +
> +/*Must be called before vcpu's creation*/
> +static int cpusockets_init(SysBusDevice *dev)
> +{
> +    CPUSockets *cpus = DO_UPCAST(CPUSockets, sysdev, dev);
> +    BusState *b = qbus_create(&icc_bus_info.qinfo,
> +                              &cpu_sockets->sysdev.qdev,
> +                              "icc");
> +    if (b == NULL) {
> +        return -1;
> +    }
> +    b->allow_hotplug = 1; /* Yes, we can */
> +    cpus->icc_bus = DO_UPCAST(ICCBus, qbus, b);
> +    cpu_sockets = cpus;
> +    return 0;
> +
> +}
> +
> +static const VMStateDescription vmstate_cpusockets = {
> +    .name = "cpusockets",
> +    .version_id = 1,
> +    .minimum_version_id = 0,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static SysBusDeviceInfo cpusockets_info = {
> +    .init = cpusockets_init,
> +    .qdev.name = "cpusockets",
> +    .qdev.size = sizeof(CPUSockets),
> +    .qdev.vmsd = &vmstate_cpusockets,
> +    .qdev.reset = NULL,
> +    .qdev.no_user = 1,
> +};
> +
> +static void cpusockets_register_devices(void)
> +{
> +    sysbus_register_withprop(&cpusockets_info);
> +}
> +
> +device_init(cpusockets_register_devices)
> diff --git a/hw/icc_bus.h b/hw/icc_bus.h
> new file mode 100644
> index 0000000..9f10e1e
> --- /dev/null
> +++ b/hw/icc_bus.h
> @@ -0,0 +1,61 @@
> +/* ICCBus.h
> + * emulate x86 ICC(INTERRUPT CONTROLLER COMMUNICATIONS) bus
> + *
> + * 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/>
> + */
> +#ifndef QEMU_ICC_H
> +#define QEMU_ICC_H
> +
> +#include "qdev.h"
> +#include "sysbus.h"
> +
> +typedef struct CPUSockets CPUSockets;
> +typedef struct ICCBus ICCBus;
> +typedef struct ICCBusInfo ICCBusInfo;
> +typedef struct ICCBusDevice ICCBusDevice;
> +typedef struct ICCBusDeviceInfo ICCBusDeviceInfo;
> +
> +struct CPUSockets {
> +    SysBusDevice sysdev;
> +    ICCBus *icc_bus;
> +};
> +
> +struct CPUSInfo {
> +    DeviceInfo info;
> +};
> +
> +struct ICCBus {
> +    BusState qbus;
> +};
> +
> +struct ICCBusInfo {
> +    BusInfo qinfo;
> +};
> +struct ICCBusDevice {
> +    DeviceState qdev;
> +};
> +
> +typedef int (*iccbus_initfn)(ICCBusDevice *dev);
> +
> +struct ICCBusDeviceInfo {
> +    DeviceInfo qdev;
> +    iccbus_initfn init;
> +};

There should be no need to make all these structures public, just keep
the typedefs as required. Some structs are even unused unless I miss
something.

> +
> +void iccbus_register_devinfo(ICCBusDeviceInfo *info);
> +BusState *get_icc_bus(void);
> +
> +#endif
> diff --git a/hw/pc.c b/hw/pc.c
> index 85304cf..33d8090 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -24,6 +24,7 @@
>  #include "hw.h"
>  #include "pc.h"
>  #include "apic.h"
> +#include "icc_bus.h"
>  #include "fdc.h"
>  #include "ide.h"
>  #include "pci.h"
> @@ -878,21 +879,21 @@ DeviceState *cpu_get_current_apic(void)
>  static DeviceState *apic_init(void *env, uint8_t apic_id)
>  {
>      DeviceState *dev;
> -    SysBusDevice *d;
> +    BusState *b;
>      static int apic_mapped;
>  
> -    dev = qdev_create(NULL, "apic");
> +    b = get_icc_bus();
> +    dev = qdev_create(b, "apic");
>      qdev_prop_set_uint8(dev, "id", apic_id);
>      qdev_prop_set_ptr(dev, "cpu_env", env);
>      qdev_init_nofail(dev);
> -    d = sysbus_from_qdev(dev);
>  
>      /* XXX: mapping more APICs at the same memory location */
>      if (apic_mapped == 0) {
>          /* NOTE: the APIC is directly connected to the CPU - it is not
>             on the global memory bus. */
>          /* XXX: what if the base changes? */
> -        sysbus_mmio_map(d, 0, MSI_ADDR_BASE);
> +        apic_mmio_map(dev, MSI_ADDR_BASE);
>          apic_mapped = 1;
>      }
>  
> @@ -959,6 +960,11 @@ void pc_cpus_init(const char *cpu_model)
>  #endif
>      }
>  
> +    if (cpu_has_apic_feature(cpu_model) || smp_cpus > 1) {
> +        DeviceState *d = qdev_create(NULL, "cpusockets");
> +        qdev_init_nofail(d);
> +    }
> +
>      for(i = 0; i < smp_cpus; i++) {
>          pc_new_cpu(cpu_model);
>      }
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 37dde79..5dd1627 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -892,6 +892,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>                     uint32_t *eax, uint32_t *ebx,
>                     uint32_t *ecx, uint32_t *edx);
>  int cpu_x86_register (CPUX86State *env, const char *cpu_model);
> +int cpu_has_apic_feature(const char *cpu_model);
>  void cpu_clear_apic_feature(CPUX86State *env);
>  void host_cpuid(uint32_t function, uint32_t count,
>                  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
> diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
> index 91a104b..3370fac 100644
> --- a/target-i386/cpuid.c
> +++ b/target-i386/cpuid.c
> @@ -850,6 +850,22 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
>      }
>  }
>  
> +int cpu_has_apic_feature(const char *cpu_model)

bool cpu_has_apic_feature(...

> +{
> +    x86_def_t def1, *def = &def1;
> +
> +    memset(def, 0, sizeof(*def));
> +
> +    if (cpu_x86_find_by_name(def, cpu_model) < 0) {
> +        return 0;
> +    }
> +    if (def->features & CPUID_APIC) {
> +        return 1;
> +    } else {
> +        return 0;
> +    }

return def->feature & CPUID_APIC;

> +}
> +
>  int cpu_x86_register (CPUX86State *env, const char *cpu_model)
>  {
>      x86_def_t def1, *def = &def1;

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

  reply	other threads:[~2012-01-17 13:57 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-17 13:17 [Qemu-devel] [PATCH 0/3] Make vcpu hotplug work for qemu Igor Mammedov
2012-01-17 13:17 ` [Qemu-devel] [PATCH 1/3] Introduce a new bus "ICC" to connect APIC Igor Mammedov
2012-01-17 13:57   ` Jan Kiszka [this message]
2012-01-17 13:17 ` [Qemu-devel] [PATCH 2/3] VCPU hotplug support Igor Mammedov
2012-01-17 14:17   ` Jan Kiszka
2012-01-17 14:22     ` Jan Kiszka
2012-01-23 16:29     ` Igor Mammedov
2012-01-23 17:55       ` Jan Kiszka
2012-01-24 16:24         ` Igor Mammedov
2012-01-24 16:37           ` Jan Kiszka
2012-01-17 13:17 ` [Qemu-devel] [PATCH 3/3] add cpu_set qmp command Igor Mammedov
2012-01-17 14:18   ` Jan Kiszka
2012-01-19  9:38     ` Igor Mammedov
2012-01-19 10:24       ` Jan Kiszka
2012-01-19 11:04         ` Igor Mammedov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F157E3A.2060203@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=gleb@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=pingfank@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.