tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bus_space(9) overrides & resource reservations
Here is a bus_space(9) patch for review. It adds the ability for MI
code to override some of the bus_space(9) routines. It also adds
new bus_space(9) routines that decouple bus-space reservations from
bus-space mapping.
Five new bus_space(9) routines decouple bus-space
reservations from bus-space mapping: now a bus can "borrow" space from a
parent just as soon as it knows its requirements, but postpone mapping
the space until the last possible moment. This helps me both to do
rbus-like management of bus space in bus hierarchies while tossing out
rbus, and to get rid of CardBus as a bus type distinct from PCI.
The new routines are bus_space_reserve(), bus_space_reserve_subregion(),
and bus_space_release() for reserving bus space and for
releasing reservations, bus_space_reservation_map() and
bus_space_reservation_unmap() for mapping/unmapping reservations.
bus_space_reserve() is only implemented on x86. On all other
architectures, it returns EOPNOTSUPP.
I have refactored bus_space(9) on x86 to make _alloc()/_map() either
re-use or share code with bus_space_reserve() and family.
Two new routines create and destroy bus_space_tag_t's. One routine,
bus_space_tag_create(), derives from an existing bus_space_tag_t a new
one whose behavior is the same as the old except where you override it.
bus_space_tag_destroy() destroys tags created by bus_space_tag_create().
Currently you can override bus_space_alloc(), _map(), and some other
routines. bus_space_tag_create() is only implemented on x86. On all
other architectures, it returns EOPNOTSUPP.
Dave
--
David Young OJC Technologies
dyoung%ojctech.com@localhost Urbana, IL * (217) 278-3933
Index: sys/arch/x86/include/bus.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/bus.h,v
retrieving revision 1.20
diff -u -p -r1.20 bus.h
--- sys/arch/x86/include/bus.h 28 Apr 2010 19:17:04 -0000 1.20
+++ sys/arch/x86/include/bus.h 26 May 2010 23:38:04 -0000
@@ -80,11 +80,24 @@
typedef paddr_t bus_addr_t;
typedef size_t bus_size_t;
-struct bus_space_tag {
- int bst_type;
+struct bus_space_reservation {
+ bus_addr_t bsr_start;
+ bus_size_t bsr_size;
};
+typedef struct bus_space_reservation bus_space_reservation_t;
+
+struct bus_space_tag;
typedef struct bus_space_tag *bus_space_tag_t;
+
+struct bus_space_tag {
+ int bst_type;
+ bus_space_tag_t bst_super;
+ uint64_t bst_present;
+ const struct bus_space_overrides *bst_ov;
+ void *bst_ctx;
+};
+
typedef vaddr_t bus_space_handle_t;
extern bus_space_tag_t x86_bus_space_mem;
Index: sys/arch/x86/x86/bus_space.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/bus_space.c,v
retrieving revision 1.29
diff -u -p -r1.29 bus_space.c
--- sys/arch/x86/x86/bus_space.c 10 May 2010 18:46:58 -0000 1.29
+++ sys/arch/x86/x86/bus_space.c 26 May 2010 23:38:04 -0000
@@ -156,42 +156,49 @@ int
bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
int flags, bus_space_handle_t *bshp)
{
+ bus_space_reservation_t bsr;
int error;
- struct extent *ex;
- /*
- * Pick the appropriate extent map.
- */
- if (x86_bus_space_is_io(t)) {
- if (flags & BUS_SPACE_MAP_LINEAR)
- return (EOPNOTSUPP);
- ex = ioport_ex;
- } else if (x86_bus_space_is_mem(t))
- ex = iomem_ex;
- else
- panic("x86_memio_map: bad bus space tag");
+ if ((t->bst_present & BUS_SPACE_OVERRIDE_SPACE_MAP) != 0) {
+ return (*t->bst_ov->ov_space_map)(t->bst_ctx, t, bpa, size,
+ flags, bshp);
+ }
+ if (t->bst_super != NULL)
+ return bus_space_map(t->bst_super, bpa, size, flags, bshp);
+
+ error = bus_space_reserve(t, bpa, size, flags, &bsr);
+ if (error != 0)
+ return error;
+
+ error = bus_space_reservation_map(t, &bsr, flags, bshp);
+ if (error != 0)
+ bus_space_release(t, &bsr);
- /*
- * Before we go any further, let's make sure that this
- * region is available.
- */
- error = extent_alloc_region(ex, bpa, size,
- EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
- if (error)
- return (error);
+ return error;
+}
+
+int
+bus_space_reservation_map(bus_space_tag_t t, bus_space_reservation_t *bsr,
+ int flags, bus_space_handle_t *bshp)
+{
+ bus_addr_t bpa;
+ bus_size_t size;
+
+ bpa = bsr->bsr_start;
+ size = bsr->bsr_size;
/*
* For I/O space, that's all she wrote.
*/
if (x86_bus_space_is_io(t)) {
*bshp = bpa;
- return (0);
+ return 0;
}
#ifndef XEN
if (bpa >= IOM_BEGIN && (bpa + size) != 0 && (bpa + size) <= IOM_END) {
*bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
- return(0);
+ return 0;
}
#endif /* !XEN */
@@ -199,18 +206,8 @@ bus_space_map(bus_space_tag_t t, bus_add
* For memory space, map the bus physical address to
* a kernel virtual address.
*/
- error = x86_mem_add_mapping(bpa, size,
- (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
- if (error) {
- if (extent_free(ex, bpa, size, EX_NOWAIT |
- (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
- printf("x86_memio_map: pa 0x%jx, size 0x%jx\n",
- (uintmax_t)bpa, (uintmax_t)size);
- printf("x86_memio_map: can't free region\n");
- }
- }
-
- return (error);
+ return x86_mem_add_mapping(bpa, size,
+ (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
}
int
@@ -237,10 +234,56 @@ _x86_memio_map(bus_space_tag_t t, bus_ad
}
int
-bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
- bus_size_t size, bus_size_t alignment, bus_size_t boundary,
- int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
+bus_space_reserve(bus_space_tag_t t,
+ bus_addr_t bpa,
+ bus_size_t size,
+ int flags, bus_space_reservation_t *bsrp)
+{
+ struct extent *ex;
+ int error;
+
+ if ((t->bst_present & BUS_SPACE_OVERRIDE_SPACE_RESERVE) != 0) {
+ return (*t->bst_ov->ov_space_reserve)(t->bst_ctx, t,
+ bpa, size, flags, bsrp);
+ }
+ if (t->bst_super != NULL)
+ return bus_space_reserve(t->bst_super, bpa, size, flags, bsrp);
+
+ /*
+ * Pick the appropriate extent map.
+ */
+ if (x86_bus_space_is_io(t)) {
+ if (flags & BUS_SPACE_MAP_LINEAR)
+ return (EOPNOTSUPP);
+ ex = ioport_ex;
+ } else if (x86_bus_space_is_mem(t))
+ ex = iomem_ex;
+ else
+ panic("x86_memio_alloc: bad bus space tag");
+
+ /*
+ * Before we go any further, let's make sure that this
+ * region is available.
+ */
+ error = extent_alloc_region(ex, bpa, size,
+ EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
+
+ if (error != 0)
+ return error;
+
+ bsrp->bsr_start = bpa;
+ bsrp->bsr_size = size;
+
+ return 0;
+}
+
+int
+bus_space_reserve_subregion(bus_space_tag_t t,
+ bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+ int flags, bus_space_reservation_t *bsrp)
{
+ bus_space_reservation_t bsr;
struct extent *ex;
u_long bpa;
int error;
@@ -274,32 +317,78 @@ bus_space_alloc(bus_space_tag_t t, bus_a
if (error)
return (error);
+ bsr.bsr_start = bpa;
+ bsr.bsr_size = size;
+
+ *bsrp = bsr;
+
+ return 0;
+}
+
+void
+bus_space_release(bus_space_tag_t t, bus_space_reservation_t *bsr)
+{
+ struct extent *ex;
+
+ if ((t->bst_present & BUS_SPACE_OVERRIDE_SPACE_RELEASE) != 0) {
+ (*t->bst_ov->ov_space_release)(t->bst_ctx, t, bsr);
+ return;
+ }
+ if (t->bst_super != NULL) {
+ bus_space_release(t->bst_super, bsr);
+ return;
+ }
/*
- * For I/O space, that's all she wrote.
+ * Pick the appropriate extent map.
*/
if (x86_bus_space_is_io(t)) {
- *bshp = *bpap = bpa;
- return (0);
+ ex = ioport_ex;
+ } else if (x86_bus_space_is_mem(t))
+ ex = iomem_ex;
+ else
+ panic("x86_memio_alloc: bad bus space tag");
+
+ if (extent_free(ex, bsr->bsr_start, bsr->bsr_size, EX_NOWAIT |
+ (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
+ printf("%s: pa 0x%jx, size 0x%jx\n", __func__,
+ (uintmax_t)bsr->bsr_start, (uintmax_t)bsr->bsr_size);
+ printf("%s: can't free region\n", __func__);
+ }
+}
+
+int
+bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+ int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+ bus_space_reservation_t bsr;
+ int error;
+
+ if ((t->bst_present & BUS_SPACE_OVERRIDE_SPACE_ALLOC) != 0) {
+ return (*t->bst_ov->ov_space_alloc)(t->bst_ctx, t, rstart, rend,
+ size, alignment, boundary, flags, bpap, bshp);
+ }
+ if (t->bst_super != NULL) {
+ return bus_space_alloc(t->bst_super, rstart, rend, size,
+ alignment, boundary, flags, bpap, bshp);
}
/*
- * For memory space, map the bus physical address to
- * a kernel virtual address.
+ * Do the requested allocation.
*/
- error = x86_mem_add_mapping(bpa, size,
- (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
- if (error) {
- if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
- (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
- printf("x86_memio_alloc: pa 0x%jx, size 0x%jx\n",
- (uintmax_t)bpa, (uintmax_t)size);
- printf("x86_memio_alloc: can't free region\n");
- }
- }
+ error = bus_space_reserve_subregion(t, rstart, rend, size, alignment,
+ boundary, flags, &bsr);
+
+ if (error != 0)
+ return error;
- *bpap = bpa;
+ error = bus_space_reservation_map(t, &bsr, flags, bshp);
+ if (error != 0)
+ bus_space_release(t, &bsr);
- return (error);
+ *bpap = bsr.bsr_start;
+
+ return error;
}
int
@@ -410,10 +499,10 @@ _x86_memio_unmap(bus_space_tag_t t, bus_
}
}
-void
-bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
+static void
+bus_space_reservation_unmap1(bus_space_tag_t t, const bus_space_handle_t bsh,
+ const bus_size_t size, bus_addr_t *bpap)
{
- struct extent *ex;
u_long va, endva;
bus_addr_t bpa;
@@ -421,11 +510,8 @@ bus_space_unmap(bus_space_tag_t t, bus_s
* Find the correct extent and bus physical address.
*/
if (x86_bus_space_is_io(t)) {
- ex = ioport_ex;
bpa = bsh;
} else if (x86_bus_space_is_mem(t)) {
- ex = iomem_ex;
-
if (bsh >= atdevbase && (bsh + size) != 0 &&
(bsh + size) <= (atdevbase + IOM_SIZE)) {
bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
@@ -452,21 +538,51 @@ bus_space_unmap(bus_space_tag_t t, bus_s
uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
} else
panic("x86_memio_unmap: bad bus space tag");
-
ok:
- if (extent_free(ex, bpa, size,
- EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
- printf("x86_memio_unmap: %s 0x%jx, size 0x%jx\n",
- x86_bus_space_is_io(t) ? "port" : "pa",
- (uintmax_t)bpa, (uintmax_t)size);
- printf("x86_memio_unmap: can't free region\n");
+ if (bpap != NULL)
+ *bpap = bpa;
+}
+
+void
+bus_space_reservation_unmap(bus_space_tag_t t, const bus_space_handle_t bsh,
+ const bus_size_t size)
+{
+ bus_space_reservation_unmap1(t, bsh, size, NULL);
+}
+
+void
+bus_space_unmap(bus_space_tag_t t, const bus_space_handle_t bsh,
+ const bus_size_t size)
+{
+ bus_space_reservation_t bsr;
+
+ if ((t->bst_present & BUS_SPACE_OVERRIDE_SPACE_UNMAP) != 0) {
+ (*t->bst_ov->ov_space_unmap)(t->bst_ctx, t, bsh, size);
+ return;
+ }
+ if (t->bst_super != NULL) {
+ bus_space_unmap(t->bst_super, bsh, size);
+ return;
}
+
+ bus_space_reservation_unmap1(t, bsh, size, &bsr.bsr_start);
+
+ bsr.bsr_size = size;
+ bus_space_release(t, &bsr);
}
void
bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
{
+ if ((t->bst_present & BUS_SPACE_OVERRIDE_SPACE_FREE) != 0) {
+ (*t->bst_ov->ov_space_free)(t->bst_ctx, t, bsh, size);
+ return;
+ }
+ if (t->bst_super != NULL) {
+ bus_space_free(t->bst_super, bsh, size);
+ return;
+ }
/* bus_space_unmap() does all that we need to do. */
bus_space_unmap(t, bsh, size);
}
Index: sys/sys/bus.h
===================================================================
RCS file: /cvsroot/src/sys/sys/bus.h,v
retrieving revision 1.3
diff -u -p -r1.3 bus.h
--- sys/sys/bus.h 19 Apr 2010 18:24:27 -0000 1.3
+++ sys/sys/bus.h 26 May 2010 23:38:08 -0000
@@ -31,48 +31,47 @@
#include <machine/bus.h>
-struct bus_space_reservation;
-
-typedef struct bus_space_reservation /* {
- bus_addr_t sr_addr;
- bus_size_t sr_size;
-} */ bus_space_reservation_t;
-
enum bus_space_override_idx {
BUS_SPACE_OVERRIDE_SPACE_MAP = __BIT(0)
, BUS_SPACE_OVERRIDE_SPACE_UNMAP = __BIT(1)
, BUS_SPACE_OVERRIDE_SPACE_ALLOC = __BIT(2)
, BUS_SPACE_OVERRIDE_SPACE_FREE = __BIT(3)
- , BUS_SPACE_OVERRIDE_SPACE_EXTEND = __BIT(4)
- , BUS_SPACE_OVERRIDE_SPACE_TRIM = __BIT(5)
+ , BUS_SPACE_OVERRIDE_SPACE_RESERVE = __BIT(4)
+ , BUS_SPACE_OVERRIDE_SPACE_RELEASE = __BIT(5)
+#if 0
+ , BUS_SPACE_OVERRIDE_SPACE_EXTEND = __BIT(6)
+ , BUS_SPACE_OVERRIDE_SPACE_TRIM = __BIT(7)
+#endif
};
/* Only add new members at the end of this struct! */
struct bus_space_overrides {
- int (*bs_space_map)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
+ int (*ov_space_map)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
int, bus_space_handle_t *);
- void (*bs_space_unmap)(void *, bus_space_tag_t, bus_space_handle_t,
+ void (*ov_space_unmap)(void *, bus_space_tag_t, bus_space_handle_t,
bus_size_t);
- int (*bs_space_alloc)(void *, bus_space_tag_t, bus_addr_t, bus_addr_t,
+ int (*ov_space_alloc)(void *, bus_space_tag_t, bus_addr_t, bus_addr_t,
bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *,
bus_space_handle_t *);
- void (*bs_space_free)(void *, bus_space_tag_t, bus_space_handle_t,
+ void (*ov_space_free)(void *, bus_space_tag_t, bus_space_handle_t,
bus_size_t);
- int (*bs_space_reserve)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
- bus_space_reservation_t *);
-
- void (*bus_space_release)(void *, bus_space_tag_t,
- bus_space_reservation_t);
+ int (*ov_space_reserve)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
+ int, bus_space_reservation_t *);
- int (*bs_space_extend)(void *, bus_space_tag_t, bus_space_reservation_t,
- bus_size_t, bus_size_t);
+ void (*ov_space_release)(void *, bus_space_tag_t,
+ bus_space_reservation_t *);
- void (*bs_space_trim)(void *, bus_space_tag_t, bus_space_reservation_t,
- bus_size_t, bus_size_t);
+#if 0
+ int (*ov_space_extend)(void *, bus_space_tag_t,
+ bus_space_reservation_t *, bus_size_t, bus_size_t);
+
+ void (*ov_space_trim)(void *, bus_space_tag_t,
+ bus_space_reservation_t *, bus_size_t, bus_size_t);
+#endif
};
bool bus_space_is_equal(bus_space_tag_t, bus_space_tag_t);
@@ -84,20 +83,33 @@ void bus_space_tag_destroy(bus_space_tag
/* Reserve a region of bus space. Reserved bus space cannot be allocated
* with bus_space_alloc(). Reserved space has not been bus_space_map()'d.
*/
-int bus_space_reserve(bus_space_tag_t, bus_addr_t, bus_size_t,
+int bus_space_reserve(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_reservation_t *);
+int
+bus_space_reserve_subregion(bus_space_tag_t,
+ bus_addr_t, bus_addr_t, bus_size_t, bus_size_t, bus_size_t,
+ int, bus_space_reservation_t *);
+
/* Cancel a reservation. */
-void bus_space_release(bus_space_tag_t, bus_space_reservation_t);
+void bus_space_release(bus_space_tag_t, bus_space_reservation_t *);
+
+int bus_space_reservation_map(bus_space_tag_t, bus_space_reservation_t *,
+ int, bus_space_handle_t *);
+
+void bus_space_reservation_unmap(bus_space_tag_t, bus_space_handle_t,
+ bus_size_t);
+#if 0
/* Extend a reservation to the left and/or to the right. The extension
* has not been bus_space_map()'d.
*/
-int bus_space_extend(bus_space_tag_t, bus_space_reservation_t, bus_size_t,
+int bus_space_extend(bus_space_tag_t, bus_space_reservation_t *, bus_size_t,
bus_size_t);
/* Trim bus space from a reservation on the left and/or on the right. */
-void bus_space_trim(bus_space_tag_t, bus_space_reservation_t, bus_size_t,
+void bus_space_trim(bus_space_tag_t, bus_space_reservation_t *, bus_size_t,
bus_size_t);
+#endif
#endif /* _SYS_BUS_H_ */
Index: sys/kern/kern_stub.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_stub.c,v
retrieving revision 1.28
diff -u -p -r1.28 kern_stub.c
--- sys/kern/kern_stub.c 28 Apr 2010 20:33:52 -0000 1.28
+++ sys/kern/kern_stub.c 27 May 2010 00:01:06 -0000
@@ -127,6 +127,8 @@ __weak_alias(spldebug_stop, voidop);
__weak_alias(machdep_init,nullop);
__weak_alias(pci_chipset_tag_create, eopnotsupp);
__weak_alias(pci_chipset_tag_destroy, voidop);
+__weak_alias(bus_space_reserve, eopnotsupp);
+__weak_alias(bus_space_release, voidop);
__weak_alias(bus_space_tag_create, eopnotsupp);
__weak_alias(bus_space_tag_destroy, voidop);
__weak_alias(bus_space_is_equal, default_bus_space_is_equal);
Home |
Main Index |
Thread Index |
Old Index