parisc/parisc64: Allow booting 64-bit kernel up into start_parisc

Add minimal code to allow booting up into C-function start_parisc.
Console output is not working yet.

Signed-off-by: Helge Deller <deller@gmx.de>
diff --git a/src/parisc/head.S b/src/parisc/head.S
index c9b96b7..b951f42 100644
--- a/src/parisc/head.S
+++ b/src/parisc/head.S
@@ -19,6 +19,13 @@
 #endif
 	.endm
 
+	/* set upper 32-bits of firmware address */
+	.macro	load_fw_upper32 reg
+#ifdef CONFIG_64BIT
+	depdi   FIRMWARE_HIGH, 31, 32, \reg
+#endif
+	.endm
+
 ;! set the W bit
 #define set_PSW_W	.level 2.0 !	ssm PSW_W_SM, %r0 !	.level LEVEL
 
@@ -41,7 +48,9 @@
 
 	.macro loadgp
 #ifdef CONFIG_64BIT
-	copy		%r0, %r27
+	ldil		L%__gp, %r27
+	ldo		R%__gp(%r27), %r27
+	load_fw_upper32	%r27
 #else
 	ldil		L%$global$, %r27
 	ldo		R%$global$(%r27), %r27
@@ -127,8 +136,28 @@
 	cmpib,<>,n 0,%r1,1f
 	.word 0xfffdead0	/* immediately halt the emulator */
 1:
-	// set_PSW_W
+	/* we now know we run on a 64-bit CPU. */
+	/* next step: turn on the PSW.W flag (enable 64-bit mode) */
+	load32		2f,%r11
+	load_fw_upper32 %r11
+
+	mtctl           %r0,%cr17       /* Clear IIASQ tail */
+	mtctl           %r0,%cr17       /* Clear IIASQ head */
+
+	/* Load RFI target into PC queue */
+	mtctl           %r11,%cr18      /* IIAOQ head */
+	ldo             4(%r11),%r11
+	mtctl           %r11,%cr18      /* IIAOQ tail */
+
+	load32          (0x08000000 | PSW_Q),%r10 /* PSW.W=1 */
+	mtctl           %r10,%ipsw
+
+	/* Jump through hyperspace to enable PSW.W */
+	rfi
+	nop
+2:
 #else
+	/* clear any PSW.W on 32-bit firmware */
 	clear_PSW_W
 #endif
 
@@ -209,6 +238,7 @@
 	cmpb,=,n  %r0,%r3,enter_smp_idle_loop
 	nop			/* failed backward branch is nullified */
 	load32	startup, %rp
+	load_fw_upper32 %rp
 	bv,n	0(%r3)
 
 $is_monarch_cpu:
@@ -226,6 +256,7 @@
 $is_monarch_cpu_reboot:
 	/* Initialize stack pointer */
 	load32	BOOTADDR(parisc_stack),%r1
+	load_fw_upper32	%r1
 	ldo	FRAME_SIZE(%r1),%sp
 
 	/* Initialize the global data pointer */
@@ -242,6 +273,7 @@
 	STREGM	%r0,WORD_LEN(%r3)
 
 	load32	BOOTADDR(start_parisc_firmware),%r3
+	load_fw_upper32 %r3
 	bv	0(%r3)
 	copy	%r0,%r2
 END(startup)
diff --git a/src/parisc/hppa_hardware.h b/src/parisc/hppa_hardware.h
index 78554af..acafda4 100644
--- a/src/parisc/hppa_hardware.h
+++ b/src/parisc/hppa_hardware.h
@@ -6,6 +6,7 @@
 
 #define FIRMWARE_START  0xf0000000
 #define FIRMWARE_END    0xf0800000
+#define FIRMWARE_HIGH   0xfffffff0  /* upper 32-bits of 64-bit firmware address */
 
 #define MEM_PDC_ENTRY       0x4800  /* PDC entry address */
 
diff --git a/src/parisc/pafirmware.lds.S b/src/parisc/pafirmware.lds.S
index 4af3865..c31ac83 100644
--- a/src/parisc/pafirmware.lds.S
+++ b/src/parisc/pafirmware.lds.S
@@ -11,7 +11,8 @@
 SECTIONS
 {
 #if BITS == 64
-	. = 0xfffffff000000000 + FIRMWARE_START;
+	/* limit firmware high bits to physical addresses to allow debug info */
+	. = ((FIRMWARE_HIGH & 0x3ffffff0) << 32) + FIRMWARE_START;
 #else
 	. = FIRMWARE_START;
 #endif
@@ -47,6 +48,21 @@
                 _sti_rom_end = .;
         }
 
+#if BITS == 64
+	. = ALIGN(16);
+	.opd : {
+		__start_opd = .;
+		*(.opd)
+		__end_opd = .;
+	} PROVIDE (__gp = .);
+	.plt : {
+		*(.plt)
+	}
+	.dlt : {
+		*(.dlt)
+	}
+#endif
+
 	. = ALIGN(8);
 	.rodata : {
 		_rodata = . ;