xref: /netbsd-src/sys/arch/sparc64/sparc64/mdesc.c (revision 1dc652ef5a0bffbd0917f95e0797bad8c6fc8efd)
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
mdesc_get_len(void)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
mdesc_init(vaddr_t va,paddr_t pa,psize_t avail_len)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
mdesc_get_prop_val(int idx,const char * name)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 *
mdesc_get_prop_str(int idx,const char * name)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 *
mdesc_get_prop_data(int idx,const char * name,size_t * len)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
mdesc_find(const char * name,uint64_t cfg_handle)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
mdesc_find_child(int idx,const char * name,uint64_t cfg_handle)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
mdesc_find_node_by_idx(int idx,const char * name)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
mdesc_find_node(const char * name)211 mdesc_find_node(const char *name)
212 {
213 	return mdesc_find_node_by_idx(0, name);
214 }
215 
216 int
mdesc_next_node(int idx)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 *
mdesc_name_by_idx(int idx)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