Date: Thu, 20 Feb 2014 23:18:30 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r262272 - projects/arm64/sys/arm64/arm64 Message-ID: <201402202318.s1KNIUWx007955@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andrew Date: Thu Feb 20 23:18:30 2014 New Revision: 262272 URL: http://svnweb.freebsd.org/changeset/base/262272 Log: Build the PA == VA map and turn the MMU on Modified: projects/arm64/sys/arm64/arm64/locore.S Modified: projects/arm64/sys/arm64/arm64/locore.S ============================================================================== --- projects/arm64/sys/arm64/arm64/locore.S Thu Feb 20 23:17:46 2014 (r262271) +++ projects/arm64/sys/arm64/arm64/locore.S Thu Feb 20 23:18:30 2014 (r262272) @@ -29,6 +29,10 @@ #include "assym.s" #include <machine/armreg.h> #include <machine/hypervisor.h> +#include <machine/param.h> +#include <machine/pte.h> + +#define VIRT_BITS 38 .globl kernbase .set kernbase, KERNBASE @@ -49,6 +53,21 @@ _start: /* Drop to EL1 */ bl drop_to_el1 + /* Get the virt -> phys offset */ + bl get_virt_delta + + /* + * At this point: + * x29 = PA - VA + * x28 = Our physical load address + */ + + /* Create the page tables */ + bl create_pagetables + + /* Enable the mmu */ + bl start_mmu + /* Load the address of the fvp UART */ mov x0, 0x1c090000 /* Load 'A' */ @@ -103,8 +122,10 @@ drop_to_el1: msr elr_el2, x30 eret + + .align 3 .Lsctlr_res1: - .word SCTLR_RES1 + .quad SCTLR_RES1 #define VECT_EMPTY \ .align 7; \ @@ -135,6 +156,184 @@ hyp_vectors: hyp_trap_invalid: b hyp_trap_invalid +/* + * Get the delta between the physical address we were loaded to and the + * virtual address we expect to run from. This is used when building the + * initial page table. + */ +get_virt_delta: + /* Load the physical address of virt_map */ + adr x29, virt_map + /* Load the virtual address of virt_map stored in virt_map */ + ldr x28, [x29] + /* Find PA - VA as PA' = VA' - VA + PA = VA' + (PA - VA) = VA' + x29 */ + sub x29, x29, x28 + /* Find the load address for the kernel */ + mov x28, #(KERNBASE) + add x28, x28, x29 + ret + + .align 3 +virt_map: + .quad virt_map + +/* + * This builds the page tables containing the identity map, and the kernel + * virtual map. + * + * It relys on: + * We were loaded to an address that is on a 2MiB boundary + * All the memory must not cross a 1GiB boundaty + * x28 contains the physical address we were loaded from + * + * TODO: This is out of date. + * There are at least 5 pages before that address for the page tables + * The pages used are: + * - The identity (PA = VA) table (TTBR0) + * - The Kernel L1 table (TTBR1)(not yet) + * - The PA != VA L2 table to jump into (not yet) + * - The FDT L2 table (not yet) + */ +create_pagetables: + /* Save the Link register */ + mov x5, x30 + + mov x15, #(PAGE_SIZE * 3) + + /* Clean the page table */ + adr x6, pagetable + mov x26, x6 + add x27, x6, x15 +1: + stp xzr, xzr, [x6], #16 + stp xzr, xzr, [x6], #16 + stp xzr, xzr, [x6], #16 + stp xzr, xzr, [x6], #16 + cmp x6, x27 + b.lo 1b + + /* + * Build the TTBR0 maps. + */ + add x27, x26, #1, lsl #PAGE_SHIFT + + /* Create the VA = PA map */ + mov x6, x27 /* The initial page table */ + mov x7, #1 + mov x9, x27 + mov x8, x9 /* VA start (== PA start) */ + bl build_section_pagetable + + /* Create a table for the UART (TODO: Remove) */ + mov x7, #0 + mov x8, #0x10000000 /* VA start (== PA start) */ + mov x9, #0x10000000 /* PA start */ + bl build_section_pagetable + + /* Restore the Link register */ + mov x30, x5 + ret + +/* + * Builds a 1 GiB page table entry + * x6 = L1 table + * x7 = Type (0 = Device, 1 = Normal) + * x8 = VA start + * x9 = PA start (trashed) + * x11, x12 and x13 are trashed + */ +build_section_pagetable: + /* + * Build the L1 table entry. + */ + /* Find the table index */ + lsr x11, x8, #L1_SHIFT + and x11, x11, #Ln_ADDR_MASK + + /* Build the L1 block entry */ + lsl x12, x7, #2 + orr x12, x12, #L1_BLOCK + orr x12, x12, #(ATTR_AF) + + /* Only use the output address bits */ + lsr x9, x9, #L1_SHIFT + orr x12, x12, x9, lsl #L1_SHIFT + + /* Store the entry */ + str x12, [x6, x11, lsl #3] + + ret + +/* + * Builds an L1 -> L2 table descriptor + * + * This is a link for a 1GiB block of memory with up to 2MiB regions mapped + * within it by build_block_pagetable. + * + * x6 = L1 table + * x8 = Virtual Address + * x9 = L2 PA + * x11, x12 and x13 are trashed + */ +link_l1_pagetable: + /* + * Link an L1 -> L2 table entry. + */ + ret + +start_mmu: + dsb sy + + /* Load ttbr0 and ttbr1 */ + msr ttbr0_el1, x27 + msr ttbr1_el1, x26 + isb + + /* Clear the Monitor Debug System control register */ + msr mdscr_el1, xzr + + /* Invalidate the TLB */ + tlbi vmalle1is + + ldr x2, mair + msr mair_el1, x2 + + /* Setup TCR */ + ldr x2, tcr + msr tcr_el1, x2 + + /* Setup SCTLR */ + ldr x2, sctlr_set + ldr x3, sctlr_clear + mrs x1, sctlr_el1 + bic x1, x1, x3 /* Clear the required bits */ + orr x1, x1, x2 /* Set the required bits */ + msr sctlr_el1, x1 + isb + + ret + + .align 3 +mair: + .quad MAIR(0x00, 0) | MAIR(0x44, 1) | MAIR(0xff, 2) +tcr: + .quad (TCR_TxSZ(63 - VIRT_BITS) | TCR_ASID_16 | TCR_IPS_40BIT | \ + TCR_TG1_4K) +sctlr_set: + /* Bits to set */ + .quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \ + SCTLR_I | SCTLR_SED | SCTLR_M) +sctlr_clear: + /* Bits to clear */ + .quad (SCTLR_EE | SCTLR_EOE | SCTLR_WXN | SCTLR_UMA | SCTLR_ITD | \ + SCTLR_THEE | SCTLR_CP15BEN | SCTLR_SA0 | SCTLR_SA | SCTLR_C | \ + SCTLR_A) + .globl abort abort: b abort + + //.section .init_pagetable + .align 12 /* 4KiB aligned */ +pagetable: + .space (PAGE_SIZE * 3) /* 3 tables */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402202318.s1KNIUWx007955>