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 2/3] VCPU hotplug support
Date: Tue, 17 Jan 2012 15:17:06 +0100	[thread overview]
Message-ID: <4F1582E2.9080007@siemens.com> (raw)
In-Reply-To: <1326806230-2734-3-git-send-email-imammedo@redhat.com>

On 2012-01-17 14:17, Igor Mammedov wrote:
> Rebase of the missing bits from qemu-kvm for vcpu hotplug

Description, please. Please try to split up, at least into PIIX4
preparations and "the rest". Maybe also a patch for a generic CPU
hotplug infrastructure.

> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  Makefile.objs     |    2 +-
>  Makefile.target   |    2 +-
>  hw/acpi_piix4.c   |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  hw/pc.c           |   21 +++++++++++++-
>  hw/pc_piix.c      |    4 ++
>  sysemu.h          |    2 +
>  target-i386/cpu.h |    1 +
>  7 files changed, 108 insertions(+), 7 deletions(-)
> 
> diff --git a/Makefile.objs b/Makefile.objs
> index 45df666..2a8ccc1 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 icc_bus.o
> +hw-obj-$(CONFIG_ACPI) += acpi.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/Makefile.target b/Makefile.target
> index 06d79b8..4865dde 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -226,7 +226,7 @@ obj-y += device-hotplug.o
>  # Hardware support
>  obj-i386-y += vga.o
>  obj-i386-y += mc146818rtc.o pc.o
> -obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
> +obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o acpi_piix4.o

That's a qemu-kvm hack, see below for the discussion. No-go for upstream
- likely.

