All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/6] Add support for cpu hotplug
@ 2009-04-17 15:20 Glauber Costa
  2009-04-17 15:20 ` [Qemu-devel] [PATCH 1/6] split pc_new_cpu Glauber Costa
  0 siblings, 1 reply; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

This is mainly the code we have in kvm-userspace, with a few small
improvements.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 1/6] split pc_new_cpu
  2009-04-17 15:20 [Qemu-devel] [PATCH 0/6] Add support for cpu hotplug Glauber Costa
@ 2009-04-17 15:20 ` Glauber Costa
  2009-04-17 15:20   ` [Qemu-devel] [PATCH 2/6] always have apic Glauber Costa
  0 siblings, 1 reply; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

since it is useful elsewhere.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 hw/pc.c |   37 ++++++++++++++++++++++---------------
 hw/pc.h |    1 +
 2 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 6a1750e..39ed066 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -775,6 +775,26 @@ static int load_option_rom(const char *oprom, target_phys_addr_t start,
         return size;
 }
 
+CPUState *pc_new_cpu(int cpu, const char *cpu_model, int pci_enabled)
+{
+    CPUState *env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find x86 CPU definition\n");
+        exit(1);
+    }
+    if (cpu != 0)
+        env->halted = 1;
+    if (smp_cpus > 1) {
+        /* XXX: enable it in all cases */
+        env->cpuid_features |= CPUID_APIC;
+    }
+    qemu_register_reset(main_cpu_reset, env);
+    if (pci_enabled) {
+        apic_init(env);
+    }
+    return env;
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
                      const char *boot_device,
@@ -816,23 +836,10 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
     }
     
     for(i = 0; i < smp_cpus; i++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
-            fprintf(stderr, "Unable to find x86 CPU definition\n");
-            exit(1);
-        }
-        if (i != 0)
-            env->halted = 1;
-        if (smp_cpus > 1) {
-            /* XXX: enable it in all cases */
-            env->cpuid_features |= CPUID_APIC;
-        }
-        qemu_register_reset(main_cpu_reset, env);
-        if (pci_enabled) {
-            apic_init(env);
-        }
+        env = pc_new_cpu(i, cpu_model, pci_enabled);
     }
 
+
     vmport_init();
 
     /* allocate RAM */
diff --git a/hw/pc.h b/hw/pc.h
index 50e6c39..59047b5 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -102,6 +102,7 @@ extern int fd_bootchk;
 
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
+CPUState *pc_new_cpu(int cpu, const char *cpu_model, int pci_enabled);
 
 /* acpi.c */
 extern int acpi_enabled;
-- 
1.5.6.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 2/6] always have apic
  2009-04-17 15:20 ` [Qemu-devel] [PATCH 1/6] split pc_new_cpu Glauber Costa
@ 2009-04-17 15:20   ` Glauber Costa
  2009-04-17 15:20     ` [Qemu-devel] [PATCH 3/6] Fix warnings and errors with DEBUG enabled Glauber Costa
  0 siblings, 1 reply; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

if we are going to initialize the apic, set cpuid bit unconditionally.
As far as I know, we should not do that for isa machines anyway.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 hw/pc.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 39ed066..7649f2c 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -784,12 +784,10 @@ CPUState *pc_new_cpu(int cpu, const char *cpu_model, int pci_enabled)
     }
     if (cpu != 0)
         env->halted = 1;
-    if (smp_cpus > 1) {
-        /* XXX: enable it in all cases */
-        env->cpuid_features |= CPUID_APIC;
-    }
+
     qemu_register_reset(main_cpu_reset, env);
     if (pci_enabled) {
+        env->cpuid_features |= CPUID_APIC;
         apic_init(env);
     }
     return env;
