From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=59412 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q4A2n-00019U-NS for qemu-devel@nongnu.org; Mon, 28 Mar 2011 06:51:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q4A2k-0003dW-Gn for qemu-devel@nongnu.org; Mon, 28 Mar 2011 06:51:33 -0400 Received: from lo.gmane.org ([80.91.229.12]:59646) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q4A2k-0003dP-02 for qemu-devel@nongnu.org; Mon, 28 Mar 2011 06:51:30 -0400 Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1Q4A2f-0002UH-6p for qemu-devel@nongnu.org; Mon, 28 Mar 2011 12:51:25 +0200 Received: from 93-34-210-217.ip51.fastwebnet.it ([93.34.210.217]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Mon, 28 Mar 2011 12:51:25 +0200 Received: from pbonzini by 93-34-210-217.ip51.fastwebnet.it with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Mon, 28 Mar 2011 12:51:25 +0200 From: Paolo Bonzini Date: Mon, 28 Mar 2011 12:51:13 +0200 Message-ID: <4D906821.6040508@redhat.com> References: <1301023292-24977-1-git-send-email-david@gibson.dropbear.id.au> <1301023292-24977-28-git-send-email-david@gibson.dropbear.id.au> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit In-Reply-To: Subject: [Qemu-devel] Re: [PATCH 27/27] Add SLOF-based partition firmware for pSeries machine, allowing more boot options List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: paulus@samba.org, anton@samba.org, David Gibson On 03/28/2011 12:30 PM, Alexander Graf wrote: > > On 25.03.2011, at 04:21, David Gibson wrote: > >> Currently, the emulated pSeries machine requires the use of the >> -kernel parameter in order to explicitly load a guest kernel. This >> means booting from the virtual disk, cdrom or network is not possible. >> >> This patch addresses this limitation by inserting a within-partition >> firmware image (derived from the "SLOF" free Open Firmware project). >> If -kernel is not specified, qemu will now load the SLOF image, which >> has access to the qemu boot device list through the device tree, and >> can boot from any of the usual virtual devices. >> >> In order to support the new firmware, an extension to the emulated >> machine/hypervisor is necessary. Unlike Linux, which expects >> multi-CPU entry to be handled kexec() style, the SLOF firmware expects >> only one CPU to be active at entry, and to use a hypervisor RTAS >> method to enable the other CPUs one by one. >> >> This patch also implements this 'start-cpu' method, so that SLOF can >> start the secondary CPUs and marshal them into the kexec() holding >> pattern ready for entry into the guest OS. Linux should, and in the >> future might directly use the start-cpu method to enable initially >> disabled CPUs, but for now it does require kexec() entry. >> >> Signed-off-by: Benjamin Herrenschmidt >> Signed-off-by: Paul Mackerras >> Signed-off-by: David Gibson >> --- >> Makefile | 2 +- >> hw/spapr.c | 35 +++++++++++++++++++++--- >> hw/spapr_rtas.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> pc-bios/README | 5 +++ >> pc-bios/slof.bin | Bin 0 -> 579072 bytes >> 5 files changed, 115 insertions(+), 5 deletions(-) >> create mode 100644 pc-bios/slof.bin >> >> diff --git a/Makefile b/Makefile >> index e0b3fea..989622b 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 9d611a7..c6454e6 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 >> >> @@ -56,6 +60,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, >> @@ -104,6 +109,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))); >> >> @@ -260,7 +266,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 7226853..16b6542 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 3fc0944..646a31a 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 > > Is this a line removal? No, it's a bug in your mailer. :) Glad to see Thunderbird isn't the only one that butcher replies to patches (in addition to patches of course). Paolo