diff options
Diffstat (limited to 'arch/parisc/mm')
-rw-r--r-- | arch/parisc/mm/init.c | 64 | ||||
-rw-r--r-- | arch/parisc/mm/ioremap.c | 100 |
2 files changed, 98 insertions, 66 deletions
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 29b998e..7847ca1 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -36,9 +36,9 @@ extern char _end; /* end of BSS, defined by linker */ extern char __init_begin, __init_end; #ifdef CONFIG_DISCONTIGMEM -struct node_map_data node_data[MAX_NUMNODES]; -bootmem_data_t bmem_data[MAX_NUMNODES]; -unsigned char pfnnid_map[PFNNID_MAP_MAX]; +struct node_map_data node_data[MAX_NUMNODES] __read_mostly; +bootmem_data_t bmem_data[MAX_NUMNODES] __read_mostly; +unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; #endif static struct resource data_resource = { @@ -58,14 +58,14 @@ static struct resource pdcdata_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; -static struct resource sysram_resources[MAX_PHYSMEM_RANGES]; +static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly; /* The following array is initialized from the firmware specific * information retrieved in kernel/inventory.c. */ -physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES]; -int npmem_ranges; +physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly; +int npmem_ranges __read_mostly; #ifdef __LP64__ #define MAX_MEM (~0UL) @@ -73,7 +73,7 @@ int npmem_ranges; #define MAX_MEM (3584U*1024U*1024U) #endif /* !__LP64__ */ -static unsigned long mem_limit = MAX_MEM; +static unsigned long mem_limit __read_mostly = MAX_MEM; static void __init mem_limit_func(void) { @@ -300,6 +300,13 @@ static void __init setup_bootmem(void) max_pfn = start_pfn + npages; } + /* IOMMU is always used to access "high mem" on those boxes + * that can support enough mem that a PCI device couldn't + * directly DMA to any physical addresses. + * ISA DMA support will need to revisit this. + */ + max_low_pfn = max_pfn; + if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) { printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n"); BUG(); @@ -364,17 +371,11 @@ static void __init setup_bootmem(void) void free_initmem(void) { - /* FIXME: */ -#if 0 - printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n", - (&__init_end - &__init_begin) >> 10); - return; -#else unsigned long addr; printk(KERN_INFO "Freeing unused kernel memory: "); -#if 1 +#ifdef CONFIG_DEBUG_KERNEL /* Attempt to catch anyone trying to execute code here * by filling the page with BRK insns. * @@ -407,9 +408,21 @@ void free_initmem(void) pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE); printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10); -#endif } + +#ifdef CONFIG_DEBUG_RODATA +void mark_rodata_ro(void) +{ + extern char __start_rodata, __end_rodata; + /* rodata memory was already mapped with KERNEL_RO access rights by + pagetable_init() and map_pages(). No need to do additional stuff here */ + printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n", + (unsigned long)(&__end_rodata - &__start_rodata) >> 10); +} +#endif + + /* * Just an arbitrary offset to serve as a "hole" between mapping areas * (between top of physical memory and a potential pcxl dma mapping @@ -431,11 +444,11 @@ void free_initmem(void) #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \ & ~(VM_MAP_OFFSET-1))) -void *vmalloc_start; +void *vmalloc_start __read_mostly; EXPORT_SYMBOL(vmalloc_start); #ifdef CONFIG_PA11 -unsigned long pcxl_dma_start; +unsigned long pcxl_dma_start __read_mostly; #endif void __init mem_init(void) @@ -470,12 +483,7 @@ void __init mem_init(void) } -int do_check_pgt_cache(int low, int high) -{ - return 0; -} - -unsigned long *empty_zero_page; +unsigned long *empty_zero_page __read_mostly; void show_mem(void) { @@ -683,7 +691,7 @@ static void __init pagetable_init(void) #ifdef CONFIG_BLK_DEV_INITRD if (initrd_end && initrd_end > mem_limit) { - printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); + printk(KERN_INFO "initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); map_pages(initrd_start, __pa(initrd_start), initrd_end - initrd_start, PAGE_KERNEL); } @@ -785,8 +793,6 @@ map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) EXPORT_SYMBOL(map_hpux_gateway_page); #endif -extern void flush_tlb_all_local(void); - void __init paging_init(void) { int i; @@ -795,7 +801,7 @@ void __init paging_init(void) pagetable_init(); gateway_init(); flush_cache_all_local(); /* start with known state */ - flush_tlb_all_local(); + flush_tlb_all_local(NULL); for (i = 0; i < npmem_ranges; i++) { unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 }; @@ -986,7 +992,7 @@ void flush_tlb_all(void) do_recycle++; } spin_unlock(&sid_lock); - on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1); + on_each_cpu(flush_tlb_all_local, NULL, 1, 1); if (do_recycle) { spin_lock(&sid_lock); recycle_sids(recycle_ndirty,recycle_dirty_array); @@ -998,7 +1004,7 @@ void flush_tlb_all(void) void flush_tlb_all(void) { spin_lock(&sid_lock); - flush_tlb_all_local(); + flush_tlb_all_local(NULL); recycle_sids(); spin_unlock(&sid_lock); } diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c index 5c7a1b3..edd9a95 100644 --- a/arch/parisc/mm/ioremap.c +++ b/arch/parisc/mm/ioremap.c @@ -1,12 +1,9 @@ /* * arch/parisc/mm/ioremap.c * - * Re-map IO memory to kernel address space so that we can access it. - * This is needed for high PCI addresses that aren't mapped in the - * 640k-1MB IO memory area on PC's - * * (C) Copyright 1995 1996 Linus Torvalds * (C) Copyright 2001 Helge Deller <deller@gmx.de> + * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org> */ #include <linux/vmalloc.h> @@ -14,81 +11,107 @@ #include <linux/module.h> #include <asm/io.h> #include <asm/pgalloc.h> +#include <asm/tlbflush.h> +#include <asm/cacheflush.h> -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline void +remap_area_pte(pte_t *pte, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) { - unsigned long end; + unsigned long end, pfn; + pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | + _PAGE_ACCESSED | flags); address &= ~PMD_MASK; + end = address + size; if (end > PMD_SIZE) end = PMD_SIZE; - if (address >= end) - BUG(); + + BUG_ON(address >= end); + + pfn = phys_addr >> PAGE_SHIFT; do { - if (!pte_none(*pte)) { - printk(KERN_ERR "remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW | - _PAGE_DIRTY | _PAGE_ACCESSED | flags))); + BUG_ON(!pte_none(*pte)); + + set_pte(pte, pfn_pte(pfn, pgprot)); + address += PAGE_SIZE; - phys_addr += PAGE_SIZE; + pfn++; pte++; } while (address && (address < end)); } -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline int +remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) { unsigned long end; address &= ~PGDIR_MASK; + end = address + size; if (end > PGDIR_SIZE) end = PGDIR_SIZE; + + BUG_ON(address >= end); + phys_addr -= address; - if (address >= end) - BUG(); do { - pte_t * pte = pte_alloc_kernel(pmd, address); + pte_t *pte = pte_alloc_kernel(pmd, address); if (!pte) return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); + + remap_area_pte(pte, address, end - address, + address + phys_addr, flags); + address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); + return 0; } -#if (USE_HPPA_IOREMAP) -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) +#if USE_HPPA_IOREMAP +static int +remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) { - int error; - pgd_t * dir; + pgd_t *dir; + int error = 0; unsigned long end = address + size; + BUG_ON(address >= end); + phys_addr -= address; - dir = pgd_offset(&init_mm, address); + dir = pgd_offset_k(address); + flush_cache_all(); - if (address >= end) - BUG(); + do { + pud_t *pud; pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); + error = -ENOMEM; + pud = pud_alloc(&init_mm, dir, address); + if (!pud) + break; + + pmd = pmd_alloc(&init_mm, pud, address); if (!pmd) break; + if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) + phys_addr + address, flags)) break; + error = 0; address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } while (address && (address < end)); + flush_tlb_all(); + return error; } #endif /* USE_HPPA_IOREMAP */ @@ -123,8 +146,7 @@ EXPORT_SYMBOL(__raw_bad_addr); /* * Remap an arbitrary physical address space into the kernel virtual - * address space. Needed when the kernel wants to access high addresses - * directly. + * address space. * * NOTE! We need to allow non-page-aligned mappings too: we will obviously * have to convert them into an offset in a page-aligned mapping, but the @@ -148,8 +170,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l #endif #else - void * addr; - struct vm_struct * area; + void *addr; + struct vm_struct *area; unsigned long offset, last_addr; /* Don't allow wraparound or zero size */ @@ -167,9 +189,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l t_addr = __va(phys_addr); t_end = t_addr + (size - 1); - for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) + for (page = virt_to_page(t_addr); + page <= virt_to_page(t_end); page++) { if(!PageReserved(page)) return NULL; + } } /* @@ -185,11 +209,13 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l area = get_vm_area(size, VM_IOREMAP); if (!area) return NULL; + addr = area->addr; if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { vfree(addr); return NULL; } + return (void __iomem *) (offset + (char *)addr); #endif } |