[PARISC] Further work for multiple page sizes
authorHelge Deller <deller@parisc-linux.org>
Thu, 20 Apr 2006 20:40:23 +0000 (20:40 +0000)
committerKyle McMartin <kyle@hera.kernel.org>
Fri, 21 Apr 2006 22:20:34 +0000 (22:20 +0000)
More work towards supporing multiple page sizes on 64-bit. Convert
some assumptions that 64bit uses 3 level page tables into testing
PT_NLEVELS. Also some BUG() to BUG_ON() conversions and some cleanups
to assembler.

Signed-off-by: Helge Deller <deller@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
arch/parisc/Kconfig
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/head.S
arch/parisc/kernel/init_task.c
arch/parisc/kernel/pacache.S
arch/parisc/kernel/syscall.S
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
include/asm-parisc/page.h
include/asm-parisc/pgtable.h

index 19f911c5dd58dce00114fc4ed397c7445952a6f8..910fb3afc0b5c91e40c24a030a7b1b8241af5d60 100644 (file)
@@ -138,6 +138,37 @@ config 64BIT
          enable this option otherwise. The 64bit kernel is significantly bigger
          and slower than the 32bit one.
 
+choice
+       prompt "Kernel page size"
+       default PARISC_PAGE_SIZE_4KB  if !64BIT
+       default PARISC_PAGE_SIZE_4KB  if 64BIT
+#      default PARISC_PAGE_SIZE_16KB if 64BIT
+
+config PARISC_PAGE_SIZE_4KB
+       bool "4KB"
+       help
+         This lets you select the page size of the kernel.  For best
+         performance, a page size of 16KB is recommended.  For best
+         compatibility with 32bit applications, a page size of 4KB should be
+         selected (the vast majority of 32bit binaries work perfectly fine
+         with a larger page size).
+
+         4KB                For best 32bit compatibility
+         16KB               For best performance
+         64KB               For best performance, might give more overhead.
+
+         If you don't know what to do, choose 4KB.
+
+config PARISC_PAGE_SIZE_16KB
+       bool "16KB (EXPERIMENTAL)"
+       depends on PA8X00 && EXPERIMENTAL
+
+config PARISC_PAGE_SIZE_64KB
+       bool "64KB (EXPERIMENTAL)"
+       depends on PA8X00 && EXPERIMENTAL
+
+endchoice
+
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
index e23c4e1e3a25c5dd8d2e73dbfe8e47bf49ade25c..c11a5bc7c067220af7ce3c552261f53e2fa93010 100644 (file)
@@ -288,8 +288,11 @@ int main(void)
        DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
        DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE);
        DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
+       DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT);
        DEFINE(ASM_PT_INITIAL, PT_INITIAL);
        DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
+       DEFINE(ASM_PAGE_SIZE_DIV64, PAGE_SIZE/64);
+       DEFINE(ASM_PAGE_SIZE_DIV128, PAGE_SIZE/128);
        BLANK();
        DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
        DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
index 7c95d7663c299980913a4c56ff144e226dac74fc..d9e53cf0372b313a368b886cc062fc33b419e5ab 100644 (file)
         * all ILP32 processes and all the kernel for machines with
         * under 4GB of memory) */
        .macro          L3_ptep pgd,pte,index,va,fault
+#if PT_NLEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
        extrd,u         \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
        copy            %r0,\pte
-       extrd,u,*=      \va,31,32,%r0
+       extrd,u,*=      \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
        ldw,s           \index(\pgd),\pgd
-       extrd,u,*=      \va,31,32,%r0
+       extrd,u,*=      \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
        bb,>=,n         \pgd,_PxD_PRESENT_BIT,\fault
-       extrd,u,*=      \va,31,32,%r0
+       extrd,u,*=      \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
        shld            \pgd,PxD_VALUE_SHIFT,\index
-       extrd,u,*=      \va,31,32,%r0
+       extrd,u,*=      \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
        copy            \index,\pgd
-       extrd,u,*<>     \va,31,32,%r0
+       extrd,u,*<>     \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
        ldo             ASM_PGD_PMD_OFFSET(\pgd),\pgd
