summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-04-12 14:53:16 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-04-12 14:53:16 +0000
commitf30a0382069fa0b5ad8b4b5ec910c2beacb6079d (patch)
tree7fe920e8941cf4d65560995228459a273981cdf7 /sys/arch/sparc64
parentab81f6843bfef86188d62a3cfc16ae38738192f3 (diff)
Move code handling Machine Descriptions out of the cbus(4) driver.
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r--sys/arch/sparc64/conf/files.sparc643
-rw-r--r--sys/arch/sparc64/dev/cbus.c215
-rw-r--r--sys/arch/sparc64/include/mdesc.h48
-rw-r--r--sys/arch/sparc64/sparc64/autoconf.c8
-rw-r--r--sys/arch/sparc64/sparc64/mdesc.c188
5 files changed, 255 insertions, 207 deletions
diff --git a/sys/arch/sparc64/conf/files.sparc64 b/sys/arch/sparc64/conf/files.sparc64
index 89b7483b602..1129de54285 100644
--- a/sys/arch/sparc64/conf/files.sparc64
+++ b/sys/arch/sparc64/conf/files.sparc64
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sparc64,v 1.119 2009/03/09 22:36:43 kettenis Exp $
+# $OpenBSD: files.sparc64,v 1.120 2009/04/12 14:53:15 kettenis Exp $
# $NetBSD: files.sparc64,v 1.50 2001/08/10 20:53:50 eeh Exp $
# maxpartitions must be first item in files.${ARCH}
@@ -302,6 +302,7 @@ file arch/sparc64/sparc64/kgdb_machdep.c kgdb
# because it must come first in the "ld" command line.
file arch/sparc64/sparc64/lock_machdep.c multiprocessor
file arch/sparc64/sparc64/machdep.c
+file arch/sparc64/sparc64/mdesc.c sun4v
file arch/sparc64/sparc64/mem.c
file arch/sparc64/sparc64/mutex.S
file arch/sparc64/sparc64/openprom.c
diff --git a/sys/arch/sparc64/dev/cbus.c b/sys/arch/sparc64/dev/cbus.c
index e1727cd61cd..a08d55819fb 100644
--- a/sys/arch/sparc64/dev/cbus.c
+++ b/sys/arch/sparc64/dev/cbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cbus.c,v 1.4 2009/04/04 11:35:03 kettenis Exp $ */
+/* $OpenBSD: cbus.c,v 1.5 2009/04/12 14:53:15 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
*
@@ -22,39 +22,18 @@
#include <machine/autoconf.h>
#include <machine/hypervisor.h>
+#include <machine/mdesc.h>
#include <machine/openfirm.h>
#include <sparc64/dev/cbusvar.h>
#include <sparc64/dev/vbusvar.h>
-struct md_header {
- uint32_t transport_version;
- uint32_t node_blk_sz;
- uint32_t name_blk_sz;
- uint32_t data_blk_sz;
-};
-
-struct md_element {
- uint8_t tag;
- uint8_t name_len;
- uint16_t _reserved_field;
- uint32_t name_offset;
- union {
- struct {
- uint32_t data_len;
- uint32_t data_offset;
- } y;
- uint64_t val;
- } d;
-};
-
struct cbus_softc {
struct device sc_dv;
bus_space_tag_t sc_bustag;
bus_dma_tag_t sc_dmatag;
/* Machine description. */
- caddr_t sc_md;
int sc_idx;
};
@@ -75,15 +54,9 @@ void *cbus_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int,
void cbus_intr_ack(struct intrhand *);
bus_space_tag_t cbus_alloc_bus_tag(struct cbus_softc *, bus_space_tag_t);
-caddr_t cbus_get_mach_desc(struct cbus_softc *);
int cbus_get_channel_endpoint(struct cbus_softc *,
struct cbus_attach_args *);
-uint64_t sun4v_mdesc_get_prop_val(caddr_t, int, const char *);
-const char *sun4v_mdesc_get_prop_string(caddr_t, int, const char *);
-int sun4v_mdesc_find(caddr_t, const char *, uint64_t);
-int sun4v_mdesc_find_child(caddr_t, int, const char *, uint64_t);
-
int
cbus_match(struct device *parent, void *match, void *aux)
{
@@ -105,15 +78,9 @@ cbus_attach(struct device *parent, struct device *self, void *aux)
sc->sc_bustag = cbus_alloc_bus_tag(sc, va->va_bustag);
sc->sc_dmatag = va->va_dmatag;
- sc->sc_md = cbus_get_mach_desc(sc);
- if (sc->sc_md == NULL) {
- printf(": can't read machine description\n");
- return;
- }
-
printf("\n");
- sc->sc_idx = sun4v_mdesc_find(sc->sc_md, va->va_name, va->va_reg[0]);
+ sc->sc_idx = mdesc_find(va->va_name, va->va_reg[0]);
if (sc->sc_idx == -1)
return;
@@ -236,66 +203,6 @@ cbus_alloc_bus_tag(struct cbus_softc *sc, bus_space_tag_t parent)
return (bt);
}
-caddr_t
-cbus_get_mach_desc(struct cbus_softc *sc)
-{
- bus_dmamap_t map;
- bus_dma_segment_t seg;
- psize_t len;
- bus_size_t size;
- caddr_t va;
- int nsegs, err = 0;
-
- len = 0;
- hv_mach_desc((paddr_t)NULL, &len);
- KASSERT(len != 0);
-
-again:
- size = roundup(len, PAGE_SIZE);
-
- if (bus_dmamap_create(sc->sc_dmatag, size, 1, size, 0,
- BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &map) != 0)
- return (NULL);
-
- if (bus_dmamem_alloc(sc->sc_dmatag, size, PAGE_SIZE, 0, &seg,
- 1, &nsegs, BUS_DMA_NOWAIT) != 0)
- goto destroy;
-
- if (bus_dmamem_map(sc->sc_dmatag, &seg, 1, size,
- &va, BUS_DMA_NOWAIT) != 0)
- goto free;
-
- if (bus_dmamap_load(sc->sc_dmatag, map, va, size,
- NULL, BUS_DMA_NOWAIT) != 0)
- goto unmap;
-
- len = size;
- err = hv_mach_desc(map->dm_segs[0].ds_addr, &len);
- if (err != H_EOK)
- goto unload;
-
- return (va);
-
-unload:
- bus_dmamap_unload(sc->sc_dmatag, map);
-unmap:
- bus_dmamem_unmap(sc->sc_dmatag, va, size);
-free:
- bus_dmamem_free(sc->sc_dmatag, &seg, 1);
-destroy:
- bus_dmamap_destroy(sc->sc_dmatag, map);
-
- /*
- * If the machine description was updated while we were trying
- * to fetch it, the allocated buffer may have been to small.
- * Try again in that case.
- */
- if (err == H_EINVAL && len > size)
- goto again;
-
- return (NULL);
-}
-
int
cbus_get_channel_endpoint(struct cbus_softc *sc, struct cbus_attach_args *ca)
{
@@ -306,14 +213,13 @@ cbus_get_channel_endpoint(struct cbus_softc *sc, struct cbus_attach_args *ca)
int idx;
int arc;
- idx = sun4v_mdesc_find_child(sc->sc_md, sc->sc_idx,
- ca->ca_name, ca->ca_reg[0]);
+ idx = mdesc_find_child(sc->sc_idx, ca->ca_name, ca->ca_reg[0]);
if (idx == -1)
return (ENOENT);
- hdr = (struct md_header *)sc->sc_md;
- elem = (struct md_element *)(sc->sc_md + sizeof(struct md_header));
- name_blk = sc->sc_md + sizeof(struct md_header) + hdr->node_blk_sz;
+ hdr = (struct md_header *)mdesc;
+ elem = (struct md_element *)(mdesc + sizeof(struct md_header));
+ name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
for (; elem[idx].tag != 'E'; idx++) {
str = name_blk + elem[idx].name_offset;
@@ -328,12 +234,9 @@ cbus_get_channel_endpoint(struct cbus_softc *sc, struct cbus_attach_args *ca)
}
if (strcmp(str, "channel-endpoint") == 0) {
- ca->ca_id =
- sun4v_mdesc_get_prop_val(sc->sc_md, arc, "id");
- ca->ca_tx_ino =
- sun4v_mdesc_get_prop_val(sc->sc_md, arc, "tx-ino");
- ca->ca_rx_ino =
- sun4v_mdesc_get_prop_val(sc->sc_md, arc, "rx-ino");
+ ca->ca_id = mdesc_get_prop_val(arc, "id");
+ ca->ca_tx_ino = mdesc_get_prop_val(arc, "tx-ino");
+ ca->ca_rx_ino = mdesc_get_prop_val(arc, "rx-ino");
return (0);
}
}
@@ -343,101 +246,3 @@ cbus_get_channel_endpoint(struct cbus_softc *sc, struct cbus_attach_args *ca)
ca->ca_rx_ino = -1;
return (0);
}
-
-uint64_t
-sun4v_mdesc_get_prop_val(caddr_t md, int idx, const char *name)
-{
- struct md_header *hdr;
- struct md_element *elem;
- const char *name_blk;
- const char *str;
-
- hdr = (struct md_header *)md;
- elem = (struct md_element *)(md + sizeof(struct md_header));
- name_blk = md + sizeof(struct md_header) + hdr->node_blk_sz;
-
- while (elem[idx].tag != 'E') {
- str = name_blk + elem[idx].name_offset;
- if (elem[idx].tag == 'v' && strcmp(str, name) == 0)
- return (elem[idx].d.val);
- idx++;
- }
-
- return (-1);
-}
-
-const char *
-sun4v_mdesc_get_prop_string(caddr_t md, int idx, const char *name)
-{
- struct md_header *hdr;
- struct md_element *elem;
- const char *name_blk;
- const char *data_blk;
- const char *str;
-
- hdr = (struct md_header *)md;
- elem = (struct md_element *)(md + sizeof(struct md_header));
- name_blk = md + sizeof(struct md_header) + hdr->node_blk_sz;
- data_blk = name_blk + hdr->name_blk_sz;
-
- while (elem[idx].tag != 'E') {
- str = name_blk + elem[idx].name_offset;
- if (elem[idx].tag == 's' && strcmp(str, name) == 0)
- return (data_blk + elem[idx].d.y.data_offset);
- idx++;
- }
-
- return (NULL);
-}
-
-int
-sun4v_mdesc_find(caddr_t md, const char *name, uint64_t cfg_handle)
-{
- struct md_header *hdr;
- struct md_element *elem;
- const char *str;
- uint64_t val;
- int idx;
-
- hdr = (struct md_header *)md;
- elem = (struct md_element *)(md + sizeof(struct md_header));
-
- for (idx = 0; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
- str = sun4v_mdesc_get_prop_string(md, idx, "name");
- val = sun4v_mdesc_get_prop_val(md, idx, "cfg-handle");
- if (str && strcmp(str, name) == 0 && val == cfg_handle)
- return (idx);
- }
-
- return (-1);
-}
-
-int
-sun4v_mdesc_find_child(caddr_t md, int idx, const char *name,
- uint64_t cfg_handle)
-{
- struct md_header *hdr;
- struct md_element *elem;
- const char *name_blk;
- const char *str;
- uint64_t val;
- int arc;
-
- hdr = (struct md_header *)md;
- elem = (struct md_element *)(md + sizeof(struct md_header));
- name_blk = md + sizeof(struct md_header) + hdr->node_blk_sz;
-
- for (; elem[idx].tag != 'E'; idx++) {
- str = name_blk + elem[idx].name_offset;
- if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
- continue;
-
- arc = elem[idx].d.val;
- str = sun4v_mdesc_get_prop_string(md, arc, "name");
- val = sun4v_mdesc_get_prop_val(md, arc, "cfg-handle");
- if (str && strcmp(str, name) == 0 && val == cfg_handle)
- return (arc);
- }
-
- return (-1);
-}
diff --git a/sys/arch/sparc64/include/mdesc.h b/sys/arch/sparc64/include/mdesc.h
new file mode 100644
index 00000000000..b60135d5649
--- /dev/null
+++ b/sys/arch/sparc64/include/mdesc.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: mdesc.h,v 1.1 2009/04/12 14:53:15 kettenis Exp $ */
+/*
+ * Copyright (c) 2009 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct md_header {
+ uint32_t transport_version;
+ uint32_t node_blk_sz;
+ uint32_t name_blk_sz;
+ uint32_t data_blk_sz;
+};
+
+struct md_element {
+ uint8_t tag;
+ uint8_t name_len;
+ uint16_t _reserved_field;
+ uint32_t name_offset;
+ union {
+ struct {
+ uint32_t data_len;
+ uint32_t data_offset;
+ } y;
+ uint64_t val;
+ } d;
+};
+
+#ifdef _KERNEL
+extern caddr_t mdesc;
+extern size_t mdesc_len;
+
+void mdesc_init(void);
+uint64_t mdesc_get_prop_val(int, const char *);
+const char * mdesc_get_prop_string(int, const char *);
+int mdesc_find(const char *, uint64_t);
+int mdesc_find_child(int, const char *, uint64_t);
+#endif
diff --git a/sys/arch/sparc64/sparc64/autoconf.c b/sys/arch/sparc64/sparc64/autoconf.c
index 2c1bc2da2a9..06cbd43b8cd 100644
--- a/sys/arch/sparc64/sparc64/autoconf.c
+++ b/sys/arch/sparc64/sparc64/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.103 2009/04/04 21:07:48 kettenis Exp $ */
+/* $OpenBSD: autoconf.c,v 1.104 2009/04/12 14:53:15 kettenis Exp $ */
/* $NetBSD: autoconf.c,v 1.51 2001/07/24 19:32:11 eeh Exp $ */
/*
@@ -68,6 +68,7 @@
#include <machine/bus.h>
#include <machine/autoconf.h>
#include <machine/hypervisor.h>
+#include <machine/mdesc.h>
#include <machine/openfirm.h>
#include <machine/sparc64.h>
#include <machine/cpu.h>
@@ -612,6 +613,11 @@ bootpath_store(storep, bp)
void
cpu_configure()
{
+#ifdef SUN4V
+ if (CPU_ISSUN4V)
+ mdesc_init();
+#endif
+
/* build the bootpath */
bootpath_build();
diff --git a/sys/arch/sparc64/sparc64/mdesc.c b/sys/arch/sparc64/sparc64/mdesc.c
new file mode 100644
index 00000000000..53feaa6bb69
--- /dev/null
+++ b/sys/arch/sparc64/sparc64/mdesc.c
@@ -0,0 +1,188 @@
+/* $OpenBSD: mdesc.c,v 1.1 2009/04/12 14:53:15 kettenis Exp $ */
+/*
+ * Copyright (c) 2009 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm.h>
+
+#include <machine/autoconf.h>
+#include <machine/hypervisor.h>
+#include <machine/mdesc.h>
+
+caddr_t mdesc;
+paddr_t mdesc_pa;
+size_t mdesc_len;
+
+void
+mdesc_init(void)
+{
+ struct pglist mlist;
+ struct vm_page *m;
+ psize_t len, size;
+ paddr_t pa;
+ vaddr_t va;
+ int err;
+
+ hv_mach_desc((paddr_t)NULL, &len);
+ KASSERT(len != 0);
+
+again:
+ size = round_page(len);
+
+ TAILQ_INIT(&mlist);
+ err = uvm_pglistalloc(len, 0, -1, PAGE_SIZE, 0, &mlist, 1, 0);
+ if (err)
+ panic("%s: out of memory", __func__);
+
+ len = size;
+ pa = VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist));
+ err = hv_mach_desc(pa, &len);
+ if (err != H_EOK)
+ goto fail;
+
+ va = uvm_km_valloc(kernel_map, len);
+ if (va == 0)
+ panic("%s: out of memory", __func__);
+
+ mdesc = (caddr_t)va;
+ mdesc_pa = pa;
+ mdesc_len = len;
+
+ m = TAILQ_FIRST(&mlist);
+ for (; m != NULL; m = TAILQ_NEXT(m,pageq)) {
+ pa = VM_PAGE_TO_PHYS(m);
+ pmap_enter(pmap_kernel(), va, pa, VM_PROT_READ|VM_PROT_WRITE,
+ VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
+ va += PAGE_SIZE;
+ }
+ pmap_update(pmap_kernel());
+
+ return;
+
+fail:
+ uvm_pglistfree(&mlist);
+
+ /*
+ * If the machine description was updated while we were trying
+ * to fetch it, the allocated buffer may have been to small.
+ * Try again in that case.
+ */
+ if (err == H_EINVAL && len > size)
+ goto again;
+
+ return;
+}
+
+uint64_t
+mdesc_get_prop_val(int idx, const char *name)
+{
+ struct md_header *hdr;
+ struct md_element *elem;
+ const char *name_blk;
+ const char *str;
+
+ hdr = (struct md_header *)mdesc;
+ elem = (struct md_element *)(mdesc + sizeof(struct md_header));
+ name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
+
+ while (elem[idx].tag != 'E') {
+ str = name_blk + elem[idx].name_offset;
+ if (elem[idx].tag == 'v' && strcmp(str, name) == 0)
+ return (elem[idx].d.val);
+ idx++;
+ }
+
+ return (-1);
+}
+
+const char *
+mdesc_get_prop_string(int idx, const char *name)
+{
+ struct md_header *hdr;
+ struct md_element *elem;
+ const char *name_blk;
+ const char *data_blk;
+ const char *str;
+
+ hdr = (struct md_header *)mdesc;
+ elem = (struct md_element *)(mdesc + sizeof(struct md_header));
+ name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
+ data_blk = name_blk + hdr->name_blk_sz;
+
+ while (elem[idx].tag != 'E') {
+ str = name_blk + elem[idx].name_offset;
+ if (elem[idx].tag == 's' && strcmp(str, name) == 0)
+ return (data_blk + elem[idx].d.y.data_offset);
+ idx++;
+ }
+
+ return (NULL);
+}
+
+int
+mdesc_find(const char *name, uint64_t cfg_handle)
+{
+ struct md_header *hdr;
+ struct md_element *elem;
+ const char *str;
+ uint64_t val;
+ int idx;
+
+ hdr = (struct md_header *)mdesc;
+ elem = (struct md_element *)(mdesc + sizeof(struct md_header));
+
+ for (idx = 0; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
+ str = mdesc_get_prop_string(idx, "name");
+ val = mdesc_get_prop_val(idx, "cfg-handle");
+ if (str && strcmp(str, name) == 0 && val == cfg_handle)
+ return (idx);
+ }
+
+ return (-1);
+}
+
+int
+mdesc_find_child(int idx, const char *name, uint64_t cfg_handle)
+{
+ struct md_header *hdr;
+ struct md_element *elem;
+ const char *name_blk;
+ const char *str;
+ uint64_t val;
+ int arc;
+
+ hdr = (struct md_header *)mdesc;
+ elem = (struct md_element *)(mdesc + sizeof(struct md_header));
+ name_blk = mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
+
+ for (; elem[idx].tag != 'E'; idx++) {
+ str = name_blk + elem[idx].name_offset;
+ if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
+ continue;
+
+ arc = elem[idx].d.val;
+ str = mdesc_get_prop_string(arc, "name");
+ val = mdesc_get_prop_val(arc, "cfg-handle");
+ if (str && strcmp(str, name) == 0 && val == cfg_handle)
+ return (arc);
+ }
+
+ return (-1);
+}