|
@@ -592,3 +592,75 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
|
|
|
pmd_t *p = pmd;
|
|
|
|
|
|
#ifndef CONFIG_ARM_LPAE
|
|
|
+ if (addr & SECTION_SIZE)
|
|
|
+ pmd++;
|
|
|
+#endif
|
|
|
+
|
|
|
+ do {
|
|
|
+ *pmd = __pmd(phys | type->prot_sect);
|
|
|
+ phys += SECTION_SIZE;
|
|
|
+ } while (pmd++, addr += SECTION_SIZE, addr != end);
|
|
|
+
|
|
|
+ flush_pmd_entry(p);
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * No need to loop; pte's aren't interested in the
|
|
|
+ * individual L1 entries.
|
|
|
+ */
|
|
|
+ alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
|
|
|
+ unsigned long end, unsigned long phys, const struct mem_type *type)
|
|
|
+{
|
|
|
+ pud_t *pud = pud_offset(pgd, addr);
|
|
|
+ unsigned long next;
|
|
|
+
|
|
|
+ do {
|
|
|
+ next = pud_addr_end(addr, end);
|
|
|
+ alloc_init_section(pud, addr, next, phys, type);
|
|
|
+ phys += next - addr;
|
|
|
+ } while (pud++, addr = next, addr != end);
|
|
|
+}
|
|
|
+
|
|
|
+#ifndef CONFIG_ARM_LPAE
|
|
|
+static void __init create_36bit_mapping(struct map_desc *md,
|
|
|
+ const struct mem_type *type)
|
|
|
+{
|
|
|
+ unsigned long addr, length, end;
|
|
|
+ phys_addr_t phys;
|
|
|
+ pgd_t *pgd;
|
|
|
+
|
|
|
+ addr = md->virtual;
|
|
|
+ phys = __pfn_to_phys(md->pfn);
|
|
|
+ length = PAGE_ALIGN(md->length);
|
|
|
+
|
|
|
+ if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
|
|
|
+ printk(KERN_ERR "MM: CPU does not support supersection "
|
|
|
+ "mapping for 0x%08llx at 0x%08lx\n",
|
|
|
+ (long long)__pfn_to_phys((u64)md->pfn), addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* N.B. ARMv6 supersections are only defined to work with domain 0.
|
|
|
+ * Since domain assignments can in fact be arbitrary, the
|
|
|
+ * 'domain == 0' check below is required to insure that ARMv6
|
|
|
+ * supersections are only allocated for domain 0 regardless
|
|
|
+ * of the actual domain assignments in use.
|
|
|
+ */
|
|
|
+ if (type->domain) {
|
|
|
+ printk(KERN_ERR "MM: invalid domain in supersection "
|
|
|
+ "mapping for 0x%08llx at 0x%08lx\n",
|
|
|
+ (long long)__pfn_to_phys((u64)md->pfn), addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) {
|
|
|
+ printk(KERN_ERR "MM: cannot create mapping for 0x%08llx"
|
|
|
+ " at 0x%08lx invalid alignment\n",
|
|
|
+ (long long)__pfn_to_phys((u64)md->pfn), addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|