aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/boot/Makefile21
-rw-r--r--arch/powerpc/boot/ps3-head.S80
-rw-r--r--arch/powerpc/boot/ps3-hvcall.S184
-rw-r--r--arch/powerpc/boot/ps3.c161
-rwxr-xr-xarch/powerpc/boot/wrapper55
-rw-r--r--arch/powerpc/boot/zImage.ps3.lds.S50
-rw-r--r--arch/powerpc/platforms/ps3/mm.c2
7 files changed, 542 insertions, 11 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 5b2c59b1b2a..396821cfaad 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -46,7 +46,8 @@ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
- cuboot-ebony.c treeboot-ebony.c prpmc2800.c
+ cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
+ ps3-head.S ps3-hvcall.S ps3.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
$(obj)/empty.c:
@touch $@
-$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
- empty.c zImage.coff.lds zImage.lds
+ empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
quiet_cmd_bootcc = BOOTCC $@
cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -102,7 +103,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
- $(obj)/zImage.lds $(obj)/zImage.coff.lds
+ $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
wrapper :=$(srctree)/$(src)/wrapper
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@@ -179,11 +180,12 @@ $(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
$(obj)/zImage.iseries: vmlinux
$(STRIP) -s -R .comment $< -o $@
-$(obj)/zImage.ps3: vmlinux
- $(STRIP) -s -R .comment $< -o $@
+$(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
+ $(STRIP) -s -R .comment $< -o vmlinux.strip
+ $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
-$(obj)/zImage.initrd.ps3: vmlinux
- @echo " WARNING zImage.initrd.ps3 not supported (yet)"
+$(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
+ $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
@@ -206,7 +208,8 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
# anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.*
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+ otheros.bld
# clean up files cached by wrapper
clean-kernel := vmlinux.strip vmlinux.bin
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
new file mode 100644
index 00000000000..1a6d64a68df
--- /dev/null
+++ b/arch/powerpc/boot/ps3-head.S
@@ -0,0 +1,80 @@
+/*
+ * PS3 bootwrapper entry.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ppc_asm.h"
+
+ .text
+
+/*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+ * The bootwraper build script copies the 0x100 bytes at symbol
+ * __system_reset_overlay to offset 0x100 of the rom image.
+ *
+ * The PS3 has a single processor with two threads.
+ */
+
+ .globl __system_reset_overlay
+__system_reset_overlay:
+
+ /* Switch to 32-bit mode. */
+
+ mfmsr r9
+ clrldi r9,r9,1
+ mtmsrd r9
+ nop
+
+ /* Get thread number in r3 and branch. */
+
+ mfspr r3, 0x88
+ cntlzw. r3, r3
+ li r4, 0
+ li r5, 0
+ beq 1f
+
+ /* Secondary goes to __secondary_hold in kernel. */
+
+ li r4, 0x60
+ mtctr r4
+ bctr
+
+ /* Primary delays then goes to _zimage_start in wrapper. */
+1:
+ or 31, 31, 31 /* db16cyc */
+ or 31, 31, 31 /* db16cyc */
+
+ lis r4, _zimage_start@ha
+ addi r4, r4, _zimage_start@l
+ mtctr r4
+ bctr
+
+/*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+ * The bootwrapper build script copies 0x100 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel. At runtime
+ * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+ * to ram address 0x100. This symbol must occupy 0x100 bytes.
+ */
+
+ .globl __system_reset_kernel
+__system_reset_kernel:
+
+ . = __system_reset_kernel + 0x100
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S
new file mode 100644
index 00000000000..c8b7df3210d
--- /dev/null
+++ b/arch/powerpc/boot/ps3-hvcall.S
@@ -0,0 +1,184 @@
+/*
+ * PS3 bootwrapper hvcalls.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ppc_asm.h"
+
+/*
+ * The PS3 hypervisor uses a 64 bit "C" language calling convention.
+ * The routines here marshal arguments between the 32 bit wrapper
+ * program and the 64 bit hvcalls.
+ *
+ * wrapper lv1
+ * 32-bit (h,l) 64-bit
+ *
+ * 1: r3,r4 <-> r3
+ * 2: r5,r6 <-> r4
+ * 3: r7,r8 <-> r5
+ * 4: r9,r10 <-> r6
+ * 5: 8(r1),12(r1) <-> r7
+ * 6: 16(r1),20(r1) <-> r8
+ * 7: 24(r1),28(r1) <-> r9
+ * 8: 32(r1),36(r1) <-> r10
+ *
+ */
+
+.macro GLOBAL name
+ .section ".text"
+ .balign 4
+ .globl \name
+\name:
+.endm
+
+.macro NO_SUPPORT name
+ GLOBAL \name
+ b ps3_no_support
+.endm
+
+.macro HVCALL num
+ li r11, \num
+ .long 0x44000022
+ extsw r3, r3
+.endm
+
+.macro SAVE_LR offset=4
+ mflr r0
+ stw r0, \offset(r1)
+.endm
+
+.macro LOAD_LR offset=4
+ lwz r0, \offset(r1)
+ mtlr r0
+.endm
+
+.macro LOAD_64_REG target,high,low
+ sldi r11, \high, 32
+ or \target, r11, \low
+.endm
+
+.macro LOAD_64_STACK target,offset
+ ld \target, \offset(r1)
+.endm
+
+.macro LOAD_R3
+ LOAD_64_REG r3,r3,r4
+.endm
+
+.macro LOAD_R4
+ LOAD_64_REG r4,r5,r6
+.endm
+
+.macro LOAD_R5
+ LOAD_64_REG r5,r7,r8
+.endm
+
+.macro LOAD_R6
+ LOAD_64_REG r6,r9,r10
+.endm
+
+.macro LOAD_R7
+ LOAD_64_STACK r7,8
+.endm
+
+.macro LOAD_R8
+ LOAD_64_STACK r8,16
+.endm
+
+.macro LOAD_R9
+ LOAD_64_STACK r9,24
+.endm
+
+.macro LOAD_R10
+ LOAD_64_STACK r10,32
+.endm
+
+.macro LOAD_REGS_0
+ stwu 1,-16(1)
+ stw 3, 8(1)
+.endm
+
+.macro LOAD_REGS_5
+ LOAD_R3
+ LOAD_R4
+ LOAD_R5
+ LOAD_R6
+ LOAD_R7
+.endm
+
+.macro LOAD_REGS_6
+ LOAD_REGS_5
+ LOAD_R8
+.endm
+
+.macro LOAD_REGS_8
+ LOAD_REGS_6
+ LOAD_R9
+ LOAD_R10
+.endm
+
+.macro STORE_REGS_0_1
+ lwz r11, 8(r1)
+ std r4, 0(r11)
+ mr r4, r3
+ li r3, 0
+ addi r1,r1,16
+.endm
+
+.macro STORE_REGS_5_2
+ lwz r11, 16(r1)
+ std r4, 0(r11)
+ lwz r11, 24(r1)
+ std r5, 0(r11)
+.endm
+
+.macro STORE_REGS_6_1
+ lwz r11, 24(r1)
+ std r4, 0(r11)
+.endm
+
+GLOBAL lv1_get_logical_ppe_id
+ SAVE_LR
+ LOAD_REGS_0
+ HVCALL 69
+ STORE_REGS_0_1
+ LOAD_LR
+ blr
+
+GLOBAL lv1_get_logical_partition_id
+ SAVE_LR
+ LOAD_REGS_0
+ HVCALL 74
+ STORE_REGS_0_1
+ LOAD_LR
+ blr
+
+GLOBAL lv1_get_repository_node_value
+ SAVE_LR
+ LOAD_REGS_5
+ HVCALL 91
+ STORE_REGS_5_2
+ LOAD_LR
+ blr
+
+GLOBAL lv1_panic
+ SAVE_LR
+ LOAD_REGS_8
+ HVCALL 255
+ LOAD_LR
+ blr
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
new file mode 100644
index 00000000000..893d59339c2
--- /dev/null
+++ b/arch/powerpc/boot/ps3.c
@@ -0,0 +1,161 @@
+/*
+ * PS3 bootwrapper support.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+extern s64 lv1_panic(u64 in_1);
+extern s64 lv1_get_logical_partition_id(u64 *out_1);
+extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+ u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+#ifdef DEBUG
+#define DBG(fmt...) printf(fmt)
+#else
+static inline int __attribute__ ((format (printf, 1, 2))) DBG(
+ const char *fmt, ...) {return 0;}
+#endif
+
+BSS_STACK(4096);
+
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char cmdline[COMMAND_LINE_SIZE]
+ __attribute__((__section__("__builtin_cmdline")));
+
+static void prep_cmdline(void *chosen)
+{
+ if (cmdline[0] == '\0')
+ getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+ else
+ setprop_str(chosen, "bootargs", cmdline);
+
+ printf("cmdline: '%s'\n", cmdline);
+}
+
+static void ps3_console_write(const char *buf, int len)
+{
+}
+
+static void ps3_exit(void)
+{
+ printf("ps3_exit\n");
+
+ /* lv1_panic will shutdown the lpar. */
+
+ lv1_panic(0); /* zero = do not reboot */
+ while (1);
+}
+
+static int ps3_repository_read_rm_size(u64 *rm_size)
+{
+ s64 result;
+ u64 lpar_id;
+ u64 ppe_id;
+ u64 v2;
+
+ result = lv1_get_logical_partition_id(&lpar_id);
+
+ if (result)
+ return -1;
+
+ result = lv1_get_logical_ppe_id(&ppe_id);
+
+ if (result)
+ return -1;
+
+ /*
+ * n1: 0000000062690000 : ....bi..
+ * n2: 7075000000000000 : pu......
+ * n3: 0000000000000001 : ........
+ * n4: 726d5f73697a6500 : rm_size.
+ */
+
+ result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
+ 0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
+ &v2);
+
+ printf("%s:%d: ppe_id %lu \n", __func__, __LINE__,
+ (unsigned long)ppe_id);
+ printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
+ (unsigned long)lpar_id);
+ printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
+
+ return result ? -1 : 0;
+}
+
+void ps3_copy_vectors(void)
+{
+ extern char __system_reset_kernel[];
+
+ memcpy((void *)0x100, __system_reset_kernel, 0x100);
+ flush_cache((void *)0x100, 0x100);
+}
+
+void platform_init(void)
+{
+ extern char _end[];
+ extern char _dtb_start[];
+ extern char _initrd_start[];
+ extern char _initrd_end[];
+ const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+ void *chosen;
+ unsigned long ft_addr;
+ u64 rm_size;
+
+ console_ops.write = ps3_console_write;
+ platform_ops.exit = ps3_exit;
+
+ printf("\n-- PS3 bootwrapper --\n");
+
+ simple_alloc_init(_end, heapsize, 32, 64);
+ ft_init(_dtb_start, 0, 4);
+
+ chosen = finddevice("/chosen");
+
+ ps3_repository_read_rm_size(&rm_size);
+ dt_fixup_memory(0, rm_size);
+
+ if (_initrd_end > _initrd_start) {
+ setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
+ setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
+ }
+
+ prep_cmdline(chosen);
+
+ ft_addr = dt_ops.finalize();
+
+ ps3_copy_vectors();
+
+ printf(" flat tree at 0x%lx\n\r", ft_addr);
+
+ ((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+ ps3_exit();
+}
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index da77adc7307..65f68547917 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -144,6 +144,15 @@ miboot|uboot)
cuboot*)
gzip=
;;
+ps3)
+ platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
+ lds=$object/zImage.ps3.lds
+ gzip=
+ ext=bin
+ objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
+ ksection=.kernel:vmlinux.bin
+ isection=.kernel:initrd
+ ;;
esac
vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@@ -239,4 +248,50 @@ treeboot*)
fi
exit 0
;;
+ps3)
+ # The ps3's loader supports loading gzipped binary images from flash
+ # rom to addr zero. The loader enters the image at addr 0x100. A
+ # bootwrapper overlay is use to arrange for the kernel to be loaded
+ # to addr zero and to have a suitable bootwrapper entry at 0x100.
+ # To construct the rom image, 0x100 bytes from offset 0x100 in the
+ # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+ # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+ # then copied to offset 0x100. At runtime the bootwrapper program
+ # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
+
+ system_reset_overlay=0x`${CROSS}nm "$ofile" \
+ | grep ' __system_reset_overlay$' \
+ | cut -d' ' -f1`
+ system_reset_overlay=`printf "%d" $system_reset_overlay`
+ system_reset_kernel=0x`${CROSS}nm "$ofile" \
+ | grep ' __system_reset_kernel$' \
+ | cut -d' ' -f1`
+ system_reset_kernel=`printf "%d" $system_reset_kernel`
+ overlay_dest="256"
+ overlay_size="256"
+
+ rm -f "$object/otheros.bld"
+
+ ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+ msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+ skip=$overlay_dest seek=$system_reset_kernel \
+ count=$overlay_size bs=1 2>&1)
+
+ if [ $? -ne "0" ]; then
+ echo $msg
+ exit 1
+ fi
+
+ msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+ skip=$system_reset_overlay seek=$overlay_dest \
+ count=$overlay_size bs=1 2>&1)
+
+ if [ $? -ne "0" ]; then
+ echo $msg
+ exit 2
+ fi
+
+ gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+ ;;
esac
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S
new file mode 100644
index 00000000000..aaa469c1e60
--- /dev/null
+++ b/arch/powerpc/boot/zImage.ps3.lds.S
@@ -0,0 +1,50 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_zimage_start)
+EXTERN(_zimage_start)
+SECTIONS
+{
+ _vmlinux_start = .;
+ .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
+ _vmlinux_end = .;
+
+ . = ALIGN(4096);
+ _dtb_start = .;
+ .kernel:dtb : { *(.kernel:dtb) }
+ _dtb_end = .;
+
+ . = ALIGN(4096);
+ _initrd_start = .;
+ .kernel:initrd : { *(.kernel:initrd) }
+ _initrd_end = .;
+
+ _start = .;
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+ }
+ _etext = .;
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.rodata*)
+ *(.data*)
+ *(.sdata*)
+ __got2_start = .;
+ *(.got2)
+ __got2_end = .;
+ }
+
+ . = ALIGN(4096);
+ _edata = .;
+
+ . = ALIGN(4096);
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss)
+ *(.bss)
+ }
+ . = ALIGN(4096);
+ _end = . ;
+}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 56d47a7a022..7bb3e162097 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -1213,8 +1213,6 @@ void __init ps3_mm_init(void)
BUG_ON(map.rm.base);
BUG_ON(!map.rm.size);
- lmb_add(map.rm.base, map.rm.size);
- lmb_analyze();
/* arrange to do this in ps3_mm_add_memory */
ps3_mm_region_create(&map.r1, map.total - map.rm.size);