VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/solaris/initterm-r0drv-solaris.c

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: initterm-r0drv-solaris.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Initialization & Termination, Ring-0 Driver, Solaris.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "the-solaris-kernel.h"
42#include "internal/iprt.h"
43
44#include <iprt/assert.h>
45#include <iprt/errcore.h>
46#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
47# include <iprt/asm-amd64-x86.h>
48#endif
49#include "internal/initterm.h"
50
51
52/*********************************************************************************************************************************
53* Global Variables *
54*********************************************************************************************************************************/
55/** Kernel debug info handle. */
56RTDBGKRNLINFO g_hKrnlDbgInfo;
57/** Indicates that the spl routines (and therefore a bunch of other ones too)
58 * will set EFLAGS::IF and break code that disables interrupts. */
59bool g_frtSolSplSetsEIF = false;
60/** timeout_generic address. */
61PFNSOL_timeout_generic g_pfnrtR0Sol_timeout_generic = NULL;
62/** untimeout_generic address. */
63PFNSOL_untimeout_generic g_pfnrtR0Sol_untimeout_generic = NULL;
64/** cyclic_reprogram address. */
65PFNSOL_cyclic_reprogram g_pfnrtR0Sol_cyclic_reprogram = NULL;
66/** page_noreloc_supported address. */
67PFNSOL_page_noreloc_supported g_pfnrtR0Sol_page_noreloc_supported = NULL;
68/** Whether to use the kernel page freelist. */
69bool g_frtSolUseKflt = false;
70/** Whether we've completed R0 initialization. */
71bool g_frtSolInitDone = false;
72/** Whether to use old-style xc_call interface. */
73bool g_frtSolOldIPI = false;
74/** Whether to use old-style xc_call interface using one ulong_t as the CPU set
75 * representation. */
76bool g_frtSolOldIPIUlong = false;
77/** The xc_call callout table structure. */
78RTR0FNSOLXCCALL g_rtSolXcCall;
79/** Whether to use the old-style installctx()/removectx() routines. */
80bool g_frtSolOldThreadCtx = false;
81/** The thread-context hooks callout table structure. */
82RTR0FNSOLTHREADCTX g_rtSolThreadCtx;
83/** Thread preemption offset in the thread structure. */
84size_t g_offrtSolThreadPreempt;
85/** Thread ID offset in the thread structure. */
86size_t g_offrtSolThreadId;
87/** The interrupt (pinned) thread pointer offset in the thread structure. */
88size_t g_offrtSolThreadIntrThread;
89/** The dispatcher lock pointer offset in the thread structure. */
90size_t g_offrtSolThreadLock;
91/** The process pointer offset in the thread structure. */
92size_t g_offrtSolThreadProc;
93/** Host scheduler preemption offset. */
94size_t g_offrtSolCpuPreempt;
95/** Host scheduler force preemption offset. */
96size_t g_offrtSolCpuForceKernelPreempt;
97/** Whether to use the old-style map_addr() routine. */
98bool g_frtSolOldMapAddr = false;
99/** The map_addr() hooks callout table structure. */
100RTR0FNSOLMAPADDR g_rtSolMapAddr;
101/* Resolve using dl_lookup (remove if no longer relevant for supported S10 versions) */
102extern void contig_free(void *addr, size_t size);
103#pragma weak contig_free
104/** contig_free address. */
105PFNSOL_contig_free g_pfnrtR0Sol_contig_free = contig_free;
106
107DECLHIDDEN(int) rtR0InitNative(void)
108{
109 /*
110 * IPRT has not yet been initialized at this point, so use Solaris' native cmn_err() for logging.
111 */
112 int rc = RTR0DbgKrnlInfoOpen(&g_hKrnlDbgInfo, 0 /* fFlags */);
113 if (RT_SUCCESS(rc))
114 {
115#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
116 /*
117 * Detect whether spl*() is preserving the interrupt flag or not.
118 * This is a problem on S10.
119 */
120 RTCCUINTREG uOldFlags = ASMIntDisableFlags();
121 int iOld = splr(DISP_LEVEL);
122 if (ASMIntAreEnabled())
123 g_frtSolSplSetsEIF = true;
124 splx(iOld);
125 if (ASMIntAreEnabled())
126 g_frtSolSplSetsEIF = true;
127 ASMSetFlags(uOldFlags);
128#else
129 /* PORTME: See if the amd64/x86 problem applies to this architecture. */
130#endif
131 /*
132 * Mandatory: Preemption offsets.
133 */
134 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "cpu_t", "cpu_runrun", &g_offrtSolCpuPreempt);
135 if (RT_FAILURE(rc))
136 {
137 cmn_err(CE_NOTE, "Failed to find cpu_t::cpu_runrun!\n");
138 goto errorbail;
139 }
140
141 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "cpu_t", "cpu_kprunrun", &g_offrtSolCpuForceKernelPreempt);
142 if (RT_FAILURE(rc))
143 {
144 cmn_err(CE_NOTE, "Failed to find cpu_t::cpu_kprunrun!\n");
145 goto errorbail;
146 }
147
148 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "kthread_t", "t_preempt", &g_offrtSolThreadPreempt);
149 if (RT_FAILURE(rc))
150 {
151 cmn_err(CE_NOTE, "Failed to find kthread_t::t_preempt!\n");
152 goto errorbail;
153 }
154
155 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "kthread_t", "t_did", &g_offrtSolThreadId);
156 if (RT_FAILURE(rc))
157 {
158 cmn_err(CE_NOTE, "Failed to find kthread_t::t_did!\n");
159 goto errorbail;
160 }
161
162 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "kthread_t", "t_intr", &g_offrtSolThreadIntrThread);
163 if (RT_FAILURE(rc))
164 {
165 cmn_err(CE_NOTE, "Failed to find kthread_t::t_intr!\n");
166 goto errorbail;
167 }
168
169 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "kthread_t", "t_lockp", &g_offrtSolThreadLock);
170 if (RT_FAILURE(rc))
171 {
172 cmn_err(CE_NOTE, "Failed to find kthread_t::t_lockp!\n");
173 goto errorbail;
174 }
175
176 rc = RTR0DbgKrnlInfoQueryMember(g_hKrnlDbgInfo, NULL, "kthread_t", "t_procp", &g_offrtSolThreadProc);
177 if (RT_FAILURE(rc))
178 {
179 cmn_err(CE_NOTE, "Failed to find kthread_t::t_procp!\n");
180 goto errorbail;
181 }
182 cmn_err(CE_CONT, "!cpu_t::cpu_runrun @ 0x%lx (%ld)\n", g_offrtSolCpuPreempt, g_offrtSolCpuPreempt);
183 cmn_err(CE_CONT, "!cpu_t::cpu_kprunrun @ 0x%lx (%ld)\n", g_offrtSolCpuForceKernelPreempt, g_offrtSolCpuForceKernelPreempt);
184 cmn_err(CE_CONT, "!kthread_t::t_preempt @ 0x%lx (%ld)\n", g_offrtSolThreadPreempt, g_offrtSolThreadPreempt);
185 cmn_err(CE_CONT, "!kthread_t::t_did @ 0x%lx (%ld)\n", g_offrtSolThreadId, g_offrtSolThreadId);
186 cmn_err(CE_CONT, "!kthread_t::t_intr @ 0x%lx (%ld)\n", g_offrtSolThreadIntrThread, g_offrtSolThreadIntrThread);
187 cmn_err(CE_CONT, "!kthread_t::t_lockp @ 0x%lx (%ld)\n", g_offrtSolThreadLock, g_offrtSolThreadLock);
188 cmn_err(CE_CONT, "!kthread_t::t_procp @ 0x%lx (%ld)\n", g_offrtSolThreadProc, g_offrtSolThreadProc);
189
190 /*
191 * Mandatory: CPU cross call infrastructure. Refer the-solaris-kernel.h for details.
192 */
193 rc = RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "xc_init_cpu", NULL /* ppvSymbol */);
194 if (RT_SUCCESS(rc))
195 {
196 if (ncpus > IPRT_SOL_NCPUS)
197 {
198 cmn_err(CE_NOTE, "rtR0InitNative: CPU count mismatch! ncpus=%d IPRT_SOL_NCPUS=%d\n", ncpus, IPRT_SOL_NCPUS);
199 rc = VERR_NOT_SUPPORTED;
200 goto errorbail;
201 }
202 g_rtSolXcCall.u.pfnSol_xc_call = (void *)xc_call;
203 }
204 else
205 {
206 g_frtSolOldIPI = true;
207 g_rtSolXcCall.u.pfnSol_xc_call_old = (void *)xc_call;
208 if (max_cpuid + 1 == sizeof(ulong_t) * 8)
209 {
210 g_frtSolOldIPIUlong = true;
211 g_rtSolXcCall.u.pfnSol_xc_call_old_ulong = (void *)xc_call;
212 }
213 else if (max_cpuid + 1 != IPRT_SOL_NCPUS)
214 {
215 cmn_err(CE_NOTE, "rtR0InitNative: cpuset_t size mismatch! max_cpuid=%d IPRT_SOL_NCPUS=%d\n", max_cpuid,
216 IPRT_SOL_NCPUS);
217 rc = VERR_NOT_SUPPORTED;
218 goto errorbail;
219 }
220 }
221
222 /*
223 * Mandatory: Thread-context hooks.
224 */
225 rc = RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "exitctx", NULL /* ppvSymbol */);
226 if (RT_SUCCESS(rc))
227 {
228 g_rtSolThreadCtx.Install.pfnSol_installctx = (void *)installctx;
229 g_rtSolThreadCtx.Remove.pfnSol_removectx = (void *)removectx;
230 }
231 else
232 {
233 g_frtSolOldThreadCtx = true;
234 g_rtSolThreadCtx.Install.pfnSol_installctx_old = (void *)installctx;
235 g_rtSolThreadCtx.Remove.pfnSol_removectx_old = (void *)removectx;
236 }
237
238 /*
239 * Mandatory: map_addr() hooks.
240 */
241 rc = RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "plat_map_align_amount", NULL /* ppvSymbol */);
242 if (RT_SUCCESS(rc))
243 {
244 g_rtSolMapAddr.u.pfnSol_map_addr = (void *)map_addr;
245 }
246 else
247 {
248 g_frtSolOldMapAddr = true;
249 g_rtSolMapAddr.u.pfnSol_map_addr_old = (void *)map_addr;
250 }
251
252 /*
253 * Optional: Timeout hooks.
254 */
255 RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "timeout_generic",
256 (void **)&g_pfnrtR0Sol_timeout_generic);
257 RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "untimeout_generic",
258 (void **)&g_pfnrtR0Sol_untimeout_generic);
259 if ((g_pfnrtR0Sol_timeout_generic == NULL) != (g_pfnrtR0Sol_untimeout_generic == NULL))
260 {
261 static const char *s_apszFn[2] = { "timeout_generic", "untimeout_generic" };
262 bool iMissingFn = g_pfnrtR0Sol_timeout_generic == NULL;
263 cmn_err(CE_NOTE, "rtR0InitNative: Weird! Found %s but not %s!\n", s_apszFn[!iMissingFn], s_apszFn[iMissingFn]);
264 g_pfnrtR0Sol_timeout_generic = NULL;
265 g_pfnrtR0Sol_untimeout_generic = NULL;
266 }
267 RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "cyclic_reprogram",
268 (void **)&g_pfnrtR0Sol_cyclic_reprogram);
269
270 /*
271 * Optional: Querying page no-relocation support.
272 */
273 RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /*pszModule */, "page_noreloc_supported",
274 (void **)&g_pfnrtR0Sol_page_noreloc_supported);
275
276 /*
277 * Weak binding failures: contig_free
278 */
279 if (g_pfnrtR0Sol_contig_free == NULL)
280 {
281 rc = RTR0DbgKrnlInfoQuerySymbol(g_hKrnlDbgInfo, NULL /* pszModule */, "contig_free",
282 (void **)&g_pfnrtR0Sol_contig_free);
283 if (RT_FAILURE(rc))
284 {
285 cmn_err(CE_NOTE, "rtR0InitNative: failed to find contig_free!\n");
286 goto errorbail;
287 }
288 }
289
290 g_frtSolInitDone = true;
291 return VINF_SUCCESS;
292 }
293 else
294 {
295 cmn_err(CE_NOTE, "RTR0DbgKrnlInfoOpen failed. rc=%d\n", rc);
296 return rc;
297 }
298
299errorbail:
300 RTR0DbgKrnlInfoRelease(g_hKrnlDbgInfo);
301 return rc;
302}
303
304
305DECLHIDDEN(void) rtR0TermNative(void)
306{
307 RTR0DbgKrnlInfoRelease(g_hKrnlDbgInfo);
308 g_frtSolInitDone = false;
309}
310
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use