MMU_init buglet in 2.4.0-mvista_010216

Grant Erickson erick205 at umn.edu
Mon Mar 12 09:03:08 EST 2001


On Sat, 10 Mar 2001, David Blythe wrote:
> memory sizes > 16M but not a multiple of 16M not quite right.  for the
> 24M config i was playing with it manifests itself as a tlb miss/kernel
> stack overflow.

David,

I've implemented a me general solution for this page pinning which you
may/may not prefer. A snippet and patch are included below.

        off_t offset;
        ssize_t pagesz, memsz;
        int slots, bits;
        bd_t *bip = (bd_t *)__res;

	[ ... ]

        slots = 0;
        offset = 0;
        memsz = bip->bi_memsize;
        while (memsz > 0 && slots <= (PPC4XX_TLB_SIZE / 2)) {
                if ((memsz - (1 << (10 + (2 * PAGESZ_16M)))) >= 0) {
                        bits = PAGESZ_16M;

                } else if ((memsz - (1 << (10 + (2 * PAGESZ_4M)))) >= 0) {
                        bits = PAGESZ_4M;

                } else if ((memsz - (1 << (10 + (2 * PAGESZ_1M)))) >= 0) {
                        bits = PAGESZ_1M;

                } else if ((memsz - (1 << (10 + (2 * PAGESZ_256K)))) >= 0) {
                        bits = PAGESZ_256K;

                } else if ((memsz - (1 << (10 + (2 * PAGESZ_64K)))) >= 0) {
                        bits = PAGESZ_64K;

                } else if ((memsz - (1 << (10 + (2 * PAGESZ_16K)))) >= 0) {
                        bits = PAGESZ_16K;

                } else if ((memsz - (1 << (10 + (2 * PAGESZ_4K)))) >= 0) {
                        bits = PAGESZ_4K;

                } else {
                        bits = PAGESZ_1K;
                }

                pagesz = 1 << (10 + (2 * bits));
                memsz -= pagesz;
                slots++;

                PPC4xx_tlb_pin(KERNELBASE + offset, offset,
                               TLB_PAGESZ(bits), 1);

                offset += pagesz;
        }

The patch against 2.4.0-mvista_010216:

--- init.c-2.4.0-mvista_010216	Sun Mar 11 13:53:01 2001
+++ init.c			Fri Feb 16 11:38:12 2001
 void __init
 MMU_init(void)
 {
-
-/*
-** The maximum tlbs we allow to use is PPC4xx_MAX_PINNED_TLB (32)
-** entries which pins up to half gigabyte of memory.
-*/
-#define PPC4xx_MAX_PINNED_TLB   32
-#define PPC4xx_MAX_MEM  (PPC4xx_MAX_PINNED_TLB * SIZE_16MB)
-#define SIZE_4MB        0x0400000
-#define SIZE_16MB       0x1000000
-
-        extern unsigned char __res[];
-
+        off_t offset;
+        ssize_t pagesz, memsz;
+        int slots, bits;
         bd_t            *bip = (bd_t *)__res;
-        int             i;
-        unsigned int    pinned_tlbs;
-        unsigned int    size_pinned;
-        unsigned int    size_DRAM;
-        unsigned long   start_vaddr;
-        unsigned long   start_paddr;
-        void            *vaddr;

         /*
          * The Zone Protection Register (ZPR) defines how protection will
@@ -948,115 +974,108 @@
          * without regard to the EX and WR bits. In user-mode, access is
          * allowed based on the EX and WR bits.
          */
+        /* ftr revisit: set zone 2..15 to zero?  (are 2..15 used ?) */
         mtspr(SPRN_ZPR, 0x2aaaaaaa);

         flush_instruction_cache();

+        /* ftr revisit
+        ** - reconsider the pin
+        ** - look at MMU_init() for other processors
+        ** - consider setting 0x0000'0000 - 0x07ff'ffff to _not_ be guarded
+        **   in real mode (see SPRN_SGR).  This could improve performance
+        **   of fault handlers.  Have to fix rfi, etc to avoid speculative
+        **   prefetches if turn off guarded protection.
+        */
+
+        slots = 0;
+        offset = 0;
+        memsz = bip->bi_memsize;
+        while (memsz > 0 && slots <= (PPC4XX_TLB_SIZE / 2)) {
+                if ((memsz - (1 << (10 + (2 * PAGESZ_16M)))) >= 0) {
+                        bits = PAGESZ_16M;
+
+                } else if ((memsz - (1 << (10 + (2 * PAGESZ_4M)))) >= 0) {

+                        bits = PAGESZ_4M;
+
+                } else if ((memsz - (1 << (10 + (2 * PAGESZ_1M)))) >= 0) {
+                        bits = PAGESZ_1M;
+
+                } else if ((memsz - (1 << (10 + (2 * PAGESZ_256K)))) >= 0) {
+                        bits = PAGESZ_256K;

-        /* -----  pin 16MB chunks of memory  ----- */
-
-        size_DRAM = bip->bi_memsize;
+                } else if ((memsz - (1 << (10 + (2 * PAGESZ_64K)))) >= 0) {
+                        bits = PAGESZ_64K;

-        if (size_DRAM < SIZE_16MB)
-                printk(KERN_EMERG "MMU_init(): current memory 0x%x is too small."
-                        "  Minimum memory requirement is 16MB\n", size_DRAM);
+                } else if ((memsz - (1 << (10 + (2 * PAGESZ_16K)))) >= 0) {
+                        bits = PAGESZ_16K;

-        if ((size_DRAM % SIZE_4MB) != 0)
-                printk(KERN_EMERG "MMU_init(): current memory 0x%x is not a multiple of 4 MB."
-                        "  This configuration is not supported\n", size_DRAM);
+                } else if ((memsz - (1 << (10 + (2 * PAGESZ_4K)))) >= 0) {
+                        bits = PAGESZ_4K;

-        if (size_DRAM > PPC4xx_MAX_MEM) {
-                printk(KERN_ERR "MMU_init(): current memory 0x%x is too large."
-                        "  Memory above 0x%x will not be used.\n", size_DRAM,
-                        PPC4xx_MAX_MEM);
-                bip->bi_memsize = PPC4xx_MAX_MEM;
-                size_DRAM       = bip->bi_memsize;
+                } else {
+                        bits = PAGESZ_1K;
         }

-        pinned_tlbs = (size_DRAM / SIZE_16MB);
-        size_pinned = 0;
-        start_vaddr = KERNELBASE;
-        start_paddr = 0x0;
-        for (i = 0; i < pinned_tlbs; i++)  {
-                PPC4xx_tlb_pin(start_vaddr, start_paddr, TLB_PAGESZ(PAGESZ_16M), 1);
-                size_pinned += SIZE_16MB;
-                start_vaddr += SIZE_16MB;
-                start_paddr += SIZE_16MB;
+                pagesz = 1 << (10 + (2 * bits));
+                memsz -= pagesz;
+                slots++;
+
+                PPC4xx_tlb_pin(KERNELBASE + offset, offset,
+                               TLB_PAGESZ(bits), 1);
+
+                offset += pagesz;
         }

--
 Grant Erickson                       University of Minnesota Alumni
  o mail:erick205 at umn.edu                                 1996 BSEE
  o http://www.umn.edu/~erick205                          1998 MSEE


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/






More information about the Linuxppc-embedded mailing list