Subject: XKPHYS_KERNEL patch - kernel in 64-bit space

From: Stanislaw Skowronek <[email-masked]>
Date: Sat, 15 May 2004 16:29:16 +0200 (MET DST)

This patch allows the kernel to run from any place in the whole physical
address space, not only the lowest 512 MB. It is REQUIRED for operation on
IP30 (Octane) and for R8000 support.

R8000 support would require changing the remaining compatibility segment
accesses, which - from what I know - are limited to loading exception
handlers. As I don't have an R8000 machine, I didn't introduce this here.

Stanislaw Skowronek

--<=>--
  "You're not as old as the trees, not as young as the leaves.
   Not as free as the breeze, not as open as the seas."
diff -urN linux-mips-cvs-mdules/arch/mips/Kconfig linux-mips-xkphys/arch/mips/Kconfig
--- linux-mips-cvs-mdules/arch/mips/Kconfig	Wed Apr 28 18:05:54 2004
+++ linux-mips-xkphys/arch/mips/Kconfig	Sat May 15 16:09:42 2004
@@ -1241,6 +1241,14 @@
 	bool "Support for 64-bit physical address space"
 	depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32
 
+config XKPHYS_KERNEL
+	bool "Allow kernel to run from 64-bit segments"
+	depends on MIPS64
+	default y if SGI_IP30
+	help
+	  This option allows to locate the kernel in 64-bit unmapped memory
+	  space (xkphys). This is required for Octane (IP30) machines.
+
 config CPU_ADVANCED
 	bool "Override CPU Options"
 	depends on MIPS32
diff -urN linux-mips-cvs-mdules/arch/mips/Makefile linux-mips-xkphys/arch/mips/Makefile
--- linux-mips-cvs-mdules/arch/mips/Makefile	Tue Apr 13 23:30:16 2004
+++ linux-mips-xkphys/arch/mips/Makefile	Sat May 15 16:13:25 2004
@@ -35,7 +35,11 @@
 endif
 ifdef CONFIG_MIPS64
 gcc-abi			= 64
+ifdef CONFIG_XKPHYS_KERNEL
+gas-abi			= 64
+else
 gas-abi			= 32
+endif
 tool-prefix		= $(64bit-tool-prefix)
 UTS_MACHINE		:= mips64
 endif
@@ -608,9 +612,15 @@
 
 ifdef CONFIG_MIPS32
 build-bfd		= $(32bit-bfd)
+output-bfd		= $(32bit-bfd)
 cflags-y		+= $(32bit-isa-y)
 endif
 ifdef CONFIG_MIPS64
+ifdef CONFIG_XKPHYS_KERNEL
+output-bfd		= $(64bit-bfd)
+else
+output-bfd		= $(32bit-bfd)
+endif
 build-bfd		= $(64bit-bfd)
 cflags-y		+= $(64bit-isa-y)
 endif
@@ -650,7 +660,7 @@
 AFLAGS		+= $(cflags-y)
 CFLAGS		+= $(cflags-y)
 
-LDFLAGS			+= --oformat $(32bit-bfd)
+LDFLAGS			+= --oformat $(output-bfd)
 
 head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
diff -urN linux-mips-cvs-mdules/arch/mips/kernel/scall64-o32.S linux-mips-xkphys/arch/mips/kernel/scall64-o32.S
--- linux-mips-cvs-mdules/arch/mips/kernel/scall64-o32.S	Mon Apr 26 17:06:10 2004
+++ linux-mips-xkphys/arch/mips/kernel/scall64-o32.S	Sat May 15 16:09:42 2004
@@ -142,7 +142,7 @@
 	ld	t0, PT_R29(sp)		# get old user stack pointer
 	PTR_LA	t1, 3f			# copy 1 to 2 arguments
 	sll	t3, t3, 2
-	subu	t1, t3
+	dsubu	t1, t3
 	jr	t1
 
 	/* Ok, copy the args from the luser stack to the kernel stack */
