git: 76384bd10fdb - main - powerpc64: fix OFWFB with Radix MMU
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 14 Oct 2021 13:46:23 UTC
The branch main has been updated by luporl: URL: https://cgit.FreeBSD.org/src/commit/?id=76384bd10fdbb97be2803d969905f15a84255d6a commit 76384bd10fdbb97be2803d969905f15a84255d6a Author: Leandro Lupori <luporl@FreeBSD.org> AuthorDate: 2021-10-14 13:39:52 +0000 Commit: Leandro Lupori <luporl@FreeBSD.org> CommitDate: 2021-10-14 13:39:52 +0000 powerpc64: fix OFWFB with Radix MMU Current implementation of Radix MMU doesn't support mapping arbitrary virtual addresses, such as the ones generated by "direct mapping" I/O addresses. This caused the system to hang, when early I/O addresses, such as those used by OpenFirmware Frame Buffer, were remapped after the MMU was up. To avoid having to modify mmu_radix_kenter_attr just to support this use case, this change makes early I/O map use virtual addresses from KVA area instead (similar to what mmu_radix_mapdev_attr does), as these can be safely remapped later. Reviewed by: alfredo (earlier version), jhibbits (in irc) MFC after: 2 weeks Sponsored by: Instituto de Pesquisas Eldorado (eldorado.org.br) Differential Revision: https://reviews.freebsd.org/D31232 --- sys/powerpc/aim/aim_machdep.c | 42 +++++++++++++++++++++++++++++++++--------- sys/powerpc/aim/mmu_radix.c | 8 +------- sys/powerpc/include/pmap.h | 3 +++ sys/powerpc/powerpc/machdep.c | 9 +++++++++ 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/sys/powerpc/aim/aim_machdep.c b/sys/powerpc/aim/aim_machdep.c index d582489d9f7e..914296440104 100644 --- a/sys/powerpc/aim/aim_machdep.c +++ b/sys/powerpc/aim/aim_machdep.c @@ -476,14 +476,9 @@ aim_cpu_init(vm_offset_t toc) * in case the platform module had a better idea of what we * should do. */ - if (cpu_features2 & PPC_FEATURE2_ARCH_3_00) { - radix_mmu = 0; - TUNABLE_INT_FETCH("radix_mmu", &radix_mmu); - if (radix_mmu) - pmap_mmu_install(MMU_TYPE_RADIX, BUS_PROBE_GENERIC); - else - pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC); - } else if (cpu_features & PPC_FEATURE_64) + if (radix_mmu) + pmap_mmu_install(MMU_TYPE_RADIX, BUS_PROBE_GENERIC); + else if (cpu_features & PPC_FEATURE_64) pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC); else pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC); @@ -586,6 +581,25 @@ va_to_vsid(pmap_t pm, vm_offset_t va) #endif +void +pmap_early_io_map_init(void) +{ + if ((cpu_features2 & PPC_FEATURE2_ARCH_3_00) == 0) + radix_mmu = 0; + else + TUNABLE_INT_FETCH("radix_mmu", &radix_mmu); + + /* + * When using Radix, set the start and end of kva early, to be able to + * use KVAs on pmap_early_io_map and avoid issues when remapping them + * later. + */ + if (radix_mmu) { + virtual_avail = VM_MIN_KERNEL_ADDRESS; + virtual_end = VM_MAX_SAFE_KERNEL_ADDRESS; + } +} + /* * These functions need to provide addresses that both (a) work in real mode * (or whatever mode/circumstances the kernel is in in early boot (now)) and @@ -601,10 +615,20 @@ pmap_early_io_map(vm_paddr_t pa, vm_size_t size) * If we have the MMU up in early boot, assume it is 1:1. Otherwise, * try to get the address in a memory region compatible with the * direct map for efficiency later. + * Except for Radix MMU, for which current implementation doesn't + * support mapping arbitrary virtual addresses, such as the ones + * generated by "direct mapping" I/O addresses. In this case, use + * addresses from KVA area. */ if (mfmsr() & PSL_DR) return (pa); - else + else if (radix_mmu) { + vm_offset_t va; + + va = virtual_avail; + virtual_avail += round_page(size + pa - trunc_page(pa)); + return (va); + } else return (DMAP_BASE_ADDRESS + pa); } diff --git a/sys/powerpc/aim/mmu_radix.c b/sys/powerpc/aim/mmu_radix.c index 50c658e58a4a..ca1a4d2f4797 100644 --- a/sys/powerpc/aim/mmu_radix.c +++ b/sys/powerpc/aim/mmu_radix.c @@ -907,7 +907,7 @@ kvtopte(vm_offset_t va) pt_entry_t *l3e; l3e = pmap_pml3e(kernel_pmap, va); - if ((be64toh(*l3e) & RPTE_VALID) == 0) + if (l3e == NULL || (be64toh(*l3e) & RPTE_VALID) == 0) return (NULL); return (pmap_l3e_to_pte(l3e, va)); } @@ -2071,12 +2071,6 @@ mmu_radix_late_bootstrap(vm_offset_t start, vm_offset_t end) for (i = 0; phys_avail[i + 2] != 0; i += 2) Maxmem = MAX(Maxmem, powerpc_btop(phys_avail[i + 1])); - /* - * Set the start and end of kva. - */ - virtual_avail = VM_MIN_KERNEL_ADDRESS; - virtual_end = VM_MAX_SAFE_KERNEL_ADDRESS; - /* * Remap any early IO mappings (console framebuffer, etc.) */ diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h index 2f1886a27093..d14398750080 100644 --- a/sys/powerpc/include/pmap.h +++ b/sys/powerpc/include/pmap.h @@ -340,6 +340,9 @@ extern int pmap_bootstrapped; extern int radix_mmu; extern int superpages_enabled; +#ifdef AIM +void pmap_early_io_map_init(void); +#endif vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size); void pmap_early_io_unmap(vm_offset_t va, vm_size_t size); void pmap_track_page(pmap_t pmap, vm_offset_t va); diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c index 622af17b3305..2dc9a3e9d549 100644 --- a/sys/powerpc/powerpc/machdep.c +++ b/sys/powerpc/powerpc/machdep.c @@ -419,6 +419,15 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp, if (ofw_bootargs) ofw_parse_bootargs(); +#ifdef AIM + /* + * Early I/O map needs to be initialized before console, in order to + * map frame buffers properly, and after boot args have been parsed, + * to handle tunables properly. + */ + pmap_early_io_map_init(); +#endif + /* * Initialize the console before printing anything. */