-- 
1.5.6.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 3/6] Fix warnings and errors with DEBUG enabled
  2009-04-17 15:20   ` [Qemu-devel] [PATCH 2/6] always have apic Glauber Costa
@ 2009-04-17 15:20     ` Glauber Costa
  2009-04-17 15:20       ` [Qemu-devel] [PATCH 4/6] disallow kqemu if we fail to load it Glauber Costa
  0 siblings, 1 reply; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

Appearently nobody tried this yet. It produces tons
of warning and an one error.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 hw/acpi.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 52f50a0..22fbc4a 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -604,7 +604,7 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr)
     }
 
 #if defined(DEBUG)
-    printf("gpe read %lx == %lx\n", addr, val);
+    printf("gpe read %x == %x\n", addr, val);
 #endif
     return val;
 }
@@ -646,7 +646,7 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
    }
 
 #if defined(DEBUG)
-    printf("gpe write %lx <== %d\n", addr, val);
+    printf("gpe write %x <== %d\n", addr, val);
 #endif
 }
 
@@ -666,7 +666,7 @@ static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
     }
 
 #if defined(DEBUG)
-    printf("pcihotplug read %lx == %lx\n", addr, val);
+    printf("pcihotplug read %x == %x\n", addr, val);
 #endif
     return val;
 }
@@ -684,14 +684,14 @@ static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
    }
 
 #if defined(DEBUG)
-    printf("pcihotplug write %lx <== %d\n", addr, val);
+    printf("pcihotplug write %x <== %d\n", addr, val);
 #endif
 }
 
 static uint32_t pciej_read(void *opaque, uint32_t addr)
 {
 #if defined(DEBUG)
-    printf("pciej read %lx == %lx\n", addr, val);
+    printf("pciej read %x == %x\n", addr, 0);
 #endif
     return 0;
 }
@@ -705,7 +705,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 #endif
 
 #if defined(DEBUG)
-    printf("pciej write %lx <== %d\n", addr, val);
+    printf("pciej write %x <== %d\n", addr, val);
 #endif
 }
 
-- 
1.5.6.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 4/6] disallow kqemu if we fail to load it.
  2009-04-17 15:20     ` [Qemu-devel] [PATCH 3/6] Fix warnings and errors with DEBUG enabled Glauber Costa
@ 2009-04-17 15:20       ` Glauber Costa
  2009-04-17 15:20         ` [Qemu-devel] [PATCH 5/6] enable cpu hotplug Glauber Costa
  0 siblings, 1 reply; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

Since we're not retrying it anyway, set kqemu_allowed = 0
if we fail to load it. It will allow us to test for kqemu
runtime presence where we don't have an env pointer, possibly
because we don't have a cpu yet.

The monitor code is such an example.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 kqemu.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/kqemu.c b/kqemu.c
index 040e817..e0e0499 100644
--- a/kqemu.c
+++ b/kqemu.c
@@ -179,14 +179,14 @@ int kqemu_init(CPUState *env)
     if (kqemu_fd == KQEMU_INVALID_FD) {
         fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated: %lu\n",
                 KQEMU_DEVICE, GetLastError());
-        return -1;
+        goto out;
     }
 #else
     kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
     if (kqemu_fd == KQEMU_INVALID_FD) {
         fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated: %s\n",
                 KQEMU_DEVICE, strerror(errno));
-        return -1;
+        goto out;
     }
 #endif
     version = 0;
@@ -239,6 +239,8 @@ int kqemu_init(CPUState *env)
     fail:
         kqemu_closefd(kqemu_fd);
         kqemu_fd = KQEMU_INVALID_FD;
+    out:
+        kqemu_allowed = 0;
         return -1;
     }
     kqemu_update_cpuid(env);
-- 
1.5.6.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 5/6] enable cpu hotplug
  2009-04-17 15:20       ` [Qemu-devel] [PATCH 4/6] disallow kqemu if we fail to load it Glauber Costa
@ 2009-04-17 15:20         ` Glauber Costa
  2009-04-17 15:20           ` [Qemu-devel] [PATCH 6/6] add bios support for " Glauber Costa
  2009-04-17 20:18           ` [Qemu-devel] Re: [PATCH 5/6] enable " Anthony Liguori
  0 siblings, 2 replies; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

This patch enable cpu hotplug to happen via acpi events.
Note that all it does is generate acpi messages. It still needs
guest cooperation, in the very way as real hardware.

It is basically what we have in kvm, but in a qemuish style, with
a few improvements.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 cpu-all.h |    1 +
 exec.c    |   13 +++++++++++
 hw/acpi.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 monitor.c |   21 ++++++++++++++++++
 sysemu.h  |    1 +
 5 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index aaaa70d..a0c97f7 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -745,6 +745,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags);
 
 void cpu_exec_init_all(unsigned long tb_size);
 CPUState *cpu_copy(CPUState *env);
+CPUState *qemu_get_cpu(int cpu);
 
 void cpu_dump_state(CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
diff --git a/exec.c b/exec.c
index 13e43d0..a7ac18f 100644
--- a/exec.c
+++ b/exec.c
@@ -538,6 +538,19 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
 }
 #endif
 
