diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index e73261025361..51b9798c131d 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -775,3 +775,11 @@ va_to_vsid(pmap_t pm, vm_offset_t va) } #endif + +vm_offset_t +pmap_early_io_map(vm_paddr_t pa, vm_size_t size) +{ + + return (pa); +} + diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c index 340c7a0d99f6..e700a56f04a7 100644 --- a/sys/powerpc/booke/machdep.c +++ b/sys/powerpc/booke/machdep.c @@ -350,13 +350,18 @@ booke_init(uint32_t arg1, uint32_t arg2) if (OF_init((void *)dtbp) != 0) while (1); - if (fdt_immr_addr(CCSRBAR_VA) != 0) - while (1); - OF_interpret("perform-fixup", 0); /* Set up TLB initially */ - booke_init_tlb(fdt_immr_pa); + tlb1_init(); + + /* Set up IMMR */ + if (fdt_immr_addr(0) == 0) { + fdt_immr_va = pmap_early_io_map(fdt_immr_pa, fdt_immr_size); + } else { + printf("Warning: SOC base registers could not be found!\n"); + fdt_immr_va = 0; + } /* Reset Time Base */ mttb(0); diff --git a/sys/powerpc/booke/machdep_e500.c b/sys/powerpc/booke/machdep_e500.c index 85805a278a6a..ab47f620424a 100644 --- a/sys/powerpc/booke/machdep_e500.c +++ b/sys/powerpc/booke/machdep_e500.c @@ -47,8 +47,6 @@ void booke_init_tlb(vm_paddr_t fdt_immr_pa) { - /* Initialize TLB1 handling */ - tlb1_init(fdt_immr_pa); } void diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 47c6056567f1..a9476a2db758 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -113,7 +113,6 @@ extern uint32_t *bootinfo; extern uint32_t bp_ntlb1s; #endif -vm_paddr_t ccsrbar_pa; vm_paddr_t kernload; vm_offset_t kernstart; vm_size_t kernsize; @@ -2662,22 +2661,25 @@ mmu_booke_mapdev_attr(mmu_t mmu, vm_paddr_t pa, vm_size_t size, vm_memattr_t ma) void *res; uintptr_t va; vm_size_t sz; + int i; /* - * CCSR is premapped. Note that (pa + size - 1) is there to make sure - * we don't wrap around. Devices on the local bus typically extend all - * the way up to and including 0xffffffff. In that case (pa + size) - * would be 0. This creates a false positive (i.e. we think it's - * within the CCSR) and not create a mapping. + * Check if this is premapped in TLB1. Note: this should probably also + * check whether a sequence of TLB1 entries exist that match the + * requirement, but now only checks the easy case. */ - if (ma == VM_MEMATTR_DEFAULT && pa >= ccsrbar_pa && - (pa + size - 1) < (ccsrbar_pa + CCSRBAR_SIZE)) { - va = CCSRBAR_VA + (pa - ccsrbar_pa); - return ((void *)va); + if (ma == VM_MEMATTR_DEFAULT) { + for (i = 0; i < tlb1_idx; i++) { + if (!(tlb1[i].mas1 & MAS1_VALID)) + continue; + if (pa >= tlb1[i].phys && + (pa + size) <= (tlb1[i].phys + tlb1[i].size)) + return (void *)(tlb1[i].virt + + (pa - tlb1[i].phys)); + } } - if (size < PAGE_SIZE) - size = PAGE_SIZE; + size = roundup(size, PAGE_SIZE); if (pa >= (VM_MAXUSER_ADDRESS + PAGE_SIZE) && (pa + size - 1) < VM_MIN_KERNEL_ADDRESS) @@ -2899,9 +2901,8 @@ tlb0_print_tlbentries(void) /* * TLB1 mapping notes: * - * TLB1[0] CCSRBAR - * TLB1[1] Kernel text and data. - * TLB1[2-15] Additional kernel text and data mappings (if required), PCI + * TLB1[0] Kernel text and data. + * TLB1[1-15] Additional kernel text and data mappings (if required), PCI * windows, other devices mappings. */ @@ -3094,14 +3095,12 @@ tlb1_mapin_region(vm_offset_t va, vm_paddr_t pa, vm_size_t size) * assembler level setup done in locore.S. */ void -tlb1_init(vm_offset_t ccsrbar) +tlb1_init() { - uint32_t mas0, mas1, mas3; + uint32_t mas0, mas1, mas2, mas3; uint32_t tsz; u_int i; - ccsrbar_pa = ccsrbar; - if (bootinfo != NULL && bootinfo[0] != 1) { tlb1_idx = *((uint16_t *)(bootinfo + 8)); } else @@ -3117,22 +3116,23 @@ tlb1_init(vm_offset_t ccsrbar) if ((mas1 & MAS1_VALID) == 0) continue; + mas2 = mfspr(SPR_MAS2); mas3 = mfspr(SPR_MAS3); tlb1[i].mas1 = mas1; tlb1[i].mas2 = mfspr(SPR_MAS2); tlb1[i].mas3 = mas3; + tlb1[i].virt = mas2 & MAS2_EPN_MASK; + tlb1[i].phys = mas3 & MAS3_RPN; if (i == 0) kernload = mas3 & MAS3_RPN; tsz = (mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; - kernsize += (tsz > 0) ? tsize2size(tsz) : 0; + tlb1[i].size = (tsz > 0) ? tsize2size(tsz) : 0; + kernsize += tlb1[i].size; } - /* Map in CCSRBAR. */ - tlb1_set_entry(CCSRBAR_VA, ccsrbar, CCSRBAR_SIZE, _TLB_ENTRY_IO); - #ifdef SMP bp_ntlb1s = tlb1_idx; #endif @@ -3145,6 +3145,43 @@ tlb1_init(vm_offset_t ccsrbar) set_mas4_defaults(); } +vm_offset_t +pmap_early_io_map(vm_paddr_t pa, vm_size_t size) +{ + static vm_offset_t early_io_map_base = VM_MAX_KERNEL_ADDRESS; + vm_paddr_t pa_base; + vm_offset_t va, sz; + int i; + + KASSERT(!pmap_bootstrapped, ("Do not use after PMAP is up!")); + + for (i = 0; i < tlb1_idx; i++) { + if (!(tlb1[i].mas1 & MAS1_VALID)) + continue; + if (pa >= tlb1[i].phys && (pa + size) <= + (tlb1[i].phys + tlb1[i].size)) + return (tlb1[i].virt + (pa - tlb1[i].phys)); + } + + pa_base = trunc_page(pa); + size = roundup(size + (pa - pa_base), PAGE_SIZE); + va = early_io_map_base + (pa - pa_base); + + do { + sz = 1 << (ilog2(size) & ~1); + tlb1_set_entry(early_io_map_base, pa_base, sz, _TLB_ENTRY_IO); + size -= sz; + pa_base += sz; + early_io_map_base += sz; + } while (size > 0); + +#ifdef SMP + bp_ntlb1s = tlb1_idx; +#endif + + return (va); +} + /* * Setup MAS4 defaults. * These values are loaded to MAS0-2 on a TLB miss. diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h index f50ff118da0f..f73e8c8a05f5 100644 --- a/sys/powerpc/include/pmap.h +++ b/sys/powerpc/include/pmap.h @@ -254,6 +254,8 @@ extern void pmap_dumpsys_unmap(struct pmap_md *, vm_size_t, vm_offset_t); extern struct pmap_md *pmap_scan_md(struct pmap_md *); +vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size); + #endif #endif /* !_MACHINE_PMAP_H_ */ diff --git a/sys/powerpc/include/tlb.h b/sys/powerpc/include/tlb.h index 7e0d909a074f..58a1a019eb42 100644 --- a/sys/powerpc/include/tlb.h +++ b/sys/powerpc/include/tlb.h @@ -126,6 +126,9 @@ #if !defined(LOCORE) typedef struct tlb_entry { + vm_paddr_t phys; + vm_offset_t virt; + vm_size_t size; uint32_t mas1; uint32_t mas2; uint32_t mas3; @@ -134,7 +137,7 @@ typedef struct tlb_entry { void tlb0_print_tlbentries(void); void tlb1_inval_entry(unsigned int); -void tlb1_init(vm_offset_t); +void tlb1_init(void); void tlb1_print_entries(void); void tlb1_print_tlbentries(void); #endif /* !LOCORE */ diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h index 5a2979623d1f..0b12933eca05 100644 --- a/sys/powerpc/include/vmparam.h +++ b/sys/powerpc/include/vmparam.h @@ -108,12 +108,6 @@ #else /* Book-E */ -/* - * Kernel CCSRBAR location. We make this the reset location. - */ -#define CCSRBAR_VA 0xfef00000 -#define CCSRBAR_SIZE 0x00100000 - #define KERNBASE 0xc0000000 /* start of kernel virtual */ #define VM_MIN_KERNEL_ADDRESS KERNBASE diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c index 0db5d5e0efef..e94a1d832b06 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.c +++ b/sys/powerpc/mpc85xx/mpc85xx.c @@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include /* diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h index fa3bde3f24ee..defb3bf2afd6 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.h +++ b/sys/powerpc/mpc85xx/mpc85xx.h @@ -33,6 +33,7 @@ /* * Configuration control and status registers */ +#define CCSRBAR_VA fdt_immr_va #define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0) #define OCP85XX_BPTR (CCSRBAR_VA + 0x20) diff --git a/sys/powerpc/powerpc/bus_machdep.c b/sys/powerpc/powerpc/bus_machdep.c index 950d02622825..1928539dbbd1 100644 --- a/sys/powerpc/powerpc/bus_machdep.c +++ b/sys/powerpc/powerpc/bus_machdep.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #define MAX_EARLYBOOT_MAPPINGS 6 static struct { + vm_offset_t virt; bus_addr_t addr; bus_size_t size; int flags; @@ -86,10 +87,12 @@ bs_gen_map(bus_addr_t addr, bus_size_t size, int flags, KASSERT(earlyboot_map_idx < MAX_EARLYBOOT_MAPPINGS, ("%s: too many early boot mapping requests", __func__)); earlyboot_mappings[earlyboot_map_idx].addr = addr; + earlyboot_mappings[earlyboot_map_idx].virt = + pmap_early_io_map(addr, size); earlyboot_mappings[earlyboot_map_idx].size = size; earlyboot_mappings[earlyboot_map_idx].flags = flags; + *bshp = earlyboot_mappings[earlyboot_map_idx].virt; earlyboot_map_idx++; - *bshp = addr; } else { ma = VM_MEMATTR_DEFAULT; switch (flags) { @@ -110,13 +113,13 @@ void bs_remap_earlyboot(void) { int i; - vm_offset_t pa, spa; + vm_offset_t pa, spa, va; vm_memattr_t ma; for (i = 0; i < earlyboot_map_idx; i++) { spa = earlyboot_mappings[i].addr; - if (pmap_dev_direct_mapped(spa, earlyboot_mappings[i].size) - == 0) + if (spa == earlyboot_mappings[i].virt && + pmap_dev_direct_mapped(spa, earlyboot_mappings[i].size) == 0) continue; ma = VM_MEMATTR_DEFAULT; @@ -130,8 +133,10 @@ bs_remap_earlyboot(void) } pa = trunc_page(spa); + va = trunc_page(earlyboot_mappings[i].virt); while (pa < spa + earlyboot_mappings[i].size) { - pmap_kenter_attr(pa, pa, ma); + pmap_kenter_attr(va, pa, ma); + va += PAGE_SIZE; pa += PAGE_SIZE; } }