Module Name: src
Committed By: palle
Date: Sat Jan 10 22:19:26 UTC 2015
Modified Files:
src/sys/arch/sparc64/conf: files.sparc64
src/sys/arch/sparc64/sparc64: autoconf.c
Added Files:
src/sys/arch/sparc64/include: mdesc.h
src/sys/arch/sparc64/sparc64: mdesc.c
Log Message:
sun4v: add hypervisor machine description (mdesc) functions - from OpenBSD
To generate a diff of this commit:
cvs rdiff -u -r1.145 -r1.146 src/sys/arch/sparc64/conf/files.sparc64
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc64/include/mdesc.h
cvs rdiff -u -r1.200 -r1.201 src/sys/arch/sparc64/sparc64/autoconf.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc64/sparc64/mdesc.c
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/sparc64/conf/files.sparc64
diff -u src/sys/arch/sparc64/conf/files.sparc64:1.145 src/sys/arch/sparc64/conf/files.sparc64:1.146
--- src/sys/arch/sparc64/conf/files.sparc64:1.145 Sat Feb 1 17:01:35 2014
+++ src/sys/arch/sparc64/conf/files.sparc64 Sat Jan 10 22:19:26 2015
@@ -1,4 +1,4 @@
-# $NetBSD: files.sparc64,v 1.145 2014/02/01 17:01:35 nakayama Exp $
+# $NetBSD: files.sparc64,v 1.146 2015/01/10 22:19:26 palle Exp $
# @(#)files.sparc64 8.1 (Berkeley) 7/19/93
# sparc64-specific configuration info
@@ -249,6 +249,7 @@ file arch/sparc64/sparc64/vm_machdep.c
file arch/sparc64/sparc64/ipifuncs.c multiprocessor
file arch/sparc64/sparc64/lock_stubs.s
file arch/sparc64/sparc64/hvcall.S sun4v
+file arch/sparc64/sparc64/mdesc.c sun4v
file arch/sparc64/sparc64/db_interface.c ddb | kgdb
file arch/sparc64/sparc64/db_machdep.c ddb
Index: src/sys/arch/sparc64/sparc64/autoconf.c
diff -u src/sys/arch/sparc64/sparc64/autoconf.c:1.200 src/sys/arch/sparc64/sparc64/autoconf.c:1.201
--- src/sys/arch/sparc64/sparc64/autoconf.c:1.200 Sat Oct 18 08:33:27 2014
+++ src/sys/arch/sparc64/sparc64/autoconf.c Sat Jan 10 22:19:26 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: autoconf.c,v 1.200 2014/10/18 08:33:27 snj Exp $ */
+/* $NetBSD: autoconf.c,v 1.201 2015/01/10 22:19:26 palle Exp $ */
/*
* Copyright (c) 1996
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.200 2014/10/18 08:33:27 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.201 2015/01/10 22:19:26 palle Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -93,6 +93,7 @@ __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v
#include <machine/bootinfo.h>
#include <sparc64/sparc64/cache.h>
#include <sparc64/sparc64/timerreg.h>
+#include <machine/mdesc.h>
#include <dev/ata/atavar.h>
#include <dev/pci/pcivar.h>
@@ -469,6 +470,10 @@ get_bootpath_from_prom(void)
void
cpu_configure(void)
{
+
+ if (CPU_ISSUN4V)
+ mdesc_init();
+
bool userconf = (boothowto & RB_USERCONF) != 0;
/* fetch boot device settings */
Added files:
Index: src/sys/arch/sparc64/include/mdesc.h
diff -u /dev/null src/sys/arch/sparc64/include/mdesc.h:1.1
--- /dev/null Sat Jan 10 22:19:26 2015
+++ src/sys/arch/sparc64/include/mdesc.h Sat Jan 10 22:19:26 2015
@@ -0,0 +1,51 @@
+/* $NetBSD: mdesc.h,v 1.1 2015/01/10 22:19:26 palle Exp $ */
+/* $OpenBSD: mdesc.h,v 1.3 2014/11/30 22:26:14 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 vaddr_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_str(int, const char *);
+const char *mdesc_get_prop_data(int, const char *, size_t *);
+int mdesc_find(const char *, uint64_t);
+int mdesc_find_child(int, const char *, uint64_t);
+int mdesc_find_node(const char *);
+#endif
Index: src/sys/arch/sparc64/sparc64/mdesc.c
diff -u /dev/null src/sys/arch/sparc64/sparc64/mdesc.c:1.1
--- /dev/null Sat Jan 10 22:19:26 2015
+++ src/sys/arch/sparc64/sparc64/mdesc.c Sat Jan 10 22:19:26 2015
@@ -0,0 +1,237 @@
+/* $NetBSD: mdesc.c,v 1.1 2015/01/10 22:19:26 palle Exp $ */
+/* $OpenBSD: mdesc.c,v 1.7 2014/11/30 22:26: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_extern.h>
+#include <uvm/uvm_page.h>
+
+#include <machine/autoconf.h>
+#include <machine/hypervisor.h>
+#include <machine/mdesc.h>
+
+vaddr_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 = (vaddr_t)uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY);
+ if (va == 0)
+ panic("%s: out of memory", __func__);
+
+ mdesc = (vaddr_t)va;
+ mdesc_pa = pa;
+ mdesc_len = len;
+
+ TAILQ_FOREACH(m, &mlist, pageq.queue) {
+ pa = VM_PAGE_TO_PHYS(m);
+ pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
+ 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 = (char *)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_str(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 = (char *)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);
+}
+
+const char *
+mdesc_get_prop_data(int idx, const char *name, size_t *len)
+{
+ 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 = (char *)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 == 'd' && strcmp(str, name) == 0) {
+ *len = elem[idx].d.y.data_len;
+ 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;
+ (void)hdr; /* XXX avoid compiler warning */
+ 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_str(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 = (char *)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_str(arc, "name");
+ val = mdesc_get_prop_val(arc, "cfg-handle");
+ if (str && strcmp(str, name) == 0 && val == cfg_handle)
+ return (arc);
+ }
+
+ return (-1);
+}
+
+int
+mdesc_find_node(const char *name)
+{
+ struct md_header *hdr;
+ struct md_element *elem;
+ const char *name_blk;
+ const char *str;
+ int idx;
+
+ hdr = (struct md_header *)mdesc;
+ elem = (struct md_element *)(mdesc + sizeof(struct md_header));
+ name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
+
+ for (idx = 0; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
+ str = name_blk + elem[idx].name_offset;
+ if (str && strcmp(str, name) == 0)
+ return (idx);
+ }
+
+ return (-1);
+}