diff --git a/include/arch/arm/arch/object/structures.bf b/include/arch/arm/arch/object/structures.bf index 26a3adc633cff02abe7acb33ff2f61c5e028a611..c3e178de807215337e6935f24568416ccbdbd53a 100644 --- a/include/arch/arm/arch/object/structures.bf +++ b/include/arch/arm/arch/object/structures.bf @@ -451,11 +451,6 @@ tagged_union pde pdeType { } -- Page table entries -block pte_invalid { - padding 30 - field pteType 2 -} - block pte_large { field_high address 16 field XN 1 @@ -467,7 +462,8 @@ block pte_large { field AP 2 field C 1 field B 1 - field pteType 2 + field pteSize 1 + field reserved 1 -- must be set } block pte_small { @@ -479,21 +475,20 @@ block pte_small { field AP 2 field C 1 field B 1 - -- The lower bit of pteType is used to store the XN bit for small pages - -- We ignore this here, and use tag 2 for small pages which sets XN always to 0. - field pteType 2 + field pteSize 1 + field XN 1 } -tagged_union pte pteType { - tag pte_invalid 0 - tag pte_large 1 - tag pte_small 2 +tagged_union pte pteSize { + tag pte_large 0 + tag pte_small 1 } -- VM attributes block vm_attributes { - padding 30 + padding 29 + field armExecuteNever 1 field armParityEnabled 1 field armPageCacheable 1 } diff --git a/include/arch/arm/arch/object/structures.h b/include/arch/arm/arch/object/structures.h index cf695db1b3df676383731965dce22c068e15849b..09046ca3271a45a7851af1a32664aefea50bc1ce 100644 --- a/include/arch/arm/arch/object/structures.h +++ b/include/arch/arm/arch/object/structures.h @@ -570,4 +570,33 @@ isArchCap(cap_t cap) return (cap_get_capType(cap) % 2); } +/* We need to supply different type getters for the bitfield generated PTE type + * because there is an implicit third type that PTEs can be. If the type bit is + * set but the reserved bit is not set, the type of the PTE is invalid, not a + * large PTE. + */ +enum { pte_pte_invalid = 2 }; + +static inline uint32_t __attribute__((__const__)) +pte_get_pteType(pte_t pte) { + if (pte_get_pteSize(pte) == pte_pte_small) { + return pte_pte_small; + } else if (pte_pte_large_get_reserved(pte) == 1) { + return pte_pte_large; + } else { + return pte_pte_invalid; + } +} + +static inline uint32_t __attribute__((__pure__)) +pte_ptr_get_pteType(pte_t *pte_ptr) { + if (pte_ptr_get_pteSize(pte_ptr) == pte_pte_small) { + return pte_pte_small; + } else if (pte_pte_large_ptr_get_reserved(pte_ptr) == 1) { + return pte_pte_large; + } else { + return pte_pte_invalid; + } +} + #endif diff --git a/libsel4/arch_include/arm/sel4/arch/types.h b/libsel4/arch_include/arm/sel4/arch/types.h index 1f396fda2a653887eeadae4110599262d01c8557..13c6750c78f98923f40de9c88874343c4dbf9570 100644 --- a/libsel4/arch_include/arm/sel4/arch/types.h +++ b/libsel4/arch_include/arm/sel4/arch/types.h @@ -48,6 +48,7 @@ typedef enum { seL4_ARM_PageCacheable = 0x01, seL4_ARM_ParityEnabled = 0x02, seL4_ARM_Default_VMAttributes = 0x03, + seL4_ARM_ExecuteNever = 0x04, /* seL4_ARM_PageCacheable | seL4_ARM_ParityEnabled */ SEL4_FORCE_LONG_ENUM(seL4_ARM_VMAttributes), } seL4_ARM_VMAttributes; diff --git a/manual/parts/vspace.tex b/manual/parts/vspace.tex index 841ba75577328e08e06a93b54a2ed1b5a2cf73d8..8aa489cb6be939af87d2d86f4d490fc898fc3647 100644 --- a/manual/parts/vspace.tex +++ b/manual/parts/vspace.tex @@ -181,6 +181,7 @@ page being mapped; possible values for ARM are shown in \autoref{tbl:vmattr_arm} to be cached \\ \texttt{seL4\_ARM\_ParityEnabled} & Enable parity checking for this mapping\\ + \texttt{seL4\_ARM\_ExecuteNever} & Map this memory as non-executable \\ \bottomrule \end{tabularx} \caption{\label{tbl:vmattr_arm} Virtual memory attributes for ARM page diff --git a/src/arch/arm/kernel/vspace.c b/src/arch/arm/kernel/vspace.c index f9e49bcb0ed3060aeecd41cc58a52f90e3ab0647..1b1d931a1d7de1f5af0109e5f35856951a2da7b4 100644 --- a/src/arch/arm/kernel/vspace.c +++ b/src/arch/arm/kernel/vspace.c @@ -130,7 +130,8 @@ map_it_frame_cap(cap_t pd_cap, cap_t frame_cap) 0, /* TEX = 0 */ APFromVMRights(VMReadWrite), 1, /* cacheable */ - 1 /* write-back caching */ + 1, /* write-back caching */ + 0 /* executable */ ); } @@ -150,7 +151,8 @@ map_kernel_frame(paddr_t paddr, pptr_t vaddr, vm_rights_t vm_rights, vm_attribut 0, /* TEX = 0 */ APFromVMRights(vm_rights), vm_attributes_get_armPageCacheable(attributes), - 1 /* Write-back caching */ + 1, /* Write-back caching */ + 0 /* executable */ ); } @@ -266,7 +268,8 @@ map_kernel_window(void) VMKernelOnly, vm_attributes_new( true, /* armParityEnabled */ - true /* armPageCacheable */ + true, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -277,7 +280,8 @@ map_kernel_window(void) VMReadOnly, vm_attributes_new( true, /* armParityEnabled */ - true /* armPageCacheable */ + true, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -288,7 +292,8 @@ map_kernel_window(void) VMKernelOnly, vm_attributes_new( true, /* armParityEnabled */ - true /* armPageCacheable */ + true, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -568,6 +573,13 @@ unmapPageTable(asid_t asid, vptr_t vaddr, pte_t* pt) } } +static pte_t pte_pte_invalid_new(void) { + /* Invalid as every PTE must have bit 0 set (large PTE) or bit 1 set (small + * PTE). 0 == 'translation fault' in ARM parlance. + */ + return (pte_t){{ 0 }}; +} + void unmapPage(vm_page_size_t page_size, asid_t asid, vptr_t vptr, void *pptr) { @@ -959,7 +971,7 @@ invalidateTLBByASID(asid_t asid) static pte_t CONST makeUserPTE(vm_page_size_t page_size, paddr_t paddr, - bool_t cacheable, vm_rights_t vm_rights) + bool_t cacheable, bool_t nonexecutable, vm_rights_t vm_rights) { pte_t pte; word_t ap; @@ -975,7 +987,8 @@ makeUserPTE(vm_page_size_t page_size, paddr_t paddr, 0, /* APX = 0, privileged full access */ 5, /* TEX = 0b101, outer write-back, write-allocate */ ap, - 0, 1 /* Inner write-back, write-allocate (except on ARM11) */); + 0, 1, /* Inner write-back, write-allocate (except on ARM11) */ + nonexecutable); } else { pte = pte_pte_small_new(paddr, 1, /* not global */ @@ -983,7 +996,8 @@ makeUserPTE(vm_page_size_t page_size, paddr_t paddr, 0, /* APX = 0, privileged full access */ 0, /* TEX = 0b000, strongly-ordered. */ ap, - 0, 0); + 0, 0, + nonexecutable); } break; } @@ -991,22 +1005,24 @@ makeUserPTE(vm_page_size_t page_size, paddr_t paddr, case ARMLargePage: { if (cacheable) { pte = pte_pte_large_new(paddr, - 0, /* XN not set */ + nonexecutable, 5, /* TEX = 0b101, outer write-back, write-allocate */ 1, /* not global */ 0, /* not shared */ 0, /* APX = 0, privileged full access */ ap, - 0, 1 /* Inner write-back, write-allocate (except on ARM11) */); + 0, 1, /* Inner write-back, write-allocate (except on ARM11) */ + 1 /* reserved */); } else { pte = pte_pte_large_new(paddr, - 0, /* XN not set */ + nonexecutable, 0, /* TEX = 0b000, strongly-ordered */ 1, /* not global */ 1, /* shared */ 0, /* APX = 0, privileged full access */ ap, - 0, 0); + 0, 0, + 1 /* reserved */); } break; } @@ -1020,7 +1036,8 @@ makeUserPTE(vm_page_size_t page_size, paddr_t paddr, static pde_t CONST makeUserPDE(vm_page_size_t page_size, paddr_t paddr, bool_t parity, - bool_t cacheable, word_t domain, vm_rights_t vm_rights) + bool_t cacheable, bool_t nonexecutable, word_t domain, + vm_rights_t vm_rights) { word_t ap, size2; @@ -1045,8 +1062,7 @@ makeUserPDE(vm_page_size_t page_size, paddr_t paddr, bool_t parity, 0, /* not shared */ 0, /* APX = 0, privileged full access */ 5, /* TEX = 0b101, outer write-back, write-allocate */ - ap, parity, domain, - 0, /* XN not set */ + ap, parity, domain, nonexecutable, 0, 1 /* Inner write-back, write-allocate (except on ARM11) */); } else { return pde_pde_section_new(paddr, size2, @@ -1054,8 +1070,7 @@ makeUserPDE(vm_page_size_t page_size, paddr_t paddr, bool_t parity, 1, /* shared */ 0, /* APX = 0, privileged full access */ 0, /* TEX = 0b000, strongly-ordered */ - ap, parity, domain, - 0, /* XN not set */ + ap, parity, domain, nonexecutable, 0, 0); } } @@ -1205,6 +1220,7 @@ createSafeMappingEntries_PTE ret.pte = makeUserPTE(ARMSmallPage, base, vm_attributes_get_armPageCacheable(attr), + vm_attributes_get_armExecuteNever(attr), vmRights); lu_ret = lookupPTSlot(pd, vaddr); @@ -1240,6 +1256,7 @@ createSafeMappingEntries_PTE ret.pte = makeUserPTE(ARMLargePage, base, vm_attributes_get_armPageCacheable(attr), + vm_attributes_get_armExecuteNever(attr), vmRights); lu_ret = lookupPTSlot(pd, vaddr); @@ -1298,7 +1315,9 @@ createSafeMappingEntries_PDE ret.pde = makeUserPDE(ARMSection, base, vm_attributes_get_armParityEnabled(attr), vm_attributes_get_armPageCacheable(attr), - 0, vmRights); + vm_attributes_get_armExecuteNever(attr), + 0, + vmRights); currentPDEType = pde_ptr_get_pdeType(ret.pde_entries.base); @@ -1322,7 +1341,9 @@ createSafeMappingEntries_PDE ret.pde = makeUserPDE(ARMSuperSection, base, vm_attributes_get_armParityEnabled(attr), vm_attributes_get_armPageCacheable(attr), - 0, vmRights); + vm_attributes_get_armExecuteNever(attr), + 0, + vmRights); for (i = 0; i < SECTIONS_PER_SUPER_SECTION; i++) { currentPDEType = diff --git a/src/plat/am335x/machine/hardware.c b/src/plat/am335x/machine/hardware.c index 2fc71d137351ee2ca840025b615df4b08b4609b8..9a2ef37d0bcdc368b58ed5812741bfca5f137cd8 100644 --- a/src/plat/am335x/machine/hardware.c +++ b/src/plat/am335x/machine/hardware.c @@ -76,7 +76,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -87,7 +88,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -99,7 +101,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); #endif diff --git a/src/plat/exynos4/machine/hardware.c b/src/plat/exynos4/machine/hardware.c index 553e6d7b839af0afec4e61a06b89cb4ec757ff1d..a8ebc96d1ffb34270c4a143b0bda064f44103f96 100644 --- a/src/plat/exynos4/machine/hardware.c +++ b/src/plat/exynos4/machine/hardware.c @@ -236,7 +236,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -247,7 +248,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); map_kernel_frame( @@ -256,7 +258,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -267,7 +270,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -279,7 +283,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); #endif /* DEBUG */ diff --git a/src/plat/exynos5/machine/hardware.c b/src/plat/exynos5/machine/hardware.c index 4027f119d3490259f32459ee45ae024d376616b1..23ed4c518f9ffcccb341a1f6dad7ec93413e8f3c 100644 --- a/src/plat/exynos5/machine/hardware.c +++ b/src/plat/exynos5/machine/hardware.c @@ -295,7 +295,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -306,7 +307,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); map_kernel_frame( @@ -315,7 +317,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -327,7 +330,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); #endif /* DEBUG */ diff --git a/src/plat/imx31/machine/hardware.c b/src/plat/imx31/machine/hardware.c index dc248887b1c3c4bdbb22b22d44802a8b616c8c85..bad6c8a94398edb8745399d8d10c3e0fc63fe621 100644 --- a/src/plat/imx31/machine/hardware.c +++ b/src/plat/imx31/machine/hardware.c @@ -229,7 +229,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -240,7 +241,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -251,7 +253,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -263,7 +266,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); #endif diff --git a/src/plat/imx6/machine/hardware.c b/src/plat/imx6/machine/hardware.c index 883e9c1cca2aba604f24df72dbacd1a769e2c56c..75745017a5f6fc0cf6f0a349159baf81ed41f0cb 100644 --- a/src/plat/imx6/machine/hardware.c +++ b/src/plat/imx6/machine/hardware.c @@ -206,7 +206,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -217,7 +218,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -228,7 +230,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -241,7 +244,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); #endif /* DEBUG */ diff --git a/src/plat/omap3/machine/hardware.c b/src/plat/omap3/machine/hardware.c index 9c18883ac4829cea2d8602ba1f107931551d560a..c3ea996d4bceefd39c5f31878e029e74b50e147c 100644 --- a/src/plat/omap3/machine/hardware.c +++ b/src/plat/omap3/machine/hardware.c @@ -179,7 +179,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -190,7 +191,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); @@ -202,7 +204,8 @@ map_kernel_devices(void) VMKernelOnly, vm_attributes_new( false, /* armParityEnabled */ - false /* armPageCacheable */ + false, /* armPageCacheable */ + false /* armExecuteNever */ ) ); #endif