summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile2
-rw-r--r--hw/spapr.c35
-rw-r--r--hw/spapr_rtas.c78
-rw-r--r--pc-bios/README5
-rw-r--r--pc-bios/slof.binbin0 -> 579072 bytes
m---------roms/SLOF0
7 files changed, 118 insertions, 5 deletions
diff --git a/.gitmodules b/.gitmodules
index 5217ce7d1c..44fdd1a02d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "roms/seabios"]
path = roms/seabios
url = git://git.qemu.org/seabios.git/
+[submodule "roms/SLOF"]
+ path = roms/SLOF
+ url = git://git.qemu.org/SLOF.git
diff --git a/Makefile b/Makefile
index e0b3fea6bc..989622b388 100644
--- a/Makefile
+++ b/Makefile
@@ -214,7 +214,7 @@ pxe-rtl8139.bin pxe-virtio.bin \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
multiboot.bin linuxboot.bin \
s390-zipl.rom \
-spapr-rtas.bin
+spapr-rtas.bin slof.bin
else
BLOBS=
endif
diff --git a/hw/spapr.c b/hw/spapr.c
index 876768631b..1152a25b2e 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -44,6 +44,10 @@
#define INITRD_LOAD_ADDR 0x02800000
#define FDT_MAX_SIZE 0x10000
#define RTAS_MAX_SIZE 0x10000
+#define FW_MAX_SIZE 0x400000
+#define FW_FILE_NAME "slof.bin"
+
+#define MIN_RAM_SLOF 512UL
#define TIMEBASE_FREQ 512000000ULL
@@ -57,6 +61,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
sPAPREnvironment *spapr,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
+ const char *boot_device,
const char *kernel_cmdline,
target_phys_addr_t rtas_addr,
target_phys_addr_t rtas_size,
@@ -105,6 +110,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
&start_prop, sizeof(start_prop))));
_FDT((fdt_property(fdt, "linux,initrd-end",
&end_prop, sizeof(end_prop))));
+ _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
_FDT((fdt_end_node(fdt)));
@@ -261,7 +267,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
ram_addr_t ram_offset;
target_phys_addr_t fdt_addr, rtas_addr;
uint32_t kernel_base, initrd_base;
- long kernel_size, initrd_size, htab_size, rtas_size;
+ long kernel_size, initrd_size, htab_size, rtas_size, fw_size;
long pteg_shift = 17;
int fdt_size;
char *filename;
@@ -392,13 +398,33 @@ static void ppc_spapr_init(ram_addr_t ram_size,
initrd_size = 0;
}
} else {
- fprintf(stderr, "pSeries machine needs -kernel for now");
- exit(1);
+ if (ram_size < (MIN_RAM_SLOF << 20)) {
+ fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
+ "%ldM guest RAM\n", MIN_RAM_SLOF);
+ exit(1);
+ }
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "slof.bin");
+ fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
+ if (fw_size < 0) {
+ hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+ exit(1);
+ }
+ qemu_free(filename);
+ kernel_base = 0x100;
+ initrd_base = 0;
+ initrd_size = 0;
+
+ /* SLOF will startup the secondary CPUs using RTAS,
+ rather than expecting a kexec() style entry */
+ for (i = 0; i < smp_cpus; i++) {
+ envs[i]->halted = 1;
+ }
}
/* Prepare the device tree */
fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
- initrd_base, initrd_size, kernel_cmdline,
+ initrd_base, initrd_size,
+ boot_device, kernel_cmdline,
rtas_addr, rtas_size, pteg_shift + 7);
assert(fdt != NULL);
@@ -409,6 +435,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
envs[0]->gpr[3] = fdt_addr;
envs[0]->gpr[5] = 0;
envs[0]->hreset_vector = kernel_base;
+ envs[0]->halted = 0;
}
static QEMUMachine spapr_machine = {
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 72268537a8..16b65422b6 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -90,6 +90,81 @@ static void rtas_power_off(sPAPREnvironment *spapr,
rtas_st(rets, 0, 0);
}
+static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong id;
+ CPUState *env;
+
+ if (nargs != 1 || nret != 2) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ id = rtas_ld(args, 0);
+ for (env = first_cpu; env; env = env->next_cpu) {
+ if (env->cpu_index != id) {
+ continue;
+ }
+
+ if (env->halted) {
+ rtas_st(rets, 1, 0);
+ } else {
+ rtas_st(rets, 1, 2);
+ }
+
+ rtas_st(rets, 0, 0);
+ return;
+ }
+
+ /* Didn't find a matching cpu */
+ rtas_st(rets, 0, -3);
+}
+
+static void rtas_start_cpu(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong id, start, r3;
+ CPUState *env;
+
+ if (nargs != 3 || nret != 1) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ id = rtas_ld(args, 0);
+ start = rtas_ld(args, 1);
+ r3 = rtas_ld(args, 2);
+
+ for (env = first_cpu; env; env = env->next_cpu) {
+ if (env->cpu_index != id) {
+ continue;
+ }
+
+ if (!env->halted) {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+ env->nip = start;
+ env->gpr[3] = r3;
+ env->halted = 0;
+
+ qemu_cpu_kick(env);
+
+ rtas_st(rets, 0, 0);
+ return;
+ }
+
+ /* Didn't find a matching cpu */
+ rtas_st(rets, 0, -3);
+}
+
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
@@ -196,5 +271,8 @@ static void register_core_rtas(void)
spapr_rtas_register("display-character", rtas_display_character);
spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
spapr_rtas_register("power-off", rtas_power_off);
+ spapr_rtas_register("query-cpu-stopped-state",
+ rtas_query_cpu_stopped_state);
+ spapr_rtas_register("start-cpu", rtas_start_cpu);
}
device_init(register_core_rtas);
diff --git a/pc-bios/README b/pc-bios/README
index 3fc09449fa..646a31a313 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -13,6 +13,11 @@
The included image for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32
and Sparc64 are built from OpenBIOS SVN revision 1018.
+- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
+ implementation for certain IBM POWER hardware. The sources are at
+ https://github.com/dgibson/SLOF, and the image currently in qemu is
+ built from git tag qemu-slof-20110323.
+
- The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
e1000 8086:100E
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
new file mode 100644
index 0000000000..22c4c7f5c4
--- /dev/null
+++ b/pc-bios/slof.bin
Binary files differ
diff --git a/roms/SLOF b/roms/SLOF
new file mode 160000
+Subproject d1d6b53b713a2b7c2c25685268fa932d28a4b4c