diff -urN linux-mips-cvs-mdules/arch/mips/kernel/setup.c linux-mips-xkphys/arch/mips/kernel/setup.c
--- linux-mips-cvs-mdules/arch/mips/kernel/setup.c	Sun Feb  8 15:57:04 2004
+++ linux-mips-xkphys/arch/mips/kernel/setup.c	Sat May 15 16:09:42 2004
@@ -221,13 +221,13 @@
 		initrd_start = (unsigned long)&initrd_header[2];
 		initrd_end = initrd_start + initrd_header[1];
 	}
-	start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
+	start_pfn = PFN_UP(KPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
 #else
 	/*
 	 * Partially used pages are not usable - thus
 	 * we are rounding upwards.
 	 */
-	start_pfn = PFN_UP(CPHYSADDR(&_end));
+	start_pfn = PFN_UP(KPHYSADDR(&_end));
 #endif	/* CONFIG_BLK_DEV_INITRD */
 
 #ifndef CONFIG_SGI_IP27
@@ -357,10 +357,10 @@
 		       (void *)initrd_start,
 		       initrd_size);
 
-		if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+		if (KPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
 			printk("initrd extends beyond end of memory "
 			       "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
-			       sizeof(long) * 2, CPHYSADDR(initrd_end),
+			       sizeof(long) * 2, KPHYSADDR(initrd_end),
 			       sizeof(long) * 2, PFN_PHYS(max_low_pfn));
 			initrd_start = initrd_end = 0;
 		}
diff -urN linux-mips-cvs-mdules/arch/mips/mm/init.c linux-mips-xkphys/arch/mips/mm/init.c
--- linux-mips-cvs-mdules/arch/mips/mm/init.c	Mon Apr 19 18:36:35 2004
+++ linux-mips-xkphys/arch/mips/mm/init.c	Sat May 15 16:09:42 2004
@@ -266,8 +266,8 @@
 {
 #ifdef CONFIG_MIPS64
 	/* Switch from KSEG0 to XKPHYS addresses */
-	start = (unsigned long)phys_to_virt(CPHYSADDR(start));
-	end = (unsigned long)phys_to_virt(CPHYSADDR(end));
+	start = (unsigned long)phys_to_virt(KPHYSADDR(start));
+	end = (unsigned long)phys_to_virt(KPHYSADDR(end));
 #endif
 	if (start < end)
 		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
@@ -293,7 +293,7 @@
 	addr = (unsigned long) &__init_begin;
 	while (addr < (unsigned long) &__init_end) {
 #ifdef CONFIG_MIPS64
-		page = PAGE_OFFSET | CPHYSADDR(addr);
+		page = PAGE_OFFSET | KPHYSADDR(addr);
 #else
 		page = addr;
 #endif
diff -urN linux-mips-cvs-mdules/arch/mips/mm/tlb-andes.c linux-mips-xkphys/arch/mips/mm/tlb-andes.c
--- linux-mips-cvs-mdules/arch/mips/mm/tlb-andes.c	Wed Mar 17 22:26:44 2004
+++ linux-mips-xkphys/arch/mips/mm/tlb-andes.c	Sat May 15 16:09:42 2004
@@ -264,7 +264,7 @@
 #endif
 #ifdef CONFIG_MIPS64
 	memcpy((void *)(CKSEG0 + 0x000), &except_vec0_generic, 0x80);
-	memcpy((void *)(CKSEG0 + 0x080), except_vec1_r10k, 0x80);
+	memcpy((void *)(CKSEG0 + 0x080), &except_vec1_r10k, 0x80);
 	flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100);
 #endif
 }
diff -urN linux-mips-cvs-mdules/include/asm-mips/addrspace.h linux-mips-xkphys/include/asm-mips/addrspace.h
--- linux-mips-cvs-mdules/include/asm-mips/addrspace.h	Sun Nov 30 02:52:25 2003
+++ linux-mips-xkphys/include/asm-mips/addrspace.h	Sat May 15 16:09:42 2004
@@ -3,6 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
+ * Copyright (C) 2004 Stanislaw Skowronek
  * Copyright (C) 1996, 99 Ralf Baechle
  * Copyright (C) 2000, 2002  Maciej W. Rozycki
  * Copyright (C) 1990, 1999 by Silicon Graphics, Inc.
