bank16k_low: first cut at swap
authorAlan Cox <alan@linux.intel.com>
Thu, 19 Feb 2015 23:15:13 +0000 (23:15 +0000)
committerAlan Cox <alan@linux.intel.com>
Thu, 19 Feb 2015 23:15:13 +0000 (23:15 +0000)
There are a couple of 6502 crawly horrors around the stack left to resolve!

Kernel/bank16k_low.c

index 0b16ac0..adcaedd 100644 (file)
 
 
 #ifdef CONFIG_BANK16_LOW
+
+#ifndef CONFIG_LOW_PAGE
+#define SWAP_SIZE_EXCL_ZP      SWAP_SIZE
+#endif
+
 /*
  * Map handling: We have flexible paging. Each map table consists of a set of pages
  * with the last page repeated to fill any holes.
@@ -150,4 +155,109 @@ uint16_t pagemap_mem_used(void)
        return pfptr << 4;
 }
 
+
+#ifdef SWAPDEV
+
+/*
+ *     Swap out the memory of a process to make room
+ *     for something else. For bank16k do this as four operations
+ *     ready for when we pass page values not processes to the drivers
+ *
+ *     FIXME: We also need to swap out page 0/1 on 6502 (ZP and S) as well
+ *     as looking at the best way to include the uarea in the swaps
+ */
+
+int swapout(ptptr p)
+{
+       uint16_t page = p->p_page;
+       uint16_t blk;
+       uint16_t map;
+       uint16_t base = SWAPBASE;
+       uint16_t size = (0x4000 - SWAPBASE) >> 9;
+
+       swapproc = p;
+
+       if (page)
+               panic("%x: process already swapped!\n", p);
+#ifdef DEBUG
+       kprintf("Swapping out %x (%d)\n", p, p->p_page);
+#endif
+
+       /* Are we out of swap ? */
+       map = swapmap_alloc();
+       if (map == 0)
+               return ENOMEM;
+       blk = map * SWAP_SIZE;
+
+#ifdef CONFIG_HAS_LOW_PAGE
+       swapwrite(SWAPDEV, blk, 1, 0x0000);
+       blk++;
+#endif
+
+       /* Write the app (and possibly the uarea etc..) to disk */
+       for (i = 0; i < 4; i ++) {
+               swapwrite(SWAPDEV, blk, size, base);
+               base += 0x4000;
+               /* Last bank is determined by SWAP SIZE. We do the maths
+                  in 512's (0x60 = 0xC000) */
+               if (i == 3)
+                       size = SWAP_SIZE_EXCL_ZP - 0x60;
+               else
+                       size = 0x20;
+       }
+       pagemap_free(p);
+       p->p_page = 0;
+       p->p_page2 = map;
+
+#ifdef DEBUG
+       kprintf("%x: swapout done %d\n", p, p->p_page);
+#endif
+       return 0;
+}
+
+/*
+ * Swap ourself in: must be on the swap stack when we do this
+ */
+void swapin(ptptr p)
+{
+       uint16_t blk = p->p_page2 * SWAP_SIZE;
+       uint16_t base = SWAPBASE;
+       uint16_t size = (0x4000 - SWAPBASE) >> 9;
+
+#ifdef DEBUG
+       kprintf("Swapin %x, %d\n", p, p->p_page);
+#endif
+       if (!p->p_page) {
+               kprintf("%x: nopage!\n", p);
+               return;
+       }
+
+       /* Return our swap */
+       swapmap_add(p->p_page2);
+
+       /* This may need other tweaks as its a special nasty case where
+          we don't want to overwrite the live stack but buffer and fix up
+          in tricks.s */
+#ifdef CONFIG_HAS_LOW_PAGE
+       swapread(SWAPDEV, blk, 1, 0x0000);
+       blk++;
+#endif
+
+       swapproc = p;           /* always ourself */
+       for (i = 0; i < 4; i ++) {
+               swapread(SWAPDEV, blk, size, base);
+               base += 0x4000;
+               /* Last bank is determined by SWAP SIZE. We do the maths
+                  in 512's (0x60 = 0xC000) */
+               if (i == 3)
+                       size = SWAP_SIZE_EXCL_ZP - 0x60;
+               else
+                       size = 0x20;    /* 16 K */
+       }
+#ifdef DEBUG
+       kprintf("%x: swapin done %d\n", p, p->p_page);
+#endif
+}
+#endif
+
 #endif