bank16k_low: Introduce 16K low common banking logic and use it
authorAlan Cox <alan@linux.intel.com>
Sat, 24 Jan 2015 21:23:18 +0000 (21:23 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 24 Jan 2015 21:23:18 +0000 (21:23 +0000)
We need a different algorithm because we must keep the low page safe not the high
one. The standard bank16k grows by inserting pages before the existing repeating
top map so that common is preserved in high space. The 6502 has common in low
space so we must instead preserve the first page mapping.

Kernel/Makefile
Kernel/bank16k_low.c [new file with mode: 0644]
Kernel/platform-tgl6502/Makefile
Kernel/platform-tgl6502/config.h
Kernel/platform-tgl6502/main.c

index 704da22..a92127f 100644 (file)
@@ -99,7 +99,7 @@ C1SRCS += inode.c tty.c
 #
 C2SRCS =  syscall_proc.c syscall_fs.c
 C2SRCS += syscall_fs2.c syscall_other.c syscall_exec.c process.c
-C2SRCS += simple.c single.c bank16k.c bank32k.c bankfixed.c
+C2SRCS += simple.c single.c bank16k.c bank16k_low.c bank32k.c bankfixed.c
 #
 #      Drop some bits into CODE3 so the 6502 banks fit nicely. May well
 #      need to do this on Z80 as well
diff --git a/Kernel/bank16k_low.c b/Kernel/bank16k_low.c
new file mode 100644 (file)
index 0000000..f550e59
--- /dev/null
@@ -0,0 +1,151 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+
+/*
+ *     16K memory banks with the common in the bottom bank. Currently only used
+ *     for the 6502 CPU.
+ */
+
+
+#ifdef CONFIG_BANK16_LOW
+/*
+ * Map handling: We have flexible paging. Each map table consists of a set of pages
+ * with the last page repeated to fill any holes.
+ */
+
+static unsigned char pfree[MAX_MAPS];
+static unsigned char pfptr = 0;
+
+/*
+ *     Helper for platform to add pages at boot
+ */
+void pagemap_add(uint8_t page)
+{
+       if (pfptr == MAX_MAPS)
+               panic("map over");
+       pfree[pfptr++] = page;
+}
+
+/*
+ *     Free the maps for this task
+ */
+void pagemap_free(ptptr p)
+{
+       uint8_t *ptr = (uint8_t *) & p->p_page;
+       uint8_t last = 0xff;
+       int i;
+       for (i = 0; i < 4; i++) {
+               if (*ptr != last) {
+                       pfree[pfptr++] = *ptr;
+                       last = *ptr;
+               }
+               ptr++;
+       }
+}
+
+static int maps_needed(uint16_t top)
+{
+       uint16_t needed = top ? top - 1 : top;
+       needed >>= 14;          /* in banks */
+       needed++;               /* rounded */
+       return needed;
+}
+
+/*
+ *     Allocate the maps for this task post fork
+ *     We have a hackish fix for init that would be nice
+ *     resolve.
+ */
+int pagemap_alloc(ptptr p)
+{
+       uint8_t *ptr = (uint8_t *) & p->p_page;
+       int needed = maps_needed(udata.u_top);
+       int i;
+
+       kprintf("pagemap_alloc, need %d (top %u)\n", needed, udata.u_top);
+#ifdef SWAPDEV
+       /* Throw our toys out of our pram until we have enough room */
+       while (needed > pfptr)
+               if (swapneeded(p, 1) == NULL)
+                       return ENOMEM;
+#else
+       if (needed > pfptr)     /* We have no swap so poof... */ {
+        kprintf("%d free, %d needed\n", pfptr, needed);
+               return ENOMEM;
+        }
+#endif
+
+       /* Pages in the low then repeat the top one */
+       for (i = 0; i < needed; i++)
+               ptr[i] = pfree[--pfptr];
+
+       while (i < 4) {
+               ptr[i] = ptr[i - 1];
+               i++;
+       }
+       return 0;
+}
+
+/*
+ *     Reallocate the maps for a process
+ */
+int pagemap_realloc(uint16_t size)
+{
+       int have = maps_needed(udata.u_top);
+       int want = maps_needed(size);
+       uint8_t *ptr = (uint8_t *) & udata.u_page;
+       int i;
+       irqflags_t irq;
+
+       /* If we are shrinking then free pages and propogate the
+          common page into the freed spaces */
+        kprintf("Maps were %x %x\n", udata.u_page, udata.u_page2);
+        kprintf("have %d want %d\n", have, want);
+       if (want == have)
+               return 0;
+       if (have > want) {
+               for (i = want; i < have; i++) {
+                       pfree[pfptr++] = ptr[i];
+                       ptr[i] = ptr[3];
+               }
+               udata.u_ptab->p_page = udata.u_page;
+               udata.u_ptab->p_page2 = udata.u_page2;
+               return 0;
+       }
+
+       /* If we are adding then just insert the new pages, keeping the common
+          unchanged at the top */
+       if (want - have > pfptr)
+               return ENOMEM;
+       /* We don't want to take an interrupt here while our page mappings are
+          incomplete. We may restore bogus mappings and then take a second IRQ
+          into hyperspace */
+        irq = di();
+
+        /* We have common low so we must only touch the higher pages. This is
+           different from the high common case */
+       for (i = have; i < want; i++)
+               ptr[i] = pfree[--pfptr];
+        while(i < 4) {
+               ptr[i] = ptr[i-1];
+               i++;
+       }
+       /* Copy the updated allocation into the ptab */
+       udata.u_ptab->p_page = udata.u_page;
+       udata.u_ptab->p_page2 = udata.u_page2;
+       /* Now fix the vectors up - they've potentially teleported up to 48K up
+          the user address space, we need to put a copy back in low memory before
+          we switch to this memory map */
+       program_vectors(&udata.u_page);
+
+       irqrestore(irq);
+       return 0;
+}
+
+uint16_t pagemap_mem_used(void)
+{
+       return pfptr << 4;
+}
+
+#endif
index a72be30..0a5f878 100644 (file)
@@ -27,6 +27,6 @@ image:
        tgl6502.o ../start.o ../version.o ../lowlevel-6502.o \
        tricks.o main.o ../timer.o ../kdata.o devrd.o devices.o \
        ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
-       ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o ../bank16k.o \
+       ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o ../bank16k_low.o \
        ../tty.o ../devsys.o ../syscall_fs2.o ../syscall_exec.o \
        ../usermem.o ../usermem_std-6502.o devtty.o
index 0561c29..7b28f1c 100644 (file)
@@ -19,7 +19,7 @@
  *     We've got 128K - 8 banks of 16K, of which the kernel eats one for data
  *     (Kernel code is in the ROM banks which are separate)
  */
-#define CONFIG_BANK16
+#define CONFIG_BANK16_LOW
 #define MAX_MAPS 7
 
 #if 0
@@ -34,6 +34,7 @@
 #endif
 
 #define TICKSPERSEC 10     /* Ticks per second */
+#define MAPBASE            0x0000  /* We map from 0 */
 #define PROGBASE    0x2000  /* also data base */
 #define PROGLOAD    0x2000
 #define PROGTOP     0xC000  /* Top of program (for debug for now, can go to 10000) */
index 15a2c57..9fb69ed 100644 (file)
@@ -24,7 +24,7 @@ void do_beep(void)
 
 void pagemap_init(void)
 {
-    /* Really 8K banks 0,1,2,... but we pair them up so we have
+    /* Really 8K banks 0,1,2,... but we pair them up so we have */
     /* 8 x 16 banks numbered 0,2,4,.... , 0 is the kernel, init starts in 2 */
     pagemap_add(14);
     pagemap_add(12);
@@ -37,4 +37,6 @@ void pagemap_init(void)
 
 void map_init(void)
 {
+    udata.u_page = 0x0202;
+    udata.u_page2 = 0x0202;
 }