Skip to content

Commit 395cac7

Browse files
ruscurmpe
authored andcommitted
powerpc/mm: Support execute-only memory on the Radix MMU
Add support for execute-only memory (XOM) for the Radix MMU by using an execute-only mapping, as opposed to the RX mapping used by powerpc's other MMUs. The Hash MMU already supports XOM through the execute-only pkey, which is a separate mechanism shared with x86. A PROT_EXEC-only mapping will map to RX, and then the pkey will be applied on top of it. mmap() and mprotect() consumers in userspace should observe the same behaviour on Hash and Radix despite the differences in implementation. Replacing the vma_is_accessible() check in access_error() with a read check should be functionally equivalent for non-Radix MMUs, since it follows write and execute checks. For Radix, the change enables detecting faults on execute-only mappings where vma_is_accessible() would return true. Signed-off-by: Russell Currey <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 4c14d7a commit 395cac7

File tree

3 files changed

+16
-3
lines changed

3 files changed

+16
-3
lines changed

arch/powerpc/include/asm/book3s/64/pgtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@
151151
#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
152152
#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ)
153153
#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
154+
/* Radix only, Hash uses PAGE_READONLY_X + execute-only pkey instead */
155+
#define PAGE_EXECONLY __pgprot(_PAGE_BASE | _PAGE_EXEC)
154156

155157
/* Permission masks used for kernel mappings */
156158
#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)

arch/powerpc/mm/book3s64/pgtable.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,15 @@ EXPORT_SYMBOL_GPL(memremap_compat_align);
553553

554554
pgprot_t vm_get_page_prot(unsigned long vm_flags)
555555
{
556-
unsigned long prot = pgprot_val(protection_map[vm_flags &
557-
(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]);
556+
unsigned long prot;
557+
558+
/* Radix supports execute-only, but protection_map maps X -> RX */
559+
if (radix_enabled() && ((vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)) {
560+
prot = pgprot_val(PAGE_EXECONLY);
561+
} else {
562+
prot = pgprot_val(protection_map[vm_flags &
563+
(VM_ACCESS_FLAGS | VM_SHARED)]);
564+
}
558565

559566
if (vm_flags & VM_SAO)
560567
prot |= _PAGE_SAO;

arch/powerpc/mm/fault.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,11 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma
270270
return false;
271271
}
272272

273-
if (unlikely(!vma_is_accessible(vma)))
273+
/*
274+
* Check for a read fault. This could be caused by a read on an
275+
* inaccessible page (i.e. PROT_NONE), or a Radix MMU execute-only page.
276+
*/
277+
if (unlikely(!(vma->vm_flags & VM_READ)))
274278
return true;
275279
/*
276280
* We should ideally do the vma pkey access check here. But in the

0 commit comments

Comments
 (0)