mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 13:56:20 +00:00
Up to now we configure the entire memory space for U-Boot as RWX.
For modern architectures and security requirements, it's better to map the memory properly. This pull request adds basics support for mapping the U-Boot binary with proper (RO, RW, RW^X) memory permissions on aarch64 right after we relocate U-Boot in the top of DRAM. It's worrth noting that the linker script annotations are only added for the aarch64 architecture. We can, in the future, try to unify the linker -- at least for the architectures that have enough in common and expand this -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEgWII69YpahbL5iK5gS8AYozs+qIFAmfUFksACgkQgS8AYozs +qLa0hAAg/wmSJhOfzYw+7fMsQebtWMcY7dEa88u3I5QyUQfYFujXuVj+Y5PbguR o6DsO26HVRwzo/+YSdVih+GTS1C0BVGVdNE5HZmM1ju4lzgnsZHLuiNx7859Uq0H 8PWpGb7okB9m22YBOqbXaj5o7QFryU6AU5gEBJYCV6aRxXv5Ha4VoQsdrOkj9eVN 8QHm5m7EKApYPmjDRul1TNlFNUjhmDNkcEij4pmpNAOl92zbyn4r62c6/u3jYov7 P9eFt9CLnkCm8k86e+ciXUvykSNxhNGSvCUMLwDJA3oqizBJPfvYF5yyHW0LeCi+ pXYtxQ9igGfh+AYeEn4vxYcLqIf1Iqr78QKg/De3Vok6e7+UJBOspxCUS/gxjvAi Yn1/n31KzaP9hAJKcZ+NTAKOhgyENnDIZ/qSTMhEDwXbiWmn36hGJlnZZE610TbR zxgeYChCbcI7eXq/wCJDPNVP51xMh/MZUGup3rREp/0YG5Cl1dMJ1WjcX1O0W1u3 WKv8MZ6XP5fKTR8dUr+H4V3tcJ6VGuMQ1oHH9xZ/dar4RMboFPMZeFFIzhBIOQT4 rcQfjmORrQ/ES6Inv+7QgjpZScJ8E+8yFEW1o9y+7tOf+CL8Jq+l0OW9NdNcRRox MxrgAIRkdAiKQj2qvLqV2RGhc/OSa/U75cLbVEcTjcJ+ya/0wfg= =AKxY -----END PGP SIGNATURE----- Merge tag 'mmu-next-14032025' of https://source.denx.de/u-boot/custodians/u-boot-tpm into next Up to now we configure the entire memory space for U-Boot as RWX. For modern architectures and security requirements, it's better to map the memory properly. This pull request adds basics support for mapping the U-Boot binary with proper (RO, RW, RW^X) memory permissions on aarch64 right after we relocate U-Boot in the top of DRAM. It's worrth noting that the linker script annotations are only added for the aarch64 architecture. We can, in the future, try to unify the linker -- at least for the architectures that have enough in common and expand this
This commit is contained in:
commit
973c366ce6
21 changed files with 313 additions and 60 deletions
|
@ -8,6 +8,7 @@
|
|||
#include <asm/global_data.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <asm/arcregs.h>
|
||||
|
@ -819,3 +820,8 @@ void sync_n_cleanup_cache_all(void)
|
|||
|
||||
__ic_entire_invalidate();
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
#include <cpu_func.h>
|
||||
#include <asm/cache.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
|
||||
|
@ -88,3 +89,8 @@ void enable_caches(void)
|
|||
dcache_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
#include <cpu_func.h>
|
||||
#include <asm/cache.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/armv7.h>
|
||||
#include <asm/utils.h>
|
||||
|
@ -209,3 +210,8 @@ __weak void v7_outer_cache_flush_all(void) {}
|
|||
__weak void v7_outer_cache_inval_all(void) {}
|
||||
__weak void v7_outer_cache_flush_range(u32 start, u32 end) {}
|
||||
__weak void v7_outer_cache_inval_range(u32 start, u32 end) {}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <asm/cache.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
/* Cache maintenance operation registers */
|
||||
|
||||
|
@ -370,3 +371,8 @@ void enable_caches(void)
|
|||
dcache_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <asm/global_data.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -421,7 +422,7 @@ static int count_ranges(void)
|
|||
return count;
|
||||
}
|
||||
|
||||
#define ALL_ATTRS (3 << 8 | PMD_ATTRINDX_MASK)
|
||||
#define ALL_ATTRS (3 << 8 | PMD_ATTRMASK)
|
||||
#define PTE_IS_TABLE(pte, level) (pte_type(&(pte)) == PTE_TYPE_TABLE && (level) < 3)
|
||||
|
||||
enum walker_state {
|
||||
|
@ -568,6 +569,20 @@ static void pretty_print_table_attrs(u64 pte)
|
|||
static void pretty_print_block_attrs(u64 pte)
|
||||
{
|
||||
u64 attrs = pte & PMD_ATTRINDX_MASK;
|
||||
u64 perm_attrs = pte & PMD_ATTRMASK;
|
||||
char mem_attrs[16] = { 0 };
|
||||
int cnt = 0;
|
||||
|
||||
if (perm_attrs & PTE_BLOCK_PXN)
|
||||
cnt += snprintf(mem_attrs + cnt, sizeof(mem_attrs) - cnt, "PXN ");
|
||||
if (perm_attrs & PTE_BLOCK_UXN)
|
||||
cnt += snprintf(mem_attrs + cnt, sizeof(mem_attrs) - cnt, "UXN ");
|
||||
if (perm_attrs & PTE_BLOCK_RO)
|
||||
cnt += snprintf(mem_attrs + cnt, sizeof(mem_attrs) - cnt, "RO");
|
||||
if (!mem_attrs[0])
|
||||
snprintf(mem_attrs, sizeof(mem_attrs), "RWX ");
|
||||
|
||||
printf(" | %-10s", mem_attrs);
|
||||
|
||||
switch (attrs) {
|
||||
case PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE):
|
||||
|
@ -613,6 +628,7 @@ static void print_pte(u64 pte, int level)
|
|||
{
|
||||
if (PTE_IS_TABLE(pte, level)) {
|
||||
printf(" %-5s", "Table");
|
||||
printf(" %-12s", "|");
|
||||
pretty_print_table_attrs(pte);
|
||||
} else {
|
||||
pretty_print_pte_type(pte);
|
||||
|
@ -642,9 +658,9 @@ static bool pagetable_print_entry(u64 start_attrs, u64 end, int va_bits, int lev
|
|||
|
||||
printf("%*s", indent * 2, "");
|
||||
if (PTE_IS_TABLE(start_attrs, level))
|
||||
printf("[%#011llx]%14s", _addr, "");
|
||||
printf("[%#016llx]%19s", _addr, "");
|
||||
else
|
||||
printf("[%#011llx - %#011llx]", _addr, end);
|
||||
printf("[%#016llx - %#016llx]", _addr, end);
|
||||
|
||||
printf("%*s | ", (3 - level) * 2, "");
|
||||
print_pte(start_attrs, level);
|
||||
|
@ -952,6 +968,34 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
|
|||
flush_dcache_range(real_start, real_start + real_size);
|
||||
}
|
||||
|
||||
void mmu_change_region_attr_nobreak(phys_addr_t addr, size_t siz, u64 attrs)
|
||||
{
|
||||
int level;
|
||||
u64 r, size, start;
|
||||
|
||||
/*
|
||||
* Loop through the address range until we find a page granule that fits
|
||||
* our alignment constraints and set the new permissions
|
||||
*/
|
||||
start = addr;
|
||||
size = siz;
|
||||
while (size > 0) {
|
||||
for (level = 1; level < 4; level++) {
|
||||
/* Set PTE to new attributes */
|
||||
r = set_one_region(start, size, attrs, true, level);
|
||||
if (r) {
|
||||
/* PTE successfully updated */
|
||||
size -= r;
|
||||
start += r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
flush_dcache_range(gd->arch.tlb_addr,
|
||||
gd->arch.tlb_addr + gd->arch.tlb_size);
|
||||
__asm_invalidate_tlb_all();
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify MMU table for a region with updated PXN/UXN/Memory type/valid bits.
|
||||
* The procecess is break-before-make. The target region will be marked as
|
||||
|
@ -986,27 +1030,31 @@ void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs)
|
|||
gd->arch.tlb_addr + gd->arch.tlb_size);
|
||||
__asm_invalidate_tlb_all();
|
||||
|
||||
/*
|
||||
* Loop through the address range until we find a page granule that fits
|
||||
* our alignment constraints, then set it to the new cache attributes
|
||||
*/
|
||||
start = addr;
|
||||
size = siz;
|
||||
while (size > 0) {
|
||||
for (level = 1; level < 4; level++) {
|
||||
/* Set PTE to new attributes */
|
||||
r = set_one_region(start, size, attrs, true, level);
|
||||
if (r) {
|
||||
/* PTE successfully updated */
|
||||
size -= r;
|
||||
start += r;
|
||||
mmu_change_region_attr_nobreak(addr, siz, attrs);
|
||||
}
|
||||
|
||||
int pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
u64 attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE | PTE_TYPE_VALID;
|
||||
|
||||
switch (perm) {
|
||||
case MMU_ATTR_RO:
|
||||
attrs |= PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_RO;
|
||||
break;
|
||||
case MMU_ATTR_RX:
|
||||
attrs |= PTE_BLOCK_RO;
|
||||
break;
|
||||
case MMU_ATTR_RW:
|
||||
attrs |= PTE_BLOCK_PXN | PTE_BLOCK_UXN;
|
||||
break;
|
||||
default:
|
||||
log_err("Unknown attribute %d\n", perm);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
flush_dcache_range(gd->arch.tlb_addr,
|
||||
gd->arch.tlb_addr + gd->arch.tlb_size);
|
||||
__asm_invalidate_tlb_all();
|
||||
|
||||
mmu_change_region_attr_nobreak(addr, size, attrs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */
|
||||
|
@ -1112,3 +1160,8 @@ void __weak enable_caches(void)
|
|||
icache_enable();
|
||||
dcache_enable();
|
||||
}
|
||||
|
||||
void arch_dump_mem_attrs(void)
|
||||
{
|
||||
dump_pagetable(gd->arch.tlb_addr, get_tcr(NULL, NULL));
|
||||
}
|
||||
|
|
|
@ -36,9 +36,18 @@ SECTIONS
|
|||
__efi_runtime_stop = .;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU_PGPROT
|
||||
.text_rest ALIGN(CONSTANT(COMMONPAGESIZE)) :
|
||||
#else
|
||||
.text_rest :
|
||||
#endif
|
||||
{
|
||||
__text_start = .;
|
||||
*(.text*)
|
||||
#ifdef CONFIG_MMU_PGPROT
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
#endif
|
||||
__text_end = .;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARMV8_PSCI
|
||||
|
@ -97,24 +106,6 @@ SECTIONS
|
|||
LONG(0x1d1071c); /* Must output something to reset LMA */
|
||||
}
|
||||
#endif
|
||||
|
||||
. = ALIGN(8);
|
||||
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
|
||||
|
||||
. = ALIGN(8);
|
||||
.data : {
|
||||
*(.data*)
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
|
||||
. = .;
|
||||
|
||||
. = ALIGN(8);
|
||||
__u_boot_list : {
|
||||
KEEP(*(SORT(__u_boot_list*)));
|
||||
}
|
||||
|
||||
.efi_runtime_rel : {
|
||||
__efi_runtime_rel_start = .;
|
||||
*(.rel*.efi_runtime)
|
||||
|
@ -122,10 +113,36 @@ SECTIONS
|
|||
__efi_runtime_rel_stop = .;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU_PGPROT
|
||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)): {
|
||||
#else
|
||||
.rodata ALIGN(8) : {
|
||||
#endif
|
||||
__start_rodata = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
|
||||
}
|
||||
|
||||
__u_boot_list ALIGN(8) : {
|
||||
KEEP(*(SORT(__u_boot_list*)));
|
||||
#ifdef CONFIG_MMU_PGPROT
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
#endif
|
||||
__end_rodata = .;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU_PGPROT
|
||||
.data ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
#else
|
||||
.data ALIGN(8) : {
|
||||
#endif
|
||||
__start_data = .;
|
||||
*(.data*)
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__image_copy_end = .;
|
||||
|
||||
.rela.dyn : {
|
||||
.rela.dyn ALIGN(8) : {
|
||||
__rel_dyn_start = .;
|
||||
*(.rela*)
|
||||
__rel_dyn_end = .;
|
||||
|
@ -136,11 +153,15 @@ SECTIONS
|
|||
/*
|
||||
* arch/arm/lib/crt0_64.S assumes __bss_start - __bss_end % 8 == 0
|
||||
*/
|
||||
.bss ALIGN(8) : {
|
||||
.bss ADDR(.rela.dyn) (OVERLAY) : {
|
||||
__bss_start = .;
|
||||
*(.bss*)
|
||||
. = ALIGN(8);
|
||||
__bss_end = .;
|
||||
#ifdef CONFIG_MMU_PGPROT
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
#endif
|
||||
__end_data = .;
|
||||
}
|
||||
|
||||
/DISCARD/ : { *(.dynsym) }
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#define PTE_BLOCK_NG (1 << 11)
|
||||
#define PTE_BLOCK_PXN (UL(1) << 53)
|
||||
#define PTE_BLOCK_UXN (UL(1) << 54)
|
||||
#define PTE_BLOCK_RO (UL(1) << 7)
|
||||
|
||||
/*
|
||||
* AttrIndx[2:0]
|
||||
|
@ -75,6 +76,7 @@
|
|||
#define PMD_ATTRMASK (PTE_BLOCK_PXN | \
|
||||
PTE_BLOCK_UXN | \
|
||||
PMD_ATTRINDX_MASK | \
|
||||
PTE_BLOCK_RO | \
|
||||
PTE_TYPE_VALID)
|
||||
|
||||
/*
|
||||
|
|
|
@ -303,8 +303,26 @@ void flush_l3_cache(void);
|
|||
* @emerg: Also map the region in the emergency table
|
||||
*/
|
||||
void mmu_map_region(phys_addr_t start, u64 size, bool emerg);
|
||||
|
||||
/**
|
||||
* mmu_change_region_attr() - change a mapped region attributes
|
||||
*
|
||||
* @start: Start address of the region
|
||||
* @size: Size of the region
|
||||
* @aatrs: New attributes
|
||||
*/
|
||||
void mmu_change_region_attr(phys_addr_t start, size_t size, u64 attrs);
|
||||
|
||||
/**
|
||||
* mmu_change_region_attr_nobreak() - change a mapped region attributes without doing
|
||||
* break-before-make
|
||||
*
|
||||
* @start: Start address of the region
|
||||
* @size: Size of the region
|
||||
* @aatrs: New attributes
|
||||
*/
|
||||
void mmu_change_region_attr_nobreak(phys_addr_t addr, size_t size, u64 attrs);
|
||||
|
||||
/*
|
||||
* smc_call() - issue a secure monitor call
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <malloc.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -170,3 +171,8 @@ __weak int arm_reserve_mmu(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <cpu_func.h>
|
||||
#include <asm/immap.h>
|
||||
#include <asm/cache.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
volatile int *cf_icache_status = (int *)ICACHE_STATUS;
|
||||
volatile int *cf_dcache_status = (int *)DCACHE_STATUS;
|
||||
|
@ -151,3 +152,8 @@ __weak void flush_dcache_range(unsigned long start, unsigned long stop)
|
|||
{
|
||||
/* An empty stub, real implementation should be in platform code */
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <cpu_func.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -127,3 +128,8 @@ void dcache_disable(void)
|
|||
{
|
||||
flush_dcache_all();
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <stdio.h>
|
||||
#include <asm/cache.h>
|
||||
#include <watchdog.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
static ulong maybe_watchdog_reset(ulong flushed)
|
||||
{
|
||||
|
@ -58,3 +59,8 @@ void invalidate_icache_all(void)
|
|||
{
|
||||
puts("No arch specific invalidate_icache_all available!\n");
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <dm.h>
|
||||
#include <asm/insn-def.h>
|
||||
#include <linux/const.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#define CBO_INVAL(base) \
|
||||
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
|
||||
|
@ -151,3 +152,8 @@ __weak void enable_caches(void)
|
|||
if (!zicbom_block_size)
|
||||
log_debug("Zicbom not initialized.\n");
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#define CACHE_VALID 1
|
||||
#define CACHE_UPDATED 2
|
||||
|
@ -126,3 +127,8 @@ int dcache_status(void)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <cpu_func.h>
|
||||
#include <asm/cache.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
/*
|
||||
* We currently run always with caches enabled when running from memory.
|
||||
|
@ -57,3 +58,8 @@ void invalidate_icache_all(void)
|
|||
{
|
||||
__invalidate_icache_all();
|
||||
}
|
||||
|
||||
int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void __weak arch_dump_mem_attrs(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void print_region(const char *name, ulong base, ulong size, ulong *uptop)
|
||||
{
|
||||
ulong end = base + size;
|
||||
|
@ -58,6 +62,8 @@ static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
if (!IS_ENABLED(CONFIG_CMD_MEMINFO_MAP))
|
||||
return 0;
|
||||
|
||||
arch_dump_mem_attrs();
|
||||
|
||||
printf("\n%-12s %8s %8s %8s %8s\n", "Region", "Base", "Size", "End",
|
||||
"Gap");
|
||||
printf("------------------------------------------------\n");
|
||||
|
|
|
@ -914,6 +914,19 @@ config STACKPROTECTOR
|
|||
Enable stack smash detection through compiler's stack-protector
|
||||
canary logic
|
||||
|
||||
config MMU_PGPROT
|
||||
bool "Enable RO, RW and RX mappings"
|
||||
help
|
||||
U-Boot maps all pages as RWX. If selected pages will
|
||||
be marked as RO(.rodata), RX(.text), RW(.data) right after
|
||||
we relocate. Since code sections needs to be page aligned
|
||||
the final binary size will increase. The mappings can be dumped
|
||||
using the 'meminfo' command.
|
||||
|
||||
Enabling this feature can expose bugs in U-Boot where we have
|
||||
code that violates read-only permissions for example. Use this
|
||||
feature with caution.
|
||||
|
||||
config SPL_STACKPROTECTOR
|
||||
bool "Stack Protector buffer overflow detection for SPL"
|
||||
depends on STACKPROTECTOR && SPL
|
||||
|
|
|
@ -170,7 +170,27 @@ static int initr_reloc_global_data(void)
|
|||
efi_save_gd();
|
||||
|
||||
efi_runtime_relocate(gd->relocaddr, NULL);
|
||||
|
||||
#endif
|
||||
/*
|
||||
* We are done with all relocations change the permissions of the binary
|
||||
* NOTE: __start_rodata etc are defined in arm64 linker scripts and
|
||||
* sections.h. If you want to add support for your platform you need to
|
||||
* add the symbols on your linker script, otherwise they will point to
|
||||
* random addresses.
|
||||
*
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_MMU_PGPROT)) {
|
||||
pgprot_set_attrs((phys_addr_t)(uintptr_t)(__start_rodata),
|
||||
(size_t)(uintptr_t)(__end_rodata - __start_rodata),
|
||||
MMU_ATTR_RO);
|
||||
pgprot_set_attrs((phys_addr_t)(uintptr_t)(__start_data),
|
||||
(size_t)(uintptr_t)(__end_data - __start_data),
|
||||
MMU_ATTR_RW);
|
||||
pgprot_set_attrs((phys_addr_t)(uintptr_t)(__text_start),
|
||||
(size_t)(uintptr_t)(__text_end - __text_start),
|
||||
MMU_ATTR_RX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ Description
|
|||
|
||||
The meminfo command shows the amount of memory. If ``CONFIG_CMD_MEMINFO_MAP`` is
|
||||
enabled, then it also shows the layout of memory used by U-Boot and the region
|
||||
which is free for use by images.
|
||||
which is free for use by images. In architectures that support it, it also prints
|
||||
the mapped pages and their permissions. The latter is architecture specific.
|
||||
|
||||
The layout of memory is set up before relocation, within the init sequence in
|
||||
``board_init_f()``, specifically the various ``reserve_...()`` functions. This
|
||||
|
@ -26,8 +27,9 @@ The layout of memory is set up before relocation, within the init sequence in
|
|||
ending with the stack. This results in the maximum possible amount of memory
|
||||
being left free for image-loading.
|
||||
|
||||
The meminfo command writes the DRAM size, then the rest of its outputs in 5
|
||||
columns:
|
||||
The meminfo command writes the DRAM size. If the architecture also supports it,
|
||||
page table entries will be shown next. Finally the rest of the outputs are
|
||||
printed in 5 columns:
|
||||
|
||||
Region
|
||||
Name of the region
|
||||
|
@ -99,28 +101,61 @@ free
|
|||
Free memory, which is available for loading images. The base address of
|
||||
this is ``gd->ram_base`` which is generally set by ``CFG_SYS_SDRAM_BASE``.
|
||||
|
||||
Aarch64 specific flags
|
||||
----------------------
|
||||
|
||||
More information on the output can be found
|
||||
Chapter D8 - The AArch64 Virtual Memory System Architecture at
|
||||
https://developer.arm.com/documentation/ddi0487/latest/
|
||||
|
||||
In short, for a stage 1 translation regime the following apply:
|
||||
|
||||
* RWX: Pages mapped with Read, Write and Execute permissions
|
||||
* RO: Pages mapped with Read-Only permissions
|
||||
* PXN: PXN (Privileged Execute Never) applies to execution at EL1 and above
|
||||
* UXN: UXN (Unprivileged Execute Never) applies to EL0
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
This example shows output with both ``CONFIG_CMD_MEMINFO`` and
|
||||
``CONFIG_CMD_MEMINFO_MAP`` enabled::
|
||||
``CONFIG_CMD_MEMINFO_MAP`` enabled for aarch64 qemu::
|
||||
|
||||
=> meminfo
|
||||
DRAM: 256 MiB
|
||||
DRAM: 8 GiB
|
||||
Walking pagetable at 000000023ffe0000, va_bits: 40. Using 4 levels
|
||||
[0x0000023ffe1000] | Table | | |
|
||||
[0x0000023ffe2000] | Table | | |
|
||||
[0x00000000000000 - 0x00000008000000] | Block | RWX | Normal | Inner-shareable
|
||||
[0x00000008000000 - 0x00000040000000] | Block | PXN UXN | Device-nGnRnE | Non-shareable
|
||||
[0x00000040000000 - 0x00000200000000] | Block | RWX | Normal | Inner-shareable
|
||||
[0x0000023ffea000] | Table | | |
|
||||
[0x00000200000000 - 0x0000023f600000] | Block | RWX | Normal | Inner-shareable
|
||||
[0x0000023ffeb000] | Table | | |
|
||||
[0x0000023f600000 - 0x0000023f68c000] | Pages | RWX | Normal | Inner-shareable
|
||||
[0x0000023f68c000 - 0x0000023f74f000] | Pages | RO | Normal | Inner-shareable
|
||||
[0x0000023f74f000 - 0x0000023f794000] | Pages | PXN UXN RO | Normal | Inner-shareable
|
||||
[0x0000023f794000 - 0x0000023f79d000] | Pages | PXN UXN | Normal | Inner-shareable
|
||||
[0x0000023f79d000 - 0x0000023f800000] | Pages | RWX | Normal | Inner-shareable
|
||||
[0x0000023f800000 - 0x00000240000000] | Block | RWX | Normal | Inner-shareable
|
||||
[0x00000240000000 - 0x00004000000000] | Block | RWX | Normal | Inner-shareable
|
||||
[0x0000023ffe3000] | Table | | |
|
||||
[0x00004010000000 - 0x00004020000000] | Block | PXN UXN | Device-nGnRnE | Non-shareable
|
||||
[0x0000023ffe4000] | Table | | |
|
||||
[0x00008000000000 - 0x00010000000000] | Block | PXN UXN | Device-nGnRnE | Non-shareable
|
||||
|
||||
Region Base Size End Gap
|
||||
------------------------------------------------
|
||||
video f000000 1000000 10000000
|
||||
code ec3a000 3c5d28 efffd28 2d8
|
||||
malloc 8c38000 6002000 ec3a000 0
|
||||
board_info 8c37f90 68 8c37ff8 8
|
||||
global_data 8c37d80 208 8c37f88 8
|
||||
devicetree 8c33000 4d7d 8c37d7d 3
|
||||
bootstage 8c32c20 3c8 8c32fe8 18
|
||||
bloblist 8c32000 400 8c32400 820
|
||||
stack 7c31ff0 1000000 8c31ff0 10
|
||||
free 0 7c31ff0 7c31ff0 0
|
||||
|
||||
video 23f7e0000 800000 23ffe0000
|
||||
code 23f68a000 156000 23f7e0000 0
|
||||
malloc 23e64a000 1040000 23f68a000 0
|
||||
board_info 23e649f80 78 23e649ff8 8
|
||||
global_data 23e649df0 188 23e649f78 8
|
||||
devicetree 23e549df0 100000 23e649df0 0
|
||||
bloblist 23e547000 2000 23e549000 df0
|
||||
stack 23d546ff0 1000000 23e546ff0 10
|
||||
lmb 23d546ff0 0 23d546ff0 0
|
||||
lmb 23d543000 3ff0 23d546ff0 0
|
||||
free 40000000 23d543000 27d543000 ffffffffc0000000
|
||||
|
||||
Return value
|
||||
------------
|
||||
|
|
|
@ -23,6 +23,7 @@ extern char __kprobes_text_start[], __kprobes_text_end[];
|
|||
extern char __entry_text_start[], __entry_text_end[];
|
||||
extern char __initdata_begin[], __initdata_end[];
|
||||
extern char __start_rodata[], __end_rodata[];
|
||||
extern char __start_data[], __end_data[];
|
||||
extern char __efi_helloworld_begin[];
|
||||
extern char __efi_helloworld_end[];
|
||||
extern char __efi_var_file_begin[];
|
||||
|
@ -63,6 +64,7 @@ static inline int arch_is_kernel_data(unsigned long addr)
|
|||
|
||||
/* Start of U-Boot text region */
|
||||
extern char __text_start[];
|
||||
extern char __text_end[];
|
||||
|
||||
/* This marks the text region which must be relocated */
|
||||
extern char __image_copy_start[], __image_copy_end[];
|
||||
|
|
|
@ -69,6 +69,23 @@ void flush_dcache_range(unsigned long start, unsigned long stop);
|
|||
void invalidate_dcache_range(unsigned long start, unsigned long stop);
|
||||
void invalidate_dcache_all(void);
|
||||
void invalidate_icache_all(void);
|
||||
|
||||
enum pgprot_attrs {
|
||||
MMU_ATTR_RO,
|
||||
MMU_ATTR_RX,
|
||||
MMU_ATTR_RW,
|
||||
};
|
||||
|
||||
/** pgprot_set_attrs() - Set page table permissions
|
||||
*
|
||||
* @addr: Physical address start
|
||||
* @size: size of memory to change
|
||||
* @perm: New permissions
|
||||
*
|
||||
* Return: 0 on success, error otherwise.
|
||||
**/
|
||||
int pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm);
|
||||
|
||||
/**
|
||||
* noncached_init() - Initialize non-cached memory region
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue