]> git.neil.brown.name Git - history.git/commitdiff
[SPARC]: Backport of 2.4.x dynamic-nocache.
authorRob Radez <rob@osinvestor.com>
Thu, 5 Dec 2002 03:55:07 +0000 (19:55 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Thu, 5 Dec 2002 03:55:07 +0000 (19:55 -0800)
arch/sparc/mm/highmem.c
arch/sparc/mm/init.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
include/asm-sparc/highmem.h
include/asm-sparc/vaddrs.h

index 7b4ebf2064a227af2f44be34b2f53c769a830773..0bfbc068bc4b6a61b665ef8be73b72d487d5f85e 100644 (file)
@@ -38,7 +38,7 @@ void *kmap_atomic(struct page *page, enum km_type type)
                return page_address(page);
 
        idx = type + KM_TYPE_NR*smp_processor_id();
-       vaddr = FIX_KMAP_BEGIN + idx * PAGE_SIZE;
+       vaddr = fix_kmap_begin + idx * PAGE_SIZE;
 
 /* XXX Fix - Anton */
 #if 0
@@ -67,12 +67,12 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
        unsigned long vaddr = (unsigned long) kvaddr;
        unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
 
-       if (vaddr < FIX_KMAP_BEGIN) { // FIXME
+       if (vaddr < fix_kmap_begin) { // FIXME
                dec_preempt_count();
                return;
        }
 
-       if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE)
+       if (vaddr != fix_kmap_begin + idx * PAGE_SIZE)
                BUG();
 
 /* XXX Fix - Anton */
index 9ea5221b708412f90972945beef3505dda58a08b..b40615999aa3c2f533a403df95a01cc7a7db7b92 100644 (file)
@@ -59,13 +59,17 @@ unsigned long highstart_pfn, highend_pfn;
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
 
+/* These are set in {srmmu,sun4c}_paging_init() */
+unsigned long fix_kmap_begin;
+unsigned long fix_kmap_end;
+
 #define kmap_get_fixed_pte(vaddr) \
        pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
 
 void __init kmap_init(void)
 {
        /* cache the first kmap pte */
-       kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN);
+       kmap_pte = kmap_get_fixed_pte(fix_kmap_begin);
        kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);
 }
 
index 1e2e1be5c4dfb7a7a648f95ba3c7b9b00e34f2c7..e9aab3723ad1c6844e74915d8b7b6e0170c301df 100644 (file)
@@ -136,8 +136,16 @@ static inline int srmmu_device_memory(unsigned long x)
 
 int srmmu_cache_pagetables;
 
-/* XXX Make this dynamic based on ram size - Anton */
-#define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16)
+/* these will be initialized in srmmu_nocache_calcsize() */
+int srmmu_nocache_npages;
+unsigned long srmmu_nocache_size;
+unsigned long srmmu_nocache_end;
+unsigned long pkmap_base;
+unsigned long pkmap_base_end;
+unsigned long srmmu_nocache_bitmap_size;
+extern unsigned long fix_kmap_begin;
+extern unsigned long fix_kmap_end;
+
 #define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4)
 
 void *srmmu_nocache_pool;
@@ -331,7 +339,7 @@ static unsigned long __srmmu_get_nocache(int size, int align)
        spin_lock(&srmmu_nocache_spinlock);
 
 repeat:
-       offset = find_next_zero_bit(srmmu_nocache_bitmap, SRMMU_NOCACHE_BITMAP_SIZE, offset);
+       offset = find_next_zero_bit(srmmu_nocache_bitmap, srmmu_nocache_bitmap_size, offset);
 
        /* we align on physical address */
        if (align) {
@@ -341,7 +349,7 @@ repeat:
                offset = (va_tmp - SRMMU_NOCACHE_VADDR) >> SRMMU_NOCACHE_BITMAP_SHIFT;
        }
 
-       if ((SRMMU_NOCACHE_BITMAP_SIZE - offset) < size) {
+       if ((srmmu_nocache_bitmap_size - offset) < size) {
                printk("Run out of nocached RAM!\n");
                spin_unlock(&srmmu_nocache_spinlock);
                return 0;
@@ -393,9 +401,9 @@ void srmmu_free_nocache(unsigned long vaddr, int size)
                    vaddr, (unsigned long)SRMMU_NOCACHE_VADDR);
                BUG();
        }
-       if (vaddr >= SRMMU_NOCACHE_END) {
+       if (vaddr >= srmmu_nocache_end) {
                printk("Vaddr %lx is bigger than nocache end 0x%lx\n",
-                   vaddr, (unsigned long)SRMMU_NOCACHE_END);
+                   vaddr, srmmu_nocache_end);
                BUG();
        }
        if (size & (size-1)) {
@@ -429,6 +437,35 @@ void srmmu_free_nocache(unsigned long vaddr, int size)
 
 void srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end);
 
