Demand paging on Windows

This commit is contained in:
mio
2023-01-28 22:04:43 +01:00
parent 7e4754ad00
commit 12a79192ee
5 changed files with 49 additions and 0 deletions

View File

@@ -7,3 +7,10 @@
#define CONFIG_CMPXCHG128 1 #define CONFIG_CMPXCHG128 1
// #define CONFIG_ATOMIC64 1 // #define CONFIG_ATOMIC64 1
#define CONFIG_PLUGIN 1 #define CONFIG_PLUGIN 1
// QEMU by default allocates (and commits) 1GB memory on Windows, and multiple Unicorn instances will result in OOM error easily.
// Unfortunately, Windows doesn't have a similar demand paging feature like mmap(), therefore a workaround is to use tcg regions mechanism.
// Note most Unicorn hacks (and even QEMU!) relies on the assumption that the translation memory won't run out and thus it might result
// in some unexpected errors. If that is case, define to align with QEMU and Unicorn <= 2.0.1 behavior.
//
// #define USE_STATIC_CODE_GEN_BUFFER

View File

@@ -869,6 +869,7 @@ static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
return buf; return buf;
} }
#elif defined(_WIN32) #elif defined(_WIN32)
#ifdef USE_STATIC_CODE_GEN_BUFFER
static inline void *alloc_code_gen_buffer(struct uc_struct *uc) static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
{ {
TCGContext *tcg_ctx = uc->tcg_ctx; TCGContext *tcg_ctx = uc->tcg_ctx;
@@ -876,6 +877,23 @@ static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE); PAGE_EXECUTE_READWRITE);
} }
#else
static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
{
TCGContext *tcg_ctx = uc->tcg_ctx;
size_t size = tcg_ctx->code_gen_buffer_size;
void* ptr = VirtualAlloc(NULL, size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
// for prolog init
VirtualAlloc(ptr,
uc->qemu_real_host_page_size * UC_TCG_REGION_PAGES_COUNT,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
return ptr;
}
#endif
void free_code_gen_buffer(struct uc_struct *uc) void free_code_gen_buffer(struct uc_struct *uc)
{ {
TCGContext *tcg_ctx = uc->tcg_ctx; TCGContext *tcg_ctx = uc->tcg_ctx;

View File

@@ -20,6 +20,7 @@
#ifndef QEMU_CPU_H #ifndef QEMU_CPU_H
#define QEMU_CPU_H #define QEMU_CPU_H
#include <stdint.h>
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#include "exec/memattrs.h" #include "exec/memattrs.h"
#include "qemu/bitmap.h" #include "qemu/bitmap.h"

View File

@@ -35,6 +35,11 @@
#include "tcg-apple-jit.h" #include "tcg-apple-jit.h"
#include "qemu/int128.h" #include "qemu/int128.h"
// Unicorn: Default region size for win32
#if defined(_WIN32) && !defined(USE_STATIC_CODE_GEN_BUFFER)
#define UC_TCG_REGION_PAGES_COUNT (128)
#endif
/* XXX: make safe guess about sizes */ /* XXX: make safe guess about sizes */
#define MAX_OP_PER_INSTR 266 #define MAX_OP_PER_INSTR 266

View File

@@ -23,6 +23,8 @@
*/ */
/* define it to use liveness analysis (better code) */ /* define it to use liveness analysis (better code) */
#include "tcg/tcg.h"
#include <stdio.h>
#define USE_TCG_OPTIMIZATIONS #define USE_TCG_OPTIMIZATIONS
#include "qemu/osdep.h" #include "qemu/osdep.h"
@@ -406,6 +408,13 @@ static void tcg_region_assign(TCGContext *s, size_t curr_region)
s->code_gen_buffer = start; s->code_gen_buffer = start;
s->code_gen_ptr = start; s->code_gen_ptr = start;
s->code_gen_buffer_size = (char *)end - (char *)start; s->code_gen_buffer_size = (char *)end - (char *)start;
#if defined(WIN32) && !defined(USE_STATIC_CODE_GEN_BUFFER)
VirtualAlloc(
s->code_gen_buffer,
ROUND_UP(s->code_gen_buffer_size, s->uc->qemu_real_host_page_size),
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
#endif
memset(s->code_gen_buffer, 0x00, s->code_gen_buffer_size); memset(s->code_gen_buffer, 0x00, s->code_gen_buffer_size);
s->code_gen_highwater = (char *)end - TCG_HIGHWATER; s->code_gen_highwater = (char *)end - TCG_HIGHWATER;
} }
@@ -500,7 +509,11 @@ void tcg_region_init(TCGContext *tcg_ctx)
size_t n_regions; size_t n_regions;
size_t i; size_t i;
#if defined(WIN32) && !defined(USE_STATIC_CODE_GEN_BUFFER)
n_regions = size / (tcg_ctx->uc->qemu_real_host_page_size * UC_TCG_REGION_PAGES_COUNT);
#else
n_regions = 1; n_regions = 1;
#endif
/* The first region will be 'aligned - buf' bytes larger than the others */ /* The first region will be 'aligned - buf' bytes larger than the others */
aligned = (void *)QEMU_ALIGN_PTR_UP(buf, page_size); aligned = (void *)QEMU_ALIGN_PTR_UP(buf, page_size);
@@ -537,6 +550,11 @@ void tcg_region_init(TCGContext *tcg_ctx)
} }
tcg_ctx->tree = g_tree_new(tb_tc_cmp); tcg_ctx->tree = g_tree_new(tb_tc_cmp);
#if defined(WIN32) && !defined(USE_STATIC_CODE_GEN_BUFFER)
// Allocate a region immediately, or the highwater is not set correctly.
tcg_region_alloc(tcg_ctx);
#endif
} }
/* /*