xref: /illumos-gate/usr/src/uts/sun4v/os/mach_descrip.c (revision 032624d56c174c5c55126582b32e314a6af15522)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/machsystm.h>
30 #include <sys/vm.h>
31 #include <sys/cpu.h>
32 #include <sys/intreg.h>
33 #include <sys/machcpuvar.h>
34 #include <sys/machparam.h>
35 #include <vm/hat_sfmmu.h>
36 #include <vm/seg_kmem.h>
37 #include <sys/error.h>
38 #include <sys/hypervisor_api.h>
39 #include <sys/types.h>
40 #include <sys/kstat.h>
41 #ifdef MACH_DESC_DEBUG
42 #include <sys/promif.h>		/* for prom_printf */
43 #endif
44 #include <sys/sysmacros.h>
45 #include <sys/mach_descrip.h>
46 
47 /*
48  * Basic code to pull in the machine description from the Hypervisor
49  * An equivalent to this should really be available from mlsetup
50  * for really early info, but for the time being we are content to
51  * invoke this from startup_end once the VM system has been initialised.
52  * To do this we use the intrq allocator which means that
53  * this function should be called after intrq_init();
54  * We try and do this early enough however that it is useful to other
55  * components within the kernel.
56  * Also, user-level entities can grab the machine description via
57  * kstat and/or the mdesc device driver.
58  */
59 
60 
61 machine_descrip_t machine_descrip;
62 
63 
64 #ifdef MACH_DESC_DEBUG
65 #define	MDP(ARGS)	prom_printf ARGS
66 static void
67 dump_buf(uint8_t *bufp, int size)
68 {
69 	int i;
70 	for (i = 0; i < size; i += 16) {
71 		int j;
72 		prom_printf("0x%04x :", i);
73 		for (j = 0; j < 16 && (i+j) < size; j++)
74 			prom_printf(" %02x", bufp[i+j]);
75 		prom_printf("\n");
76 	}
77 }
78 #else
79 #define	MDP(x)
80 #endif
81 
82 
83 
84 
85 
86 void
87 mach_descrip_init(void)
88 {
89 	uint64_t md_size, ret;
90 
91 	MDP(("MD: Requesting buffer size\n"));
92 
93 	md_size = 0LL;
94 	(void) hv_mach_desc((uint64_t)0, &md_size);
95 	MDP(("MD: buffer size is %d\n", md_size));
96 
97 	/*
98 	 * Align allocated space to nearest page contig_mem_alloc_align
99 	 * requires a Power of 2 alignment
100 	 */
101 	machine_descrip.space = P2ROUNDUP(md_size, PAGESIZE);
102 	MDP(("MD: allocated space is %d\n", machine_descrip.space));
103 	machine_descrip.va = contig_mem_alloc_align(machine_descrip.space,
104 	    PAGESIZE);
105 	if (machine_descrip.va == NULL)
106 		cmn_err(CE_PANIC, "Allocation for machine description failed");
107 
108 	MDP(("MD: allocated va = 0x%p (size 0x%llx)\n",
109 		machine_descrip.va, machine_descrip.space));
110 
111 	machine_descrip.pa = va_to_pa(machine_descrip.va);
112 
113 	MDP(("MD: allocated pa = 0x%llx\n", machine_descrip.pa));
114 
115 	ret = hv_mach_desc(machine_descrip.pa, &md_size);
116 	MDP(("MD: HV return code = %ld\n", ret));
117 
118 	if (ret != H_EOK) {
119 		MDP(("MD: Failed with code %ld from HV\n", ret));
120 
121 		machine_descrip.size = 0;
122 
123 	} else {
124 		MDP(("MD: Grabbed %d bytes from HV\n", md_size));
125 #ifdef	MACH_DESC_DEBUG
126 		dump_buf((uint8_t *)machine_descrip.va, md_size);
127 #endif	/* MACH_DESC_DEBUG */
128 
129 		machine_descrip.size = md_size;
130 
131 			/*
132 			 * Allocate the kstat to get at the data
133 			 */
134 		machine_descrip.ksp = kstat_create("unix", 0, "machdesc",
135 		    "misc",
136 		    KSTAT_TYPE_RAW,
137 		    (uint_t)machine_descrip.size,
138 		    KSTAT_FLAG_VIRTUAL);
139 
140 		if (machine_descrip.ksp == NULL) {
141 			cmn_err(CE_PANIC,
142 			    "Failed to create kstat for machine description");
143 		} else {
144 			machine_descrip.ksp->ks_data = machine_descrip.va;
145 			kstat_install(machine_descrip.ksp);
146 		}
147 	}
148 }
149