diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-02-04 11:06:35 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-02-04 11:06:35 +0000 |
commit | 071aacc9c9e15859500bbacf153e03b45008ee50 (patch) | |
tree | 1b0145834043ed90e4e051013c8229556bad65fc /target-arm | |
parent | 382d34ff9fcc534db32d54eb82590de7c04f9b33 (diff) | |
parent | 1df7d1f9303aef9a2b1f703e887553416b7c0586 (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160203' into staging
target-arm queue:
* virt-acpi-build: add always-on property for timer
* various fixes for EL2 and EL3 behaviour
* arm: virt-acpi: each MADT.GICC entry as enabled unconditionally
* target-arm: Don't report presence of EL2 if it doesn't exist
* raspi: add raspberry pi 2 machine
# gpg: Signature made Wed 03 Feb 2016 18:58:02 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
* remotes/pmaydell/tags/pull-target-arm-20160203:
raspi: add raspberry pi 2 machine
arm/boot: move highbank secure board setup code to common routine
bcm2836: add bcm2836 SoC device
bcm2836_control: add bcm2836 ARM control logic
bcm2835_peripherals: add rollup device for bcm2835 peripherals
bcm2835_ic: add bcm2835 interrupt controller
bcm2835_property: add bcm2835 property channel
bcm2835_mbox: add BCM2835 mailboxes
target-arm: Don't report presence of EL2 if it doesn't exist
libvixl: Avoid std::abs() of 64-bit type
arm: virt-acpi: each MADT.GICC entry as enabled unconditionally
target-arm: Implement the S2 MMU inputsize > pamax check
target-arm: Rename check_s2_startlevel to check_s2_mmu_setup
target-arm: Apply S2 MMU startlevel table size check to AArch64
hw/arm: Setup EL1 and EL2 in AArch64 mode for 64bit Linux boots
target-arm: Make various system registers visible to EL3
virt-acpi-build: add always-on property for timer
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/cpu.c | 9 | ||||
-rw-r--r-- | target-arm/helper.c | 94 |
2 files changed, 60 insertions, 43 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 0e582c4410..7ddbf3d19b 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -650,6 +650,15 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cpu->id_aa64pfr0 &= ~0xf000; } + if (!arm_feature(env, ARM_FEATURE_EL2)) { + /* Disable the hypervisor feature bits in the processor feature + * registers if we don't have EL2. These are id_pfr1[15:12] and + * id_aa64pfr0_el1[11:8]. + */ + cpu->id_aa64pfr0 &= ~0xf00; + cpu->id_pfr1 &= ~0xf000; + } + if (!cpu->has_mpu) { unset_feature(env, ARM_FEATURE_MPU); } diff --git a/target-arm/helper.c b/target-arm/helper.c index ae024869d0..5ea507f5bc 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3167,6 +3167,35 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .type = ARM_CP_ALIAS, .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]), .access = PL2_RW, .accessfn = fpexc32_access }, + { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0, + .access = PL2_RW, .resetvalue = 0, + .writefn = dacr_write, .raw_writefn = raw_write, + .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) }, + { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1, + .access = PL2_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) }, + { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, + { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, + { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) }, + { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_ALIAS, + .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, REGINFO_SENTINEL }; @@ -3294,11 +3323,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2), .writefn = hcr_write }, - { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0, - .access = PL2_RW, .resetvalue = 0, - .writefn = dacr_write, .raw_writefn = raw_write, - .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) }, { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1, @@ -3308,10 +3332,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) }, - { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1, - .access = PL2_RW, .resetvalue = 0, - .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) }, { .name = "FAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) }, @@ -3320,26 +3340,6 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0, .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) }, - { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, - { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, - { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) }, - { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64, - .type = ARM_CP_ALIAS, - .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3, - .access = PL2_RW, - .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0, .access = PL2_RW, .writefn = vbar_write, @@ -6763,24 +6763,34 @@ typedef enum { } MMUFaultType; /* - * check_s2_startlevel + * check_s2_mmu_setup * @cpu: ARMCPU * @is_aa64: True if the translation regime is in AArch64 state * @startlevel: Suggested starting level * @inputsize: Bitsize of IPAs * @stride: Page-table stride (See the ARM ARM) * - * Returns true if the suggested starting level is OK and false otherwise. + * Returns true if the suggested S2 translation parameters are OK and + * false otherwise. */ -static bool check_s2_startlevel(ARMCPU *cpu, bool is_aa64, int level, - int inputsize, int stride) +static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, + int inputsize, int stride) { + const int grainsize = stride + 3; + int startsizecheck; + /* Negative levels are never allowed. */ if (level < 0) { return false; } + startsizecheck = inputsize - ((3 - level) * stride + grainsize); + if (startsizecheck < 1 || startsizecheck > stride + 4) { + return false; + } + if (is_aa64) { + CPUARMState *env = &cpu->env; unsigned int pamax = arm_pamax(cpu); switch (stride) { @@ -6802,21 +6812,20 @@ static bool check_s2_startlevel(ARMCPU *cpu, bool is_aa64, int level, default: g_assert_not_reached(); } - } else { - const int grainsize = stride + 3; - int startsizecheck; + /* Inputsize checks. */ + if (inputsize > pamax && + (arm_el_is_aa64(env, 1) || inputsize > 40)) { + /* This is CONSTRAINED UNPREDICTABLE and we choose to fault. */ + return false; + } + } else { /* AArch32 only supports 4KB pages. Assert on that. */ assert(stride == 9); if (level == 0) { return false; } - - startsizecheck = inputsize - ((3 - level) * stride + grainsize); - if (startsizecheck < 1 || startsizecheck > stride + 4) { - return false; - } } return true; } @@ -7013,8 +7022,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, } /* Check that the starting level is valid. */ - ok = check_s2_startlevel(cpu, va_size == 64, level, - inputsize, stride); + ok = check_s2_mmu_setup(cpu, va_size == 64, level, inputsize, stride); if (!ok) { /* AArch64 reports these as level 0 faults. * AArch32 reports these as level 1 faults. |