From patchwork Sun Apr 15 13:46:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 7838 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 DB26023E47 for ; Sun, 15 Apr 2012 13:46:36 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 85319A18189 for ; Sun, 15 Apr 2012 13:46:36 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id e36so8543068iag.11 for ; Sun, 15 Apr 2012 06:46:36 -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=U1fJOh2vDa6bvCV7FESJVuuo4aXXoVFUgq6/ados3Ag=; b=PsWXBRhanRITIEzdHAoItdN0pZcQXDrmAfRNRuysns0rnEfU+xsfTphO4Fqx1+5NVx TOzrO5XflqGnM2stLA2d42X4mk21iPbYoTmtgaYVuwedScdunwrqqjJxTxHsO2C8kfwO 3R9TwsPwHDeVsqSxmzvsoMPTVLsfrG1ETHuUif/DwFfNUXdANC9e2A+Srqgp5y4UdLIf a2ARb0JMqo4DIHmdO5keksTq7tPXv525jR8DjtDNXxxy579YBgUEOebVzhnKsvlNxJS1 WL6D0DVaE9JpdbabDW+pdCWR6cZkAiLL/RnAw7JujhL4djzBwxjam6xRXFZRZ1cepY/G sX1A== Received: by 10.50.187.226 with SMTP id fv2mr3152345igc.40.1334497596291; Sun, 15 Apr 2012 06:46:36 -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.70.69 with SMTP id c5csp22202ibj; Sun, 15 Apr 2012 06:46:34 -0700 (PDT) Received: by 10.68.221.197 with SMTP id qg5mr17758888pbc.57.1334497593786; Sun, 15 Apr 2012 06:46:33 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id to9si5120274pbc.221.2012.04.15.06.46.32 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 15 Apr 2012 06:46:33 -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 1SJPmd-0000F5-4g; Sun, 15 Apr 2012 14:46:27 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, =?UTF-8?q?Andreas=20F=C3=A4rber?= , Paul Brook Subject: [PATCH 18/32] target-arm: Convert cp15 crn=15 registers Date: Sun, 15 Apr 2012 14:46:11 +0100 Message-Id: <1334497585-867-19-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1334497585-867-1-git-send-email-peter.maydell@linaro.org> References: <1334497585-867-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQkPygb5tSa0oFgsihyg6g0yqZJwxMsSuMmaBMKlhx6b4mY90E1XPzldnMiqEL09v1i1X8WV 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 083da3e..cf59e08 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(env->cp_regs, cp_reg_reset, env); - 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)); @@ -392,6 +390,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); @@ -426,6 +453,15 @@ static void cortex_a9_initfn(Object *obj) cpu->clidr = (1 << 27) | (2 << 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->env, &cbar); + define_arm_cp_regs(&cpu->env, cortexa9_cp_reginfo); + } } static void cortex_a15_initfn(Object *obj) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index c23c760..4df35e2 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -383,6 +383,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 463ae4f..6a7ac5b 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -498,10 +498,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, .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 }; @@ -558,6 +639,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) if (arm_feature(env, ARM_FEATURE_OMAPCP)) { define_arm_cp_regs(env, omap_cp_reginfo); } + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + define_arm_cp_regs(env, xscale_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) { + define_arm_cp_regs(env, dummy_c15_cp_reginfo); + } } CPUARMState *cpu_arm_init(const char *cpu_model) @@ -1790,58 +1877,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: @@ -2068,69 +2103,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. */