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