Linux MIPS Architecture development
 help / color / mirror / Atom feed
* [PATCH 2] 64K page size
@ 2006-08-25 14:42 Peter Watkins
  2006-08-25 15:04 ` Ralf Baechle
  2006-08-25 15:21 ` Thiemo Seufer
  0 siblings, 2 replies; 4+ messages in thread
From: Peter Watkins @ 2006-08-25 14:42 UTC (permalink / raw)
  To: linux-mips, Ralf Baechle, Jonathan Day

[-- Attachment #1: Type: text/plain, Size: 970 bytes --]

Hello,

Attached is the rest of the 64K page patch. It's been tested 
uniprocessor on Malta 20KC and 25KF. It also runs on a 6-way SMP 
functional simulator containing 5KF's. Ran tests with 16K and 64K page 
size.

Question: Is there an SMP malta board?

There are 2 areas which could use improvement:

(1) Because 64K is larger than a 15 bit immediate operand, I could not 
get the asm-offsets mechanism to produce the correct constants. So I 
enlisted a fairly gruesome hack of using #define's for _PAGE_SIZE and 
_THREAD_SIZE, for that page size. Hopefully someone has a better idea.

(2) In tlbex.c:build_adjust_context(), I suspect the change for shift = 
PAGE_SHIFT - 12 should be more generally true, rather than just for the 
CPU's mentioned in the case statement. I was conservative there because 
I'm not familiar with the CPU_VR41* machines. Hopefully someone more 
intimate with that code can comment.


Signed-off-by: Peter Watkins <treestem@gmail.com>





[-- Attachment #2: patch-pagesize-2.6.18-rc1.txt --]
[-- Type: text/plain, Size: 8839 bytes --]

diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ec28077..07b6566 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -99,7 +99,10 @@ void output_thread_info_defines(void)
 	offset("#define TI_RESTART_BLOCK   ", struct thread_info, restart_block);
 	offset("#define TI_TP_VALUE	   ", struct thread_info, tp_value);
 	constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
+#ifndef CONFIG_PAGE_SIZE_64KB
+	/* See comment in page.h */
 	constant("#define _THREAD_SIZE       ", THREAD_SIZE);
+#endif
 	constant("#define _THREAD_MASK       ", THREAD_MASK);
 	linefeed;
 }
@@ -219,7 +222,10 @@ void output_mm_defines(void)
 	offset("#define MM_PGD        ", struct mm_struct, pgd);
 	offset("#define MM_CONTEXT    ", struct mm_struct, context);
 	linefeed;
+#ifndef CONFIG_PAGE_SIZE_64KB
+	/* See comment in page.h */
 	constant("#define _PAGE_SIZE     ", PAGE_SIZE);
+#endif
 	constant("#define _PAGE_SHIFT    ", PAGE_SHIFT);
 	linefeed;
 	constant("#define _PGD_T_SIZE    ", sizeof(pgd_t));
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index c06f63e..c9de17c 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -190,7 +190,12 @@ #endif /* CONFIG_MIPS_MT_SMTC */
 
 	MTC0		zero, CP0_CONTEXT	# clear context register
 	PTR_LA		$28, init_thread_union
+#ifdef CONFIG_PAGE_SIZE_64KB
+	PTR_ADDIU	sp, $28, (_THREAD_SIZE - 32)/2
+	PTR_ADDIU	sp,  sp, (_THREAD_SIZE - 32)/2
+#else
 	PTR_ADDIU	sp, $28, _THREAD_SIZE - 32
+#endif
 	set_saved_sp	sp, t0, t1
 	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
 
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index d5c8b82..fe534c7 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -85,7 +85,12 @@ #endif
 	move	$28, a2
 	cpu_restore_nonscratch a1
 
+#ifdef CONFIG_PAGE_SIZE_64KB
+	PTR_ADDIU	t0, $28, (_THREAD_SIZE - 32)/2
+	PTR_ADDIU	t0,  t0, (_THREAD_SIZE - 32)/2
+#else
 	PTR_ADDIU	t0, $28, _THREAD_SIZE - 32
+#endif
 	set_saved_sp	t0, t1, t2
 #ifdef CONFIG_MIPS_MT_SMTC
 	/* Read-modify-writes of Status must be atomic on a VPE */
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 0bb9cd8..ad7d6ff 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -1,6 +1,10 @@
 #include <asm/asm-offsets.h>
 #include <asm-generic/vmlinux.lds.h>
 
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define _PAGE_SIZE	0x10000
+#endif
+
 #undef mips
 #define mips mips
 OUTPUT_ARCH(mips)
@@ -50,6 +54,7 @@ #endif
   /* writeable */
   .data : {			/* Data */
     . = . + DATAOFFSET;		/* for CONFIG_MAPPED_KERNEL */
+    . = ALIGN(_PAGE_SIZE);
     *(.data.init_task)
 
     *(.data)
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
index 6db44c7..cc6fd23 100644
--- a/arch/mips/lib-64/dump_tlb.c
+++ b/arch/mips/lib-64/dump_tlb.c
@@ -147,7 +147,7 @@ void dump_list_process(struct task_struc
 	printk("Addr                 == %08lx\n", addr);
 	printk("tasks->mm.pgd        == %08lx\n", (unsigned long) t->mm->pgd);
 
-	page_dir = pgd_offset(t->mm, 0);
+	page_dir = pgd_offset(t->mm, 0UL);
 	printk("page_dir == %016lx\n", (unsigned long) page_dir);
 
 	pgd = pgd_offset(t->mm, addr);
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index be80c5d..eeed944 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -176,7 +176,7 @@ unsigned long __init prom_free_prom_memo
 		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
 
-		addr = boot_mem_map.map[i].addr;
+		addr = PAGE_ALIGN(boot_mem_map.map[i].addr);
 		while (addr < boot_mem_map.map[i].addr
 			      + boot_mem_map.map[i].size) {
 			ClearPageReserved(virt_to_page(__va(addr)));
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index b7c7492..b173a8d 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -270,6 +270,20 @@ static inline void build_addiu_a2_a0(uns
 	emit_instruction(mi);
 }
 
+static inline void build_addiu_a2(unsigned long offset)
+{
+	union mips_instruction mi;
+
+	BUG_ON(offset > 0x7fff);
+
+	mi.i_format.opcode     = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
+	mi.i_format.rs         = 6;		/* $a2 */
+	mi.i_format.rt         = 6;		/* $a2 */
+	mi.i_format.simmediate = offset;
+
+	emit_instruction(mi);
+}
+
 static inline void build_addiu_a1(unsigned long offset)
 {
 	union mips_instruction mi;
@@ -369,7 +383,14 @@ void __init build_clear_page(void)
 		}
 	}
 
-	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0));
+        unsigned long off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0);
+	if (off > 0x7fff) {
+	    build_addiu_a2_a0(off>>1);
+	    build_addiu_a2(off>>1);
+	}
+	else {
+	    build_addiu_a2_a0(off);
+	}
 
 	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
