From 4919f161cc7a0cfa31f91b0d1e2d0ff600044ff6 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Sun, 14 Mar 2021 17:58:04 +0100 Subject: [DYNAREC] Added Basic blocks for dynarec --- src/custommem.c | 869 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 482 insertions(+), 387 deletions(-) (limited to 'src/custommem.c') diff --git a/src/custommem.c b/src/custommem.c index 8febe5a0..62f15664 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -23,19 +23,21 @@ #include "khash.h" #ifdef DYNAREC #include "dynablock.h" -#include "dynarec/arm_lock_helper.h" +#include "dynarec/arm64_lock_helper.h" -#define USE_MMAP +//#define USE_MMAP // init inside dynablocks.c KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*) -static dynablocklist_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block +static dynablocklist_t*** dynmap123[1<=size) { -// int rsize = 0; -// sub = getFirstBlock(mmaplist[i].block, size, &rsize); -// if(sub) { -// uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size); -// if(rsize==mmaplist[i].maxfree) -// mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size); -// kh_dynablocks_t *blocks = mmaplist[i].dblist; -// if(!blocks) { -// blocks = mmaplist[i].dblist = kh_init(dynablocks); -// kh_resize(dynablocks, blocks, 64); -// } -// khint_t k; -// int r; -// k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r); -// kh_value(blocks, k) = db; -// for(int j=0; jprev.x32 = 0; -// m->next.fill = 0; -// m->next.size = MMAPSIZE-sizeof(blockmark_t); -// m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t)); -// m->next.x32 = 0; -// m->prev.fill = 0; -// m->prev.size = MMAPSIZE-sizeof(blockmark_t); -// // alloc 1st block -// uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size); -// mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size); -// kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks); -// kh_resize(dynablocks, blocks, 64); -// khint_t k; -// int ret; -// k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret); -// kh_value(blocks, k) = db; -// for(int j=0; j(uintptr_t)mmaplist[i].block) -// && (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) { -// void* sub = (void*)(addr-sizeof(blockmark_t)); -// freeBlock(mmaplist[i].block, sub); -// mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size); -// kh_dynablocks_t *blocks = mmaplist[i].dblist; -// if(blocks) { -// khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub); -// if(k!=kh_end(blocks)) -// kh_del(dynablocks, blocks, k); -// for(int j=0; j=(uintptr_t)mmaplist[i].block -// && ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) { -// if(!mmaplist[i].helper) -// return FindDynablockDynablocklist(addr, mmaplist[i].dblist); -// else { -// uintptr_t p = (uintptr_t)addr - (uintptr_t)mmaplist[i].block; -// while(mmaplist[i].helper[p]) p -= mmaplist[i].helper[p]; -// khint_t k = kh_get(dynablocks, mmaplist[i].dblist, (uintptr_t)mmaplist[i].block + p); -// if(k!=kh_end(mmaplist[i].dblist)) -// return kh_value(mmaplist[i].dblist, k); -// return NULL; -// } -// } -// } -// // look in oversized -// return FindDynablockDynablocklist(addr, dblist_oversized); -//} - -//uintptr_t AllocDynarecMap(dynablock_t* db, int size) -//{ -// if(!size) -// return 0; -// if(size>MMAPSIZE-2*sizeof(blockmark_t)) { -// #ifndef USE_MMAP -// void *p = NULL; -// if(posix_memalign(&p, box64_pagesize, size)) { -// dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size); -// return 0; -// } -// mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC); -// #else -// void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); -// if(p==(void*)-1) { -// dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size); -// return 0; -// } -// #endif -// setProtection((uintptr_t)p, size, PROT_READ | PROT_WRITE | PROT_EXEC); -// kh_dynablocks_t *blocks = dblist_oversized; -// if(!blocks) { -// blocks = dblist_oversized = kh_init(dynablocks); -// kh_resize(dynablocks, blocks, 64); -// } -// khint_t k; -// int ret; -// k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret); -// kh_value(blocks, k) = db; -// return (uintptr_t)p; -// } -// -// if(pthread_mutex_trylock(&mutex_mmap)) { -// sched_yield(); // give it a chance -// if(pthread_mutex_trylock(&mutex_mmap)) -// return 0; // cannot lock, baillout -// } -// -// uintptr_t ret = FindFreeDynarecMap(db, size); -// if(!ret) -// ret = AddNewDynarecMap(db, size); -// -// pthread_mutex_unlock(&mutex_mmap); -// -// return ret; -//} - -//void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size) -//{ -// if(size>MMAPSIZE-2*sizeof(blockmark_t)) { -// #ifndef USE_MMAP -// free((void*)addr); -// #else -// munmap((void*)addr, size); -// #endif -// kh_dynablocks_t *blocks = dblist_oversized; -// if(blocks) { -// khint_t k = kh_get(dynablocks, blocks, addr); -// if(k!=kh_end(blocks)) -// kh_del(dynablocks, blocks, k); -// } -// return; -// } -// pthread_mutex_lock(&mutex_mmap); -// ActuallyFreeDynarecMap(db, addr, size); -// pthread_mutex_unlock(&mutex_mmap); -//} - -//dynablocklist_t* getDB(uintptr_t idx) -//{ -// return dynmap[idx]; -//} +typedef struct mmaplist_s { + void* block; + int maxfree; + size_t size; + kh_dynablocks_t* dblist; + uint8_t* helper; +} mmaplist_t; + +uintptr_t FindFreeDynarecMap(dynablock_t* db, int size) +{ + // look for free space + void* sub = NULL; + for(int i=0; i=size) { + int rsize = 0; + sub = getFirstBlock(mmaplist[i].block, size, &rsize); + if(sub) { + uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size); + if(rsize==mmaplist[i].maxfree) + mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size); + kh_dynablocks_t *blocks = mmaplist[i].dblist; + if(!blocks) { + blocks = mmaplist[i].dblist = kh_init(dynablocks); + kh_resize(dynablocks, blocks, 64); + } + khint_t k; + int r; + k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r); + kh_value(blocks, k) = db; + for(int j=0; jprev.x32 = 0; + m->next.fill = 0; + m->next.size = MMAPSIZE-sizeof(blockmark_t); + m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t)); + m->next.x32 = 0; + m->prev.fill = 0; + m->prev.size = MMAPSIZE-sizeof(blockmark_t); + // alloc 1st block + uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size); + mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size); + kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks); + kh_resize(dynablocks, blocks, 64); + khint_t k; + int ret; + k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret); + kh_value(blocks, k) = db; + for(int j=0; j(uintptr_t)mmaplist[i].block) + && (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) { + void* sub = (void*)(addr-sizeof(blockmark_t)); + freeBlock(mmaplist[i].block, sub); + mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size); + kh_dynablocks_t *blocks = mmaplist[i].dblist; + if(blocks) { + khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub); + if(k!=kh_end(blocks)) + kh_del(dynablocks, blocks, k); + for(int j=0; j=(uintptr_t)mmaplist[i].block + && ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) { + if(!mmaplist[i].helper) + return FindDynablockDynablocklist(addr, mmaplist[i].dblist); + else { + uintptr_t p = (uintptr_t)addr - (uintptr_t)mmaplist[i].block; + while(mmaplist[i].helper[p]) p -= mmaplist[i].helper[p]; + khint_t k = kh_get(dynablocks, mmaplist[i].dblist, (uintptr_t)mmaplist[i].block + p); + if(k!=kh_end(mmaplist[i].dblist)) + return kh_value(mmaplist[i].dblist, k); + return NULL; + } + } + } + // look in oversized + return FindDynablockDynablocklist(addr, dblist_oversized); +} + +uintptr_t AllocDynarecMap(dynablock_t* db, int size) +{ + if(!size) + return 0; + if(size>MMAPSIZE-2*sizeof(blockmark_t)) { + #ifndef USE_MMAP + void *p = NULL; + if(posix_memalign(&p, box64_pagesize, size)) { + dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size); + return 0; + } + mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC); + #else + void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + if(p==(void*)-1) { + dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size); + return 0; + } + #endif + setProtection((uintptr_t)p, size, PROT_READ | PROT_WRITE | PROT_EXEC); + kh_dynablocks_t *blocks = dblist_oversized; + if(!blocks) { + blocks = dblist_oversized = kh_init(dynablocks); + kh_resize(dynablocks, blocks, 64); + } + khint_t k; + int ret; + k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret); + kh_value(blocks, k) = db; + return (uintptr_t)p; + } + + if(pthread_mutex_trylock(&mutex_mmap)) { + sched_yield(); // give it a chance + if(pthread_mutex_trylock(&mutex_mmap)) + return 0; // cannot lock, baillout + } + + uintptr_t ret = FindFreeDynarecMap(db, size); + if(!ret) + ret = AddNewDynarecMap(db, size); + + pthread_mutex_unlock(&mutex_mmap); + + return ret; +} + +void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size) +{ + if(size>MMAPSIZE-2*sizeof(blockmark_t)) { + #ifndef USE_MMAP + free((void*)addr); + #else + munmap((void*)addr, size); + #endif + kh_dynablocks_t *blocks = dblist_oversized; + if(blocks) { + khint_t k = kh_get(dynablocks, blocks, addr); + if(k!=kh_end(blocks)) + kh_del(dynablocks, blocks, k); + } + return; + } + pthread_mutex_lock(&mutex_mmap); + ActuallyFreeDynarecMap(db, addr, size); + pthread_mutex_unlock(&mutex_mmap); +} + +dynablocklist_t* getDB(uintptr_t idx) +{ + // already 16bits shifted + uintptr_t idx3 = (idx>>32)&((1<>16)&((1< %p\n", (void*)addr, (void*)(addr+size-1)); -// uintptr_t idx = (addr>>DYNAMAP_SHIFT); -// uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT); -// for (uintptr_t i=idx; i<=end; ++i) { -// if(!dynmap[i]) { -// dynmap[i] = NewDynablockList(i< %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark"); -// uintptr_t idx = (addr>>DYNAMAP_SHIFT); -// uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT); -// for (uintptr_t i=idx; i<=end; ++i) { -// dynablocklist_t* dblist = dynmap[i]; -// if(dblist) { -// if(destroy) -// FreeRangeDynablock(dblist, addr, size); -// else -// MarkRangeDynablock(dblist, addr, size); -// } -// } -//} - -#ifdef ARM -//void arm_next(void); +void addDBFromAddressRange(uintptr_t addr, uintptr_t size) +{ + dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1)); + uintptr_t idx = (addr>>DYNAMAP_SHIFT); + uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT); + for (uintptr_t i=idx; i<=end; ++i) { + int idx3 = (i>>32)&((1<>16)&((1< %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark"); + uintptr_t idx = (addr>>DYNAMAP_SHIFT); + uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT); + for (uintptr_t i=idx; i<=end; ++i) { + int idx3 = (i>>32)&((1<>16)&((1<>JMPTABL_SHIFT); -// if(box64_jumptable[idx] == box64_jmptbl_default) { -// uintptr_t* tbl = (uintptr_t*)malloc((1<>JMPTABL_SHIFT); -// if(box64_jumptable[idx] == box64_jmptbl_default) { -// return; -// } -// const uintptr_t off = (uintptr_t)addr&((1<>JMPTABL_SHIFT); -// if(box64_jumptable[idx] == box64_jmptbl_default) { -// uintptr_t* tbl = (uintptr_t*)malloc((1<>48)&0xffff; + idx2 = (((uintptr_t)addr)>>32)&0xffff; + idx1 = (((uintptr_t)addr)>>16)&0xffff; + idx0 = (((uintptr_t)addr) )&0xffff; + if(box64_jmptbl3[idx3] == box64_jmptbldefault2) { + uintptr_t*** tbl = (uintptr_t***)malloc((1<>48)&0xffff; + idx2 = (((uintptr_t)addr)>>32)&0xffff; + idx1 = (((uintptr_t)addr)>>16)&0xffff; + idx0 = (((uintptr_t)addr) )&0xffff; + if(box64_jmptbl3[idx3] == box64_jmptbldefault2) + return; + if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) + return; + if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) + return; + if(box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next) + return; + box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)arm64_next; +} +uintptr_t getJumpTable64() +{ + return (uintptr_t)box64_jmptbl3; +} + +uintptr_t getJumpTableAddress64(uintptr_t addr) +{ + uintptr_t idx3, idx2, idx1, idx0; + idx3 = (((uintptr_t)addr)>>48)&0xffff; + idx2 = (((uintptr_t)addr)>>32)&0xffff; + idx1 = (((uintptr_t)addr)>>16)&0xffff; + idx0 = (((uintptr_t)addr) )&0xffff; + if(box64_jmptbl3[idx3] == box64_jmptbldefault2) { + uintptr_t*** tbl = (uintptr_t***)malloc((1< %p\n", (void*)addr, (void*)(addr+size-1)); -// uintptr_t idx = (addr>>MEMPROT_SHIFT); -// uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT); -// pthread_mutex_lock(&mutex_prot); -// for (uintptr_t i=idx; i<=end; ++i) { -// uint32_t prot = memprot[i]; -// if(!prot) -// prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute -// memprot[i] = prot|PROT_DYNAREC; -// if(!(prot&PROT_DYNAREC)) -// mprotect((void*)(i< %p\n", (void*)addr, (void*)(addr+size-1)); -// uintptr_t idx = (addr>>MEMPROT_SHIFT); -// uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT); -// for (uintptr_t i=idx; i<=end; ++i) { -// uint32_t prot = memprot[i]; -// if(!prot) -// prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute -// memprot[i] = prot|PROT_DYNAREC; -// if(!(prot&PROT_DYNAREC)) -// mprotect((void*)(i< %p\n", (void*)addr, (void*)(addr+size-1)); + uintptr_t idx = (addr>>MEMPROT_SHIFT); + uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT); + int ret; + pthread_mutex_lock(&mutex_prot); + for (uintptr_t i=idx; i<=end; ++i) { + const uint32_t key = (i>>16)&0xffffffff; + khint_t k = kh_put(memprot, memprot, key, &ret); + if(ret) { + uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE); + kh_value(memprot, k) = m; + } + const uintptr_t ii = i&(MEMPROT_SIZE-1); + uint8_t prot = kh_value(memprot, k)[ii]; + if(!prot) + prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute + kh_value(memprot, k)[ii] = prot|PROT_DYNAREC; + if(!(prot&PROT_DYNAREC)) + mprotect((void*)(i< %p\n", (void*)addr, (void*)(addr+size-1)); + uintptr_t idx = (addr>>MEMPROT_SHIFT); + uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT); + int ret; + for (uintptr_t i=idx; i<=end; ++i) { + const uint32_t key = (i>>16)&0xffffffff; + khint_t k = kh_put(memprot, memprot, key, &ret); + if(ret) { + uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE); + kh_value(memprot, k) = m; + } + const uintptr_t ii = i&(MEMPROT_SIZE-1); + uint8_t prot = kh_value(memprot, k)[ii]; + if(!prot) + prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute + kh_value(memprot, k)[ii] = prot|PROT_DYNAREC; + if(!(prot&PROT_DYNAREC)) + mprotect((void*)(i< %p\n", (void*)addr, (void*)(addr+size-1)); -// uintptr_t idx = (addr>>MEMPROT_SHIFT); -// uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT); -// pthread_mutex_lock(&mutex_prot); -// for (uintptr_t i=idx; i<=end; ++i) { -// uint32_t prot = memprot[i]; -// memprot[i] = prot&~PROT_DYNAREC; -// if(prot&PROT_DYNAREC) { -// mprotect((void*)(i< %p\n", (void*)addr, (void*)(addr+size-1)); + uintptr_t idx = (addr>>MEMPROT_SHIFT); + uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT); + int ret; + pthread_mutex_lock(&mutex_prot); + for (uintptr_t i=idx; i<=end; ++i) { + const uint32_t key = (i>>16)&0xffffffff; + khint_t k = kh_put(memprot, memprot, key, &ret); + if(ret) { + uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE); + kh_value(memprot, k) = m; + } + const uintptr_t ii = i&(MEMPROT_SIZE-1); + uint8_t prot = kh_value(memprot, k)[ii]; + kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC; + if(prot&PROT_DYNAREC) { + mprotect((void*)(i<>DYNAMAP_SHIFT); -// for (uintptr_t i=idx; i<=end; ++i) { -// dynablocklist_t* dblist = dynmap[i]; -// if(dblist) { -// uintptr_t startdb = StartDynablockList(dblist); -// uintptr_t enddb = EndDynablockList(dblist); -// uintptr_t startaddr = 0; -// if(startaddrenddb) endaddr = enddb; -// FreeRangeDynablock(dblist, startaddr, endaddr-startaddr+1); -// } -// } -// for (uintptr_t i=idx; i<=end; ++i) -// if(dynmap[i]) -// FreeDynablockList(&dynmap[i]); -// pthread_mutex_destroy(&mutex_mmap); -// free(mmaplist); -// for (int i=0; i