The branch main has been updated by luporl:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=76384bd10fdbb97be2803d969905f15a84255d6a

commit 76384bd10fdbb97be2803d969905f15a84255d6a
Author:     Leandro Lupori <lup...@freebsd.org>
AuthorDate: 2021-10-14 13:39:52 +0000
Commit:     Leandro Lupori <lup...@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.
         */

Reply via email to