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
This commit is contained in:
parent
0a8159d8ca
commit
76384bd10f
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.)
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user