Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc64 sun4v: add hypervisor machine description (...
details: https://anonhg.NetBSD.org/src/rev/fcca307a5f68
branches: trunk
changeset: 335504:fcca307a5f68
user: palle <palle%NetBSD.org@localhost>
date: Sat Jan 10 22:19:26 2015 +0000
description:
sun4v: add hypervisor machine description (mdesc) functions - from OpenBSD
diffstat:
sys/arch/sparc64/conf/files.sparc64 | 3 +-
sys/arch/sparc64/include/mdesc.h | 51 +++++++
sys/arch/sparc64/sparc64/autoconf.c | 9 +-
sys/arch/sparc64/sparc64/mdesc.c | 237 ++++++++++++++++++++++++++++++++++++
4 files changed, 297 insertions(+), 3 deletions(-)
diffs (truncated from 350 to 300 lines):
diff -r 4d72d311bc1e -r fcca307a5f68 sys/arch/sparc64/conf/files.sparc64
--- a/sys/arch/sparc64/conf/files.sparc64 Sat Jan 10 17:16:01 2015 +0000
+++ b/sys/arch/sparc64/conf/files.sparc64 Sat Jan 10 22:19:26 2015 +0000
@@ -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/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
diff -r 4d72d311bc1e -r fcca307a5f68 sys/arch/sparc64/include/mdesc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/sparc64/include/mdesc.h Sat Jan 10 22:19:26 2015 +0000
@@ -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
diff -r 4d72d311bc1e -r fcca307a5f68 sys/arch/sparc64/sparc64/autoconf.c
--- a/sys/arch/sparc64/sparc64/autoconf.c Sat Jan 10 17:16:01 2015 +0000
+++ b/sys/arch/sparc64/sparc64/autoconf.c Sat Jan 10 22:19:26 2015 +0000
@@ -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 @@
#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 @@
void
cpu_configure(void)
{
+
+ if (CPU_ISSUN4V)
+ mdesc_init();
+
bool userconf = (boothowto & RB_USERCONF) != 0;
/* fetch boot device settings */
diff -r 4d72d311bc1e -r fcca307a5f68 sys/arch/sparc64/sparc64/mdesc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/sparc64/sparc64/mdesc.c Sat Jan 10 22:19:26 2015 +0000
@@ -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);
+}
+
Home |
Main Index |
Thread Index |
Old Index