+extern unsigned long probe_memory(void);       /* in fault.c */
+
+/* Reserve nocache dynamically proportionally to the amount of
+ * system RAM. -- Tomas Szepe <szepe@pinerecords.com>, June 2002
+ */
+void srmmu_nocache_calcsize(void)
+{
+       unsigned long sysmemavail = probe_memory() / 1024;
+
+       srmmu_nocache_npages =
+               sysmemavail / SRMMU_NOCACHE_ALCRATIO / 1024 * 256;
+       if (sysmemavail % (SRMMU_NOCACHE_ALCRATIO * 1024))
+               srmmu_nocache_npages += 256;
+
+       /* anything above 1280 blows up */
+       if (srmmu_nocache_npages > 1280) srmmu_nocache_npages = 1280;
+
+       srmmu_nocache_size = srmmu_nocache_npages * PAGE_SIZE;
+       srmmu_nocache_bitmap_size = srmmu_nocache_npages * 16;
+       srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size;
+       fix_kmap_begin = srmmu_nocache_end;
+       fix_kmap_end = fix_kmap_begin + (KM_TYPE_NR * NR_CPUS - 1) * PAGE_SIZE;
+       pkmap_base = SRMMU_NOCACHE_VADDR + srmmu_nocache_size + 0x40000;
+       pkmap_base_end = pkmap_base + LAST_PKMAP * PAGE_SIZE;
+
+       /* printk("system memory available = %luk\nnocache ram size = %luk\n",
+               sysmemavail, srmmu_nocache_size / 1024); */
+}
+
 void srmmu_nocache_init(void)
 {
        pgd_t *pgd;
@@ -437,24 +474,24 @@ void srmmu_nocache_init(void)
        unsigned long paddr, vaddr;
        unsigned long pteval;
 
-       srmmu_nocache_pool = __alloc_bootmem(SRMMU_NOCACHE_SIZE, PAGE_SIZE, 0UL);
-       memset(srmmu_nocache_pool, 0, SRMMU_NOCACHE_SIZE);
+       srmmu_nocache_pool = __alloc_bootmem(srmmu_nocache_size, PAGE_SIZE, 0UL);
+       memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
 
-       srmmu_nocache_bitmap = __alloc_bootmem(SRMMU_NOCACHE_BITMAP_SIZE, SMP_CACHE_BYTES, 0UL);
-       memset(srmmu_nocache_bitmap, 0, SRMMU_NOCACHE_BITMAP_SIZE);
+       srmmu_nocache_bitmap = __alloc_bootmem(srmmu_nocache_bitmap_size, SMP_CACHE_BYTES, 0UL);
+       memset(srmmu_nocache_bitmap, 0, srmmu_nocache_bitmap_size);
 
        srmmu_swapper_pg_dir = (pgd_t *)__srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
        memset(__nocache_fix(srmmu_swapper_pg_dir), 0, SRMMU_PGD_TABLE_SIZE);
        init_mm.pgd = srmmu_swapper_pg_dir;
 
-       srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, SRMMU_NOCACHE_END);
+       srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, srmmu_nocache_end);
 
        spin_lock_init(&srmmu_nocache_spinlock);
 
        paddr = __pa((unsigned long)srmmu_nocache_pool);
        vaddr = SRMMU_NOCACHE_VADDR;
 
-       while (vaddr < SRMMU_NOCACHE_END) {
+       while (vaddr < srmmu_nocache_end) {
                pgd = pgd_offset_k(vaddr);
                pmd = srmmu_pmd_offset(__nocache_fix(pgd), vaddr);
                pte = srmmu_pte_offset(__nocache_fix(pmd), vaddr);
@@ -1286,6 +1323,7 @@ void __init srmmu_paging_init(void)
        pages_avail = 0;
        last_valid_pfn = bootmem_init(&pages_avail);
 
+       srmmu_nocache_calcsize();
        srmmu_nocache_init();
         srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE));
        map_kernel();
@@ -1307,12 +1345,12 @@ void __init srmmu_paging_init(void)
        srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END);
 #endif
 
-       srmmu_allocate_ptable_skeleton(FIX_KMAP_BEGIN, FIX_KMAP_END);
-       srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_BASE_END);
+       srmmu_allocate_ptable_skeleton(fix_kmap_begin, fix_kmap_end);
+       srmmu_allocate_ptable_skeleton(pkmap_base, pkmap_base_end);
 
-       pgd = pgd_offset_k(PKMAP_BASE);
-       pmd = srmmu_pmd_offset(pgd, PKMAP_BASE);
-       pte = srmmu_pte_offset(pmd, PKMAP_BASE);
+       pgd = pgd_offset_k(pkmap_base);
+       pmd = srmmu_pmd_offset(pgd, pkmap_base);
+       pte = srmmu_pte_offset(pmd, pkmap_base);
        pkmap_page_table = pte;
 
        flush_cache_all();
@@ -1359,7 +1397,7 @@ static void srmmu_mmu_info(struct seq_file *m)
                   "nocache used\t: %d\n",
                   srmmu_name,
                   num_contexts,