+CPUState *qemu_get_cpu(int cpu)
+{
+    CPUState *env = first_cpu;
+
+    while (env) {
+        if (env->cpu_index == cpu)
+            break;
+        env = env->next_cpu;
+    }
+
+    return env;
+}
+
 void cpu_exec_init(CPUState *env)
 {
     CPUState **penv;
diff --git a/hw/acpi.c b/hw/acpi.c
index 22fbc4a..10c0e69 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -26,6 +26,7 @@
 #include "kvm.h"
 
 //#define DEBUG
+//#define DEBUG_CPU
 
 /* i82731AB (PIIX4) compatible power management function */
 #define PM_FREQ 3579545
@@ -563,6 +564,7 @@ void qemu_system_powerdown(void)
 #endif
 
 #define GPE_BASE 0xafe0
+#define PROC_BASE 0xaf00
 #define PCI_BASE 0xae00
 #define PCI_EJ_BASE 0xae08
 
@@ -578,6 +580,7 @@ struct pci_status {
 
 static struct gpe_regs gpe;
 static struct pci_status pci0_status;
+static uint8_t cpus_sts[32];
 
 static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
 {
@@ -709,11 +712,44 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
+static uint32_t cpuhotplug_read(void *opaque, uint32_t addr)
+{
+    if ((addr < PROC_BASE) || (addr > (PROC_BASE + 31))) {
+        /* should never happen, so return a poison */
+        return 0xabcdefab;
+    }
+    else {
+        uint8_t *cpu_status = opaque;
+#if defined(DEBUG_CPU)
+        printf("cpuhotplug read %x == %x\n", addr, cpu_status[addr - PROC_BASE]);
+#endif
+        return cpu_status[addr - PROC_BASE];
+    }
+}
+
+static void cpuhotplug_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    /* don't allow to change cpus_sts from inside a guest */
+#if defined(DEBUG_CPU)
+    printf("cpuhotplug write %x <== %d\n", addr, val);
+#endif
+}
+
 void qemu_system_hot_add_init(void)
 {
+    int i = 0, cpus = smp_cpus;
+
+    while (cpus > 0) {
+        cpus_sts[i++] = (cpus < 8) ? (1 << cpus) - 1 : 0xff;
+        cpus -= 8;
+    }
+
     register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
     register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, &gpe);
 
+    register_ioport_write(PROC_BASE, 32, 1, cpuhotplug_write, &cpus_sts);
+    register_ioport_read(PROC_BASE, 32, 1,  cpuhotplug_read, &cpus_sts);
+
     register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
     register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
 
@@ -733,6 +769,18 @@ static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
     p->down |= (1 << slot);
 }
 
+static void enable_processor(struct gpe_regs *g, int cpu)
+{
+    g->sts |= 4;
+    cpus_sts[cpu/8] |= (1 << (cpu%8));
+}
+
+static void disable_processor(struct gpe_regs *g, int cpu)
+{
+    g->sts |= 4;
+    cpus_sts[cpu/8] &= ~(1 << (cpu%8));
+}
+
 void qemu_system_device_hot_add(int bus, int slot, int state)
 {
     pci0_status.up = 0;
@@ -747,6 +795,27 @@ void qemu_system_device_hot_add(int bus, int slot, int state)
     }
 }
 
+void qemu_system_cpu_hot_add(int cpu, int state)
+{
+    CPUState *env;
+
+    if ((state) && !qemu_get_cpu(cpu)) {
+#ifdef DEBUG_CPU
+        printf("creatng new cpu %d\n", cpu);
+#endif
+        env = pc_new_cpu(cpu, first_cpu->cpu_model_str, 1);
+        enable_processor(&gpe, cpu);
+    }
+    else {
+        disable_processor(&gpe, cpu);
+    }
+
+    if (gpe.en & 4) {
+        qemu_set_irq(pm_state->irq, 1);
+        qemu_set_irq(pm_state->irq, 0);
+    }
+}
+
 struct acpi_table_header
 {
     char signature [4];    /* ACPI signature (4 ASCII characters) */
diff --git a/monitor.c b/monitor.c
index e764b5d..53e5938 100644
--- a/monitor.c
+++ b/monitor.c
@@ -372,6 +372,26 @@ static void do_cpu_set(Monitor *mon, int index)
         monitor_printf(mon, "Invalid CPU index\n");
 }
 
