From a0358984cec08d8005159ff366a2d02af6819b90 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 24 Jan 2015 21:23:18 +0000 Subject: [PATCH] bank16k_low: Introduce 16K low common banking logic and use it 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 | 2 +- Kernel/bank16k_low.c | 151 +++++++++++++++++++++++++++++++ Kernel/platform-tgl6502/Makefile | 2 +- Kernel/platform-tgl6502/config.h | 3 +- Kernel/platform-tgl6502/main.c | 4 +- 5 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 Kernel/bank16k_low.c diff --git a/Kernel/Makefile b/Kernel/Makefile index 704da227..a92127f5 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -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 index 00000000..f550e59a --- /dev/null +++ b/Kernel/bank16k_low.c @@ -0,0 +1,151 @@ +#include +#include +#include + +/* + * 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 diff --git a/Kernel/platform-tgl6502/Makefile b/Kernel/platform-tgl6502/Makefile index a72be309..0a5f878f 100644 --- a/Kernel/platform-tgl6502/Makefile +++ b/Kernel/platform-tgl6502/Makefile @@ -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 diff --git a/Kernel/platform-tgl6502/config.h b/Kernel/platform-tgl6502/config.h index 0561c29d..7b28f1c2 100644 --- a/Kernel/platform-tgl6502/config.h +++ b/Kernel/platform-tgl6502/config.h @@ -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) */ diff --git a/Kernel/platform-tgl6502/main.c b/Kernel/platform-tgl6502/main.c index 15a2c575..9fb69ede 100644 --- a/Kernel/platform-tgl6502/main.c +++ b/Kernel/platform-tgl6502/main.c @@ -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; } -- 2.34.1