-                  SRMMU_NOCACHE_SIZE,
+                  srmmu_nocache_size,
                   (srmmu_nocache_used << SRMMU_NOCACHE_BITMAP_SHIFT));
 }
 
index babe16d9bea7be5c23302714d14bbcca2633ef2c..74c23da4a7b030073f994ab65ca467fbb8ce0751 100644 (file)
@@ -2002,6 +2002,9 @@ extern unsigned long end;
 extern unsigned long bootmem_init(unsigned long *pages_avail);
 extern unsigned long last_valid_pfn;
 
+extern unsigned long fix_kmap_begin;
+extern unsigned long fix_kmap_end;
+
 void __init sun4c_paging_init(void)
 {
        int i, cnt;
@@ -2009,6 +2012,9 @@ void __init sun4c_paging_init(void)
        extern struct resource sparc_iomap;
        unsigned long end_pfn, pages_avail;
 
+       fix_kmap_begin = KERNBASE + SRMMU_MAXMEM; /* Why bother with SRMMU_MAXMEM? */
+       fix_kmap_end = fix_kmap_begin + ((KM_TYPE_NR*NR_CPUS)-1)*PAGE_SIZE;
+
        kernel_end = (unsigned long) &end;
        kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4);
        kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
index e4c8edc4409df21d2e649a8a97b884404372098b..68d6402b3aa3cb256c8a274676c184638acff4b3 100644 (file)
@@ -33,6 +33,12 @@ extern pte_t *kmap_pte;
 extern pgprot_t kmap_prot;
 extern pte_t *pkmap_page_table;
 
+/* This gets set in {srmmu,sun4c}_paging_init() */
+extern unsigned long fix_kmap_begin;
+
+/* Only used and set with srmmu? */
+extern unsigned long pkmap_base;
+
 extern void kmap_init(void) __init;
 
 /*
@@ -42,9 +48,9 @@ extern void kmap_init(void) __init;
  */
 #define LAST_PKMAP 1024
 
-#define LAST_PKMAP_MASK (LAST_PKMAP-1)
-#define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
-#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt)  ((virt - pkmap_base) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)  (pkmap_base + ((nr) << PAGE_SHIFT))
 
 extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
@@ -75,10 +81,10 @@ static inline struct page *kmap_atomic_to_page(void *ptr)
        unsigned long idx, vaddr = (unsigned long)ptr;
        pte_t *pte;
 
-       if (vaddr < FIX_KMAP_BEGIN)
+       if (vaddr < fix_kmap_begin)
                return virt_to_page(ptr);
 
-       idx = ((vaddr - FIX_KMAP_BEGIN) >> PAGE_SHIFT);
+       idx = ((vaddr - fix_kmap_begin) >> PAGE_SHIFT);
        pte = kmap_pte + idx;
        return pte_page(*pte);
 }
index 0470ea55e6a98a96df34f136e14392e7bc8dd31c..d823a79b0746927b0738238fd8ec8bcbe4b4f42c 100644 (file)
 
 #define SRMMU_MAXMEM           0x0c000000
 
-#define SRMMU_NOCACHE_VADDR    0xfc000000      /* KERNBASE + SRMMU_MAXMEM */
-/* XXX Make this dynamic based on ram size - Anton */
-#define SRMMU_NOCACHE_NPAGES   256
-#define SRMMU_NOCACHE_SIZE     (SRMMU_NOCACHE_NPAGES * PAGE_SIZE)
-#define SRMMU_NOCACHE_END      (SRMMU_NOCACHE_VADDR + SRMMU_NOCACHE_SIZE)
+#define SRMMU_NOCACHE_VADDR    (KERNBASE + SRMMU_MAXMEM)
+                               /* = 0x0fc000000 */
 
-#define FIX_KMAP_BEGIN         0xfc100000
-#define FIX_KMAP_END (FIX_KMAP_BEGIN + ((KM_TYPE_NR*NR_CPUS)-1)*PAGE_SIZE)
-
-#define PKMAP_BASE             0xfc140000
-#define PKMAP_BASE_END         (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE)
+/* The following constant is used in mm/srmmu.c::srmmu_nocache_calcsize()
+ * to determine the amount of memory that will be reserved as nocache:
+ *
+ * 256 pages will be taken as nocache per each
+ * SRMMU_NOCACHE_ALCRATIO MB of system memory.
+ *
+ * limits enforced:    nocache minimum = 256 pages
+ *                     nocache maximum = 1280 pages
+ */
+#define SRMMU_NOCACHE_ALCRATIO 64      /* 256 pages per 64MB of system RAM */
 
 #define SUN4M_IOBASE_VADDR     0xfd000000 /* Base for mapping pages */
 #define IOBASE_VADDR           0xfe000000
 #define IOBASE_END             0xfe300000
 
 #define VMALLOC_START          0xfe300000
+
 /* XXX Alter this when I get around to fixing sun4c - Anton */
 #define VMALLOC_END            0xffc00000