@@ -38,14 +39,40 @@
 #endif
 
 /*
+ * Memory segments (64bit kernel mode addresses)
+ * The compatibility segments use the full 64-bit sign extended value.  Note
+ * the R8000 doesn't have them so don't reference these in generic MIPS code.
+ */
+#define XKUSEG			0x0000000000000000
+#define XKSSEG			0x4000000000000000
+#define XKPHYS			0x8000000000000000
+#define XKSEG			0xc000000000000000
+#define CKSEG0			0xffffffff80000000
+#define CKSEG1			0xffffffffa0000000
+#define CKSSEG			0xffffffffc0000000
+#define CKSEG3			0xffffffffe0000000
+
+
+/*
  * Memory segments (32bit kernel mode addresses)
  * These are the traditional names used in the 32-bit universe.
- */
+ * On MIPS64 they are 64-bit long constants because:
+ *  1) drivers which use them for longs or pointers will work correctly
+ *  2) drivers which use them from ints will only truncate them
+ */
+#ifdef CONFIG_MIPS64
+#define KUSEG			XKUSEG
+#define KSEG0			CKSEG0
+#define KSEG1			CKSEG1
+#define KSEG2			CKSEG2
+#define KSEG3			CKSEG3
+#else
 #define KUSEG			0x00000000
 #define KSEG0			0x80000000
 #define KSEG1			0xa0000000
 #define KSEG2			0xc0000000
 #define KSEG3			0xe0000000
+#endif
 
 /*
  * Returns the kernel segment base of a given address
@@ -71,19 +98,20 @@
 #define CKSEG2ADDR(a)		(CPHYSADDR(a) | CKSEG2)
 #define CKSEG3ADDR(a)		(CPHYSADDR(a) | CKSEG3)
 
-/*
- * Memory segments (64bit kernel mode addresses)
- * The compatibility segments use the full 64-bit sign extended value.  Note
- * the R8000 doesn't have them so don't reference these in generic MIPS code.
- */
-#define XKUSEG			0x0000000000000000
-#define XKSSEG			0x4000000000000000
-#define XKPHYS			0x8000000000000000
-#define XKSEG			0xc000000000000000
-#define CKSEG0			0xffffffff80000000
-#define CKSEG1			0xffffffffa0000000
-#define CKSSEG			0xffffffffc0000000
-#define CKSEG3			0xffffffffe0000000
+
+#ifdef CONFIG_MIPS64
+#define K0BASE			0xa800000000000000
+#else
+#define K0BASE			KSEG0
+#endif
+
+#ifdef CONFIG_XKPHYS_KERNEL
+#define K0RAMBASE		0xa800000020000000
+#define KPHYSADDR		XPHYSADDR
+#else
+#define K0RAMBASE		K0BASE
+#define KPHYSADDR		CPHYSADDR
+#endif
 
 /*
  * Cache modes for XKPHYS address conversion macros

---

From: Thiemo Seufer <[email-masked]>
Date: Sat, 15 May 2004 16:50:56 +0200

Stanislaw Skowronek wrote:
[snip]
> +++ linux-mips-xkphys/arch/mips/mm/tlb-andes.c	Sat May 15 16:09:42 2004

This flush_icache_range should start from CKSEG0, not (CKSEG0 + 80).

Thiemo

---

From: Stanislaw Skowronek <[email-masked]>
Date: Sat, 15 May 2004 16:54:31 +0200 (MET DST)

> This flush_icache_range should start from CKSEG0, not (CKSEG0 + 80).

Ahh, yeah - not important as we can't get the first exception anyway. But
would be nice to fix.

Stanislaw Skowronek