@@ -31,7 +31,7 @@ int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **trans_pgd,
unsigned long start, unsigned long end);
int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0,
- unsigned long *t0sz, void *page);
+ unsigned long *t0sz, void *page, pgprot_t prot);
int trans_pgd_copy_el2_vectors(struct trans_pgd_info *info,
phys_addr_t *el2_vectors);
@@ -203,7 +203,8 @@ static int create_safe_exec_page(void *src_start, size_t length,
memcpy(page, src_start, length);
caches_clean_inval_pou((unsigned long)page, (unsigned long)page + length);
- rc = trans_pgd_idmap_page(&trans_info, &trans_ttbr0, &t0sz, page);
+ rc = trans_pgd_idmap_page(&trans_info, &trans_ttbr0, &t0sz, page,
+ PAGE_KERNEL_ROX);
if (rc)
return rc;
@@ -141,8 +141,8 @@ int machine_kexec_post_load(struct kimage *kimage)
reloc_size = __relocate_new_kernel_end - __relocate_new_kernel_start;
memcpy(reloc_code, __relocate_new_kernel_start, reloc_size);
kimage->arch.kern_reloc = __pa(reloc_code);
- rc = trans_pgd_idmap_page(&info, &kimage->arch.ttbr0,
- &kimage->arch.t0sz, reloc_code);
+ rc = trans_pgd_idmap_page(&info, &kimage->arch.ttbr0, &kimage->arch.t0sz,
+ reloc_code, PAGE_KERNEL_EXEC);
if (rc)
return rc;
kimage->arch.phys_offset = virt_to_phys(kimage) - (long)kimage;
@@ -230,7 +230,7 @@ int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **dst_pgdp,
* maximum T0SZ for this page.
*/
int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0,
- unsigned long *t0sz, void *page)
+ unsigned long *t0sz, void *page, pgprot_t prot)
{
phys_addr_t dst_addr = virt_to_phys(page);
unsigned long pfn = __phys_to_pfn(dst_addr);
@@ -240,7 +240,7 @@ int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0,
int this_level, index, level_lsb, level_msb;
dst_addr &= PAGE_MASK;
- prev_level_entry = pte_val(pfn_pte(pfn, PAGE_KERNEL_ROX));
+ prev_level_entry = pte_val(pfn_pte(pfn, prot));
for (this_level = 3; this_level >= 0; this_level--) {
levels[this_level] = trans_alloc(info);
Since relocate_kernel code will build stack at the rear of the page, it requires 'wx' on the page. Adapting the prototype of trans_pgd_idmap_page() to make it doable. The trans_pgd_idmap_page() can be enhanced further to support multiple pages. But since the change has met the requirement, it is not necessary to enhance for the time being. Signed-off-by: Pingfan Liu <piliu@redhat.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Kees Cook <keescook@chromium.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Pasha Tatashin <pasha.tatashin@soleen.com> To: linux-arm-kernel@lists.infradead.org --- arch/arm64/include/asm/trans_pgd.h | 2 +- arch/arm64/kernel/hibernate.c | 3 ++- arch/arm64/kernel/machine_kexec.c | 4 ++-- arch/arm64/mm/trans_pgd.c | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-)