arm: enable enforcing memory access permissions

Bootloader:
* set permissions to kernel read/write, no user access
  for initially mapped memory areas
* set permissions to kernel read/write, no execute,
  no user access for UART

Kernel:
* physical memory mapper uses kernel read/write mapping
  with no-execute bit enabled
* all other pages are mapped as read/write/execute for
  kernel and user
* proper access permissions and memory types to be
  implemented later

Enforce memory access permissions by setting DACR to
client mode for domain #0, no access for other domains.

see ARM Architecture Reference Manual, section B3.7 Memory access control
and in particular the following subsections:
B3.7.1 Access permissions
B3.7.2 Execute-never restrictions on instruction fetching
B3.7.3 Domains, Short-descriptor format only

Change-Id: I8127b4c72dc516d013cb9751d80d6f3a9ec835e6
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5233
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
David Karoly 2022-04-22 13:17:40 +02:00 committed by Fredrik Holmqvist
parent 097f72e92c
commit adc32659fb
4 changed files with 28 additions and 23 deletions

View File

@ -43,26 +43,26 @@
// found it in the cortex A8 reference... so I set t to 0
// page table must obviously be on multiple of 1KB
/*
* L2-Page descriptors... now things get really complicated...
* there are three different types of pages large pages (64KB) and small(4KB)
* and "small extended".
* only small extende is used by now....
* and there is a new and a old format of page table entries
* I will use the old format...
*/
#define ARM_MMU_L2_TYPE_LARGE 0x1
#define ARM_MMU_L2_TYPE_SMALLNEW 0x2
#define ARM_MMU_L2_TYPE_SMALLEXT 0x3
/* for new format entries (cortex-a8) */
#define ARM_MMU_L2_TYPE_SMALLNEW 0x2
#define ARM_MMU_L2_FLAG_XN 0x001
#define ARM_MMU_L2_FLAG_B 0x004
#define ARM_MMU_L2_FLAG_C 0x008
#define ARM_MMU_L2_FLAG_AP0 0x010
#define ARM_MMU_L2_FLAG_AP1 0x020
#define ARM_MMU_L2_FLAG_TEX0 0x040
#define ARM_MMU_L2_FLAG_TEX1 0x080
#define ARM_MMU_L2_FLAG_TEX2 0x100
#define ARM_MMU_L2_FLAG_AP2 0x200
#define ARM_MMU_L2_FLAG_S 0x400
#define ARM_MMU_L2_FLAG_NG 0x800
// for B C and TEX see ARM arm B4-11
#define ARM_MMU_L2_FLAG_B 0x4
#define ARM_MMU_L2_FLAG_C 0x8
#define ARM_MMU_L2_FLAG_TEX 0 // use 0b000 as TEX
#define ARM_MMU_L2_FLAG_AP_RW 0x30
#define ARM_MMU_L2_FLAG_AP_KRW 0x010
// allow read and write for kernel only
#define ARM_MMU_L2_FLAG_AP_RW 0x030
// allow read and write for user and system
#define ARM_MMU_L1_TABLE_ENTRY_COUNT 4096

View File

@ -325,7 +325,7 @@ arch_mmu_generate_post_efi_page_tables(size_t memoryMapSize,
(efi_memory_descriptor *)(memoryMapAddr + i * descriptorSize);
if ((entry->Attribute & EFI_MEMORY_RUNTIME) != 0) {
map_range_to_new_area(entry,
ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C | ARM_MMU_L2_FLAG_AP_RW);
ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C | ARM_MMU_L2_FLAG_AP_KRW);
}
}
@ -335,10 +335,11 @@ arch_mmu_generate_post_efi_page_tables(size_t memoryMapSize,
size_t size;
while (mmu_next_region(&cookie, &vaddr, &paddr, &size)) {
map_range(vaddr, paddr, size,
ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C | ARM_MMU_L2_FLAG_AP_RW);
ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C | ARM_MMU_L2_FLAG_AP_KRW);
}
map_range_to_new_area(gKernelArgs.arch_args.uart.regs, ARM_MMU_L2_FLAG_B);
map_range_to_new_area(gKernelArgs.arch_args.uart.regs,
ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_AP_KRW | ARM_MMU_L2_FLAG_XN);
sort_address_ranges(gKernelArgs.virtual_allocated_range,
gKernelArgs.num_virtual_allocated_ranges);

View File

@ -83,11 +83,13 @@ _pl1_entry:
MCR p15, 0, r1, c8, c7, 0
// write DACR
mov r9, #0xffffffff
MCR p15, 0, r9, c3, c0, 0
mov r9, #0x00000001
mcr p15, 0, r9, c3, c0, 0
// enable MMU and caches
mrc p15, 0, r9, c1, c0, 0
bic r9, r9, #0x20000000 // access flag disabled
bic r9, r9, #0x10000000 // TEX remap disabled
orr r9, r9, #0x00001000 // i-cache enabled
orr r9, r9, #0x00000004 // d-cache enabled
orr r9, r9, #0x00000001 // MMU enabled

View File

@ -182,7 +182,8 @@ ARMPagingMethod32Bit::PhysicalPageSlotPool::Map(phys_addr_t physicalAddress,
(virtualAddress - fVirtualBase) / B_PAGE_SIZE];
pte = (physicalAddress & ARM_PTE_ADDRESS_MASK)
| ARM_MMU_L2_TYPE_SMALLNEW
| ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C;
| ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C
| ARM_MMU_L2_FLAG_AP_KRW | ARM_MMU_L2_FLAG_XN;
arch_cpu_invalidate_TLB_range(virtualAddress, virtualAddress + B_PAGE_SIZE);
// invalidate_TLB(virtualAddress);
@ -510,7 +511,8 @@ ARMPagingMethod32Bit::PutPageTableEntryInTable(page_table_entry* entry,
{
page_table_entry page = (physicalAddress & ARM_PTE_ADDRESS_MASK)
| ARM_MMU_L2_TYPE_SMALLNEW
| ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C;
| ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C
| ARM_MMU_L2_FLAG_AP_RW;
#if 0 //IRA
| X86_PTE_PRESENT | (globalPage ? X86_PTE_GLOBAL : 0)
| MemoryTypeToPageTableEntryFlags(memoryType);