Home | History | Annotate | Line # | Download | only in sparc64
      1 /*	$NetBSD: mdesc.c,v 1.7 2023/12/20 05:33:59 thorpej Exp $	*/
      2 /*	$OpenBSD: mdesc.c,v 1.7 2014/11/30 22:26:15 kettenis Exp $	*/
      3 /*
      4  * Copyright (c) 2009 Mark Kettenis
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/param.h>
     20 #include <sys/device.h>
     21 #include <sys/systm.h>
     22 
     23 #include <uvm/uvm_extern.h>
     24 #include <uvm/uvm_page.h>
     25 
     26 #include <machine/autoconf.h>
     27 #include <machine/hypervisor.h>
     28 #include <machine/mdesc.h>
     29 #include <machine/sparc64.h>
     30 
     31 vaddr_t mdesc;
     32 paddr_t mdesc_pa;
     33 size_t mdesc_len;
     34 
     35 psize_t
     36 mdesc_get_len(void)
     37 {
     38 	psize_t len = 0;
     39 
     40 	len = 0;
     41 	hv_mach_desc(0, &len);
     42 	KASSERT(len != 0);
     43 
     44 	return len;
     45 }
     46 
     47 void
     48 mdesc_init(vaddr_t va, paddr_t pa, psize_t avail_len)
     49 {
     50 	psize_t len;
     51 	int64_t err;
     52 
     53 	len = avail_len;
     54 	err = hv_mach_desc(pa, &len);
     55 	if (err != H_EOK)
     56 		panic("hv_mach_desc() failed - err = %" PRId64 "\n", err);
     57 	KASSERT(len <= avail_len);
     58 	mdesc = (vaddr_t)va;
     59 	mdesc_pa = pa;
     60 	mdesc_len = len;
     61 
     62 	return;
     63 }
     64 
     65 uint64_t
     66 mdesc_get_prop_val(int idx, const char *name)
     67 {
     68 	struct md_header *hdr;
     69 	struct md_element *elem;
     70 	const char *name_blk;
     71 	const char *str;
     72 
     73 	hdr = (struct md_header *)mdesc;
     74 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
     75 	name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
     76 
     77 	while (elem[idx].tag != 'E') {
     78 		str = name_blk + elem[idx].name_offset;
     79 		if (elem[idx].tag == 'v' && strcmp(str, name) == 0)
     80 			return (elem[idx].d.val);
     81 		idx++;
     82 	}
     83 
     84 	return (-1);
     85 }
     86 
     87 const char *
     88 mdesc_get_prop_str(int idx, const char *name)
     89 {
     90 	struct md_header *hdr;
     91 	struct md_element *elem;
     92 	const char *name_blk;
     93 	const char *data_blk;
     94 	const char *str;
     95 
     96 	hdr = (struct md_header *)mdesc;
     97 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
     98 	name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
     99 	data_blk = name_blk + hdr->name_blk_sz;
    100 
    101 	while (elem[idx].tag != 'E') {
    102 		str = name_blk + elem[idx].name_offset;
    103 		if (elem[idx].tag == 's' && strcmp(str, name) == 0)
    104 			return (data_blk + elem[idx].d.y.data_offset);
    105 		idx++;
    106 	}
    107 
    108 	return (NULL);
    109 }
    110 
    111 const char *
    112 mdesc_get_prop_data(int idx, const char *name, size_t *len)
    113 {
    114 	struct md_header *hdr;
    115 	struct md_element *elem;
    116 	const char *name_blk;
    117 	const char *data_blk;
    118 	const char *str;
    119 
    120 	hdr = (struct md_header *)mdesc;
    121 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
    122 	name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
    123 	data_blk = name_blk + hdr->name_blk_sz;
    124 
    125 	while (elem[idx].tag != 'E') {
    126 		str = name_blk + elem[idx].name_offset;
    127 		if (elem[idx].tag == 'd' && strcmp(str, name) == 0) {
    128 			*len = elem[idx].d.y.data_len;
    129 			return (data_blk + elem[idx].d.y.data_offset);
    130 		}
    131 		idx++;
    132 	}
    133 
    134 	return (NULL);
    135 }
    136 
    137 int
    138 mdesc_find(const char *name, uint64_t cfg_handle)
    139 {
    140 	struct md_header *hdr;
    141 	struct md_element *elem;
    142 	const char *str;
    143 	uint64_t val;
    144 	int idx;
    145 
    146 	hdr = (struct md_header *)mdesc;
    147 	(void)hdr; /* XXX avoid compiler warning */
    148 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
    149 
    150 	for (idx = 0; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
    151 		str = mdesc_get_prop_str(idx, "name");
    152 		val = mdesc_get_prop_val(idx, "cfg-handle");
    153 		if (str && strcmp(str, name) == 0 && val == cfg_handle)
    154 			return (idx);
    155 	}
    156 
    157 	return (-1);
    158 }
    159 
    160 int
    161 mdesc_find_child(int idx, const char *name, uint64_t cfg_handle)
    162 {
    163 	struct md_header *hdr;
    164 	struct md_element *elem;
    165 	const char *name_blk;
    166 	const char *str;
    167 	uint64_t val;
    168 	int arc;
    169 
    170 	hdr = (struct md_header *)mdesc;
    171 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
    172 	name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
    173 
    174 	for (; elem[idx].tag != 'E'; idx++) {
    175 		str = name_blk + elem[idx].name_offset;
    176 		if (elem[idx].tag != 'a' || strcmp(str, "fwd") != 0)
    177 			continue;
    178 
    179 		arc = elem[idx].d.val;
    180 		str = mdesc_get_prop_str(arc, "name");
    181 		val = mdesc_get_prop_val(arc, "cfg-handle");
    182 		if (str && strcmp(str, name) == 0 && val == cfg_handle)
    183 			return (arc);
    184 	}
    185 
    186 	return (-1);
    187 }
    188 
    189 int
    190 mdesc_find_node_by_idx(int idx, const char *name)
    191 {
    192 	struct md_header *hdr;
    193 	struct md_element *elem;
    194 	const char *name_blk;
    195 	const char *str;
    196 
    197 	hdr = (struct md_header *)mdesc;
    198 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
    199 	name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
    200 
    201 	for ( ; elem[idx].tag == 'N'; idx = elem[idx].d.val) {
    202 		str = name_blk + elem[idx].name_offset;
    203 		if (str && strcmp(str, name) == 0)
    204 			return (idx);
    205 	}
    206 
    207 	return (-1);
    208 }
    209 
    210 int
    211 mdesc_find_node(const char *name)
    212 {
    213 	return mdesc_find_node_by_idx(0, name);
    214 }
    215 
    216 int
    217 mdesc_next_node(int idx)
    218 {
    219 	struct md_element *elem;
    220 
    221 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
    222 
    223 	return elem[idx].d.val;
    224 }
    225 
    226 const char *
    227 mdesc_name_by_idx(int idx)
    228 {
    229 	struct md_header *hdr;
    230 	struct md_element *elem;
    231 	const char *name_blk;
    232 	const char *str;
    233 
    234 	hdr = (struct md_header *)mdesc;
    235 	elem = (struct md_element *)(mdesc + sizeof(struct md_header));
    236 	name_blk = (char *)mdesc + sizeof(struct md_header) + hdr->node_blk_sz;
    237 
    238 	str = name_blk + elem[idx].name_offset;
    239 
    240 	return str;
    241 
    242 }
    243 
    244 
    245 
    246