From patchwork Mon May 14 19:03:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 8636 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 7DD0323EAB for ; Mon, 14 May 2012 19:27:16 +0000 (UTC) Received: from mail-yw0-f52.google.com (mail-yw0-f52.google.com [209.85.213.52]) by fiordland.canonical.com (Postfix) with ESMTP id 4DB22A1880F for ; Mon, 14 May 2012 19:27:16 +0000 (UTC) Received: by mail-yw0-f52.google.com with SMTP id p61so5835105yhp.11 for ; Mon, 14 May 2012 12:27:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=EpUaWYPo9qgyF2dwmZ3TDEsFz53TQKwqc7mZmQAiuig=; b=BFJy2o9Z6GchF2ZRlXRfl0b6yZs4MtcXRB3jmDKdbOvfbLYLRNPSKlWcLNinXwnREA txgmZiHjl74Tags9rrol3NuRBByM/aLcoFQGrNrj0ilHJro4buR6GC74+Z7+/Ztvgs7z Viuwl7mp77txhPidua/16KCeBB1BCaG4Iy0lzQtgwZgZkl6ifeTpxsbQmvAqO5hhUE10 RMJR3UtFMDjw7sRIDPkMvWh2B2t07a2P7HHgt12ojDA3u0XX2jfHffgnWbMWysWNZ24e dn/Ioz/l1v5AndF3OYgbv8ojbcxCCIouM2JXR9xA41PGgSTo5LjhZ0lbKMES3/WdMF06 /vsg== Received: by 10.50.87.227 with SMTP id bb3mr177295igb.57.1337023635960; Mon, 14 May 2012 12:27:15 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.35.72 with SMTP id o8csp367288ibd; Mon, 14 May 2012 12:27:14 -0700 (PDT) Received: by 10.180.107.101 with SMTP id hb5mr22953089wib.7.1337023634060; Mon, 14 May 2012 12:27:14 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id s1si20608898wiy.19.2012.05.14.12.27.12 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 14 May 2012 12:27:14 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1SU0YP-0005nQ-LH; Mon, 14 May 2012 20:03:33 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Paul Brook , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Rusty Russell Subject: [PATCH qom-next v2 19/33] target-arm: Convert cp15 crn=15 registers Date: Mon, 14 May 2012 20:03:18 +0100 Message-Id: <1337022212-22219-20-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1337022212-22219-1-git-send-email-peter.maydell@linaro.org> References: <1337022212-22219-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQn/z/A49bVGwF8FYU74zQIcGw6U56c2Yt9rDo48y7+qI8Okt4mnIEvik2PzcqjFcUFkNM2I Convert the cp15 crn=15 (implementation specific) registers to the new scheme. Signed-off-by: Peter Maydell --- target-arm/cpu.c | 40 ++++++++++- target-arm/cpu.h | 1 + target-arm/helper.c | 202 ++++++++++++++++++++++----------------------------- 3 files changed, 126 insertions(+), 117 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 8fcb730..6190091 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -71,7 +71,6 @@ static void arm_cpu_reset(CPUState *s) memset(env, 0, offsetof(CPUARMState, breakpoints)); g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu); - env->cp15.c15_config_base_address = cpu->reset_cbar; env->cp15.c0_cpuid = cpu->midr; env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0; @@ -92,7 +91,6 @@ static void arm_cpu_reset(CPUState *s) env->cp15.c0_c2[3] = cpu->id_isar3; env->cp15.c0_c2[4] = cpu->id_isar4; env->cp15.c0_c2[5] = cpu->id_isar5; - env->cp15.c15_i_min = 0xff0; env->cp15.c0_clid = cpu->clidr; memcpy(env->cp15.c0_ccsid, cpu->ccsidr, ARRAY_SIZE(cpu->ccsidr)); @@ -399,6 +397,35 @@ static void cortex_a8_initfn(Object *obj) cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */ } +static const ARMCPRegInfo cortexa9_cp_reginfo[] = { + /* power_control should be set to maximum latency. Again, + * default to 0 and set by private hook + */ + { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) }, + { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1, + .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) }, + { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2, + .access = PL1_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) }, + { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST }, + /* TLB lockdown control */ + { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2, + .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP }, + { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4, + .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP }, + { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2, + .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST }, + { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2, + .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST }, + { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2, + .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST }, + REGINFO_SENTINEL +}; + static void cortex_a9_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); @@ -434,6 +461,15 @@ static void cortex_a9_initfn(Object *obj) cpu->clidr = (1 << 27) | (1 << 24) | 3; cpu->ccsidr[0] = 0xe00fe015; /* 16k L1 dcache. */ cpu->ccsidr[1] = 0x200fe015; /* 16k L1 icache. */ + { + ARMCPRegInfo cbar = { + .name = "CBAR", .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, + .opc2 = 0, .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar, + .fieldoffset = offsetof(CPUARMState, cp15.c15_config_base_address) + }; + define_one_arm_cp_reg(cpu, &cbar); + define_arm_cp_regs(cpu, cortexa9_cp_reginfo); + } } static void cortex_a15_initfn(Object *obj) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index a61cb07..b94503d 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -386,6 +386,7 @@ enum arm_features { ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */ ARM_FEATURE_GENERIC_TIMER, ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */ + ARM_FEATURE_DUMMY_C15_REGS, /* RAZ/WI all of cp15 crn=15 */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/helper.c b/target-arm/helper.c index e83f1c8..c371224 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -497,10 +497,91 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = { REGINFO_SENTINEL }; +static int omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c15_ticonfig = value & 0xe7; + /* The OS_TYPE bit in this register changes the reported CPUID! */ + env->cp15.c0_cpuid = (value & (1 << 5)) ? + ARM_CPUID_TI915T : ARM_CPUID_TI925T; + return 0; +} + +static int omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c15_threadid = value & 0xffff; + return 0; +} + +static int omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Wait-for-interrupt (deprecated) */ + cpu_interrupt(env, CPU_INTERRUPT_HALT); + return 0; +} + static const ARMCPRegInfo omap_cp_reginfo[] = { { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE, .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, }, + { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, .type = ARM_CP_NOP }, + { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, + .fieldoffset = offsetof(CPUARMState, cp15.c15_ticonfig), .resetvalue = 0, + .writefn = omap_ticonfig_write }, + { .name = "IMAX", .cp = 15, .crn = 15, .crm = 2, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, + .fieldoffset = offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = 0, }, + { .name = "IMIN", .cp = 15, .crn = 15, .crm = 3, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, .resetvalue = 0xff0, + .fieldoffset = offsetof(CPUARMState, cp15.c15_i_min) }, + { .name = "THREADID", .cp = 15, .crn = 15, .crm = 4, .opc1 = 0, .opc2 = 0, + .access = PL1_RW, + .fieldoffset = offsetof(CPUARMState, cp15.c15_threadid), .resetvalue = 0, + .writefn = omap_threadid_write }, + { .name = "TI925T_STATUS", .cp = 15, .crn = 15, + .crm = 8, .opc1 = 0, .opc2 = 0, .access = PL1_RW, + .readfn = arm_cp_read_zero, .writefn = omap_wfi_write, }, + /* TODO: Peripheral port remap register: + * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt controller + * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff), + * when MMU is off. + */ + REGINFO_SENTINEL +}; + +static int xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + value &= 0x3fff; + if (env->cp15.c15_cpar != value) { + /* Changes cp0 to cp13 behavior, so needs a TB flush. */ + tb_flush(env); + env->cp15.c15_cpar = value; + } + return 0; +} + +static const ARMCPRegInfo xscale_cp_reginfo[] = { + { .name = "XSCALE_CPAR", + .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0, .access = PL1_RW, + .fieldoffset = offsetof(CPUARMState, cp15.c15_cpar), .resetvalue = 0, + .writefn = xscale_cpar_write, }, + REGINFO_SENTINEL +}; + +static const ARMCPRegInfo dummy_c15_cp_reginfo[] = { + /* RAZ/WI the whole crn=15 space, when we don't have a more specific + * implementation of this implementation-defined space. + * Ideally this should eventually disappear in favour of actually + * implementing the correct behaviour for all cores. + */ + { .name = "C15_IMPDEF", .cp = 15, .crn = 15, + .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, + .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, REGINFO_SENTINEL }; @@ -557,6 +638,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) if (arm_feature(env, ARM_FEATURE_OMAPCP)) { define_arm_cp_regs(cpu, omap_cp_reginfo); } + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + define_arm_cp_regs(cpu, xscale_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) { + define_arm_cp_regs(cpu, dummy_c15_cp_reginfo); + } } ARMCPU *cpu_arm_init(const char *cpu_model) @@ -1807,58 +1894,6 @@ void HELPER(set_cp15)(CPUARMState *env, uint32_t insn, uint32_t val) break; case 12: /* Reserved. */ goto bad_reg; - case 15: /* Implementation specific. */ - if (arm_feature(env, ARM_FEATURE_XSCALE)) { - if (op2 == 0 && crm == 1) { - if (env->cp15.c15_cpar != (val & 0x3fff)) { - /* Changes cp0 to cp13 behavior, so needs a TB flush. */ - tb_flush(env); - env->cp15.c15_cpar = val & 0x3fff; - } - break; - } - goto bad_reg; - } - if (arm_feature(env, ARM_FEATURE_OMAPCP)) { - switch (crm) { - case 0: - break; - case 1: /* Set TI925T configuration. */ - env->cp15.c15_ticonfig = val & 0xe7; - env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */ - ARM_CPUID_TI915T : ARM_CPUID_TI925T; - break; - case 2: /* Set I_max. */ - env->cp15.c15_i_max = val; - break; - case 3: /* Set I_min. */ - env->cp15.c15_i_min = val; - break; - case 4: /* Set thread-ID. */ - env->cp15.c15_threadid = val & 0xffff; - break; - case 8: /* Wait-for-interrupt (deprecated). */ - cpu_interrupt(env, CPU_INTERRUPT_HALT); - break; - default: - goto bad_reg; - } - } - if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) { - switch (crm) { - case 0: - if ((op1 == 0) && (op2 == 0)) { - env->cp15.c15_power_control = val; - } else if ((op1 == 0) && (op2 == 1)) { - env->cp15.c15_diagnostic = val; - } else if ((op1 == 0) && (op2 == 2)) { - env->cp15.c15_power_diagnostic = val; - } - default: - break; - } - } - break; } return; bad_reg: @@ -2085,69 +2120,6 @@ uint32_t HELPER(get_cp15)(CPUARMState *env, uint32_t insn) case 11: /* TCM DMA control. */ case 12: /* Reserved. */ goto bad_reg; - case 15: /* Implementation specific. */ - if (arm_feature(env, ARM_FEATURE_XSCALE)) { - if (op2 == 0 && crm == 1) - return env->cp15.c15_cpar; - - goto bad_reg; - } - if (arm_feature(env, ARM_FEATURE_OMAPCP)) { - switch (crm) { - case 0: - return 0; - case 1: /* Read TI925T configuration. */ - return env->cp15.c15_ticonfig; - case 2: /* Read I_max. */ - return env->cp15.c15_i_max; - case 3: /* Read I_min. */ - return env->cp15.c15_i_min; - case 4: /* Read thread-ID. */ - return env->cp15.c15_threadid; - case 8: /* TI925T_status */ - return 0; - } - /* TODO: Peripheral port remap register: - * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt - * controller base address at $rn & ~0xfff and map size of - * 0x200 << ($rn & 0xfff), when MMU is off. */ - goto bad_reg; - } - if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) { - switch (crm) { - case 0: - if ((op1 == 4) && (op2 == 0)) { - /* The config_base_address should hold the value of - * the peripheral base. ARM should get this from a CPU - * object property, but that support isn't available in - * December 2011. Default to 0 for now and board models - * that care can set it by a private hook */ - return env->cp15.c15_config_base_address; - } else if ((op1 == 0) && (op2 == 0)) { - /* power_control should be set to maximum latency. Again, - default to 0 and set by private hook */ - return env->cp15.c15_power_control; - } else if ((op1 == 0) && (op2 == 1)) { - return env->cp15.c15_diagnostic; - } else if ((op1 == 0) && (op2 == 2)) { - return env->cp15.c15_power_diagnostic; - } - break; - case 1: /* NEON Busy */ - return 0; - case 5: /* tlb lockdown */ - case 6: - case 7: - if ((op1 == 5) && (op2 == 2)) { - return 0; - } - break; - default: - break; - } - goto bad_reg; - } - return 0; } bad_reg: /* ??? For debugging only. Should raise illegal instruction exception. */