+#endif
        L2_ptep         \pgd,\pte,\index,\va,\fault
        .endm
 
        extrd,u,*=      \pte,_PAGE_GATEWAY_BIT+32,1,%r0
        depd            %r0,11,2,\prot  /* If Gateway, Set PL2 to 0 */
 
-       /* Get rid of prot bits and convert to page addr for iitlbt and idtlbt */
+       /* Enforce uncacheable pages.
+        * This should ONLY be use for MMIO on PA 2.0 machines.
+        * Memory/DMA is cache coherent on all PA2.0 machines we support
+        * (that means T-class is NOT supported) and the memory controllers
+        * on most of those machines only handles cache transactions.
+        */
+       extrd,u,*=      \pte,_PAGE_NO_CACHE_BIT+32,1,%r0
+       depi            1,12,1,\prot
 
-       depd            %r0,63,PAGE_SHIFT,\pte
-       extrd,s         \pte,(63-PAGE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+       /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
+       extrd,u         \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+       depdi           _PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte
        .endm
 
        /* Identical macro to make_insert_tlb above, except it
 
        /* Get rid of prot bits and convert to page addr for iitlba */
 
-       depi            0,31,PAGE_SHIFT,\pte
+       depi            _PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte
        extru           \pte,24,25,\pte
-
        .endm
 
        /* This is for ILP32 PA2.0 only.  The TLB insertion needs
@@ -1201,10 +1210,9 @@ intr_save:
         */
 
        /* adjust isr/ior. */
-
-       extrd,u         %r16,63,7,%r1    /* get high bits from isr for ior */
-       depd            %r1,31,7,%r17    /* deposit them into ior */
-       depdi           0,63,7,%r16      /* clear them from isr */
+       extrd,u         %r16,63,SPACEID_SHIFT,%r1       /* get high bits from isr for ior */
+       depd            %r1,31,SPACEID_SHIFT,%r17       /* deposit them into ior */
+       depdi           0,63,SPACEID_SHIFT,%r16         /* clear them from isr */
 #endif
        STREG           %r16, PT_ISR(%r29)
        STREG           %r17, PT_IOR(%r29)
index 0b47afc2069038a8d9774e085762eb90e2db882f..3e79e62f7b0b24f38609a1f5ba609ee1fca1057d 100644 (file)
@@ -76,16 +76,16 @@ $bss_loop:
        mtctl           %r4,%cr24       /* Initialize kernel root pointer */
        mtctl           %r4,%cr25       /* Initialize user root pointer */
 
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
        /* Set pmd in pgd */
        load32          PA(pmd0),%r5
        shrd            %r5,PxD_VALUE_SHIFT,%r3 
-        ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3     
+       ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
        stw             %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
        ldo             ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
 #else
        /* 2-level page table, so pmd == pgd */
-        ldo             ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
+       ldo             ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
 #endif
 
        /* Fill in pmd with enough pte directories */
@@ -99,7 +99,7 @@ $bss_loop:
        stw             %r3,0(%r4)
        ldo             (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
        addib,>         -1,%r1,1b
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
        ldo             ASM_PMD_ENTRY_SIZE(%r4),%r4
 #else
        ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
@@ -107,13 +107,14 @@ $bss_loop:
 
 
        /* Now initialize the PTEs themselves */
-       ldo             _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+       ldo             0+_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+       ldi             (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
        load32          PA(pg0),%r1
 
 $pgt_fill_loop:
        STREGM          %r3,ASM_PTE_ENTRY_SIZE(%r1)
-       ldo             ASM_PAGE_SIZE(%r3),%r3
-       bb,>=           %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
+       ldo             (1<<PFN_PTE_SHIFT)(%r3),%r3 /* add one PFN */
+       addib,>         -1,%r11,$pgt_fill_loop
        nop
 
        /* Load the return address...er...crash 'n burn */
index 7e898fd6441536d82ef876ac99e6f2bd5d7983a7..8384bf9cecd240c77ae5f2b9f4ec6c2e1ced5eab 100644 (file)
@@ -53,17 +53,17 @@ union thread_union init_thread_union
        __attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
                { INIT_THREAD_INFO(init_task) };
 
-#ifdef __LP64__
+#if PT_NLEVELS == 3
 /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
  * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
  * guarantee that global objects will be laid out in memory in the same order 
  * as the order of declaration, so put these in different sections and use
  * the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
-
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data.vm0.pmd"), aligned(PAGE_SIZE)));
 #endif
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte")))  = { {0}, };
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data.vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data.vm0.pte"), aligned(PAGE_SIZE)));
 
 /*
  * Initial task structure.
index 7a4f07e8d3c301fafa65e9a767ad151ce9d35f33..f600556414d1a3afb0e7ae5d96f95832e3da5e1a 100644 (file)
@@ -65,7 +65,7 @@ flush_tlb_all_local:
         */
 
        /* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
-       rsm     PSW_SM_I, %r19          /* save I-bit state */
+       rsm             PSW_SM_I, %r19          /* save I-bit state */
        load32          PA(1f), %r1
        nop
        nop
@@ -84,8 +84,7 @@ flush_tlb_all_local:
        rfi
        nop
 
-1:      ldil           L%PA(cache_info), %r1
-       ldo             R%PA(cache_info)(%r1), %r1
+1:      load32         PA(cache_info), %r1
 
        /* Flush Instruction Tlb */
 
@@ -212,8 +211,7 @@ flush_instruction_cache_local:
        .entry
 
        mtsp            %r0, %sr1
-       ldil            L%cache_info, %r1
-       ldo             R%cache_info(%r1), %r1
+       load32          cache_info, %r1
 
        /* Flush Instruction Cache */
 
@@ -254,8 +252,7 @@ flush_data_cache_local:
        .entry
 
        mtsp            %r0, %sr1
-       ldil            L%cache_info, %r1
-       ldo             R%cache_info(%r1), %r1
+       load32          cache_info, %r1
 
        /* Flush Data Cache */
 
@@ -303,7 +300,8 @@ copy_user_page_asm:
         */
 
        ldd             0(%r25), %r19
-       ldi             32, %r1                 /* PAGE_SIZE/128 == 32 */
+       ldi             ASM_PAGE_SIZE_DIV128, %r1
+
        ldw             64(%r25), %r0           /* prefetch 1 cacheline ahead */
        ldw             128(%r25), %r0          /* prefetch 2 */
 
@@ -368,7 +366,7 @@ copy_user_page_asm:
         * use ldd/std on a 32 bit kernel.
         */
        ldw             0(%r25), %r19
-       ldi             64, %r1         /* PAGE_SIZE/64 == 64 */
+       ldi             ASM_PAGE_SIZE_DIV64, %r1
 
 1:
        ldw             4(%r25), %r20
@@ -461,6 +459,7 @@ copy_user_page_asm:
        sub             %r25, %r1, %r23         /* move physical addr into non shadowed reg */
 
        ldil            L%(TMPALIAS_MAP_START), %r28
+       /* FIXME for different page sizes != 4k */
 #ifdef CONFIG_64BIT
        extrd,u         %r26,56,32, %r26                /* convert phys addr to tlb insert format */
        extrd,u         %r23,56,32, %r23                /* convert phys addr to tlb insert format */
@@ -551,6 +550,7 @@ __clear_user_page_asm:
 #ifdef CONFIG_64BIT
 #if (TMPALIAS_MAP_START >= 0x80000000)
        depdi           0, 31,32, %r28          /* clear any sign extension */
+       /* FIXME: page size dependend */
 #endif
        extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
        depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
@@ -566,10 +566,10 @@ __clear_user_page_asm:
        pdtlb           0(%r28)
 
 #ifdef CONFIG_64BIT
-       ldi             32, %r1                 /* PAGE_SIZE/128 == 32 */
+       ldi             ASM_PAGE_SIZE_DIV128, %r1
 
        /* PREFETCH (Write) has not (yet) been proven to help here */
-/* #define     PREFETCHW_OP    ldd             256(%0), %r0 */
+       /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
 
 1:     std             %r0, 0(%r28)
        std             %r0, 8(%r28)
@@ -591,8 +591,7 @@ __clear_user_page_asm:
        ldo             128(%r28), %r28
 
 #else  /* ! CONFIG_64BIT */
-
-       ldi             64, %r1                 /* PAGE_SIZE/64 == 64 */
+       ldi             ASM_PAGE_SIZE_DIV64, %r1
 
 1:
        stw             %r0, 0(%r28)
index af88afef41bdc029d446e43038d3dd4578b7b18e..479d9a017cd1ff3e19ea90c30f579a7b64f7acbb 100644 (file)
@@ -55,7 +55,7 @@
         * pointers.
         */
 
-       .align 4096
+       .align ASM_PAGE_SIZE
 linux_gateway_page:
 
         /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
@@ -632,7 +632,7 @@ cas_action:
 end_compare_and_swap:
 
        /* Make sure nothing else is placed on this page */
-       .align 4096
+       .align ASM_PAGE_SIZE
        .export end_linux_gateway_page
 end_linux_gateway_page:
 
@@ -652,7 +652,7 @@ end_linux_gateway_page:
 
        .section .rodata,"a"
 
-       .align 4096
+       .align ASM_PAGE_SIZE
        /* Light-weight-syscall table */
        /* Start of lws table. */
        .export lws_table
@@ -662,14 +662,14 @@ lws_table:
        LWS_ENTRY(compare_and_swap64)   /* 1 - ELF64 Atomic compare and swap */
        /* End of lws table */
 
-       .align 4096
+       .align ASM_PAGE_SIZE
        .export sys_call_table
 .Lsys_call_table:
 sys_call_table:
 #include "syscall_table.S"
 
 #ifdef CONFIG_64BIT
-       .align 4096
+       .align ASM_PAGE_SIZE
        .export sys_call_table64
 .Lsys_call_table64:
 sys_call_table64:
index 6d6436a6b624e2da48c0edd38780b9fed2b396a6..94dcc03a28edb024cfdf04c459a3485436d8290e 100644 (file)
@@ -6,6 +6,7 @@
  *    Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *    Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
+ *    Copyright (C) 2006 Helge Deller <deller@gmx.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -27,6 +28,7 @@
 /* needed for the processor specific cache alignment size */   
 #include <asm/cache.h>
 #include <asm/page.h>
+#include <asm/asm-offsets.h>
        
 /* ld script to make hppa Linux kernel */
 #ifndef CONFIG_64BIT
@@ -68,7 +70,7 @@ SECTIONS
   RODATA
 
   /* writeable */
-  . = ALIGN(4096);             /* Make sure this is page aligned so
+  . = ALIGN(ASM_PAGE_SIZE);    /* Make sure this is page aligned so
                                   that we can properly leave these
                                   as writable */
   data_start = .;
@@ -81,23 +83,17 @@ SECTIONS
   __start___unwind = .;         /* unwind info */
   .PARISC.unwind : { *(.PARISC.unwind) }
   __stop___unwind = .;
+
+  /* rarely changed data like cpu maps */
+  . = ALIGN(16);
+  .data.read_mostly : { *(.data.read_mostly) }
+
+  . = ALIGN(L1_CACHE_BYTES);
   .data : {                    /* Data */
        *(.data)
-       *(.data.vm0.pmd)
-       *(.data.vm0.pgd)
-       *(.data.vm0.pte)
        CONSTRUCTORS
        }
 
-  . = ALIGN(4096);
-  /* nosave data is really only used for software suspend...it's here
-   * just in case we ever implement it */
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
-
   . = ALIGN(L1_CACHE_BYTES);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
@@ -105,12 +101,29 @@ SECTIONS
   . = ALIGN(16);
   .data.lock_aligned : { *(.data.lock_aligned) }
 
-  /* rarely changed data like cpu maps */
-  . = ALIGN(16);
-  .data.read_mostly : { *(.data.read_mostly) }
+  . = ALIGN(ASM_PAGE_SIZE);
+  /* nosave data is really only used for software suspend...it's here
+   * just in case we ever implement it */
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(ASM_PAGE_SIZE);
+  __nosave_end = .;
 
   _edata = .;                  /* End of data section */
 
+  __bss_start = .;             /* BSS */
+  /* page table entries need to be PAGE_SIZE aligned */
+  . = ALIGN(ASM_PAGE_SIZE);
+  .data.vmpages : {
+       *(.data.vm0.pmd)
+       *(.data.vm0.pgd)
+       *(.data.vm0.pte)
+       }
+  .bss : { *(.bss) *(COMMON) }
+  __bss_stop = .;
+
+
+  /* assembler code expects init_task to be 16k aligned */
   . = ALIGN(16384);            /* init_task */
   .data.init_task : { *(.data.init_task) }
 
@@ -126,6 +139,7 @@ SECTIONS
   .dlt : { *(.dlt) }
 #endif
 
+  /* reserve space for interrupt stack by aligning __init* to 16k */
   . = ALIGN(16384);
   __init_begin = .;
   .init.text : { 
@@ -166,7 +180,7 @@ SECTIONS
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
   .exit.data : { *(.exit.data) }
-  . = ALIGN(4096);
+  . = ALIGN(ASM_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
@@ -174,14 +188,10 @@ SECTIONS
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(ASM_PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
        
-  __bss_start = .;             /* BSS */
-  .bss : { *(.bss) *(COMMON) }
-  __bss_stop = .; 
-
   _end = . ;
 
   /* Sections to be discarded */
index 3796be67cd53cc9f6dfe433d89020261ca129a9f..6317125626569ec713b5471adf07fb9b50b260ad 100644 (file)
@@ -6,6 +6,7 @@
  *    changed by Philipp Rumpf
  *  Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  *  Copyright 2004 Randolph Chung (tausq@debian.org)
+ *  Copyright 2006 Helge Deller (deller@gmx.de)
  *
  */
 
@@ -371,8 +372,8 @@ static void __init setup_bootmem(void)
 
 void free_initmem(void)
 {
-       unsigned long addr;
-       
+       unsigned long addr, init_begin, init_end;
+
        printk(KERN_INFO "Freeing unused kernel memory: ");
 
 #ifdef CONFIG_DEBUG_KERNEL
@@ -395,8 +396,11 @@ void free_initmem(void)
        local_irq_enable();
 #endif
        
-       addr = (unsigned long)(&__init_begin);
-       for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+       /* align __init_begin and __init_end to page size,
+          ignoring linker script where we might have tried to save RAM */
+       init_begin = PAGE_ALIGN((unsigned long)(&__init_begin));
+       init_end   = PAGE_ALIGN((unsigned long)(&__init_end));
+       for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
                free_page(addr);
@@ -407,7 +411,7 @@ void free_initmem(void)
        /* set up a new led state on systems shipped LED State panel */
        pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
        
-       printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
+       printk("%luk freed\n", (init_end - init_begin) >> 10);
 }
 
 
@@ -639,11 +643,13 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
                                 * Map the fault vector writable so we can
                                 * write the HPMC checksum.
                                 */
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
                                if (address >= ro_start && address < ro_end
                                                        && address != fv_addr
                                                        && address != gw_addr)
                                    pte = __mk_pte(address, PAGE_KERNEL_RO);
                                else
+#endif
                                    pte = __mk_pte(address, pgprot);
 
                                if (address >= end_paddr)
@@ -874,8 +880,7 @@ unsigned long alloc_sid(void)
                        flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
                        spin_lock(&sid_lock);
                }
-               if (free_space_ids == 0)
-                       BUG();
+               BUG_ON(free_space_ids == 0);
        }
 
        free_space_ids--;
@@ -899,8 +904,7 @@ void free_sid(unsigned long spaceid)
 
        spin_lock(&sid_lock);
 
-       if (*dirty_space_offset & (1L << index))
-           BUG(); /* attempt to free space id twice */
+       BUG_ON(*dirty_space_offset & (1L << index)); /* attempt to free space id twice */
 
        *dirty_space_offset |= (1L << index);
        dirty_space_ids++;
@@ -975,7 +979,7 @@ static void recycle_sids(void)
 
 static unsigned long recycle_ndirty;
 static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
-static unsigned int recycle_inuse = 0;
+static unsigned int recycle_inuse;
 
 void flush_tlb_all(void)
 {
@@ -984,9 +988,7 @@ void flush_tlb_all(void)
        do_recycle = 0;
        spin_lock(&sid_lock);
        if (dirty_space_ids > RECYCLE_THRESHOLD) {
-           if (recycle_inuse) {
-               BUG();  /* FIXME: Use a semaphore/wait queue here */
-           }
+           BUG_ON(recycle_inuse);  /* FIXME: Use a semaphore/wait queue here */
            get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
            recycle_inuse++;
            do_recycle++;
index 45e02aa5bf4be4e9e745c233e595227c5898fe78..c0dd461fb8f10f2c5b52aa417d4bf7421407bb13 100644 (file)
@@ -1,13 +1,30 @@
 #ifndef _PARISC_PAGE_H
 #define _PARISC_PAGE_H
 
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT     12
-#define PAGE_SIZE      (1UL << PAGE_SHIFT)
-#define PAGE_MASK      (~(PAGE_SIZE-1))
+#if !defined(__KERNEL__)
+/* this is for userspace applications (4k page size) */
+# define PAGE_SHIFT    12      /* 4k */
+# define PAGE_SIZE     (1UL << PAGE_SHIFT)
+# define PAGE_MASK     (~(PAGE_SIZE-1))
+#endif
+
 
 #ifdef __KERNEL__
 #include <linux/config.h>
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define PAGE_SHIFT    12      /* 4k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define PAGE_SHIFT    14      /* 16k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define PAGE_SHIFT    16      /* 64k */
+#else
+# error "unknown default kernel page size"
+#endif
+#define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#define PAGE_MASK      (~(PAGE_SIZE-1))
+
+
 #ifndef __ASSEMBLY__
 
 #include <asm/types.h>
index 4e34c6b44059b569b61318e6df3474115084a29c..aec089eb8b85e6e49f8d30db30c260f56eb57eb9 100644 (file)
 #define  ISTACK_SIZE  32768 /* Interrupt Stack Size */
 #define  ISTACK_ORDER 3
 
-/* This is the size of the initially mapped kernel memory (i.e. currently
- * 0 to 1<<23 == 8MB */
+/* This is the size of the initially mapped kernel memory */
 #ifdef CONFIG_64BIT
-#define KERNEL_INITIAL_ORDER   24
+#define KERNEL_INITIAL_ORDER   24      /* 0 to 1<<24 = 16MB */
 #else
-#define KERNEL_INITIAL_ORDER   23
+#define KERNEL_INITIAL_ORDER   23      /* 0 to 1<<23 = 8MB */
 #endif
 #define KERNEL_INITIAL_SIZE    (1 << KERNEL_INITIAL_ORDER)
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
 #define PT_NLEVELS     3
 #define PGD_ORDER      1 /* Number of pages per pgd */
 #define PMD_ORDER      1 /* Number of pages per pmd */
 #define MAX_ADDRBITS   (PGDIR_SHIFT + BITS_PER_PGD)
 #define MAX_ADDRESS    (1UL << MAX_ADDRBITS)
 
-#define SPACEID_SHIFT (MAX_ADDRBITS - 32)
+#define SPACEID_SHIFT  (MAX_ADDRBITS - 32)
 
 /* This calculates the number of initial pages we need for the initial
  * page tables */
-#define PT_INITIAL     (1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#if (KERNEL_INITIAL_ORDER) >= (PMD_SHIFT)
+# define PT_INITIAL    (1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#else
+# define PT_INITIAL    (1)  /* all initial PTEs fit into one page */
+#endif
 
 /*
  * pgd entries used up by user/kernel:
@@ -160,6 +163,10 @@ extern  void *vmalloc_start;
  * to zero */
 #define PTE_SHIFT              xlate_pabit(_PAGE_USER_BIT)
 
+/* PFN_PTE_SHIFT defines the shift of a PTE value to access the PFN field */
+#define PFN_PTE_SHIFT          12
+
+
 /* this is how many bits may be used by the file functions */
 #define PTE_FILE_MAX_BITS      (BITS_PER_LONG - PTE_SHIFT)
 
@@ -188,7 +195,8 @@ extern  void *vmalloc_start;
 /* The pgd/pmd contains a ptr (in phys addr space); since all pgds/pmds
  * are page-aligned, we don't care about the PAGE_OFFSET bits, except
  * for a few meta-information bits, so we shift the address to be
- * able to effectively address 40-bits of physical address space. */
+ * able to effectively address 40/42/44-bits of physical address space
+ * depending on 4k/16k/64k PAGE_SIZE */
 #define _PxD_PRESENT_BIT   31
 #define _PxD_ATTACHED_BIT  30
 #define _PxD_VALID_BIT     29
@@ -198,7 +206,7 @@ extern  void *vmalloc_start;
 #define PxD_FLAG_VALID    (1 << xlate_pabit(_PxD_VALID_BIT))
 #define PxD_FLAG_MASK     (0xf)
 #define PxD_FLAG_SHIFT    (4)
-#define PxD_VALUE_SHIFT   (8)
+#define PxD_VALUE_SHIFT   (8) /* (PAGE_SHIFT-PxD_FLAG_SHIFT) */
 
 #ifndef __ASSEMBLY__
 
@@ -246,6 +254,7 @@ extern  void *vmalloc_start;
 #define __S110  PAGE_RWX
 #define __S111  PAGE_RWX
 
+
 extern pgd_t swapper_pg_dir[]; /* declared in init_task.c */
 
 /* initial page tables for 0-8MB for kernel */
@@ -272,7 +281,7 @@ extern unsigned long *empty_zero_page;
 #define pgd_flag(x)    (pgd_val(x) & PxD_FLAG_MASK)
 #define pgd_address(x) ((unsigned long)(pgd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
 
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
 /* The first entry of the permanent pmd is not there if it contains
  * the gateway marker */
 #define pmd_none(x)    (!pmd_val(x) || pmd_flag(x) == PxD_FLAG_ATTACHED)
@@ -282,7 +291,7 @@ extern unsigned long *empty_zero_page;
 #define pmd_bad(x)     (!(pmd_flag(x) & PxD_FLAG_VALID))
 #define pmd_present(x) (pmd_flag(x) & PxD_FLAG_PRESENT)
 static inline void pmd_clear(pmd_t *pmd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
        if (pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
                /* This is the entry pointing to the permanent pmd
                 * attached to the pgd; cannot clear it */
@@ -303,7 +312,7 @@ static inline void pmd_clear(pmd_t *pmd) {
 #define pgd_bad(x)      (!(pgd_flag(x) & PxD_FLAG_VALID))
 #define pgd_present(x)  (pgd_flag(x) & PxD_FLAG_PRESENT)
 static inline void pgd_clear(pgd_t *pgd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
        if(pgd_flag(*pgd) & PxD_FLAG_ATTACHED)
                /* This is the permanent pmd attached to the pgd; cannot
                 * free it */
@@ -351,7 +360,7 @@ extern inline pte_t pte_mkwrite(pte_t pte)  { pte_val(pte) |= _PAGE_WRITE; return
 ({                                                                     \
        pte_t __pte;                                                    \
                                                                        \
-       pte_val(__pte) = ((addr)+pgprot_val(pgprot));                   \
+       pte_val(__pte) = ((((addr)>>PAGE_SHIFT)<<PFN_PTE_SHIFT) + pgprot_val(pgprot));  \
                                                                        \
        __pte;                                                          \
 })
@@ -361,20 +370,16 @@ extern inline pte_t pte_mkwrite(pte_t pte)        { pte_val(pte) |= _PAGE_WRITE; return
 static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
 {
        pte_t pte;
-       pte_val(pte) = (pfn << PAGE_SHIFT) | pgprot_val(pgprot);
+       pte_val(pte) = (pfn << PFN_PTE_SHIFT) | pgprot_val(pgprot);
        return pte;
 }
 
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
-
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
 
 /* Permanent address of a page.  On parisc we don't have highmem. */
 
-#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
+#define pte_pfn(x)             (pte_val(x) >> PFN_PTE_SHIFT)
 
 #define pte_page(pte)          (pfn_to_page(pte_pfn(pte)))
 
@@ -499,6 +504,26 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
 
 #endif /* !__ASSEMBLY__ */
 
+
+/* TLB page size encoding - see table 3-1 in parisc20.pdf */
+#define _PAGE_SIZE_ENCODING_4K         0
+#define _PAGE_SIZE_ENCODING_16K        1
+#define _PAGE_SIZE_ENCODING_64K        2
+#define _PAGE_SIZE_ENCODING_256K       3
+#define _PAGE_SIZE_ENCODING_1M         4
+#define _PAGE_SIZE_ENCODING_4M         5
+#define _PAGE_SIZE_ENCODING_16M        6
+#define _PAGE_SIZE_ENCODING_64M        7
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_16K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_64K
+#endif
+
+
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
                remap_pfn_range(vma, vaddr, pfn, size, prot)