qemu: wind up new cpu chip

Add boot cpu to the device tree.  Figure the number of CPUs installed
(using the qemu firmware config interface) and add cpu devices for them,
so they show up in all generated BIOS tables correctly.  This gets SMP
going.

Change-Id: I0e99f98942d8ca90150b27fc13c1c7e926a1a644
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-on: http://review.coreboot.org/3345
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/src/mainboard/emulation/qemu-x86/northbridge.c b/src/mainboard/emulation/qemu-x86/northbridge.c
index d785beb..992a39e 100644
--- a/src/mainboard/emulation/qemu-x86/northbridge.c
+++ b/src/mainboard/emulation/qemu-x86/northbridge.c
@@ -1,4 +1,5 @@
 #include <console/console.h>
+#include <cpu/cpu.h>
 #include <cpu/x86/lapic_def.h>
 #include <arch/io.h>
 #include <arch/ioapic.h>
@@ -11,6 +12,8 @@
 #include <smbios.h>
 #include <cbmem.h>
 
+#include "fw_cfg.h"
+
 #include "memory.c"
 
 static void cpu_pci_domain_set_resources(device_t dev)
@@ -130,6 +133,46 @@
 #endif
 };
 
+static void cpu_bus_init(device_t dev)
+{
+	initialize_cpus(dev->link_list);
+}
+
+static unsigned int cpu_bus_scan(device_t bus, unsigned int max)
+{
+	int max_cpus = fw_cfg_max_cpus();
+	device_t cpu;
+	int i;
+
+	if (max_cpus < 0)
+		return 0;
+
+	/*
+	 * TODO: This only handles the simple "qemu -smp $nr" case
+	 * correctly.  qemu also allows to specify the number of
+	 * cores, threads & sockets.
+	 */
+	printk(BIOS_INFO, "QEMU: max_cpus is %d\n", max_cpus);
+	for (i = 0; i < max_cpus; i++) {
+		cpu = add_cpu_device(bus->link_list, i, 1);
+		if (cpu)
+			set_cpu_topology(cpu, 1, 0, i, 0);
+	}
+	return max_cpus;
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static struct device_operations cpu_bus_ops = {
+	.read_resources   = cpu_bus_noop,
+	.set_resources    = cpu_bus_noop,
+	.enable_resources = cpu_bus_noop,
+	.init             = cpu_bus_init,
+	.scan_bus         = cpu_bus_scan,
+};
+
 static void northbridge_enable(struct device *dev)
 {
 	/* Set the operations if it is a special bus type */
@@ -137,6 +180,9 @@
 		dev->ops = &pci_domain_ops;
 		pci_set_method(dev);
 	}
+	else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+		dev->ops = &cpu_bus_ops;
+	}
 }
 
 struct chip_operations mainboard_emulation_qemu_x86_ops = {