From patchwork Thu Jan 31 18:47:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Evgeny Voevodin X-Patchwork-Id: 217257 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2158A2C008D for ; Fri, 1 Feb 2013 08:54:43 +1100 (EST) Received: from localhost ([::1]:57582 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U125h-0007w0-76 for incoming@patchwork.ozlabs.org; Thu, 31 Jan 2013 16:54:41 -0500 Received: from eggs.gnu.org ([208.118.235.92]:57454) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U0zAm-00075a-Q9 for qemu-devel@nongnu.org; Thu, 31 Jan 2013 13:47:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U0zAf-0006P9-3B for qemu-devel@nongnu.org; Thu, 31 Jan 2013 13:47:44 -0500 Received: from mail-lb0-f170.google.com ([209.85.217.170]:65407) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U0zAe-0006Oi-NA for qemu-devel@nongnu.org; Thu, 31 Jan 2013 13:47:37 -0500 Received: by mail-lb0-f170.google.com with SMTP id ge1so3738520lbb.1 for ; Thu, 31 Jan 2013 10:47:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=GMXCtXIBt2MqiN4099S96aHaxcYznFFG/6ae0H8VL3s=; b=WR0xAE/+3Kb9t82XB0HkFvRg8AdxD87UadQhnzkqVIpnkJsGoXGxRQ22ddUCDVoQJF g7DtU/DKyly+cfWaGXwFFIQL8rNQ15d8DBHqUnCvFR4AKjAZmRKNG545sOaCLNsDOhrA 2XfdS6Ou9fQMvgXFh0Htah3jd+30Yk4GQ6BU7Xs4lhYLY0zjw6MJT5Wz3Lg0JJkUfslt ztP09Lpwnp1jmB+oPauUSH/qCFGuF8q5V44/nWhHAWDJoJ5VVm1gGHkkyONgDjTWqh1R fQGhVKJN0ebeCjb78Q5OkUf5ea9E94zG3W0mM+2SBXJnPvIwqaBx0uIo8UdMdnzktIOK MvKw== X-Received: by 10.152.147.103 with SMTP id tj7mr8816607lab.54.1359658055395; Thu, 31 Jan 2013 10:47:35 -0800 (PST) Received: from localhost.localdomain (37-144-47-224.broadband.corbina.ru. [37.144.47.224]) by mx.google.com with ESMTPS id pk1sm2860616lab.0.2013.01.31.10.47.33 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 31 Jan 2013 10:47:34 -0800 (PST) From: Evgeny Voevodin To: qemu-devel@nongnu.org Date: Fri, 1 Feb 2013 01:47:22 +0700 Message-Id: <1359658043-2425-2-git-send-email-evgenyvoevodin@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1359658043-2425-1-git-send-email-evgenyvoevodin@gmail.com> References: <1359658043-2425-1-git-send-email-evgenyvoevodin@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.217.170 X-Mailman-Approved-At: Thu, 31 Jan 2013 16:54:05 -0500 Cc: blauwirbel@gmail.com, Evgeny Voevodin Subject: [Qemu-devel] [PATCH 1/2] TCG: Final globals clean-up X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Evgeny Voevodin --- tcg/tcg.c | 2 +- tcg/tcg.h | 14 ++++++-- translate-all.c | 97 ++++++++++++++++++++++++++++--------------------------- 3 files changed, 61 insertions(+), 52 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 9275e37..c8a843e 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -263,7 +263,7 @@ void tcg_context_init(TCGContext *s) void tcg_prologue_init(TCGContext *s) { /* init global prologue and epilogue */ - s->code_buf = code_gen_prologue; + s->code_buf = s->code_gen_prologue; s->code_ptr = s->code_buf; tcg_target_qemu_prologue(s); flush_icache_range((tcg_target_ulong)s->code_buf, diff --git a/tcg/tcg.h b/tcg/tcg.h index a427972..4086e98 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -462,6 +462,15 @@ struct TCGContext { uint16_t gen_opc_icount[OPC_BUF_SIZE]; uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; + /* Code generation */ + int code_gen_max_blocks; + uint8_t *code_gen_prologue; + uint8_t *code_gen_buffer; + size_t code_gen_buffer_size; + /* threshold to flush the translated code buffer */ + size_t code_gen_buffer_max_size; + uint8_t *code_gen_ptr; + #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) /* labels info for qemu_ld/st IRs The labels help to generate TLB miss case codes at the end of TB */ @@ -658,12 +667,11 @@ TCGv_i64 tcg_const_i64(int64_t val); TCGv_i32 tcg_const_local_i32(int32_t val); TCGv_i64 tcg_const_local_i64(int64_t val); -extern uint8_t *code_gen_prologue; - /* TCG targets may use a different definition of tcg_qemu_tb_exec. */ #if !defined(tcg_qemu_tb_exec) # define tcg_qemu_tb_exec(env, tb_ptr) \ - ((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(env, tb_ptr) + ((tcg_target_ulong (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, \ + tb_ptr) #endif void tcg_register_jit(void *buf, size_t buf_size); diff --git a/translate-all.c b/translate-all.c index d367fc4..d666562 100644 --- a/translate-all.c +++ b/translate-all.c @@ -72,21 +72,13 @@ #define SMC_BITMAP_USE_THRESHOLD 10 -/* Code generation and translation blocks */ +/* Translation blocks */ static TranslationBlock *tbs; -static int code_gen_max_blocks; TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; static int nb_tbs; /* any access to the tbs or the page table must use this lock */ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; -uint8_t *code_gen_prologue; -static uint8_t *code_gen_buffer; -static size_t code_gen_buffer_size; -/* threshold to flush the translated code buffer */ -static size_t code_gen_buffer_max_size; -static uint8_t *code_gen_ptr; - typedef struct PageDesc { /* list of TBs intersecting this ram page */ TranslationBlock *first_tb; @@ -514,7 +506,7 @@ static inline size_t size_code_gen_buffer(size_t tb_size) if (tb_size > MAX_CODE_GEN_BUFFER_SIZE) { tb_size = MAX_CODE_GEN_BUFFER_SIZE; } - code_gen_buffer_size = tb_size; + tcg_ctx.code_gen_buffer_size = tb_size; return tb_size; } @@ -524,7 +516,7 @@ static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE] static inline void *alloc_code_gen_buffer(void) { - map_exec(static_code_gen_buffer, code_gen_buffer_size); + map_exec(static_code_gen_buffer, tcg_ctx.code_gen_buffer_size); return static_code_gen_buffer; } #elif defined(USE_MMAP) @@ -547,8 +539,8 @@ static inline void *alloc_code_gen_buffer(void) Leave the choice of exact location with the kernel. */ flags |= MAP_32BIT; /* Cannot expect to map more than 800MB in low memory. */ - if (code_gen_buffer_size > 800u * 1024 * 1024) { - code_gen_buffer_size = 800u * 1024 * 1024; + if (tcg_ctx.code_gen_buffer_size > 800u * 1024 * 1024) { + tcg_ctx.code_gen_buffer_size = 800u * 1024 * 1024; } # elif defined(__sparc__) start = 0x40000000ul; @@ -556,17 +548,17 @@ static inline void *alloc_code_gen_buffer(void) start = 0x90000000ul; # endif - buf = mmap((void *)start, code_gen_buffer_size, + buf = mmap((void *)start, tcg_ctx.code_gen_buffer_size, PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0); return buf == MAP_FAILED ? NULL : buf; } #else static inline void *alloc_code_gen_buffer(void) { - void *buf = g_malloc(code_gen_buffer_size); + void *buf = g_malloc(tcg_ctx.code_gen_buffer_size); if (buf) { - map_exec(buf, code_gen_buffer_size); + map_exec(buf, tcg_ctx.code_gen_buffer_size); } return buf; } @@ -574,27 +566,30 @@ static inline void *alloc_code_gen_buffer(void) static inline void code_gen_alloc(size_t tb_size) { - code_gen_buffer_size = size_code_gen_buffer(tb_size); - code_gen_buffer = alloc_code_gen_buffer(); - if (code_gen_buffer == NULL) { + tcg_ctx.code_gen_buffer_size = size_code_gen_buffer(tb_size); + tcg_ctx.code_gen_buffer = alloc_code_gen_buffer(); + if (tcg_ctx.code_gen_buffer == NULL) { fprintf(stderr, "Could not allocate dynamic translator buffer\n"); exit(1); } - qemu_madvise(code_gen_buffer, code_gen_buffer_size, QEMU_MADV_HUGEPAGE); + qemu_madvise(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size, + QEMU_MADV_HUGEPAGE); /* Steal room for the prologue at the end of the buffer. This ensures (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches from TB's to the prologue are going to be in range. It also means that we don't need to mark (additional) portions of the data segment as executable. */ - code_gen_prologue = code_gen_buffer + code_gen_buffer_size - 1024; - code_gen_buffer_size -= 1024; + tcg_ctx.code_gen_prologue = tcg_ctx.code_gen_buffer + + tcg_ctx.code_gen_buffer_size - 1024; + tcg_ctx.code_gen_buffer_size -= 1024; - code_gen_buffer_max_size = code_gen_buffer_size - + tcg_ctx.code_gen_buffer_max_size = tcg_ctx.code_gen_buffer_size - (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); - code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; - tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock)); + tcg_ctx.code_gen_max_blocks = tcg_ctx.code_gen_buffer_size / + CODE_GEN_AVG_BLOCK_SIZE; + tbs = g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock)); } /* Must be called before using the QEMU cpus. 'tb_size' is the size @@ -604,8 +599,8 @@ void tcg_exec_init(unsigned long tb_size) { cpu_gen_init(); code_gen_alloc(tb_size); - code_gen_ptr = code_gen_buffer; - tcg_register_jit(code_gen_buffer, code_gen_buffer_size); + tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer; + tcg_register_jit(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size); page_init(); #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) /* There's no guest base to take into account, so go ahead and @@ -616,7 +611,7 @@ void tcg_exec_init(unsigned long tb_size) bool tcg_enabled(void) { - return code_gen_buffer != NULL; + return tcg_ctx.code_gen_buffer != NULL; } /* Allocate a new translation block. Flush the translation buffer if @@ -625,8 +620,9 @@ static TranslationBlock *tb_alloc(target_ulong pc) { TranslationBlock *tb; - if (nb_tbs >= code_gen_max_blocks || - (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size) { + if (nb_tbs >= tcg_ctx.code_gen_max_blocks || + (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >= + tcg_ctx.code_gen_buffer_max_size) { return NULL; } tb = &tbs[nb_tbs++]; @@ -641,7 +637,7 @@ void tb_free(TranslationBlock *tb) Ignore the hard cases and just back up if this TB happens to be the last one generated. */ if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) { - code_gen_ptr = tb->tc_ptr; + tcg_ctx.code_gen_ptr = tb->tc_ptr; nb_tbs--; } } @@ -696,12 +692,13 @@ void tb_flush(CPUArchState *env1) #if defined(DEBUG_FLUSH) printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n", - (unsigned long)(code_gen_ptr - code_gen_buffer), + (unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer), nb_tbs, nb_tbs > 0 ? - ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); + ((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer)) / + nb_tbs : 0); #endif - if ((unsigned long)(code_gen_ptr - code_gen_buffer) - > code_gen_buffer_size) { + if ((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) + > tcg_ctx.code_gen_buffer_size) { cpu_abort(env1, "Internal error: code buffer overflow\n"); } nb_tbs = 0; @@ -713,7 +710,7 @@ void tb_flush(CPUArchState *env1) memset(tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof(void *)); page_flush_tb(); - code_gen_ptr = code_gen_buffer; + tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer; /* XXX: flush processor icache at this point if cache flush is expensive */ tb_flush_count++; @@ -960,14 +957,14 @@ TranslationBlock *tb_gen_code(CPUArchState *env, /* Don't forget to invalidate previous TB info. */ tb_invalidated_flag = 1; } - tc_ptr = code_gen_ptr; + tc_ptr = tcg_ctx.code_gen_ptr; tb->tc_ptr = tc_ptr; tb->cs_base = cs_base; tb->flags = flags; tb->cflags = cflags; cpu_gen_code(env, tb, &code_gen_size); - code_gen_ptr = (void *)(((uintptr_t)code_gen_ptr + code_gen_size + - CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); + tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)tcg_ctx.code_gen_ptr + + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); /* check next page if needed */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; @@ -1312,8 +1309,9 @@ bool is_tcg_gen_code(uintptr_t tc_ptr) { /* This can be called during code generation, code_gen_buffer_max_size is used instead of code_gen_ptr for upper boundary checking */ - return (tc_ptr >= (uintptr_t)code_gen_buffer && - tc_ptr < (uintptr_t)(code_gen_buffer + code_gen_buffer_max_size)); + return (tc_ptr >= (uintptr_t)tcg_ctx.code_gen_buffer && + tc_ptr < (uintptr_t)(tcg_ctx.code_gen_buffer + + tcg_ctx.code_gen_buffer_max_size)); } #endif @@ -1328,8 +1326,8 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) if (nb_tbs <= 0) { return NULL; } - if (tc_ptr < (uintptr_t)code_gen_buffer || - tc_ptr >= (uintptr_t)code_gen_ptr) { + if (tc_ptr < (uintptr_t)tcg_ctx.code_gen_buffer || + tc_ptr >= (uintptr_t)tcg_ctx.code_gen_ptr) { return NULL; } /* binary search (cf Knuth) */ @@ -1587,16 +1585,19 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) /* XXX: avoid using doubles ? */ cpu_fprintf(f, "Translation buffer state:\n"); cpu_fprintf(f, "gen code size %td/%zd\n", - code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size); + tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer, + tcg_ctx.code_gen_buffer_max_size); cpu_fprintf(f, "TB count %d/%d\n", - nb_tbs, code_gen_max_blocks); + nb_tbs, tcg_ctx.code_gen_max_blocks); cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", nb_tbs ? target_code_size / nb_tbs : 0, max_target_code_size); cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n", - nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0, - target_code_size ? (double) (code_gen_ptr - code_gen_buffer) - / target_code_size : 0); + nb_tbs ? (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) / + nb_tbs : 0, + target_code_size ? + (double) (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) / + target_code_size : 0); cpu_fprintf(f, "cross page TB count %d (%d%%)\n", cross_page, nb_tbs ? (cross_page * 100) / nb_tbs : 0);