From 741d1e9d3f368908e3cd1861ddd707e81e1fd576 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 15 Nov 2023 18:35:23 -0700 Subject: [PATCH 1/8] bootstd: Avoid freeing a non-allocated buffer EFI applications can be very large and thus used to cause boot failures when malloc() space was exhausted. A recent changed fixed this by using the kernel_addr_r environment var as the address of the buffer. However, it still frees the buffer when the bootflow is discarded. Fix this by introducing a flag to indicate whether the buffer was allocated, or not. Note that kernel_addr_r is not the last word here. It might be better to use lmb to place images. But there is a lot of refactoring to do before we can remove the environment variables. The distro scripts rely on them so it is safe for bootstd to do so too. Fixes: 6a8c2f9781c bootstd: Avoid allocating memory for the EFI file Signed-off-by: Simon Glass Reported by: Simon Glass Reported by: Shantur Rathore Reviewed-by: Heinrich Schuchardt Tested-by: Shantur Rathore --- boot/bootflow.c | 3 ++- boot/bootmeth_efi.c | 1 + include/bootflow.h | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index 6922e7e0c4e..1ea2966ae9a 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -467,7 +467,8 @@ void bootflow_free(struct bootflow *bflow) free(bflow->name); free(bflow->subdir); free(bflow->fname); - free(bflow->buf); + if (!(bflow->flags & BOOTFLOWF_STATIC_BUF)) + free(bflow->buf); free(bflow->os_name); free(bflow->fdt_fname); free(bflow->bootmeth_priv); diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index ae936c8daa1..9ba7734911e 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -160,6 +160,7 @@ static int efiload_read_file(struct bootflow *bflow, ulong addr) if (ret) return log_msg_ret("read", ret); bflow->buf = map_sysmem(addr, bflow->size); + bflow->flags |= BOOTFLOWF_STATIC_BUF; set_efi_bootdev(desc, bflow); diff --git a/include/bootflow.h b/include/bootflow.h index 44d3741eaca..fede8f22a2b 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -43,9 +43,12 @@ enum bootflow_state_t { * and it is using the prior-stage FDT, which is the U-Boot control FDT. * This is only possible with the EFI bootmeth (distro-efi) and only when * CONFIG_OF_HAS_PRIOR_STAGE is enabled + * @BOOTFLOWF_STATIC_BUF: Indicates that @bflow->buf is statically set, rather + * than being allocated by malloc(). */ enum bootflow_flags_t { BOOTFLOWF_USE_PRIOR_FDT = 1 << 0, + BOOTFLOWF_STATIC_BUF = 1 << 1, }; /** @@ -72,7 +75,7 @@ enum bootflow_flags_t { * @fname: Filename of bootflow file (allocated) * @logo: Logo to display for this bootflow (BMP format) * @logo_size: Size of the logo in bytes - * @buf: Bootflow file contents (allocated) + * @buf: Bootflow file contents (allocated unless @flags & BOOTFLOWF_STATIC_BUF) * @size: Size of bootflow file in bytes * @err: Error number received (0 if OK) * @os_name: Name of the OS / distro being booted, or NULL if not known From 45c4b276f0a4d67e06c94de3d0a5dadf4bee530a Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 7 Nov 2023 16:09:00 +0000 Subject: [PATCH 2/8] virtio: rng: gracefully handle 0 byte returns According to the virtio v1.x "entropy device" specification, a virtio-rng device is supposed to always return at least one byte of entropy. However the virtio v0.9 spec does not mention such a requirement. The Arm Fixed Virtual Platform (FVP) implementation of virtio-rng always returns 8 bytes less of entropy than requested. If 8 bytes or less are requested, it will return 0 bytes. This behaviour makes U-Boot's virtio_rng_read() implementation go into an endless loop, hanging the system. Work around this problem by always requesting 8 bytes more than needed, but only if a previous call to virtqueue_get_buf() returned 0 bytes. This should never trigger on a v1.x spec compliant implementation, but fixes the hang on the Arm FVP. Signed-off-by: Andre Przywara Reported-by: Peter Hoyes --- drivers/virtio/virtio_rng.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_rng.c b/drivers/virtio/virtio_rng.c index b85545c2ee5..786359a6e36 100644 --- a/drivers/virtio/virtio_rng.c +++ b/drivers/virtio/virtio_rng.c @@ -20,7 +20,7 @@ struct virtio_rng_priv { static int virtio_rng_read(struct udevice *dev, void *data, size_t len) { int ret; - unsigned int rsize; + unsigned int rsize = 1; unsigned char buf[BUFFER_SIZE] __aligned(4); unsigned char *ptr = data; struct virtio_sg sg; @@ -29,7 +29,12 @@ static int virtio_rng_read(struct udevice *dev, void *data, size_t len) while (len) { sg.addr = buf; - sg.length = min(len, sizeof(buf)); + /* + * Work around implementations which always return 8 bytes + * less than requested, down to 0 bytes, which would + * cause an endless loop otherwise. + */ + sg.length = min(rsize ? len : len + 8, sizeof(buf)); sgs[0] = &sg; ret = virtqueue_add(priv->rng_vq, sgs, 0, 1); From e319ef02fb5accff6372ccbd23556713c3d1945d Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 14 Nov 2023 11:30:17 +0000 Subject: [PATCH 3/8] spl: fix TPL_SYS_MALLOC_F description This config option enables the malloc() pool in TPL not the SPL. Fix the description to accurately reflect this. Fixes: fd8497dae54 (spl: Create proper symbols for enabling the malloc() pool) Signed-off-by: John Keeping Reviewed-by: Simon Glass --- Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kconfig b/Kconfig index 7df91d789f6..00ed1ecc173 100644 --- a/Kconfig +++ b/Kconfig @@ -327,7 +327,7 @@ config SPL_SYS_MALLOC_F_LEN malloc() region in SDRAM once it is inited. config TPL_SYS_MALLOC_F - bool "Enable malloc() pool in SPL" + bool "Enable malloc() pool in TPL" depends on SYS_MALLOC_F && TPL default y if SPL_SYS_MALLOC_F help From e2dcadbba4ecbe5e58289996cabaf78fa62f964b Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Thu, 26 Oct 2023 09:32:19 +0200 Subject: [PATCH 4/8] imx: spl_imx_romapi: fix comment about stream(usb) download failure Fix comment about Stream(USB) download failure. Fixes: 1cbebc786276 ("imx: add rom api support") Signed-off-by: Marcel Ziswiler Reviewed-by: Fabio Estevam --- arch/arm/mach-imx/spl_imx_romapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 93d48e56aca..cb220869b50 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -285,7 +285,7 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, ret = rom_api_download_image(p, 0, pg); if (ret != ROM_API_OKAY) { - puts("Steam(USB) download failure\n"); + puts("Stream(USB) download failure\n"); return -1; } @@ -305,7 +305,7 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, ret = rom_api_download_image(p, 0, pg); if (ret != ROM_API_OKAY) { - puts("Steam(USB) download failure\n"); + puts("Stream(USB) download failure\n"); return -1; } From ac33a7976a5631e05fdb8f6c75be5f824dcf5229 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Thu, 26 Oct 2023 09:32:20 +0200 Subject: [PATCH 5/8] imx: spl_imx_romapi: fix emmc fast boot mode case This fixes a regression in the eMMC fast boot mode case where the buffer was missing 464 bytes. The code figures out how many bytes must at least be fetched to honor the current read, rounds that up to the ss->pagesize [which is a no-op in the USB download case because that has ->pagesize==1], fetches that many bytes, but then recorded the original upper bound as the new end of the valid data. However, this did not take into account the rounding up to the ss->pagesize. Fix this by recording the actual bytes downloaded. Fixes: 4b4472438f5a ("imx: spl_imx_romapi: avoid tricky use of spl_load_simple_fit() to get full FIT size") Signed-off-by: Marcel Ziswiler Acked-by: Rasmus Villemoes Reviewed-by: Fabio Estevam --- arch/arm/mach-imx/spl_imx_romapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index cb220869b50..5eb5a3d3c4a 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -162,7 +162,7 @@ static ulong spl_romapi_read_stream(struct spl_load_info *load, ulong sector, return 0; } - ss->end = end; + ss->end += bytes; } memcpy(buf, (void *)(sector), count); From ee23d7466c77d01ee63efb76db2c5fd3b7cdd6f7 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 27 Oct 2023 13:23:52 +1300 Subject: [PATCH 6/8] Revert "armv8: enable HAFDBS for other ELx when FEAT_HAFDBS is present" This reverts commit c1da6fdb5c239b432440721772d993e63cfdeb20. This is part of a series trying to make use of the arm64 hardware features for tracking dirty pages. Unfortunately this series causes problems for the AC5/AC5X SoCs. Having exhausted other options the consensus seems to be reverting this series is the best course of action. Signed-off-by: Chris Packham --- arch/arm/cpu/armv8/cache_v8.c | 6 +----- arch/arm/include/asm/armv8/mmu.h | 10 ++-------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index cb1131a0480..4c6a1b1d6c5 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -94,15 +94,11 @@ u64 get_tcr(u64 *pips, u64 *pva_bits) if (el == 1) { tcr = TCR_EL1_RSVD | (ips << 32) | TCR_EPD1_DISABLE; if (gd->arch.has_hafdbs) - tcr |= TCR_EL1_HA | TCR_EL1_HD; + tcr |= TCR_HA | TCR_HD; } else if (el == 2) { tcr = TCR_EL2_RSVD | (ips << 16); - if (gd->arch.has_hafdbs) - tcr |= TCR_EL2_HA | TCR_EL2_HD; } else { tcr = TCR_EL3_RSVD | (ips << 16); - if (gd->arch.has_hafdbs) - tcr |= TCR_EL3_HA | TCR_EL3_HD; } /* PTWs cacheable, inner/outer WBWA and inner shareable */ diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 4f0adb07325..27658e56395 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -102,14 +102,8 @@ #define TCR_TG0_16K (2 << 14) #define TCR_EPD1_DISABLE (1 << 23) -#define TCR_EL1_HA BIT(39) -#define TCR_EL1_HD BIT(40) - -#define TCR_EL2_HA BIT(21) -#define TCR_EL2_HD BIT(22) - -#define TCR_EL3_HA BIT(21) -#define TCR_EL3_HD BIT(22) +#define TCR_HA BIT(39) +#define TCR_HD BIT(40) #define TCR_EL1_RSVD (1U << 31) #define TCR_EL2_RSVD (1U << 31 | 1 << 23) From eed8294b75a5908a486945ff6655d4dc9aae5fed Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 27 Oct 2023 13:23:53 +1300 Subject: [PATCH 7/8] Revert "arm64: Use level-2 for largest block mappings when FEAT_HAFDBS is present" This reverts commit 836b8d4b205d2175b57cb9ef271e638b0c116e89. This is part of a series trying to make use of the arm64 hardware features for tracking dirty pages. Unfortunately this series causes problems for the AC5/AC5X SoCs. Having exhausted other options the consensus seems to be reverting this series is the best course of action. Signed-off-by: Chris Packham --- arch/arm/cpu/armv8/cache_v8.c | 14 ++++---------- arch/arm/include/asm/global_data.h | 1 - 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 4c6a1b1d6c5..4760064ee18 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -314,7 +314,7 @@ static void map_range(u64 virt, u64 phys, u64 size, int level, for (i = idx; size; i++) { u64 next_size, *next_table; - if (level >= gd->arch.first_block_level && + if (level >= 1 && size >= map_size && !(virt & (map_size - 1))) { if (level == 3) table[i] = phys | attrs | PTE_TYPE_PAGE; @@ -353,9 +353,6 @@ static void add_map(struct mm_region *map) if (va_bits < 39) level = 1; - if (!gd->arch.first_block_level) - gd->arch.first_block_level = 1; - if (gd->arch.has_hafdbs) attrs |= PTE_DBM | PTE_RDONLY; @@ -372,7 +369,7 @@ static void count_range(u64 virt, u64 size, int level, int *cntp) for (i = idx; size; i++) { u64 next_size; - if (level >= gd->arch.first_block_level && + if (level >= 1 && size >= map_size && !(virt & (map_size - 1))) { virt += map_size; size -= map_size; @@ -413,13 +410,10 @@ __weak u64 get_page_table_size(void) u64 size, mmfr1; asm volatile("mrs %0, id_aa64mmfr1_el1" : "=r" (mmfr1)); - if ((mmfr1 & 0xf) == 2) { + if ((mmfr1 & 0xf) == 2) gd->arch.has_hafdbs = true; - gd->arch.first_block_level = 2; - } else { + else gd->arch.has_hafdbs = false; - gd->arch.first_block_level = 1; - } /* Account for all page tables we would need to cover our memory map */ size = one_pt * count_ranges(); diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index b385bae0266..1325b064424 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -52,7 +52,6 @@ struct arch_global_data { #if defined(CONFIG_ARM64) unsigned long tlb_fillptr; unsigned long tlb_emerg; - unsigned int first_block_level; bool has_hafdbs; #endif #endif From 0585c28fda1007e4a90dea5f70723cff0b63dd98 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 27 Oct 2023 13:23:54 +1300 Subject: [PATCH 8/8] Revert "arm64: Use FEAT_HAFDBS to track dirty pages when available" This reverts commit 6cdf6b7a340db4ddd008516181de7e08e3f8c213. This is part of a series trying to make use of the arm64 hardware features for tracking dirty pages. Unfortunately this series causes problems for the AC5/AC5X SoCs. Having exhausted other options the consensus seems to be reverting this series is the best course of action. Signed-off-by: Chris Packham --- arch/arm/cpu/armv8/cache_v8.c | 16 +--------------- arch/arm/include/asm/armv8/mmu.h | 14 ++++---------- arch/arm/include/asm/global_data.h | 1 - 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 4760064ee18..697334086fd 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -93,8 +93,6 @@ u64 get_tcr(u64 *pips, u64 *pva_bits) if (el == 1) { tcr = TCR_EL1_RSVD | (ips << 32) | TCR_EPD1_DISABLE; - if (gd->arch.has_hafdbs) - tcr |= TCR_HA | TCR_HD; } else if (el == 2) { tcr = TCR_EL2_RSVD | (ips << 16); } else { @@ -202,9 +200,6 @@ static void __cmo_on_leaves(void (*cmo_fn)(unsigned long, unsigned long), attrs != PTE_BLOCK_MEMTYPE(MT_NORMAL_NC)) continue; - if (gd->arch.has_hafdbs && (pte & (PTE_RDONLY | PTE_DBM)) != PTE_DBM) - continue; - end = va + BIT(level2shift(level)) - 1; /* No intersection with RAM? */ @@ -353,9 +348,6 @@ static void add_map(struct mm_region *map) if (va_bits < 39) level = 1; - if (gd->arch.has_hafdbs) - attrs |= PTE_DBM | PTE_RDONLY; - map_range(map->virt, map->phys, map->size, level, (u64 *)gd->arch.tlb_addr, attrs); } @@ -407,13 +399,7 @@ static int count_ranges(void) __weak u64 get_page_table_size(void) { u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64); - u64 size, mmfr1; - - asm volatile("mrs %0, id_aa64mmfr1_el1" : "=r" (mmfr1)); - if ((mmfr1 & 0xf) == 2) - gd->arch.has_hafdbs = true; - else - gd->arch.has_hafdbs = false; + u64 size; /* Account for all page tables we would need to cover our memory map */ size = one_pt * count_ranges(); diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 27658e56395..ce655ce7a95 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -49,13 +49,10 @@ #define PTE_TYPE_BLOCK (1 << 0) #define PTE_TYPE_VALID (1 << 0) -#define PTE_RDONLY BIT(7) -#define PTE_DBM BIT(51) - -#define PTE_TABLE_PXN BIT(59) -#define PTE_TABLE_XN BIT(60) -#define PTE_TABLE_AP BIT(61) -#define PTE_TABLE_NS BIT(63) +#define PTE_TABLE_PXN (1UL << 59) +#define PTE_TABLE_XN (1UL << 60) +#define PTE_TABLE_AP (1UL << 61) +#define PTE_TABLE_NS (1UL << 63) /* * Block @@ -102,9 +99,6 @@ #define TCR_TG0_16K (2 << 14) #define TCR_EPD1_DISABLE (1 << 23) -#define TCR_HA BIT(39) -#define TCR_HD BIT(40) - #define TCR_EL1_RSVD (1U << 31) #define TCR_EL2_RSVD (1U << 31 | 1 << 23) #define TCR_EL3_RSVD (1U << 31 | 1 << 23) diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 1325b064424..75bd9d56f89 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -52,7 +52,6 @@ struct arch_global_data { #if defined(CONFIG_ARM64) unsigned long tlb_fillptr; unsigned long tlb_emerg; - bool has_hafdbs; #endif #endif #ifdef CFG_SYS_MEM_RESERVE_SECURE