+static void do_cpu_set_nr(Monitor *mon, int value, const char *status)
+{
+    int state;
+
+    if (kvm_enabled() || kqemu_allowed) {
+        monitor_printf(mon, "CPU hotplug not supported\n");
+        return;
+    }
+
+    if (!strcmp(status, "online"))
+       state = 1;
+    else if (!strcmp(status, "offline"))
+       state = 0;
+    else {
+        monitor_printf(mon, "invalid status: %s\n", status);
+        return;
+    }
+    qemu_system_cpu_hot_add(value, state);
+}
+
 static void do_info_jit(Monitor *mon)
 {
     dump_exec_info((FILE *)mon, monitor_fprintf);
@@ -1739,6 +1759,7 @@ static const mon_cmd_t mon_cmds[] = {
       "target", "request VM to change it's memory allocation (in MB)" },
     { "set_link", "ss", do_set_link,
       "name [up|down]", "change the link status of a network adapter" },
+    { "cpu_set", "is", do_cpu_set_nr, "cpu [online|offline]", "change cpu state" },
     { "acl", "sss?i?", do_acl, "<command> <aclname> [<match>] [<index>]\n",
                                "acl show vnc.username\n"
                                "acl policy vnc.username deny\n"
diff --git a/sysemu.h b/sysemu.h
index 3eab34b..b69c6f0 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -175,6 +175,7 @@ extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
 /* acpi */
 void qemu_system_hot_add_init(void);
 void qemu_system_device_hot_add(int pcibus, int slot, int state);
+void qemu_system_cpu_hot_add(int cpu, int state);
 
 /* device-hotplug */
 
-- 
1.5.6.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 6/6] add bios support for cpu hotplug.
  2009-04-17 15:20         ` [Qemu-devel] [PATCH 5/6] enable cpu hotplug Glauber Costa
@ 2009-04-17 15:20           ` Glauber Costa
  2009-04-17 20:06             ` [Qemu-devel] " Anthony Liguori
  2009-04-17 20:18           ` [Qemu-devel] Re: [PATCH 5/6] enable " Anthony Liguori
  1 sibling, 1 reply; 9+ messages in thread
From: Glauber Costa @ 2009-04-17 15:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: jan.kiszka, aliguori

This adds patches to bochs-bios to support cpu hotplug

first one creates entries in acpi tables, and the second one
removes the now unused static sdt.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 ...012-qemu-bios-create-acpi-cpu-definitions.patch |  293 ++++++++++++++++++++
 ...emu-bios-remove-acpi_build_processor_ssdt.patch |   55 ++++
 pc-bios/bios-pq/series                             |    2 +
 3 files changed, 350 insertions(+), 0 deletions(-)
 create mode 100644 pc-bios/bios-pq/0012-qemu-bios-create-acpi-cpu-definitions.patch
 create mode 100644 pc-bios/bios-pq/0013-qemu-bios-remove-acpi_build_processor_ssdt.patch

diff --git a/pc-bios/bios-pq/0012-qemu-bios-create-acpi-cpu-definitions.patch b/pc-bios/bios-pq/0012-qemu-bios-create-acpi-cpu-definitions.patch
new file mode 100644
index 0000000..89bf081
--- /dev/null
+++ b/pc-bios/bios-pq/0012-qemu-bios-create-acpi-cpu-definitions.patch
@@ -0,0 +1,293 @@
+From 09ce41fd61e075c47777df08641cd76ca733f172 Mon Sep 17 00:00:00 2001
+From: Glauber Costa <glommer@redhat.com>
+Date: Fri, 17 Apr 2009 10:51:18 -0400
+Subject: [PATCH] create acpi cpu definitions
+
+This comes directly from kvm-userspace. It creates
+the necessary infrastructure for cpu hotplug, by
+creating _MAT and _STA entries in cpu devices,
+and by allowing notifications to the guest to happen
+
+note that now, we have to fill acpi tables with MAX_CPUS,
+instead of smp_cpus, otherwise we'll never be able to grow
+the cpu number.
+
+Signed-off-by: Glauber Costa <glommer@redhat.com>
+---
+ bios/acpi-dsdt.dsl |  116 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ bios/rombios.h     |    2 +
+ bios/rombios32.c   |   72 +++++---------------------------
+ 3 files changed, 128 insertions(+), 62 deletions(-)
+
+diff --git a/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl
+index 7bff30a..23d8d6c 100644
+--- a/bios/acpi-dsdt.dsl
++++ b/bios/acpi-dsdt.dsl
+@@ -25,6 +25,120 @@ DefinitionBlock (
+     0x1                 // OEM Revision
+     )
+ {
++   Scope (\_PR)
++   {
++	OperationRegion(PRST, SystemIO, 0xaf00, 32)
++	Field (PRST, ByteAcc, NoLock, Preserve)
++	{
++		PRS, 256
++	}
++
++	Name(PRSS, Buffer(32){}) /* shadow CPU status bitmask */
++	Name(SSVL, 0)
++
++	Method(CRST, 1) {
++		If (LEqual(SSVL, 0)) {
++			Store(PRS, PRSS) /* read CPUs status bitmaks from HW */
++			Store(1, SSVL)
++                }
++		ShiftRight(Arg0, 3, Local1)
++		Store(DerefOf(Index(PRSS, Local1)), Local2)
++	        Return(And(Local2, ShiftLeft(1, And(Arg0, 0x7))))
++	}
++
++#define gen_processor(nr, name) 				            \
++	Processor (CPU##name, nr, 0x0000b010, 0x06) {                       \
++            Name (PREN, Buffer(0x8) {0x0, 0x8, nr, nr, 0x1, 0x0, 0x0, 0x0}) \
++            Name (PRDS, Buffer(0x8) {0x0, 0x8, nr, nr, 0x0, 0x0, 0x0, 0x0}) \
++            Method(_MAT, 0) {                                               \
++                If (CRST(nr)) { Return(PREN) }                              \
++                Else { Return(PRDS) }                                       \
++            }                                                               \
++            Method (_STA) {                                                 \
++                If (CRST(nr)) { Return(0xF) }                               \
++                Else { Return(0x9) }                                        \
++            }                                                               \
++        }                                                                   \
++
++
++	gen_processor(0, 0)
++	gen_processor(1, 1)
++	gen_processor(2, 2)
++	gen_processor(3, 3)
++	gen_processor(4, 4)
++	gen_processor(5, 5)
++	gen_processor(6, 6)
++	gen_processor(7, 7)
++	gen_processor(8, 8)
++	gen_processor(9, 9)
++	gen_processor(10, A)
++	gen_processor(11, B)
++	gen_processor(12, C)
++	gen_processor(13, D)
++	gen_processor(14, E)
++
++	Method (NTFY, 2) {
++#define gen_ntfy(nr)                              \
++	If (LEqual(Arg0, 0x##nr)) {               \
++		Notify(CPU##nr, Arg1)             \
++	}
++		gen_ntfy(0)
++		gen_ntfy(1)
++		gen_ntfy(2)
++		gen_ntfy(3)
++		gen_ntfy(4)
++		gen_ntfy(5)
++		gen_ntfy(6)
++		gen_ntfy(7)
++		gen_ntfy(8)
++		gen_ntfy(9)
++		gen_ntfy(A)
++		gen_ntfy(B)
++		gen_ntfy(C)
++		gen_ntfy(D)
++		gen_ntfy(E)
++		Return(One)
++	}
++
++	/* Works on 8 bit quentity.
++         * Arg1 - Shadow status bits
++         * Arg2 - Current status bits
++	 */
++        Method(PR1, 3) {
++	    Xor(Arg1, Arg2, Local0) /* figure out what chaged */
++	    ShiftLeft(Arg0, 3, Local1)
++            While (LNotEqual(Local0, Zero)) {
++		If (And(Local0, 1)) {      /* if staus have changed */
++                    if(And(Arg2, 1)) {     /* check previous status */
++	                Store(3, Local3)
++		    } Else {
++	                Store(1, Local3)
++	            }
++		    NTFY(Local1, Local3)
++                }
++		ShiftRight(Local0, 1, Local0)
++		ShiftRight(Arg2, 1, Arg2)
++		Increment(Local1)
++	    }
++	    Return(One)
++	}
++
++	Method(PRSC, 0) {
++		Store(Buffer(32){}, Local0)
++		Store(PRS, Local0) /* read CPUs status bitmask into Local0 */
++		Store(Zero, Local1)
++		/* loop over bitmask byte by byte to see what have chaged */
++		While(LLess(Local1, 32)) {
++			Store(DerefOf(Index(Local0, Local1)), Local2)
++			Store(DerefOf(Index(PRSS, Local1)), Local3)
++			PR1(Local1, Local2, Local3)
++			Increment(Local1)
++                }
++		Store(Local0, PRSS) /* store curr satust bitmask into shadow */
++		Return(One)
++	}
++    }
++
+     Scope (\)
+     {
+         /* Debug Output */
+@@ -706,7 +820,7 @@ DefinitionBlock (
+
+         }
+         Method(_L02) {
+-            Return(0x01)
++	    Return(\_PR.PRSC())
+         }
+         Method(_L03) {
+             Return(0x01)
+diff --git a/bios/rombios.h b/bios/rombios.h
+index 6f9cbb1..085e287 100644
+--- a/bios/rombios.h
++++ b/bios/rombios.h
+@@ -58,6 +58,8 @@
+ #define SMB_IO_BASE       0xb100
+ #define SMP_MSR_ADDR      0x0510
+
++#define MAX_CPUS	256
++
+   // Define the application NAME
+ #if defined(BX_QEMU)
+ #  define BX_APPNAME "QEMU"
+diff --git a/bios/rombios32.c b/bios/rombios32.c
+index 7be4216..3063409 100644
+--- a/bios/rombios32.c
++++ b/bios/rombios32.c
+@@ -1126,20 +1126,22 @@ static void mptable_init(void)
+     putstr(&q, "0.1         "); /* vendor id */
+     putle32(&q, 0); /* OEM table ptr */
+     putle16(&q, 0); /* OEM table size */
+-    putle16(&q, smp_cpus + 18); /* entry count */
++    putle16(&q, MAX_CPUS + 18); /* entry count */
+     putle32(&q, 0xfee00000); /* local APIC addr */
+     putle16(&q, 0); /* ext table length */
+     putb(&q, 0); /* ext table checksum */
+     putb(&q, 0); /* reserved */
+
+-    for(i = 0; i < smp_cpus; i++) {
++    for(i = 0; i < MAX_CPUS ; i++) {
+         putb(&q, 0); /* entry type = processor */
+         putb(&q, i); /* APIC id */
+         putb(&q, 0x11); /* local APIC version number */
+         if (i == 0)
+             putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
+-        else
++        else if ( i < smp_cpus)
+             putb(&q, 1); /* cpu flags: enabled */
++        else
++            putb(&q, 0); /* cpu flags: disabled */
+         putb(&q, 0); /* cpu signature */
+         putb(&q, 6);
+         putb(&q, 0);
+@@ -1508,57 +1510,6 @@ static void acpi_build_table_header(struct acpi_table_header *h,
+     h->checksum = acpi_checksum((void *)h, len);
+ }
+
+-int acpi_build_processor_ssdt(uint8_t *ssdt)
+-{
+-    uint8_t *ssdt_ptr = ssdt;
+-    int i, length;
+-    int acpi_cpus = smp_cpus > 0xff ? 0xff : smp_cpus;
+-
+-    ssdt_ptr[9] = 0; // checksum;
+-    ssdt_ptr += sizeof(struct acpi_table_header);
+-
+-    // caluculate the length of processor block and scope block excluding PkgLength
+-    length = 0x0d * acpi_cpus + 4;
+-
+-    // build processor scope header
+-    *(ssdt_ptr++) = 0x10; // ScopeOp
+-    if (length <= 0x3e) {
+-        *(ssdt_ptr++) = length + 1;
+-    } else {
+-        *(ssdt_ptr++) = 0x7F;
+-        *(ssdt_ptr++) = (length + 2) >> 6;
+-    }
+-    *(ssdt_ptr++) = '_'; // Name
+-    *(ssdt_ptr++) = 'P';
+-    *(ssdt_ptr++) = 'R';
+-    *(ssdt_ptr++) = '_';
+-
+-    // build object for each processor
+-    for(i=0;i<acpi_cpus;i++) {
+-        *(ssdt_ptr++) = 0x5B; // ProcessorOp
+-        *(ssdt_ptr++) = 0x83;
+-        *(ssdt_ptr++) = 0x0B; // Length
+-        *(ssdt_ptr++) = 'C';  // Name (CPUxx)
+-        *(ssdt_ptr++) = 'P';
+-        if ((i & 0xf0) != 0)
+-            *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
+-        else
+-            *(ssdt_ptr++) = 'U';
+-        *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
+-        *(ssdt_ptr++) = i;
+-        *(ssdt_ptr++) = 0x10; // Processor block address
+-        *(ssdt_ptr++) = 0xb0;
+-        *(ssdt_ptr++) = 0;
+-        *(ssdt_ptr++) = 0;
+-        *(ssdt_ptr++) = 6;    // Processor block length
+-    }
+-
+-    acpi_build_table_header((struct acpi_table_header *)ssdt,
+-                            "SSDT", ssdt_ptr - ssdt, 1);
+-
+-    return ssdt_ptr - ssdt;
+-}
+-
+ /* base_addr must be a multiple of 4KB */
+ void acpi_bios_init(void)
+ {
+@@ -1613,14 +1564,10 @@ void acpi_bios_init(void)
+     dsdt = (void *)(addr);
+     addr += sizeof(AmlCode);
+
+-    ssdt_addr = addr;
+-    ssdt = (void *)(addr);
+-    addr += acpi_build_processor_ssdt(ssdt);
+-
+     addr = (addr + 7) & ~7;
+     madt_addr = addr;
+     madt_size = sizeof(*madt) +
+-        sizeof(struct madt_processor_apic) * smp_cpus +
++        sizeof(struct madt_processor_apic) * MAX_CPUS +
+ #ifdef BX_QEMU
+         sizeof(struct madt_io_apic) + sizeof(struct madt_int_override);
+ #else
+@@ -1693,12 +1640,15 @@ void acpi_bios_init(void)
+         madt->local_apic_address = cpu_to_le32(0xfee00000);
+         madt->flags = cpu_to_le32(1);
+         apic = (void *)(madt + 1);
+-        for(i=0;i<smp_cpus;i++) {
++        for(i=0;i< MAX_CPUS;i++) {
+             apic->type = APIC_PROCESSOR;
+             apic->length = sizeof(*apic);
+             apic->processor_id = i;
+             apic->local_apic_id = i;
+-            apic->flags = cpu_to_le32(1);
++            if (i < smp_cpus)
++                apic->flags = cpu_to_le32(1);
++            else
++                apic->flags = 0;
+             apic++;
+         }
+         io_apic = (void *)apic;
+--
+1.5.6.6
+
diff --git a/pc-bios/bios-pq/0013-qemu-bios-remove-acpi_build_processor_ssdt.patch b/pc-bios/bios-pq/0013-qemu-bios-remove-acpi_build_processor_ssdt.patch
new file mode 100644
index 0000000..492a625
--- /dev/null
+++ b/pc-bios/bios-pq/0013-qemu-bios-remove-acpi_build_processor_ssdt.patch
@@ -0,0 +1,55 @@
+From 10ab1258c77ee1de9f56bf284cdde97990a81575 Mon Sep 17 00:00:00 2001
+From: Glauber Costa <gcosta@redhat.com>
+Date: Tue, 26 Feb 2008 16:56:45 -0300
+Subject: [PATCH] kvm: bios: remove acpi_build_processor_ssdt
+
+now present in the dsdt.
+
+Signed-off-by: Glauber Costa <gcosta@redhat.com>
+Signed-off-by: Avi Kivity <avi@qumranet.com>
+---
+ bios/rombios32.c |   55 ------------------------------------------------------
+ 1 files changed, 0 insertions(+), 55 deletions(-)
+
+Index: bochs/bios/rombios32.c
+===================================================================
+--- bochs.orig/bios/rombios32.c
++++ bochs/bios/rombios32.c
+@@ -1275,9 +1275,9 @@ struct rsdt_descriptor_rev1
+ {
+ 	ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
+ #ifdef BX_QEMU
+-	uint32_t                             table_offset_entry [4]; /* Array of pointers to other */
+-#else
+ 	uint32_t                             table_offset_entry [3]; /* Array of pointers to other */
++#else
++	uint32_t                             table_offset_entry [2]; /* Array of pointers to other */
+ #endif
+ 			 /* ACPI tables */
+ } __attribute__((__packed__));
+@@ -1518,12 +1518,12 @@ void acpi_bios_init(void)
+     struct fadt_descriptor_rev1 *fadt;
+     struct facs_descriptor_rev1 *facs;
+     struct multiple_apic_table *madt;
+-    uint8_t *dsdt, *ssdt;
++    uint8_t *dsdt;
+ #ifdef BX_QEMU
+     struct acpi_20_hpet *hpet;
+     uint32_t hpet_addr;
+ #endif
+-    uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
++    uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
+     uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size;
+     uint16_t i, external_tables;
+ 
+@@ -1700,9 +1700,8 @@ void acpi_bios_init(void)
+     /* RSDT */
+     rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
+     rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
+-    rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
+ #ifdef BX_QEMU
+-    rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr);
++    rsdt->table_offset_entry[2] = cpu_to_le32(hpet_addr);
+ #endif
+     acpi_build_table_header((struct acpi_table_header *)rsdt,
+                             "RSDT", rsdt_size, 1);
diff --git a/pc-bios/bios-pq/series b/pc-bios/bios-pq/series
index 5a29df9..8f88ee1 100644
--- a/pc-bios/bios-pq/series
+++ b/pc-bios/bios-pq/series
@@ -9,3 +9,5 @@
 0009_qemu-bios-pci-hotplug-support.patch
 0010_bios-mark-the-acpi-sci-interrupt-as-connected-to-irq-9.patch
 0011_read-additional-acpi-tables-from-a-vm.patch
+0012-qemu-bios-create-acpi-cpu-definitions.patch
+0013-qemu-bios-remove-acpi_build_processor_ssdt.patch
-- 
1.5.6.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] Re: [PATCH 6/6] add bios support for cpu hotplug.
  2009-04-17 15:20           ` [Qemu-devel] [PATCH 6/6] add bios support for " Glauber Costa
@ 2009-04-17 20:06             ` Anthony Liguori
  0 siblings, 0 replies; 9+ messages in thread
From: Anthony Liguori @ 2009-04-17 20:06 UTC (permalink / raw)
  To: Glauber Costa; +Cc: jan.kiszka, qemu-devel

Glauber Costa wrote:
> This adds patches to bochs-bios to support cpu hotplug
>
> first one creates entries in acpi tables, and the second one
> removes the now unused static sdt.
>
> Signed-off-by: Glauber Costa <glommer@redhat.com>
>   
Please send these as patches against bochs, and CC bochs-devel.  I'll 
stick them into the appropriate place in the patch queue when committing.

-- 
Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] Re: [PATCH 5/6] enable cpu hotplug
  2009-04-17 15:20         ` [Qemu-devel] [PATCH 5/6] enable cpu hotplug Glauber Costa
  2009-04-17 15:20           ` [Qemu-devel] [PATCH 6/6] add bios support for " Glauber Costa
@ 2009-04-17 20:18           ` Anthony Liguori
  1 sibling, 0 replies; 9+ messages in thread
From: Anthony Liguori @ 2009-04-17 20:18 UTC (permalink / raw)
  To: Glauber Costa; +Cc: jan.kiszka, qemu-devel

Glauber Costa wrote:
> This patch enable cpu hotplug to happen via acpi events.
> Note that all it does is generate acpi messages. It still needs
> guest cooperation, in the very way as real hardware.
>
> It is basically what we have in kvm, but in a qemuish style, with
> a few improvements.
>
> Signed-off-by: Glauber Costa <glommer@redhat.com>
> ---
>  cpu-all.h |    1 +
>  exec.c    |   13 +++++++++++
>  hw/acpi.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  monitor.c |   21 ++++++++++++++++++
>  sysemu.h  |    1 +
>  5 files changed, 105 insertions(+), 0 deletions(-)
>
> diff --git a/cpu-all.h b/cpu-all.h
> index aaaa70d..a0c97f7 100644
> --- a/cpu-all.h
> +++ b/cpu-all.h
> @@ -745,6 +745,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags);
>
>  void cpu_exec_init_all(unsigned long tb_size);
>  CPUState *cpu_copy(CPUState *env);
> +CPUState *qemu_get_cpu(int cpu);
>
>  void cpu_dump_state(CPUState *env, FILE *f,
>                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
> diff --git a/exec.c b/exec.c
> index 13e43d0..a7ac18f 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -538,6 +538,19 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
>  }
>  #endif
>
> +CPUState *qemu_get_cpu(int cpu)
> +{
> +    CPUState *env = first_cpu;
> +
> +    while (env) {
> +        if (env->cpu_index == cpu)
> +            break;
> +        env = env->next_cpu;
> +    }
> +
> +    return env;
> +}
> +
>  void cpu_exec_init(CPUState *env)
>  {
>      CPUState **penv;
> diff --git a/hw/acpi.c b/hw/acpi.c
> index 22fbc4a..10c0e69 100644
> --- a/hw/acpi.c
> +++ b/hw/acpi.c
> @@ -26,6 +26,7 @@
>  #include "kvm.h"
>
>  //#define DEBUG
> +//#define DEBUG_CPU
>   

Consider introducing a cpu_dprintf() or something like that.

> @@ -709,11 +712,44 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
>  #endif
>  }
>
> +static uint32_t cpuhotplug_read(void *opaque, uint32_t addr)
> +{
> +    if ((addr < PROC_BASE) || (addr > (PROC_BASE + 31))) {
> +        /* should never happen, so return a poison */
> +        return 0xabcdefab;
> +    }
> +    else {
>   

Should be one line.

> +void qemu_system_cpu_hot_add(int cpu, int state)
> +{
> +    CPUState *env;
> +
> +    if ((state) && !qemu_get_cpu(cpu)) {
> +#ifdef DEBUG_CPU
> +        printf("creatng new cpu %d\n", cpu);
> +#endif
> +        env = pc_new_cpu(cpu, first_cpu->cpu_model_str, 1);
> +        enable_processor(&gpe, cpu);
> +    }
> +    else {
>   

Should be one line.

> +
> +    if (!strcmp(status, "online"))
> +       state = 1;
> +    else if (!strcmp(status, "offline"))
> +       state = 0;
>   

Should have {}s.


-- 
Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-04-17 20:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-17 15:20 [Qemu-devel] [PATCH 0/6] Add support for cpu hotplug Glauber Costa
2009-04-17 15:20 ` [Qemu-devel] [PATCH 1/6] split pc_new_cpu Glauber Costa
2009-04-17 15:20   ` [Qemu-devel] [PATCH 2/6] always have apic Glauber Costa
2009-04-17 15:20     ` [Qemu-devel] [PATCH 3/6] Fix warnings and errors with DEBUG enabled Glauber Costa
2009-04-17 15:20       ` [Qemu-devel] [PATCH 4/6] disallow kqemu if we fail to load it Glauber Costa
2009-04-17 15:20         ` [Qemu-devel] [PATCH 5/6] enable cpu hotplug Glauber Costa
2009-04-17 15:20           ` [Qemu-devel] [PATCH 6/6] add bios support for " Glauber Costa
2009-04-17 20:06             ` [Qemu-devel] " Anthony Liguori
2009-04-17 20:18           ` [Qemu-devel] Re: [PATCH 5/6] enable " Anthony Liguori

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.