From: Alan Cox Date: Thu, 19 Feb 2015 23:15:13 +0000 (+0000) Subject: bank16k_low: first cut at swap X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=11ee533986edc1f5ffd25366c5ee500bbac7b5cd;p=FUZIX.git bank16k_low: first cut at swap There are a couple of 6502 crawly horrors around the stack left to resolve! --- diff --git a/Kernel/bank16k_low.c b/Kernel/bank16k_low.c index 0b16ac0c..adcaedd2 100644 --- a/Kernel/bank16k_low.c +++ b/Kernel/bank16k_low.c @@ -25,6 +25,11 @@ #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