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);
+}

Reply via email to