@@ -425,7 +446,14 @@ void __init build_copy_page(void)
 	store_offset = load_offset = 0;
 	instruction_pending = 0;
 
-	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0));
+	unsigned long off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0);
+	if (off > 0x7fff) {
+	    build_addiu_a2_a0(off>>1);
+	    build_addiu_a2(off>>1);
+	}
+	else {
+	    build_addiu_a2_a0(off);
+	}
 
 	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 375e099..bf093aa 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -97,6 +97,8 @@ #define FUNC_SH		0
 #define SET_MASK	0x7
 #define SET_SH		0
 
+#define OP_ERET		0x42000018
+
 enum opcode {
 	insn_invalid,
 	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
@@ -631,6 +633,9 @@ static __init void copy_handler(struct r
 static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel,
 							  u32 *addr)
 {
+	if (*addr == OP_ERET)
+		return 1;
+
 	for (; rel->lab != label_invalid; rel++) {
 		if (rel->addr == addr
 		    && (rel->type == R_MIPS_PC16
@@ -996,7 +1001,12 @@ #else
 #endif
 
 	l_vmalloc_done(l, *p);
-	i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */
+
+	/* Want PGDIR_SHIFT-3 here, but break it into two ops so we don't
+	 * exceed the max shift amount of 31 with large page sizes. */
+	i_dsrl(p, tmp, tmp, PGDIR_SHIFT-16);   	/* get pgd offset in bytes */
+	i_dsrl(p, tmp, tmp, 16-3); 		/* get pgd offset in bytes */
+
 	i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
 	i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
 	i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
@@ -1087,6 +1097,11 @@ static __init void build_adjust_context(
 	case CPU_VR4133:
 		shift += 2;
 		break;
+	case CPU_20KC:
+	case CPU_25KF:
+	case CPU_5KC:
+		shift  = PAGE_SHIFT - 12;
+		break;
 
 	default:
 		break;
@@ -1811,7 +1826,7 @@ void __init build_tlb_refill_handler(voi
 	default:
 		build_r4000_tlb_refill_handler();
 		if (!run_once) {
-			build_r4000_tlb_load_handler();
+ 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
 			run_once++;
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 6ed1151..64cc068 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,6 +34,14 @@ #endif
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
 
+/* 
+ * Since asm-offsets.c does not work for more than 15 bit values,
+ * we defines these here.
+ */
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define _PAGE_SIZE      0x10000
+#define _THREAD_SIZE    0x10000 
+#endif
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index 582c1fe..af121c6 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -48,7 +48,7 @@ static inline pgd_t *pgd_alloc(struct mm
 
 	ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
 	if (ret) {
-		init = pgd_offset(&init_mm, 0);
+		init = pgd_offset(&init_mm, 0UL);
 		pgd_init((unsigned long)ret);
 		memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
 		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h
index 9ce72bd..05a0e66 100644
--- a/include/asm-mips/pgtable-64.h
+++ b/include/asm-mips/pgtable-64.h
@@ -174,7 +174,7 @@ #define __pud_offset(address)	(((address
 #define __pmd_offset(address)	pmd_index(address)
 
 /* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, 0)
+#define pgd_offset_k(address) pgd_offset(&init_mm, 0UL)
 
 #define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 #define pmd_index(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2] 64K page size
  2006-08-25 14:42 [PATCH 2] 64K page size Peter Watkins
@ 2006-08-25 15:04 ` Ralf Baechle
  2006-08-25 15:21 ` Thiemo Seufer
  1 sibling, 0 replies; 4+ messages in thread
From: Ralf Baechle @ 2006-08-25 15:04 UTC (permalink / raw)
  To: Peter Watkins; +Cc: linux-mips, Jonathan Day

On Fri, Aug 25, 2006 at 10:42:41AM -0400, Peter Watkins wrote:

> Question: Is there an SMP malta board?

A CoreFPGA 2 or 3 card with a 34K bitfile is as close as you can get.
The 34K would run either run a VSMP kernel which is a hyperthreading-like
dual-processor kernel or an SMTC kernel which is uses the 34K's fancier
multithreading features to implement upto 5 processors.

Of course the CoreFPGA cards being an FPGA CPU card allows you to roll
your own stuff ;-)

  Ralf

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2] 64K page size
  2006-08-25 14:42 [PATCH 2] 64K page size Peter Watkins
  2006-08-25 15:04 ` Ralf Baechle
@ 2006-08-25 15:21 ` Thiemo Seufer
  2006-08-29 17:27   ` [PATCH 3] " Peter Watkins
  1 sibling, 1 reply; 4+ messages in thread
From: Thiemo Seufer @ 2006-08-25 15:21 UTC (permalink / raw)
  To: Peter Watkins; +Cc: linux-mips, Ralf Baechle, Jonathan Day

Peter Watkins wrote:
> Hello,
> 
> Attached is the rest of the 64K page patch. It's been tested 
> uniprocessor on Malta 20KC and 25KF. It also runs on a 6-way SMP 
> functional simulator containing 5KF's. Ran tests with 16K and 64K page 
> size.
> 
> Question: Is there an SMP malta board?

You mean a SMP core card? None I heard of.

> There are 2 areas which could use improvement:
> 
> (1) Because 64K is larger than a 15 bit immediate operand, I could not 
> get the asm-offsets mechanism to produce the correct constants. So I 
> enlisted a fairly gruesome hack of using #define's for _PAGE_SIZE and 
> _THREAD_SIZE, for that page size. Hopefully someone has a better idea.
> 
> (2) In tlbex.c:build_adjust_context(), I suspect the change for shift = 
> PAGE_SHIFT - 12 should be more generally true, rather than just for the 
> CPU's mentioned in the case statement.

It should be added to the initial shift calculation instead, i suspect
it will break 32bit kernels elsewise. It should be generally the same
for all CPUs with r4k-style TLBs.

> I was conservative there because 
> I'm not familiar with the CPU_VR41* machines. Hopefully someone more 
> intimate with that code can comment.

The vr41xx has a different/broken page mask in order to support 1k pages
(which aren't used by linux). The shift += 2 fixes this up.

[snip]
> index c06f63e..c9de17c 100644
> --- a/arch/mips/kernel/head.S
> +++ b/arch/mips/kernel/head.S
> @@ -190,7 +190,12 @@ #endif /* CONFIG_MIPS_MT_SMTC */
>  
>  	MTC0		zero, CP0_CONTEXT	# clear context register
>  	PTR_LA		$28, init_thread_union
> +#ifdef CONFIG_PAGE_SIZE_64KB
> +	PTR_ADDIU	sp, $28, (_THREAD_SIZE - 32)/2
> +	PTR_ADDIU	sp,  sp, (_THREAD_SIZE - 32)/2
> +#else
>  	PTR_ADDIU	sp, $28, _THREAD_SIZE - 32
> +#endif

A PTR_LI ... ; PTR_ADDU sequence would be better, without an #ifdef.
This isn't a critical path of execution, and one day we might go for
even bigger pagesizes. Likewise for the other doubled addiu in this
patch.

[snip]
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 375e099..bf093aa 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -97,6 +97,8 @@ #define FUNC_SH		0
>  #define SET_MASK	0x7
>  #define SET_SH		0
>  
> +#define OP_ERET		0x42000018
> +
>  enum opcode {
>  	insn_invalid,
>  	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
> @@ -631,6 +633,9 @@ static __init void copy_handler(struct r
>  static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel,
>  							  u32 *addr)
>  {
> +	if (*addr == OP_ERET)
> +		return 1;
> +

Why? Eret has no BD slot.

>  	for (; rel->lab != label_invalid; rel++) {
>  		if (rel->addr == addr
>  		    && (rel->type == R_MIPS_PC16
> @@ -996,7 +1001,12 @@ #else
>  #endif
>  
>  	l_vmalloc_done(l, *p);
> -	i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */
> +
> +	/* Want PGDIR_SHIFT-3 here, but break it into two ops so we don't
> +	 * exceed the max shift amount of 31 with large page sizes. */
> +	i_dsrl(p, tmp, tmp, PGDIR_SHIFT-16);   	/* get pgd offset in bytes */
> +	i_dsrl(p, tmp, tmp, 16-3); 		/* get pgd offset in bytes */

This cries for a single i_dsrl32 for the large page case.

> +
>  	i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
>  	i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
>  	i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
> @@ -1087,6 +1097,11 @@ static __init void build_adjust_context(
>  	case CPU_VR4133:
>  		shift += 2;
>  		break;
> +	case CPU_20KC:
> +	case CPU_25KF:
> +	case CPU_5KC:
> +		shift  = PAGE_SHIFT - 12;
> +		break;

As said, should be done for all CPUs. (This will also fix the vr41xx
case, just in case somebody is crazy enough to go for large pages
on his PDA. :-)


Thiemo

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 3] 64K page size
  2006-08-25 15:21 ` Thiemo Seufer
@ 2006-08-29 17:27   ` Peter Watkins
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Watkins @ 2006-08-29 17:27 UTC (permalink / raw)
  To: Thiemo Seufer; +Cc: linux-mips, Ralf Baechle, Jonathan Day

[-- Attachment #1: Type: text/plain, Size: 238 bytes --]

Hello again,

This patch incorporates all of Thiemo's suggestions.

Basic retesting with 4K, 16K, and 64K pages on Malta 20KC and 25KF, and 
an SMP simulator.

FWIW, some of these changes are required to get 16K pages working.

- Peter



[-- Attachment #2: patch-pagesize1-2.6.18-rc1.txt --]
[-- Type: text/plain, Size: 9955 bytes --]

diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ec28077..07b6566 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -99,7 +99,10 @@ void output_thread_info_defines(void)
 	offset("#define TI_RESTART_BLOCK   ", struct thread_info, restart_block);
 	offset("#define TI_TP_VALUE	   ", struct thread_info, tp_value);
 	constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
+#ifndef CONFIG_PAGE_SIZE_64KB
+	/* See comment in page.h */
 	constant("#define _THREAD_SIZE       ", THREAD_SIZE);
+#endif
 	constant("#define _THREAD_MASK       ", THREAD_MASK);
 	linefeed;
 }
@@ -219,7 +222,10 @@ void output_mm_defines(void)
 	offset("#define MM_PGD        ", struct mm_struct, pgd);
 	offset("#define MM_CONTEXT    ", struct mm_struct, context);
 	linefeed;
+#ifndef CONFIG_PAGE_SIZE_64KB
+	/* See comment in page.h */
 	constant("#define _PAGE_SIZE     ", PAGE_SIZE);
+#endif
 	constant("#define _PAGE_SHIFT    ", PAGE_SHIFT);
 	linefeed;
 	constant("#define _PGD_T_SIZE    ", sizeof(pgd_t));
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index c06f63e..ace4ba6 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -190,7 +190,8 @@ #endif /* CONFIG_MIPS_MT_SMTC */
 
 	MTC0		zero, CP0_CONTEXT	# clear context register
 	PTR_LA		$28, init_thread_union
-	PTR_ADDIU	sp, $28, _THREAD_SIZE - 32
+	PTR_LI		sp, _THREAD_SIZE - 32
+	PTR_ADDU	sp, $28
 	set_saved_sp	sp, t0, t1
 	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
 
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index d5c8b82..839867e 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -85,7 +85,8 @@ #endif
 	move	$28, a2
 	cpu_restore_nonscratch a1
 
-	PTR_ADDIU	t0, $28, _THREAD_SIZE - 32
+	PTR_LI		t0, _THREAD_SIZE - 32
+	PTR_ADDU	t0, $28
 	set_saved_sp	t0, t1, t2
 #ifdef CONFIG_MIPS_MT_SMTC
 	/* Read-modify-writes of Status must be atomic on a VPE */
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 0bb9cd8..ad7d6ff 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -1,6 +1,10 @@
 #include <asm/asm-offsets.h>
 #include <asm-generic/vmlinux.lds.h>
 
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define _PAGE_SIZE	0x10000
+#endif
+
 #undef mips
 #define mips mips
 OUTPUT_ARCH(mips)
@@ -50,6 +54,7 @@ #endif
   /* writeable */
   .data : {			/* Data */
     . = . + DATAOFFSET;		/* for CONFIG_MAPPED_KERNEL */
+    . = ALIGN(_PAGE_SIZE);
     *(.data.init_task)
 
     *(.data)
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
index 6db44c7..cc6fd23 100644
--- a/arch/mips/lib-64/dump_tlb.c
+++ b/arch/mips/lib-64/dump_tlb.c
@@ -147,7 +147,7 @@ void dump_list_process(struct task_struc
 	printk("Addr                 == %08lx\n", addr);
 	printk("tasks->mm.pgd        == %08lx\n", (unsigned long) t->mm->pgd);
 
-	page_dir = pgd_offset(t->mm, 0);
+	page_dir = pgd_offset(t->mm, 0UL);
 	printk("page_dir == %016lx\n", (unsigned long) page_dir);
 
 	pgd = pgd_offset(t->mm, addr);
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index be80c5d..eeed944 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -176,7 +176,7 @@ unsigned long __init prom_free_prom_memo
 		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
 
-		addr = boot_mem_map.map[i].addr;
+		addr = PAGE_ALIGN(boot_mem_map.map[i].addr);
 		while (addr < boot_mem_map.map[i].addr
 			      + boot_mem_map.map[i].size) {
 			ClearPageReserved(virt_to_page(__va(addr)));
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index b7c7492..b173a8d 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -270,6 +270,20 @@ static inline void build_addiu_a2_a0(uns
 	emit_instruction(mi);
 }
 
+static inline void build_addiu_a2(unsigned long offset)
+{
+	union mips_instruction mi;
+
+	BUG_ON(offset > 0x7fff);
+
+	mi.i_format.opcode     = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
+	mi.i_format.rs         = 6;		/* $a2 */
+	mi.i_format.rt         = 6;		/* $a2 */
+	mi.i_format.simmediate = offset;
+
+	emit_instruction(mi);
+}
+
 static inline void build_addiu_a1(unsigned long offset)
 {
 	union mips_instruction mi;
@@ -369,7 +383,14 @@ void __init build_clear_page(void)
 		}
 	}
 
-	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0));
+        unsigned long off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0);
+	if (off > 0x7fff) {
+	    build_addiu_a2_a0(off>>1);
+	    build_addiu_a2(off>>1);
+	}
+	else {
+	    build_addiu_a2_a0(off);
+	}
 
 	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
@@ -425,7 +446,14 @@ void __init build_copy_page(void)
 	store_offset = load_offset = 0;
 	instruction_pending = 0;
 
-	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0));
+	unsigned long off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0);
+	if (off > 0x7fff) {
+	    build_addiu_a2_a0(off>>1);
+	    build_addiu_a2(off>>1);
+	}
+	else {
+	    build_addiu_a2_a0(off);
+	}
 
 	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 375e099..d1035ca 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -102,7 +102,7 @@ enum opcode {
 	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
 	insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
 	insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
-	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
+	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
 	insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
 	insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
 	insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
@@ -145,6 +145,7 @@ static __initdata struct insn insn_table
 	{ insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
 	{ insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
 	{ insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE },
+	{ insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
 	{ insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD },
 	{ insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 },
 	{ insn_j, M(j_op,0,0,0,0,0), JIMM },
@@ -385,6 +386,7 @@ I_u2u1u3(_dsll);
 I_u2u1u3(_dsll32);
 I_u2u1u3(_dsra);
 I_u2u1u3(_dsrl);
+I_u2u1u3(_dsrl32);
 I_u3u1u2(_dsubu);
 I_0(_eret);
 I_u1(_j);
@@ -996,7 +998,15 @@ #else
 #endif
 
 	l_vmalloc_done(l, *p);
-	i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */
+
+	/* Want PGDIR_SHIFT-3 here, but handle shifts greater than 32
+	 * bits for large page sizes. */
+#ifdef CONFIG_PAGE_SIZE_4KB
+	i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3);   		/* get pgd offset in bytes */
+#else
+	i_dsrl32(p, tmp, tmp, PGDIR_SHIFT-3-32);   	/* get pgd offset in bytes */
+#endif
+
 	i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
 	i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
 	i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
@@ -1073,7 +1083,7 @@ #endif /* !CONFIG_64BIT */
 
 static __init void build_adjust_context(u32 **p, unsigned int ctx)
 {
-	unsigned int shift = 4 - (PTE_T_LOG2 + 1);
+	unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12;
 	unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1);
 
 	switch (current_cpu_data.cputype) {
@@ -1811,7 +1821,7 @@ void __init build_tlb_refill_handler(voi
 	default:
 		build_r4000_tlb_refill_handler();
 		if (!run_once) {
-			build_r4000_tlb_load_handler();
+ 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
 			run_once++;
diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h
index e3038a4..838eb31 100644
--- a/include/asm-mips/asm.h
+++ b/include/asm-mips/asm.h
@@ -344,6 +344,7 @@ #define PTR_SUBU	subu
 #define PTR_L		lw
 #define PTR_S		sw
 #define PTR_LA		la
+#define PTR_LI		li
 #define PTR_SLL		sll
 #define PTR_SLLV	sllv
 #define PTR_SRL		srl
@@ -368,6 +369,7 @@ #define PTR_SUBU	dsubu
 #define PTR_L		ld
 #define PTR_S		sd
 #define PTR_LA		dla
+#define PTR_LI		dli
 #define PTR_SLL		dsll
 #define PTR_SLLV	dsllv
 #define PTR_SRL		dsrl
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 6ed1151..be9bb68 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,6 +34,14 @@ #endif
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
 
+/* 
+ * Since asm-offsets.c does not work for more than 15 bit values,
+ * we define these here.
+ */
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define _PAGE_SIZE      0x10000
+#define _THREAD_SIZE    0x10000 
+#endif
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index 582c1fe..af121c6 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -48,7 +48,7 @@ static inline pgd_t *pgd_alloc(struct mm
 
 	ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
 	if (ret) {
-		init = pgd_offset(&init_mm, 0);
+		init = pgd_offset(&init_mm, 0UL);
 		pgd_init((unsigned long)ret);
 		memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
 		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h
index 9ce72bd..05a0e66 100644
--- a/include/asm-mips/pgtable-64.h
+++ b/include/asm-mips/pgtable-64.h
@@ -174,7 +174,7 @@ #define __pud_offset(address)	(((address
 #define __pmd_offset(address)	pmd_index(address)
 
 /* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, 0)
+#define pgd_offset_k(address) pgd_offset(&init_mm, 0UL)
 
 #define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 #define pmd_index(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-08-29 17:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-25 14:42 [PATCH 2] 64K page size Peter Watkins
2006-08-25 15:04 ` Ralf Baechle
2006-08-25 15:21 ` Thiemo Seufer
2006-08-29 17:27   ` [PATCH 3] " Peter Watkins

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox