VirtualBox

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

Last change on this file since 94155 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette