/* * Initialize page tables for the lpae case */ void init_mmu_lpae(void) { unsigned base; unsigned ncpu = lsp.syspage.p->num_cpu; unsigned l1_size = ncpu * ARM_LPAE_L1_SIZE; // Get the CPU-specific PTE descriptors - Not implemented for A15 under LPAE... arm_pte_setup(); // As paddr == vaddr in startup, we require the L1/L2 tables to be allocated from memory < 4G // However, if calloc_ram ever starts handing out high memory, things will promptly stop working. // It will not be a subtle failure. // LPAE L1 table is only 32 bytes per cpu. (So we can only get 512 on a single page!) L1_paddr = calloc_ram(l1_size, __PAGESIZE); if (debug_flag) { kprintf("LPAE: %s:%d allocated 0x%x bytes at 0x%x for L1 page table\n", __func__, __LINE__, l1_size, L1_paddr); } // One page per cpu for kernel L2; three pages for user L2, shared between cpus // We allocate user and kernel l2 pages together so we can pass both to procnto with one param L2_size = (ncpu * ARM_LPAE_L2_SIZE) + ARM_LPAE_USER_L2_SIZE; L2_paddr = calloc_ram(L2_size, __PAGESIZE); if (debug_flag) { kprintf("LPAE: %s:%d allocated 0x%x bytes at 0x%x for L2 page tables\n", __func__, __LINE__, L2_size, L2_paddr); } // Init the L1/L2 tables and make the kernel L2/L3 tables accessible at the specified vaddrs // This function uses the above globals directly; doesn't need them as params. arm_lpae_table_init(ARM_LPAE_KERN_L2, ARM_LPAE_KERN_L3); // Map the L1 table into virtual space L1_vaddr = arm_map(~0L, L1_paddr, l1_size, ARM_MAP_NOEXEC | ARM_PTE_RW | armv_chip->pte_attr); // Block map startup code to allow transition to virtual addresses. // This 1-1 mapping is also used by kdebug to access the imagefs. // procnto uses syspage->un.arm.startup_base/startup_size to unmap it. // Under LPAE we use 2MB blocks instead of v6 1MB sections startup_base = shdr->ram_paddr & ~ARM_LPAE_BMASK; startup_size = shdr->ram_size; for (base = startup_base; base < startup_base + startup_size; base += ARM_LPAE_BSIZE) { arm_lpae_bmap(base, base, ARM_PTE_RO); } /* * Map RAM into the 1-1 mapping area */ lpae_map_1to1_ram(); if (debug_flag>2) { kprintf("%s dump table\n", __func__); dump_ptbl(); kprintf("%s dump table done\n", __func__); } }
/* * Initialize page tables for the non-lpae case. */ void init_mmu_32(void) { unsigned base; unsigned ncpu = lsp.syspage.p->num_cpu; unsigned L1size = ncpu * ARM_L1_SIZE; L2_size = ncpu * __PAGESIZE; /* * Get the CPU-specific PTE descriptors */ arm_pte_setup(); /* * Allocate the L1 table and the "page directory" used to map L2 tables */ L1_paddr = calloc_ram(L1size, ARM_L1_SIZE); L2_paddr = calloc_ram(L2_size, __PAGESIZE); /* * Make these tables accessible at vaddr ARM_PTP_BASE * This function uses the above globals directly; doesn't need them as params. */ arm_pdmap(ARM_PTP_BASE); /* * Map the real L1 table */ L1_vaddr = arm_map(~0L, L1_paddr, L1size, ARM_MAP_NOEXEC | ARM_PTE_RW | armv_chip->pte_attr); L1_paddr |= armv_chip->ttb_attr; /* * Section map startup code to allow transition to virtual addresses. * This 1-1 mapping is also used by kdebug to access the imagefs. * procnto uses syspage->un.arm.startup_base/startup_size to unmap it. */ startup_base = shdr->ram_paddr & ~ARM_SCMASK; startup_size = shdr->ram_size; for (base = startup_base; base < startup_base + startup_size; base += ARM_SCSIZE) { arm_scmap(base, base, ARM_PTE_RO); } /* * Map RAM into the 1-1 mapping area */ map_1to1_ram(); }
void * callout_memory_map(unsigned size, paddr_t phys, unsigned prot_flags) { int pf = ARM_PTE_RO | ARM_PTE_CB; if (prot_flags & PROT_WRITE) pf |= ARM_PTE_RW; if (prot_flags & PROT_USER) pf |= ARM_PTE_U; if (prot_flags & PROT_NOCACHE) pf &= ~ARM_PTE_CB; /* * FIXME: should this check if the range is already mapped? */ return (void *)arm_map(~0, phys, size, pf); }
/* * On ARMv7 callout_io_map() will set memory attributes to strongly ordered * (assuming armv_pte_v7mp.mask_nc = ARM_PTE_CB | ARM_PTE_V6_SP_TEX_MASK). * For ARMv7 "shareable device" memory type add ARM_PTE_B bit: */ uintptr_t callout_io_map_armv7_dev(unsigned size, paddr_t phys) { return arm_map(~0, phys, size, ARM_PTE_RW | ARM_MAP_NOEXEC | ARM_PTE_B); }