diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index 6621ab7205..32dc5eb22e 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -79,6 +79,10 @@ virtualization Set ``on``/``off`` to enable/disable emulating a guest CPU which implements the Arm Virtualization Extensions. The default is ``off``. +mte + Set ``on``/``off`` to enable/disable emulating a guest CPU which implements the + Arm Memory Tagging Extensions. The default is ``off``. + highmem Set ``on``/``off`` to enable/disable placing devices and RAM in physical address space above 32 bits. The default is ``on`` for machine types diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index b363bc331d..f0ee9f51ca 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -204,16 +204,12 @@ static int acpi_ghes_record_mem_error(uint64_t error_block_address, /* This is the length if adding a new generic error data entry*/ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH; - /* - * Check whether it will run out of the preallocated memory if adding a new - * generic error data entry + * It should not run out of the preallocated memory if adding a new generic + * error data entry */ - if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) { - error_report("Not enough memory to record new CPER!!!"); - g_array_free(block, true); - return -1; - } + assert((data_length + ACPI_GHES_GESB_SIZE) <= + ACPI_GHES_MAX_RAW_DATA_LENGTH); /* Build the new generic error status block header */ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE, diff --git a/hw/arm/boot.c b/hw/arm/boot.c index fef4072db1..3e9816af80 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -736,6 +736,12 @@ static void do_cpu_reset(void *opaque) } else { env->pstate = PSTATE_MODE_EL1h; } + if (cpu_isar_feature(aa64_pauth, cpu)) { + env->cp15.scr_el3 |= SCR_API | SCR_APK; + } + if (cpu_isar_feature(aa64_mte, cpu)) { + env->cp15.scr_el3 |= SCR_ATA; + } /* AArch64 kernels never boot in secure mode */ assert(!info->secure_boot); /* This hook is only supported for AArch32 currently: diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index 0737d8de81..855848b7d2 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -255,6 +255,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp) AspeedSDMCState *s = ASPEED_SDMC(dev); AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); + assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */ s->max_ram_size = asc->max_ram_size; memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s, @@ -341,7 +342,7 @@ static void aspeed_2400_sdmc_class_init(ObjectClass *klass, void *data) AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass); dc->desc = "ASPEED 2400 SDRAM Memory Controller"; - asc->max_ram_size = 512 << 20; + asc->max_ram_size = 512 * MiB; asc->compute_conf = aspeed_2400_sdmc_compute_conf; asc->write = aspeed_2400_sdmc_write; asc->valid_ram_sizes = aspeed_2400_ram_sizes; @@ -408,7 +409,7 @@ static void aspeed_2500_sdmc_class_init(ObjectClass *klass, void *data) AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass); dc->desc = "ASPEED 2500 SDRAM Memory Controller"; - asc->max_ram_size = 1024 << 20; + asc->max_ram_size = 1 * GiB; asc->compute_conf = aspeed_2500_sdmc_compute_conf; asc->write = aspeed_2500_sdmc_write; asc->valid_ram_sizes = aspeed_2500_ram_sizes; @@ -485,7 +486,7 @@ static void aspeed_2600_sdmc_class_init(ObjectClass *klass, void *data) AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass); dc->desc = "ASPEED 2600 SDRAM Memory Controller"; - asc->max_ram_size = 2048 << 20; + asc->max_ram_size = 2 * GiB; asc->compute_conf = aspeed_2600_sdmc_compute_conf; asc->write = aspeed_2600_sdmc_write; asc->valid_ram_sizes = aspeed_2600_ram_sizes; diff --git a/target/arm/helper.c b/target/arm/helper.c index c69a2baf1d..8ef0fb478f 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10204,21 +10204,11 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, int s2prot; int ret; ARMCacheAttrs cacheattrs = {}; - ARMCacheAttrs *pcacheattrs = NULL; - - if (env->cp15.hcr_el2 & HCR_PTW) { - /* - * PTW means we must fault if this S1 walk touches S2 Device - * memory; otherwise we don't care about the attributes and can - * save the S2 translation the effort of computing them. - */ - pcacheattrs = &cacheattrs; - } ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, ARMMMUIdx_Stage2, false, &s2pa, &txattrs, &s2prot, &s2size, fi, - pcacheattrs); + &cacheattrs); if (ret) { assert(fi->type != ARMFault_None); fi->s2addr = addr; @@ -10226,8 +10216,11 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, fi->s1ptw = true; return ~0; } - if (pcacheattrs && (pcacheattrs->attrs & 0xf0) == 0) { - /* Access was to Device memory: generate Permission fault */ + if ((env->cp15.hcr_el2 & HCR_PTW) && (cacheattrs.attrs & 0xf0) == 0) { + /* + * PTW set and S1 walk touched S2 Device memory: + * generate Permission fault. + */ fi->type = ARMFault_Permission; fi->s2addr = addr; fi->stage2 = true; diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index 5ea57d487a..104752041f 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -24,6 +24,8 @@ #include "exec/ram_addr.h" #include "exec/cpu_ldst.h" #include "exec/helper-proto.h" +#include "qapi/error.h" +#include "qemu/guest-random.h" static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude) @@ -211,16 +213,37 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, uint64_t HELPER(irg)(CPUARMState *env, uint64_t rn, uint64_t rm) { - int rtag; - - /* - * Our IMPDEF choice for GCR_EL1.RRND==1 is to behave as if - * GCR_EL1.RRND==0, always producing deterministic results. - */ uint16_t exclude = extract32(rm | env->cp15.gcr_el1, 0, 16); + int rrnd = extract32(env->cp15.gcr_el1, 16, 1); int start = extract32(env->cp15.rgsr_el1, 0, 4); int seed = extract32(env->cp15.rgsr_el1, 8, 16); - int offset, i; + int offset, i, rtag; + + /* + * Our IMPDEF choice for GCR_EL1.RRND==1 is to continue to use the + * deterministic algorithm. Except that with RRND==1 the kernel is + * not required to have set RGSR_EL1.SEED != 0, which is required for + * the deterministic algorithm to function. So we force a non-zero + * SEED for that case. + */ + if (unlikely(seed == 0) && rrnd) { + do { + Error *err = NULL; + uint16_t two; + + if (qemu_guest_getrandom(&two, sizeof(two), &err) < 0) { + /* + * Failed, for unknown reasons in the crypto subsystem. + * Best we can do is log the reason and use a constant seed. + */ + qemu_log_mask(LOG_UNIMP, "IRG: Crypto failure: %s\n", + error_get_pretty(err)); + error_free(err); + two = 1; + } + seed = two; + } while (seed == 0); + } /* RandomTag */ for (i = offset = 0; i < 4; ++i) {