diff options
| author | Leandro Lupori <luporl@FreeBSD.org> | 2019-12-09 13:40:23 +0000 |
|---|---|---|
| committer | Leandro Lupori <luporl@FreeBSD.org> | 2019-12-09 13:40:23 +0000 |
| commit | 35f294270c55d2bdddfad74522e90a854ee85544 (patch) | |
| tree | a44ab26ffbca43cec83f81eab42b83b84cc80c36 /sys/powerpc/ofw | |
| parent | a16111e6a27c2e9dd1bfbdd29f114b2abaa1eae7 (diff) | |
Notes
Diffstat (limited to 'sys/powerpc/ofw')
| -rw-r--r-- | sys/powerpc/ofw/ofw_real.c | 91 |
1 files changed, 84 insertions, 7 deletions
diff --git a/sys/powerpc/ofw/ofw_real.c b/sys/powerpc/ofw/ofw_real.c index 83206d7d7eb4..cc21dab6a4f9 100644 --- a/sys/powerpc/ofw/ofw_real.c +++ b/sys/powerpc/ofw/ofw_real.c @@ -168,7 +168,45 @@ static vm_offset_t of_bounce_phys; static caddr_t of_bounce_virt; static off_t of_bounce_offset; static size_t of_bounce_size; + +/* + * To be able to use OFW console on PPC, that requires real mode OFW, + * the mutex that guards the mapping/unmapping of virtual to physical + * buffers (of_real_mtx) must be of SPIN type. This is needed because + * kernel console first locks a SPIN mutex before calling OFW real. + * By default, of_real_mtx is a sleepable mutex. To make it of SPIN + * type, use the following tunnable: + * machdep.ofw.mtx_spin=1 + * + * Besides that, a few more tunables are needed to select and use the + * OFW console with real mode OFW. + * + * In order to disable the use of OFW FrameBuffer and fallback to the + * OFW console, use: + * hw.ofwfb.disable=1 + * + * To disable the use of FDT (that doesn't support OFW read/write methods) + * and use real OFW instead, unset the following loader variable: + * unset usefdt + * + * OFW is put in quiesce state in early kernel boot, which usually disables + * OFW read/write capabilities (in QEMU write continue to work, but + * read doesn't). To avoid OFW quiesce, use: + * debug.quiesce_ofw=0 + * + * Note that disabling OFW quiesce can cause conflicts between kernel and + * OFW trying to control the same hardware. Thus, it must be used with care. + * Some conflicts can be avoided by disabling kernel drivers with hints. + * For instance, to disable a xhci controller and an USB keyboard connected + * to it, that may be already being used for input by OFW, use: + * hint.xhci.0.disabled=1 + */ + static struct mtx of_bounce_mtx; +static struct mtx of_spin_mtx; +static struct mtx *of_real_mtx; +static void (*of_mtx_lock)(void); +static void (*of_mtx_unlock)(void); extern int ofw_real_mode; @@ -182,16 +220,40 @@ SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, ofw_real_bounce_alloc, NULL); static void +ofw_real_mtx_lock_spin(void) +{ + mtx_lock_spin(of_real_mtx); +} + +static void +ofw_real_mtx_lock(void) +{ + mtx_lock(of_real_mtx); +} + +static void +ofw_real_mtx_unlock_spin(void) +{ + mtx_unlock_spin(of_real_mtx); +} + +static void +ofw_real_mtx_unlock(void) +{ + mtx_unlock(of_real_mtx); +} + +static void ofw_real_start(void) { - mtx_lock(&of_bounce_mtx); + (*of_mtx_lock)(); of_bounce_offset = 0; } - + static void ofw_real_stop(void) { - mtx_unlock(&of_bounce_mtx); + (*of_mtx_unlock)(); } static void @@ -228,7 +290,7 @@ ofw_real_bounce_alloc(void *junk) * we have a 32-bit virtual address to give OF. */ - if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0)) + if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0)) pmap_kenter(of_bounce_phys, of_bounce_phys); mtx_unlock(&of_bounce_mtx); @@ -240,7 +302,7 @@ ofw_real_map(const void *buf, size_t len) static char emergency_buffer[255]; cell_t phys; - mtx_assert(&of_bounce_mtx, MA_OWNED); + mtx_assert(of_real_mtx, MA_OWNED); if (of_bounce_virt == NULL) { /* @@ -290,7 +352,7 @@ ofw_real_map(const void *buf, size_t len) static void ofw_real_unmap(cell_t physaddr, void *buf, size_t len) { - mtx_assert(&of_bounce_mtx, MA_OWNED); + mtx_assert(of_real_mtx, MA_OWNED); if (of_bounce_virt == NULL) return; @@ -306,9 +368,24 @@ ofw_real_unmap(cell_t physaddr, void *buf, size_t len) static int ofw_real_init(ofw_t ofw, void *openfirm) { - openfirmware = (int (*)(void *))openfirm; + int mtx_spin; + openfirmware = (int (*)(void *))openfirm; mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF); + + mtx_spin = 0; + TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin); + if (mtx_spin) { + mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN); + of_real_mtx = &of_spin_mtx; + of_mtx_lock = ofw_real_mtx_lock_spin; + of_mtx_unlock = ofw_real_mtx_unlock_spin; + } else { + of_real_mtx = &of_bounce_mtx; + of_mtx_lock = ofw_real_mtx_lock; + of_mtx_unlock = ofw_real_mtx_unlock; + } + of_bounce_virt = NULL; return (0); } |