>  obj-i386-y += vmport.o
>  obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
>  obj-i386-y += debugcon.o multiboot.o
> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
> index bdc55a1..f1cdcc1 100644
> --- a/hw/acpi_piix4.c
> +++ b/hw/acpi_piix4.c
> @@ -39,13 +39,19 @@
>  #define ACPI_DBG_IO_ADDR  0xb044
>  
>  #define GPE_BASE 0xafe0
> +#define PROC_BASE 0xaf00
>  #define GPE_LEN 4
>  #define PCI_BASE 0xae00
>  #define PCI_EJ_BASE 0xae08
>  #define PCI_RMV_BASE 0xae0c
>  
> +#define PIIX4_CPU_HOTPLUG_STATUS 4
>  #define PIIX4_PCI_HOTPLUG_STATUS 2
>  
> +struct gpe_regs {
> +    uint8_t cpus_sts[32];
> +};
> +
>  struct pci_status {
>      uint32_t up;
>      uint32_t down;
> @@ -71,6 +77,7 @@ typedef struct PIIX4PMState {
>  
>      /* for pci hotplug */
>      ACPIGPE gpe;
> +    struct gpe_regs gpe_cpu;
>      struct pci_status pci0_status;
>      uint32_t pci0_hotplug_enable;
>  } PIIX4PMState;
> @@ -90,9 +97,11 @@ static void pm_update_sci(PIIX4PMState *s)
>                     ACPI_BITMASK_POWER_BUTTON_ENABLE |
>                     ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
>                     ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
> -        (((s->gpe.sts[0] & s->gpe.en[0]) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
> +        (((s->gpe.sts[0] & s->gpe.en[0]) &
> +         (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) != 0);
>  
>      qemu_set_irq(s->irq, sci_level);
> +
>      /* schedule a timer interruption if needed */
>      acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
>                         !(pmsts & ACPI_BITMASK_TIMER_STATUS));
> @@ -219,10 +228,9 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
>   {                                                                   \
>       .name       = (stringify(_field)),                              \
>       .version_id = 0,                                                \
> -     .num        = GPE_LEN,                                          \
>       .info       = &vmstate_info_uint16,                             \
>       .size       = sizeof(uint16_t),                                 \
> -     .flags      = VMS_ARRAY | VMS_POINTER,                          \
> +     .flags      = VMS_SINGLE | VMS_POINTER,                         \

Does this make the vmstate incompatible to the current version?

>       .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
>   }
>  
> @@ -329,11 +337,16 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
>  
>  }
>  
> +static PIIX4PMState *global_piix4_pm_state; /* cpu hotadd */
> +
>  static int piix4_pm_initfn(PCIDevice *dev)
>  {
>      PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
>      uint8_t *pci_conf;
>  
> +    /* for cpu hotadd */
> +    global_piix4_pm_state = s;
> +
>      pci_conf = s->dev.config;
>      pci_conf[0x06] = 0x80;
>      pci_conf[0x07] = 0x02;
> @@ -425,7 +438,16 @@ device_init(piix4_pm_register);
>  static uint32_t gpe_readb(void *opaque, uint32_t addr)
>  {
>      PIIX4PMState *s = opaque;
> -    uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr);
> +    uint32_t val = 0;
> +    struct gpe_regs *g = &s->gpe_cpu;
> +
> +    switch (addr) {
> +    case PROC_BASE ... PROC_BASE+31:
> +        val = g->cpus_sts[addr - PROC_BASE];
> +        break;
> +    default:
> +        val = acpi_gpe_ioport_readb(&s->gpe, addr);
> +    }
>  
>      PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
>      return val;
> @@ -519,11 +541,20 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
>  static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
>  {
>      struct pci_status *pci0_status = &s->pci0_status;
> +    int i = 0, cpus = smp_cpus;
> +
> +    while (cpus > 0) {
> +        s->gpe_cpu.cpus_sts[i++] = (cpus < 8) ? (1 << cpus) - 1 : 0xff;
> +        cpus -= 8;
> +    }
>  
>      register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
>      register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
>      acpi_gpe_blk(&s->gpe, GPE_BASE);
>  
> +    register_ioport_write(PROC_BASE, 32, 1, gpe_writeb, s);
> +    register_ioport_read(PROC_BASE, 32, 1,  gpe_readb, s);
> +
>      register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
>      register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
>  
> @@ -536,6 +567,50 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
>      pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
>  }
>  
> +extern const char *global_cpu_model;
> +
> +#ifdef TARGET_I386

Why only TARGET_I386? If the PIIX4 is used on other targets, the
infrastructure should be prepared to enable hotplugging for them as well
(at a later point). pc_new_cpu is a bad name then. And APIC fiddling
should be pushed into the arch-specific new-cpu handler.

Also note that target dependencies are a no-go for hwlib compilations
which is clearly preferrable today.

> +static void enable_processor(PIIX4PMState *s, int cpu)
> +{
> +    struct gpe_regs *g = &s->gpe_cpu;
> +    ACPIGPE *gpe = &s->gpe;
> +
> +    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
> +    g->cpus_sts[cpu/8] |= (1 << (cpu%8));

"cpu / 8", "cpu % 8", please. Here and below. checkpatch doesn't complain?

> +}
> +
> +static void disable_processor(PIIX4PMState *s, int cpu)
> +{
> +    struct gpe_regs *g = &s->gpe_cpu;
> +    ACPIGPE *gpe = &s->gpe;
> +
> +    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
> +    g->cpus_sts[cpu/8] &= ~(1 << (cpu%8));
> +}
> +
> +void qemu_system_cpu_hot_add(int cpu, int state)
> +{
> +    CPUState *env;
> +    PIIX4PMState *s = global_piix4_pm_state;
> +
> +    if (state && !qemu_get_cpu(cpu)) {
> +        env = pc_new_cpu(global_cpu_model);
> +        if (!env) {
> +            fprintf(stderr, "cpu %d creation failed\n", cpu);
> +            return;
> +        }
> +        env->cpuid_apic_id = cpu;

See comment above about proper target abstraction.

> +    }
> +
> +    if (state) {
> +        enable_processor(s, cpu);
> +    } else {
> +        disable_processor(s, cpu);
> +    }
> +    pm_update_sci(s);
> +}
> +#endif
> +
>  static void enable_device(PIIX4PMState *s, int slot)
>  {
>      s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
> diff --git a/hw/pc.c b/hw/pc.c
> index 33d8090..c7342d8 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -44,6 +44,8 @@
>  #include "ui/qemu-spice.h"
>  #include "memory.h"
>  #include "exec-memory.h"
> +#include "cpus.h"
> +#include "kvm.h"

kvm? Likely not what you want.

>  
>  /* output Bochs bios info messages */
>  //#define DEBUG_BIOS
> @@ -930,10 +932,22 @@ static void pc_cpu_reset(void *opaque)
>      env->halted = !cpu_is_bsp(env);
>  }
>  
> -static CPUState *pc_new_cpu(const char *cpu_model)
> +CPUState *pc_new_cpu(const char *cpu_model)
>  {
>      CPUState *env;
>  
> +    if (cpu_model == NULL) {
> +#ifdef TARGET_X86_64
> +        cpu_model = "qemu64";
> +#else
> +        cpu_model = "qemu32";
> +#endif

Just always initialize global_cpu_model to a non-NULL value.

> +    }
> +
> +    if (runstate_is_running()) {
> +        pause_all_vcpus();
> +    }
> +
>      env = cpu_init(cpu_model);
>      if (!env) {
>          fprintf(stderr, "Unable to find x86 CPU definition\n");
> @@ -944,6 +958,11 @@ static CPUState *pc_new_cpu(const char *cpu_model)
>      }
>      qemu_register_reset(pc_cpu_reset, env);
>      pc_cpu_reset(env);
> +
> +    cpu_synchronize_post_init(env);
> +    if (runstate_is_running()) {
> +        resume_all_vcpus();
> +    }
>      return env;
>  }
>  
> diff --git a/hw/pc_piix.c b/hw/pc_piix.c
> index b70431f..1c77ea1 100644
> --- a/hw/pc_piix.c
> +++ b/hw/pc_piix.c
> @@ -53,6 +53,8 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
>  static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
>  static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
>  
> +const char *global_cpu_model; /* cpu hotadd */
> +
>  static void ioapic_init(GSIState *gsi_state)
>  {
>      DeviceState *dev;
> @@ -102,6 +104,8 @@ static void pc_init1(MemoryRegion *system_memory,
>      MemoryRegion *rom_memory;
>      DeviceState *dev;
>  
> +    global_cpu_model = cpu_model;
> +

Move this into pc_cpus_init, and you automatically resolve the cpu_model
== NULL issue.

>      pc_cpus_init(cpu_model);
>  
>      if (kvmclock_enabled) {
> diff --git a/sysemu.h b/sysemu.h
> index ddef2bb..678b478 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -155,6 +155,8 @@ void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
>  int do_pcie_aer_inject_error(Monitor *mon,
>                               const QDict *qdict, QObject **ret_data);
>  
> +void qemu_system_cpu_hot_add(int cpu, int state);
> +
>  /* serial ports */
>  
>  #define MAX_SERIAL_PORTS 4
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 5dd1627..a9a6136 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -931,6 +931,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
>  /* hw/pc.c */
>  void cpu_smm_update(CPUX86State *env);
>  uint64_t cpu_get_tsc(CPUX86State *env);
> +CPUState *pc_new_cpu(const char *cpu_model);

"cpu_new" or so would be better. Every target supporting hotplug would
have to implement it.

>  
>  /* used to debug */
>  #define X86_DUMP_FPU  0x0001 /* dump FPU state too */

Jan

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

  reply	other threads:[~2012-01-17 14:17 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
2012-01-17 13:17 ` [Qemu-devel] [PATCH 2/3] VCPU hotplug support Igor Mammedov
2012-01-17 14:17   ` Jan Kiszka [this message]
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=4F1582E2.9080007@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.