From patchwork Wed Dec 5 03:15:20 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 203782 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 AC8C02C0082 for ; Wed, 5 Dec 2012 14:55:47 +1100 (EST) Received: from localhost ([::1]:53074 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tg5TJ-0008Fw-2l for incoming@patchwork.ozlabs.org; Tue, 04 Dec 2012 22:16:29 -0500 Received: from eggs.gnu.org ([208.118.235.92]:60570) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tg5Sb-0006JU-6z for qemu-devel@nongnu.org; Tue, 04 Dec 2012 22:15:47 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tg5SZ-00021t-9J for qemu-devel@nongnu.org; Tue, 04 Dec 2012 22:15:45 -0500 Received: from mail-la0-f45.google.com ([209.85.215.45]:39861) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tg5SY-00021d-Gp for qemu-devel@nongnu.org; Tue, 04 Dec 2012 22:15:42 -0500 Received: by mail-la0-f45.google.com with SMTP id p9so3416568laa.4 for ; Tue, 04 Dec 2012 19:15:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=S/x5wC25QEyWNpWBIaurLnj5afCsMuGlzMLzkSsSB00=; b=WBiTWSBk4H2SpNS3Sd+bJry51mcX5YHgYeAafGh2HVzhwgfVx8cR5Nmqn39bnHpYbT 8ZuOJgyHjFme9Jj7zYIJQ6DSUdA2ERvvK3H/n/D/mEeyNgxSQGliY8T6hYXDDrnEUuSj ltyWktsY4kgYzYO/weYLyDDeO6LPUFES13HMm52Q2pWT4suptdNnTMKMAB7COX/Vtdj8 6RFm1YjLo+ZCo03HpNk8cyx5lv0e79LKmLgPXvULBFh6HEcCZX2aYEKC5bLsF+EXbxLx brSI/OuEupDVBEj8ZlcBiKR0x0p0j2YCZHFWy0DMC5Xe35bQ4uxHwNxQNLgx/m1q4wTb fVRQ== Received: by 10.112.11.98 with SMTP id p2mr6764579lbb.34.1354677342064; Tue, 04 Dec 2012 19:15:42 -0800 (PST) Received: from octofox.metropolis ([188.134.19.124]) by mx.google.com with ESMTPS id er8sm1475005lbb.9.2012.12.04.19.15.40 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 04 Dec 2012 19:15:41 -0800 (PST) From: Max Filippov To: qemu-devel@nongnu.org Date: Wed, 5 Dec 2012 07:15:20 +0400 Message-Id: <1354677327-22552-2-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1354677327-22552-1-git-send-email-jcmvbkbc@gmail.com> References: <1354677327-22552-1-git-send-email-jcmvbkbc@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.215.45 Cc: Blue Swirl , Max Filippov Subject: [Qemu-devel] [PATCH 1/8] target-xtensa: implement ATOMCTL SR 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 ATOMCTL SR controls s32c1i opcode behavior depending on targeted memory type. See ISA, 4.3.12.4 for details. Signed-off-by: Max Filippov --- target-xtensa/cpu.c | 2 + target-xtensa/cpu.h | 10 +++++++ target-xtensa/helper.c | 56 +++++++++++++++++++++++++++++++---------- target-xtensa/helper.h | 1 + target-xtensa/op_helper.c | 57 ++++++++++++++++++++++++++++++++++++++++++ target-xtensa/overlay_tool.h | 6 ++++ target-xtensa/translate.c | 13 +++++++++ 7 files changed, 131 insertions(+), 14 deletions(-) diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c index 9d01983..c6aa45e 100644 --- a/target-xtensa/cpu.c +++ b/target-xtensa/cpu.c @@ -48,6 +48,8 @@ static void xtensa_cpu_reset(CPUState *s) XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10; env->sregs[VECBASE] = env->config->vecbase; env->sregs[IBREAKENABLE] = 0; + env->sregs[ATOMCTL] = xtensa_option_enabled(env->config, + XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15; env->pending_irq_level = 0; reset_mmu(env); diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 74e9888..d240ab7 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -65,6 +65,7 @@ enum { XTENSA_OPTION_FP_COPROCESSOR, XTENSA_OPTION_MP_SYNCHRO, XTENSA_OPTION_CONDITIONAL_STORE, + XTENSA_OPTION_ATOMCTL, /* Interrupts and exceptions */ XTENSA_OPTION_EXCEPTION, @@ -128,6 +129,7 @@ enum { ITLBCFG = 91, DTLBCFG = 92, IBREAKENABLE = 96, + ATOMCTL = 99, IBREAKA = 128, DBREAKA = 144, DBREAKC = 160, @@ -193,6 +195,14 @@ enum { #define REGION_PAGE_MASK 0xe0000000 +#define PAGE_CACHE_MASK 0x700 +#define PAGE_CACHE_SHIFT 8 +#define PAGE_CACHE_INVALID 0x000 +#define PAGE_CACHE_BYPASS 0x100 +#define PAGE_CACHE_WT 0x200 +#define PAGE_CACHE_WB 0x400 +#define PAGE_CACHE_ISOLATE 0x600 + enum { /* Static vectors */ EXC_RESET, diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index d94bae2..ecd0182 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -390,6 +390,7 @@ int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb, static unsigned mmu_attr_to_access(uint32_t attr) { unsigned access = 0; + if (attr < 12) { access |= PAGE_READ; if (attr & 0x1) { @@ -398,8 +399,22 @@ static unsigned mmu_attr_to_access(uint32_t attr) if (attr & 0x2) { access |= PAGE_WRITE; } + + switch (attr & 0xc) { + case 0: + access |= PAGE_CACHE_BYPASS; + break; + + case 4: + access |= PAGE_CACHE_WB; + break; + + case 8: + access |= PAGE_CACHE_WT; + break; + } } else if (attr == 13) { - access |= PAGE_READ | PAGE_WRITE; + access |= PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE; } return access; } @@ -410,14 +425,17 @@ static unsigned mmu_attr_to_access(uint32_t attr) */ static unsigned region_attr_to_access(uint32_t attr) { - unsigned access = 0; - if ((attr < 6 && attr != 3) || attr == 14) { - access |= PAGE_READ | PAGE_WRITE; - } - if (attr > 0 && attr < 6) { - access |= PAGE_EXEC; - } - return access; + static const unsigned access[16] = { + [0] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_WT, + [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT, + [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS, + [3] = PAGE_EXEC | PAGE_CACHE_WB, + [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB, + [5] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB, + [14] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE, + }; + + return access[attr & 0xf]; } static bool is_access_granted(unsigned access, int is_write) @@ -566,7 +584,7 @@ int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, } else { *paddr = vaddr; *page_size = TARGET_PAGE_SIZE; - *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + *access = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS; return 0; } } @@ -599,24 +617,34 @@ static void dump_tlb(FILE *f, fprintf_function cpu_fprintf, xtensa_tlb_get_entry(env, dtlb, wi, ei); if (entry->asid) { + static const char * const cache_text[8] = { + [PAGE_CACHE_BYPASS >> PAGE_CACHE_SHIFT] = "Bypass", + [PAGE_CACHE_WT >> PAGE_CACHE_SHIFT] = "WT", + [PAGE_CACHE_WB >> PAGE_CACHE_SHIFT] = "WB", + [PAGE_CACHE_ISOLATE >> PAGE_CACHE_SHIFT] = "Isolate", + }; unsigned access = attr_to_access(entry->attr); + unsigned cache_idx = (access & PAGE_CACHE_MASK) >> + PAGE_CACHE_SHIFT; if (print_header) { print_header = false; cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text); cpu_fprintf(f, - "\tVaddr Paddr ASID Attr RWX\n" - "\t---------- ---------- ---- ---- ---\n"); + "\tVaddr Paddr ASID Attr RWX Cache\n" + "\t---------- ---------- ---- ---- --- -------\n"); } cpu_fprintf(f, - "\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c\n", + "\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %-7s\n", entry->vaddr, entry->paddr, entry->asid, entry->attr, (access & PAGE_READ) ? 'R' : '-', (access & PAGE_WRITE) ? 'W' : '-', - (access & PAGE_EXEC) ? 'X' : '-'); + (access & PAGE_EXEC) ? 'X' : '-', + cache_text[cache_idx] ? cache_text[cache_idx] : + "Invalid"); } } } diff --git a/target-xtensa/helper.h b/target-xtensa/helper.h index 1163c09..5b4cd27 100644 --- a/target-xtensa/helper.h +++ b/target-xtensa/helper.h @@ -23,6 +23,7 @@ DEF_HELPER_3(waiti, void, env, i32, i32) DEF_HELPER_3(timer_irq, void, env, i32, i32) DEF_HELPER_2(advance_ccount, void, env, i32) DEF_HELPER_1(check_interrupts, void, env) +DEF_HELPER_3(check_atomctl, void, env, i32, i32) DEF_HELPER_2(wsr_rasid, void, env, i32) DEF_HELPER_FLAGS_3(rtlb0, TCG_CALL_NO_RWG_SE, i32, env, i32, i32) diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index ae0c099..0e0f21d 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -415,6 +415,63 @@ void HELPER(check_interrupts)(CPUXtensaState *env) check_interrupts(env); } +/*! + * Check vaddr accessibility/cache attributes and raise an exception if + * specified by the ATOMCTL SR. + * + * Note: local memory exclusion is not implemented + */ +void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr) +{ + uint32_t paddr, page_size, access; + uint32_t atomctl = env->sregs[ATOMCTL]; + int rc = xtensa_get_physical_addr(env, true, vaddr, 1, + xtensa_get_cring(env), &paddr, &page_size, &access); + + /* + * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions, + * see opcode description in the ISA + */ + if (rc == 0 && + (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) { + rc = STORE_PROHIBITED_CAUSE; + } + + if (rc) { + HELPER(exception_cause_vaddr)(env, pc, rc, vaddr); + } + + /* + * When data cache is not configured use ATOMCTL bypass field. + * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL) + * under the Conditional Store Option. + */ + if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { + access = PAGE_CACHE_BYPASS; + } + + switch (access & PAGE_CACHE_MASK) { + case PAGE_CACHE_WB: + atomctl >>= 2; + case PAGE_CACHE_WT: + atomctl >>= 2; + case PAGE_CACHE_BYPASS: + if ((atomctl & 0x3) == 0) { + HELPER(exception_cause_vaddr)(env, pc, + LOAD_STORE_ERROR_CAUSE, vaddr); + } + break; + + case PAGE_CACHE_ISOLATE: + HELPER(exception_cause_vaddr)(env, pc, + LOAD_STORE_ERROR_CAUSE, vaddr); + break; + + default: + break; + } +} + void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v) { v = (v & 0xffffff00) | 0x1; diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h index e395053..50bf573 100644 --- a/target-xtensa/overlay_tool.h +++ b/target-xtensa/overlay_tool.h @@ -42,6 +42,10 @@ #define XCHAL_VECBASE_RESET_VADDR 0 #endif +#ifndef XCHAL_HW_MIN_VERSION +#define XCHAL_HW_MIN_VERSION 0 +#endif + #define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0) #define XTENSA_OPTIONS ( \ @@ -62,6 +66,8 @@ XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \ XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \ XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \ + XCHAL_OPTION(XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION >= 230000, \ + XTENSA_OPTION_ATOMCTL) | \ /* Interrupts and exceptions */ \ XCHAL_OPTION(XCHAL_HAVE_EXCEPTIONS, XTENSA_OPTION_EXCEPTION) | \ XCHAL_OPTION(XCHAL_HAVE_VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR) | \ diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index e5a3f49..2ba2360 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -99,6 +99,7 @@ static const char * const sregnames[256] = { [ITLBCFG] = "ITLBCFG", [DTLBCFG] = "DTLBCFG", [IBREAKENABLE] = "IBREAKENABLE", + [ATOMCTL] = "ATOMCTL", [IBREAKA] = "IBREAKA0", [IBREAKA + 1] = "IBREAKA1", [DBREAKA] = "DBREAKA0", @@ -556,6 +557,11 @@ static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) gen_jumpi_check_loop_end(dc, 0); } +static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) +{ + tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f); +} + static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) { unsigned id = sr - IBREAKA; @@ -693,6 +699,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) [ITLBCFG] = gen_wsr_tlbcfg, [DTLBCFG] = gen_wsr_tlbcfg, [IBREAKENABLE] = gen_wsr_ibreakenable, + [ATOMCTL] = gen_wsr_atomctl, [IBREAKA] = gen_wsr_ibreaka, [IBREAKA + 1] = gen_wsr_ibreaka, [DBREAKA] = gen_wsr_dbreaka, @@ -2317,10 +2324,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) int label = gen_new_label(); TCGv_i32 tmp = tcg_temp_local_new_i32(); TCGv_i32 addr = tcg_temp_local_new_i32(); + TCGv_i32 tpc; tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]); tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); gen_load_store_alignment(dc, 2, addr, true); + + gen_advance_ccount(dc); + tpc = tcg_const_i32(dc->pc); + gen_helper_check_atomctl(cpu_env, tpc, addr); tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring); tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T], cpu_SR[SCOMPARE1], label); @@ -2328,6 +2340,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) tcg_gen_qemu_st32(tmp, addr, dc->cring); gen_set_label(label); + tcg_temp_free(tpc); tcg_temp_free(addr); tcg_temp_free(tmp); }