diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 5169fc627fa..08f9e7dceac 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -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; +} diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c index 5b87a3af91b..71b8ad0f71d 100644 --- a/arch/arm/cpu/arm926ejs/cache.c +++ b/arch/arm/cpu/arm926ejs/cache.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #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; +} diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c index d11420d2fdd..371dc92cd46 100644 --- a/arch/arm/cpu/armv7/cache_v7.c +++ b/arch/arm/cpu/armv7/cache_v7.c @@ -6,6 +6,7 @@ */ #include #include +#include #include #include #include @@ -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; +} diff --git a/arch/arm/cpu/armv7m/cache.c b/arch/arm/cpu/armv7m/cache.c index b6d08b7aad7..8e7db734055 100644 --- a/arch/arm/cpu/armv7m/cache.c +++ b/arch/arm/cpu/armv7m/cache.c @@ -11,6 +11,7 @@ #include #include #include +#include /* 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; +} diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 5d6953ffedd..12ae9bd0603 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -14,6 +14,7 @@ #include #include #include +#include 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; - break; - } - } + 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)); +} diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds index 857f44412e0..f4ce98c82c8 100644 --- a/arch/arm/cpu/armv8/u-boot.lds +++ b/arch/arm/cpu/armv8/u-boot.lds @@ -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) } diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 0ab681c893d..6af8cd111a4 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -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) /* diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 091082281c7..849b3d0efb7 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -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 * diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index 516754caeaf..dd19bd3e4fb 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -10,6 +10,7 @@ #include #include #include +#include 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; +} diff --git a/arch/m68k/lib/cache.c b/arch/m68k/lib/cache.c index 370ad40f142..a21fe327944 100644 --- a/arch/m68k/lib/cache.c +++ b/arch/m68k/lib/cache.c @@ -8,6 +8,7 @@ #include #include #include +#include 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; +} diff --git a/arch/nios2/lib/cache.c b/arch/nios2/lib/cache.c index 8f543f2a2f2..d7fd9ca8bd4 100644 --- a/arch/nios2/lib/cache.c +++ b/arch/nios2/lib/cache.c @@ -8,6 +8,7 @@ #include #include #include +#include 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; +} diff --git a/arch/powerpc/lib/cache.c b/arch/powerpc/lib/cache.c index a9cd7b8d30a..e4d9546039d 100644 --- a/arch/powerpc/lib/cache.c +++ b/arch/powerpc/lib/cache.c @@ -8,6 +8,7 @@ #include #include #include +#include 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; +} diff --git a/arch/riscv/lib/cache.c b/arch/riscv/lib/cache.c index 71e4937ab54..31aa30bc7d7 100644 --- a/arch/riscv/lib/cache.c +++ b/arch/riscv/lib/cache.c @@ -8,6 +8,7 @@ #include #include #include +#include #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; +} diff --git a/arch/sh/cpu/sh4/cache.c b/arch/sh/cpu/sh4/cache.c index 99acc599965..56161ee72e4 100644 --- a/arch/sh/cpu/sh4/cache.c +++ b/arch/sh/cpu/sh4/cache.c @@ -11,6 +11,7 @@ #include #include #include +#include #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; +} diff --git a/arch/xtensa/lib/cache.c b/arch/xtensa/lib/cache.c index e6a7f6827fc..1229b407783 100644 --- a/arch/xtensa/lib/cache.c +++ b/arch/xtensa/lib/cache.c @@ -6,6 +6,7 @@ #include #include +#include /* * 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; +} diff --git a/cmd/meminfo.c b/cmd/meminfo.c index 5e83d61c2dd..acdb38dcba0 100644 --- a/cmd/meminfo.c +++ b/cmd/meminfo.c @@ -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"); diff --git a/common/Kconfig b/common/Kconfig index a1f65559a1b..be517b80eb5 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -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 diff --git a/common/board_r.c b/common/board_r.c index db0c5cb8032..8d69db1875d 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -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; } diff --git a/doc/usage/cmd/meminfo.rst b/doc/usage/cmd/meminfo.rst index 6c94493cccc..e10bdc6832c 100644 --- a/doc/usage/cmd/meminfo.rst +++ b/doc/usage/cmd/meminfo.rst @@ -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 ------------ diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 3fd5c772a1a..024b1adde27 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -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[]; diff --git a/include/cpu_func.h b/include/cpu_func.h index 7e81c4364a7..70a41ead3f7 100644 --- a/include/cpu_func.h +++ b/include/cpu_func.h @@ -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 *