Module Name: src Committed By: jmcneill Date: Tue Oct 20 23:03:30 UTC 2020
Modified Files: src/sys/arch/arm/fdt: arm_simplefb.c arm_simplefb.h src/sys/arch/evbarm/fdt: fdt_machdep.c src/sys/dev/fdt: simplefb.c src/sys/dev/pci: pciconf.c pciconf.h Log Message: Instead of trying to prevent pciconf from reconfiguring the firmware's framebuffer, instead allow MD code to register callbacks. If a resource is changed, the driver can unmap the old resource and remap the new. Do this with simplefb so the console doesn't explode when the VGA device is (potentially) reconfigured at boot. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/fdt/arm_simplefb.c cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/fdt/arm_simplefb.h cvs rdiff -u -r1.76 -r1.77 src/sys/arch/evbarm/fdt/fdt_machdep.c cvs rdiff -u -r1.9 -r1.10 src/sys/dev/fdt/simplefb.c cvs rdiff -u -r1.49 -r1.50 src/sys/dev/pci/pciconf.c cvs rdiff -u -r1.15 -r1.16 src/sys/dev/pci/pciconf.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/fdt/arm_simplefb.c diff -u src/sys/arch/arm/fdt/arm_simplefb.c:1.2 src/sys/arch/arm/fdt/arm_simplefb.c:1.3 --- src/sys/arch/arm/fdt/arm_simplefb.c:1.2 Mon Oct 19 01:12:14 2020 +++ src/sys/arch/arm/fdt/arm_simplefb.c Tue Oct 20 23:03:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: arm_simplefb.c,v 1.2 2020/10/19 01:12:14 rin Exp $ */ +/* $NetBSD: arm_simplefb.c,v 1.3 2020/10/20 23:03:30 jmcneill Exp $ */ /*- * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -33,7 +33,7 @@ #include "opt_pci.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: arm_simplefb.c,v 1.2 2020/10/19 01:12:14 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: arm_simplefb.c,v 1.3 2020/10/20 23:03:30 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -85,6 +85,10 @@ static struct wsdisplay_accessops arm_si static struct vcons_data arm_simplefb_vcons_data; static struct vcons_screen arm_simplefb_screen; +static bus_addr_t arm_simplefb_addr; +static bus_size_t arm_simplefb_size; +static bus_space_handle_t arm_simplefb_bsh; + static int arm_simplefb_find_node(void) { @@ -157,6 +161,29 @@ arm_simplefb_pollc(void *v, int on) { } +static void +arm_simplefb_reconfig(void *arg, uint64_t new_addr) +{ + struct arm_simplefb_softc * const sc = &arm_simplefb_softc; + struct rasops_info *ri = &arm_simplefb_screen.scr_ri; + bus_space_tag_t bst = &arm_generic_bs_tag; + + bus_space_unmap(bst, arm_simplefb_bsh, arm_simplefb_size); + bus_space_map(bst, new_addr, arm_simplefb_size, + BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &arm_simplefb_bsh); + + sc->sc_bits = bus_space_vaddr(bst, arm_simplefb_bsh); + ri->ri_bits = sc->sc_bits; + + arm_simplefb_addr = (bus_addr_t)new_addr; +} + +uint64_t +arm_simplefb_physaddr(void) +{ + return arm_simplefb_addr; +} + void arm_simplefb_preattach(void) { @@ -205,6 +232,10 @@ arm_simplefb_preattach(void) BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &bsh) != 0) return; + arm_simplefb_addr = addr; + arm_simplefb_size = size; + arm_simplefb_bsh = bsh; + sc->sc_width = width; sc->sc_height = height; sc->sc_depth = depth; @@ -240,9 +271,10 @@ arm_simplefb_preattach(void) #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) /* * Let the PCI resource allocator know about our framebuffer. This - * protects the VGA device BARs from being reprogrammed when we the - * framebuffer is located in VRAM. + * lets us know if the FB base address changes so we can remap the + * framebuffer if necessary. */ - pciconf_resource_reserve(PCI_CONF_MAP_MEM, addr, size); + pciconf_resource_reserve(PCI_CONF_MAP_MEM, addr, size, + arm_simplefb_reconfig, NULL); #endif } Index: src/sys/arch/arm/fdt/arm_simplefb.h diff -u src/sys/arch/arm/fdt/arm_simplefb.h:1.1 src/sys/arch/arm/fdt/arm_simplefb.h:1.2 --- src/sys/arch/arm/fdt/arm_simplefb.h:1.1 Sat Oct 10 15:25:31 2020 +++ src/sys/arch/arm/fdt/arm_simplefb.h Tue Oct 20 23:03:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: arm_simplefb.h,v 1.1 2020/10/10 15:25:31 jmcneill Exp $ */ +/* $NetBSD: arm_simplefb.h,v 1.2 2020/10/20 23:03:30 jmcneill Exp $ */ /*- * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -33,5 +33,6 @@ #define _ARM_ARM_SIMPLEFB_H void arm_simplefb_preattach(void); +uint64_t arm_simplefb_physaddr(void); #endif /* !_ARM_ARM_SIMPLEFB_H */ Index: src/sys/arch/evbarm/fdt/fdt_machdep.c diff -u src/sys/arch/evbarm/fdt/fdt_machdep.c:1.76 src/sys/arch/evbarm/fdt/fdt_machdep.c:1.77 --- src/sys/arch/evbarm/fdt/fdt_machdep.c:1.76 Mon Oct 19 01:12:14 2020 +++ src/sys/arch/evbarm/fdt/fdt_machdep.c Tue Oct 20 23:03:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_machdep.c,v 1.76 2020/10/19 01:12:14 rin Exp $ */ +/* $NetBSD: fdt_machdep.c,v 1.77 2020/10/20 23:03:30 jmcneill Exp $ */ /*- * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.76 2020/10/19 01:12:14 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.77 2020/10/20 23:03:30 jmcneill Exp $"); #include "opt_machdep.h" #include "opt_bootconfig.h" @@ -880,6 +880,14 @@ fdt_device_register(device_t self, void #endif } +#if NWSDISPLAY > 0 && NGENFB > 0 + if (device_is_a(self, "genfb")) { + prop_dictionary_t dict = device_properties(self); + prop_dictionary_set_uint64(dict, + "simplefb-physaddr", arm_simplefb_physaddr()); + } +#endif + if (plat && plat->ap_device_register) plat->ap_device_register(self, aux); } Index: src/sys/dev/fdt/simplefb.c diff -u src/sys/dev/fdt/simplefb.c:1.9 src/sys/dev/fdt/simplefb.c:1.10 --- src/sys/dev/fdt/simplefb.c:1.9 Mon Oct 19 01:12:14 2020 +++ src/sys/dev/fdt/simplefb.c Tue Oct 20 23:03:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: simplefb.c,v 1.9 2020/10/19 01:12:14 rin Exp $ */ +/* $NetBSD: simplefb.c,v 1.10 2020/10/20 23:03:30 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include "opt_wsdisplay_compat.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: simplefb.c,v 1.9 2020/10/19 01:12:14 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: simplefb.c,v 1.10 2020/10/20 23:03:30 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -132,7 +132,7 @@ simplefb_attach_genfb(struct simplefb_so uint32_t width, height, stride; uint16_t depth; const char *format; - bus_addr_t addr; + bus_addr_t addr, sfb_addr; bus_size_t size; if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { @@ -168,6 +168,12 @@ simplefb_attach_genfb(struct simplefb_so return ENXIO; } + /* Device may have been reconfigured. MD code will tell us. */ + if (prop_dictionary_get_uint64(dict, "simplefb-physaddr", &sfb_addr) && + sfb_addr != 0) { + addr = (bus_addr_t)sfb_addr; + } + if (bus_space_map(sc->sc_bst, addr, size, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_bsh) != 0) { Index: src/sys/dev/pci/pciconf.c diff -u src/sys/dev/pci/pciconf.c:1.49 src/sys/dev/pci/pciconf.c:1.50 --- src/sys/dev/pci/pciconf.c:1.49 Sat Oct 10 15:22:15 2020 +++ src/sys/dev/pci/pciconf.c Tue Oct 20 23:03:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pciconf.c,v 1.49 2020/10/10 15:22:15 jmcneill Exp $ */ +/* $NetBSD: pciconf.c,v 1.50 2020/10/20 23:03:30 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.49 2020/10/10 15:22:15 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.50 2020/10/20 23:03:30 jmcneill Exp $"); #include "opt_pci.h" @@ -121,6 +121,8 @@ struct pciconf_resource_rsvd { int type; uint64_t start; bus_size_t size; + void (*callback)(void *, uint64_t); + void *callback_arg; LIST_ENTRY(pciconf_resource_rsvd) next; }; @@ -516,7 +518,7 @@ err: return NULL; } -static bool +static struct pciconf_resource_rsvd * pci_resource_is_reserved(int type, uint64_t addr, uint64_t size) { struct pciconf_resource_rsvd *rsvd; @@ -525,62 +527,61 @@ pci_resource_is_reserved(int type, uint6 if (rsvd->type != type) continue; if (rsvd->start <= addr + size && rsvd->start + rsvd->size >= addr) - return true; + return rsvd; } - return false; + return NULL; } -static bool -pci_device_is_reserved(pciconf_bus_t *pb, pcitag_t tag) +static struct pciconf_resource_rsvd * +pci_bar_is_reserved(pciconf_bus_t *pb, pciconf_dev_t *pd, int br) { pcireg_t base, base64, mask, mask64; + pcitag_t tag; uint64_t addr, size; - int br, width; /* - * Look to see if this device is enabled and one of the resources - * is already in use (firmware configured console device). If so, - * skip resource assignment and use firmware values. + * Resource reservation does not apply to bridges */ - width = 4; - for (br = PCI_MAPREG_START; br < PCI_MAPREG_END; br += width) { + if (pd->ppb) + return NULL; - base = pci_conf_read(pb->pc, tag, br); - pci_conf_write(pb->pc, tag, br, 0xffffffff); - mask = pci_conf_read(pb->pc, tag, br); - pci_conf_write(pb->pc, tag, br, base); - width = 4; + tag = pd->tag; - switch (PCI_MAPREG_TYPE(base)) { - case PCI_MAPREG_TYPE_IO: - addr = PCI_MAPREG_IO_ADDR(base); - size = PCI_MAPREG_IO_SIZE(mask); - if (pci_resource_is_reserved(PCI_CONF_MAP_IO, addr, size)) - return true; - break; - case PCI_MAPREG_TYPE_MEM: - if (PCI_MAPREG_MEM_TYPE(base) == PCI_MAPREG_MEM_TYPE_64BIT) { - base64 = pci_conf_read(pb->pc, tag, br + 4); - pci_conf_write(pb->pc, tag, br + 4, 0xffffffff); - mask64 = pci_conf_read(pb->pc, tag, br + 4); - pci_conf_write(pb->pc, tag, br + 4, base64); - addr = (uint64_t)PCI_MAPREG_MEM64_ADDR( - (((uint64_t)base64) << 32) | base); - size = (uint64_t)PCI_MAPREG_MEM64_SIZE( - (((uint64_t)mask64) << 32) | mask); - width = 8; - } else { - addr = PCI_MAPREG_MEM_ADDR(base); - size = PCI_MAPREG_MEM_SIZE(mask); - } - if (pci_resource_is_reserved(PCI_CONF_MAP_MEM, addr, size)) - return true; - break; + /* + * Look to see if this device is enabled and one of the resources + * is already in use (eg. firmware configured console device). + */ + base = pci_conf_read(pb->pc, tag, br); + pci_conf_write(pb->pc, tag, br, 0xffffffff); + mask = pci_conf_read(pb->pc, tag, br); + pci_conf_write(pb->pc, tag, br, base); + + switch (PCI_MAPREG_TYPE(base)) { + case PCI_MAPREG_TYPE_IO: + addr = PCI_MAPREG_IO_ADDR(base); + size = PCI_MAPREG_IO_SIZE(mask); + return pci_resource_is_reserved(PCI_CONF_MAP_IO, addr, size); + + case PCI_MAPREG_TYPE_MEM: + if (PCI_MAPREG_MEM_TYPE(base) == PCI_MAPREG_MEM_TYPE_64BIT) { + base64 = pci_conf_read(pb->pc, tag, br + 4); + pci_conf_write(pb->pc, tag, br + 4, 0xffffffff); + mask64 = pci_conf_read(pb->pc, tag, br + 4); + pci_conf_write(pb->pc, tag, br + 4, base64); + addr = (uint64_t)PCI_MAPREG_MEM64_ADDR( + (((uint64_t)base64) << 32) | base); + size = (uint64_t)PCI_MAPREG_MEM64_SIZE( + (((uint64_t)mask64) << 32) | mask); + } else { + addr = PCI_MAPREG_MEM_ADDR(base); + size = PCI_MAPREG_MEM_SIZE(mask); } - } + return pci_resource_is_reserved(PCI_CONF_MAP_MEM, addr, size); - return false; + default: + return NULL; + } } static int @@ -672,14 +673,6 @@ pci_do_device_query(pciconf_bus_t *pb, p (pd->min_gnt + pd->max_lat); } - if (PCI_HDRTYPE_TYPE(bhlc) == PCI_HDRTYPE_DEVICE && - pci_device_is_reserved(pb, tag)) { - /* - * Device already configured by firmware. - */ - return 0; - } - width = 4; for (br = reg_start; br < reg_end; br += width) { #if 0 @@ -910,19 +903,23 @@ setup_iowins(pciconf_bus_t *pb) { pciconf_win_t *pi; pciconf_dev_t *pd; - int error; + struct pciconf_resource_rsvd *rsvd; + int error; for (pi = pb->pciiowin; pi < &pb->pciiowin[pb->niowin]; pi++) { if (pi->size == 0) continue; pd = pi->dev; + rsvd = pci_bar_is_reserved(pb, pd, pi->reg); + if (pb->io_res.arena == NULL) { /* Bus has no IO ranges, disable IO BAR */ pi->address = 0; pd->enable &= ~PCI_CONF_ENABLE_IO; goto write_ioaddr; } + pi->address = pci_allocate_range(&pb->io_res, pi->size, pi->align, false); if (~pi->address == 0) { @@ -956,6 +953,9 @@ write_ioaddr: } pci_conf_write(pd->pc, pd->tag, pi->reg, PCI_MAPREG_IO_ADDR(pi->address) | PCI_MAPREG_TYPE_IO); + + if (rsvd != NULL && rsvd->start != pi->address) + rsvd->callback(rsvd->callback_arg, pi->address); } return 0; } @@ -967,6 +967,7 @@ setup_memwins(pciconf_bus_t *pb) pciconf_dev_t *pd; pcireg_t base; struct pciconf_resource *r; + struct pciconf_resource_rsvd *rsvd; bool ok64; int error; @@ -976,6 +977,8 @@ setup_memwins(pciconf_bus_t *pb) ok64 = false; pd = pm->dev; + rsvd = pci_bar_is_reserved(pb, pd, pm->reg); + if (pm->prefetch) { r = &pb->pmem_res; ok64 = pb->pmem_64bit; @@ -1048,6 +1051,10 @@ setup_memwins(pciconf_bus_t *pb) base); } } + + if (rsvd != NULL && rsvd->start != pm->address) { + rsvd->callback(rsvd->callback_arg, pm->address); + } } for (pm = pb->pcimemwin; pm < &pb->pcimemwin[pb->nmemwin]; pm++) { if (pm->reg == PCI_MAPREG_ROM && pm->address != -1) { @@ -1467,11 +1474,12 @@ pciconf_resource_add(struct pciconf_reso * pciconf_resource_reserve: * * Mark a pci configuration resource as in-use. Devices - * already configured to use these resources are skipped - * during resource assignment. + * already configured to use these resources are notified + * during resource assignment if their resources are changed. */ void -pciconf_resource_reserve(int type, bus_addr_t start, bus_size_t size) +pciconf_resource_reserve(int type, bus_addr_t start, bus_size_t size, + void (*callback)(void *, uint64_t), void *callback_arg) { struct pciconf_resource_rsvd *rsvd; @@ -1479,6 +1487,8 @@ pciconf_resource_reserve(int type, bus_a rsvd->type = type; rsvd->start = start; rsvd->size = size; + rsvd->callback = callback; + rsvd->callback_arg = callback_arg; LIST_INSERT_HEAD(&pciconf_resource_reservations, rsvd, next); } Index: src/sys/dev/pci/pciconf.h diff -u src/sys/dev/pci/pciconf.h:1.15 src/sys/dev/pci/pciconf.h:1.16 --- src/sys/dev/pci/pciconf.h:1.15 Sat Oct 10 15:22:15 2020 +++ src/sys/dev/pci/pciconf.h Tue Oct 20 23:03:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pciconf.h,v 1.15 2020/10/10 15:22:15 jmcneill Exp $ */ +/* $NetBSD: pciconf.h,v 1.16 2020/10/20 23:03:30 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -51,7 +51,8 @@ struct pciconf_resources * void pciconf_resource_fini(struct pciconf_resources *); int pciconf_resource_add(struct pciconf_resources *, int, bus_addr_t, bus_size_t); -void pciconf_resource_reserve(int, bus_addr_t, bus_size_t); +void pciconf_resource_reserve(int, bus_addr_t, bus_size_t, + void (*)(void *, uint64_t), void *); /* * args: pci_chipset_tag_t, resources, firstbus, cacheline_size