VirtualBox

source: vbox/trunk/include/VBox/sup.h@ 1674

Last change on this file since 1674 was 1480, checked in by vboxsync, 18 years ago

No longer require contiguous memory for the VM structure.
Did long overdue IOCtl cleanup wrt R3/R0 pointers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.6 KB
Line 
1/** @file
2 * SUP - Support Library.
3 */
4
5/*
6 * Copyright (C) 2006 InnoTek Systemberatung GmbH
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License as published by the Free Software Foundation,
12 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
13 * distribution. VirtualBox OSE is distributed in the hope that it will
14 * be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * If you received this file as part of a commercial VirtualBox
17 * distribution, then only the terms of your commercial VirtualBox
18 * license agreement apply instead of the previous paragraph.
19 */
20
21#ifndef __VBox_sup_h__
22#define __VBox_sup_h__
23
24#include <VBox/cdefs.h>
25#include <VBox/types.h>
26#include <iprt/assert.h>
27#include <iprt/asm.h>
28
29__BEGIN_DECLS
30
31/** @defgroup grp_sup The Support Library API
32 * @{
33 */
34
35/**
36 * Physical page descriptor.
37 */
38#pragma pack(4) /* space is more important. */
39typedef struct SUPPAGE
40{
41 /** Physical memory address. */
42 RTHCPHYS Phys;
43 /** Reserved entry for internal use by the caller. */
44 RTHCUINTPTR uReserved;
45} SUPPAGE;
46#pragma pack()
47/** Pointer to a page descriptor. */
48typedef SUPPAGE *PSUPPAGE;
49/** Pointer to a const page descriptor. */
50typedef const SUPPAGE *PCSUPPAGE;
51
52/**
53 * The paging mode.
54 */
55typedef enum SUPPAGINGMODE
56{
57 /** The usual invalid entry.
58 * This is returned by SUPGetPagingMode() */
59 SUPPAGINGMODE_INVALID = 0,
60 /** Normal 32-bit paging, no global pages */
61 SUPPAGINGMODE_32_BIT,
62 /** Normal 32-bit paging with global pages. */
63 SUPPAGINGMODE_32_BIT_GLOBAL,
64 /** PAE mode, no global pages, no NX. */
65 SUPPAGINGMODE_PAE,
66 /** PAE mode with global pages. */
67 SUPPAGINGMODE_PAE_GLOBAL,
68 /** PAE mode with NX, no global pages. */
69 SUPPAGINGMODE_PAE_NX,
70 /** PAE mode with global pages and NX. */
71 SUPPAGINGMODE_PAE_GLOBAL_NX,
72 /** AMD64 mode, no global pages. */
73 SUPPAGINGMODE_AMD64,
74 /** AMD64 mode with global pages, no NX. */
75 SUPPAGINGMODE_AMD64_GLOBAL,
76 /** AMD64 mode with NX, no global pages. */
77 SUPPAGINGMODE_AMD64_NX,
78 /** AMD64 mode with global pages and NX. */
79 SUPPAGINGMODE_AMD64_GLOBAL_NX
80} SUPPAGINGMODE;
81
82
83#pragma pack(1) /* paranoia */
84
85/**
86 * Per CPU data.
87 * This is only used when
88 */
89typedef struct SUPGIPCPU
90{
91 /** Update transaction number.
92 * This number is incremented at the start and end of each update. It follows
93 * thusly that odd numbers indicates update in progress, while even numbers
94 * indicate stable data. Use this to make sure that the data items you fetch
95 * are consistent. */
96 volatile uint32_t u32TransactionId;
97 /** The interval in TSC ticks between two NanoTS updates.
98 * This is the average interval over the last 2, 4 or 8 updates + a little slack.
99 * The slack makes the time go a tiny tiny bit slower and extends the interval enough
100 * to avoid ending up with too many 1ns increments. */
101 volatile uint32_t u32UpdateIntervalTSC;
102 /** Current nanosecond timestamp. */
103 volatile uint64_t u64NanoTS;
104 /** The TSC at the time of u64NanoTS. */
105 volatile uint64_t u64TSC;
106 /** Current CPU Frequency. */
107 volatile uint64_t u64CpuHz;
108 /** Number of errors during updating.
109 * Typical errors are under/overflows. */
110 volatile uint32_t cErrors;
111 /** Index of the head item in au32TSCHistory. */
112 volatile uint32_t iTSCHistoryHead;
113 /** Array of recent TSC interval deltas.
114 * The most recent item is at index iTSCHistoryHead.
115 * This history is used to calculate u32UpdateIntervalTSC.
116 */
117 volatile uint32_t au32TSCHistory[8];
118 /** Reserved for future per processor data. */
119 volatile uint32_t au32Reserved[6];
120} SUPGIPCPU;
121AssertCompileSize(SUPGIPCPU, 96);
122/*AssertCompileMemberAlignment(SUPGIPCPU, u64TSC, 8); -fixme */
123
124/** Pointer to per cpu data. */
125typedef SUPGIPCPU *PSUPGIPCPU;
126/** Pointer to const per cpu data. */
127typedef const SUPGIPCPU *PCSUPGIPCPU;
128
129/**
130 * Global Information Page.
131 *
132 * This page contains useful information and can be mapped into any
133 * process or VM. It can be accessed thru the g_pSUPGlobalInfoPage
134 * pointer when a session is open.
135 */
136typedef struct SUPGLOBALINFOPAGE
137{
138 /** Magic (SUPGLOBALINFOPAGE_MAGIC). */
139 uint32_t u32Magic;
140
141 /** The GIP update mode, see SUPGIPMODE. */
142 uint32_t u32Mode;
143
144 /** The update frequency of the of the NanoTS. */
145 volatile uint32_t u32UpdateHz;
146 /** The update interval in nanoseconds. (10^9 / u32UpdateHz) */
147 volatile uint32_t u32UpdateIntervalNS;
148 /** The timestamp of the last time we update the update frequency. */
149 volatile uint64_t u64NanoTSLastUpdateHz;
150
151 /** Padding / reserved space for future data. */
152 uint32_t au32Padding0[10];
153
154 /** Array of per-cpu data.
155 * If u32Mode == SUPGIPMODE_SYNC_TSC then only the first entry is used.
156 * If u32Mode == SUPGIPMODE_ASYNC_TSC then the CPU ACPI ID is used as an
157 * index into the array. */
158 SUPGIPCPU aCPUs[32];
159} SUPGLOBALINFOPAGE;
160AssertCompile(sizeof(SUPGLOBALINFOPAGE) <= 0x1000);
161/* AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPU, 32); - fixme */
162
163/** Pointer to the global info page. */
164typedef SUPGLOBALINFOPAGE *PSUPGLOBALINFOPAGE;
165/** Const pointer to the global info page. */
166typedef const SUPGLOBALINFOPAGE *PCSUPGLOBALINFOPAGE;
167
168#pragma pack() /* end of paranoia */
169
170/** The value of the SUPGLOBALINFOPAGE::u32Magic field. (Soryo Fuyumi) */
171#define SUPGLOBALINFOPAGE_MAGIC 0x19590106
172
173/**
174 * SUPGLOBALINFOPAGE::u32Mode values.
175 */
176typedef enum SUPGIPMODE
177{
178 /** The usual invalid null entry. */
179 SUPGIPMODE_INVALID = 0,
180 /** The TSC of the cores and cpus in the system is in sync. */
181 SUPGIPMODE_SYNC_TSC,
182 /** Each core has it's own TSC. */
183 SUPGIPMODE_ASYNC_TSC,
184 /** The usual 32-bit hack. */
185 SUPGIPMODE_32BIT_HACK = 0x7fffffff
186} SUPGIPMODE;
187
188/** Pointer to the Global Information Page.
189 *
190 * This pointer is valid as long as SUPLib has a open session. Anyone using
191 * the page must treat this pointer as higly volatile and not trust it beyond
192 * one transaction.
193 */
194#if defined(IN_SUP_R0) || defined(IN_SUP_R3) || defined(IN_SUP_GC)
195extern DECLEXPORT(PCSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
196#elif defined(IN_RING0)
197extern DECLIMPORT(const SUPGLOBALINFOPAGE) g_SUPGlobalInfoPage;
198# if defined(__GNUC__) && !defined(__DARWIN__) && defined(__AMD64__)
199/** Workaround for ELF+GCC problem on 64-bit hosts.
200 * (GCC emits a mov with a R_X86_64_32 reloc, we need R_X86_64_64.) */
201DECLINLINE(PCSUPGLOBALINFOPAGE) SUPGetGIP(void)
202{
203 PCSUPGLOBALINFOPAGE pGIP;
204 __asm__ __volatile__ ("movabs g_SUPGlobalInfoPage,%0\n\t"
205 : "=a" (pGIP));
206 return pGIP;
207}
208# define g_pSUPGlobalInfoPage (SUPGetGIP())
209# else
210# define g_pSUPGlobalInfoPage (&g_SUPGlobalInfoPage)
211#endif
212#else
213extern DECLIMPORT(PCSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
214#endif
215
216
217/**
218 * Gets the TSC frequency of the calling CPU.
219 *
220 * @returns TSC frequency.
221 * @param pGip The GIP pointer.
222 */
223DECLINLINE(uint64_t) SUPGetCpuHzFromGIP(PCSUPGLOBALINFOPAGE pGip)
224{
225 unsigned iCpu;
226
227 if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC))
228 return ~(uint64_t)0;
229
230 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
231 iCpu = 0;
232 else
233 {
234 iCpu = ASMGetApicId();
235 if (RT_UNLIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs)))
236 return ~(uint64_t)0;
237 }
238
239 return pGip->aCPUs[iCpu].u64CpuHz;
240}
241
242
243#ifdef IN_RING3
244
245/** @defgroup grp_sup_r3 SUP Host Context Ring 3 API
246 * @ingroup grp_sup
247 * @{
248 */
249
250/**
251 * Installs the support library.
252 *
253 * @returns VBox status code.
254 */
255SUPR3DECL(int) SUPInstall(void);
256
257/**
258 * Uninstalls the support library.
259 *
260 * @returns VBox status code.
261 */
262SUPR3DECL(int) SUPUninstall(void);
263
264/**
265 * Initializes the support library.
266 * Each succesful call to SUPInit() must be countered by a
267 * call to SUPTerm(false).
268 *
269 * @returns VBox status code.
270 * @param ppSession Where to store the session handle. Defaults to NULL.
271 * @param cbReserve The number of bytes of contiguous memory that should be reserved by
272 * the runtime / support library.
273 * Set this to 0 if no reservation is required. (default)
274 * Set this to ~0 if the maximum amount supported by the VM is to be
275 * attempted reserved, or the maximum available.
276 */
277#ifdef __cplusplus
278SUPR3DECL(int) SUPInit(PSUPDRVSESSION *ppSession = NULL, size_t cbReserve = 0);
279#else
280SUPR3DECL(int) SUPInit(PSUPDRVSESSION *ppSession, size_t cbReserve);
281#endif
282
283/**
284 * Terminates the support library.
285 *
286 * @returns VBox status code.
287 * @param fForced Forced termination. This means to ignore the
288 * init call count and just terminated.
289 */
290#ifdef __cplusplus
291SUPR3DECL(int) SUPTerm(bool fForced = false);
292#else
293SUPR3DECL(int) SUPTerm(int fForced);
294#endif
295
296/**
297 * Sets the ring-0 VM handle for use with fast IOCtls.
298 *
299 * @returns VBox status code.
300 * @param pVMR0 The ring-0 VM handle.
301 * NIL_RTR0PTR can be used to unset the handle when the
302 * VM is about to be destroyed.
303 */
304SUPR3DECL(int) SUPSetVMForFastIOCtl(PVMR0 pVMR0);
305
306/**
307 * Calls the HC R0 VMM entry point.
308 * See VMMR0Entry() for more details.
309 *
310 * @returns error code specific to uFunction.
311 * @param pVMR0 Pointer to the Ring-0 (Host Context) mapping of the VM structure.
312 * @param uOperation Operation to execute.
313 * @param pvArg Argument.
314 */
315SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
316
317/**
318 * Calls the HC R0 VMM entry point, in a safer but slower manner than SUPCallVMMR0.
319 * When entering using this call the R0 components can call into the host kernel
320 * (i.e. use the SUPR0 and RT APIs).
321 *
322 * See VMMR0Entry() for more details.
323 *
324 * @returns error code specific to uFunction.
325 * @param pVMR0 Pointer to the Ring-0 (Host Context) mapping of the VM structure.
326 * @param uOperation Operation to execute.
327 * @param pvArg Pointer to argument structure or if cbArg is 0 just an value.
328 * @param cbArg The size of the argument. This is used to copy whatever the argument
329 * points at into a kernel buffer to avoid problems like the user page
330 * being invalidated while we're executing the call.
331 */
332SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, unsigned uOperation, void *pvArg, unsigned cbArg);
333
334/**
335 * Queries the paging mode of the host OS.
336 *
337 * @returns The paging mode.
338 */
339SUPR3DECL(SUPPAGINGMODE) SUPGetPagingMode(void);
340
341/**
342 * Allocate zero-filled pages.
343 *
344 * Use this to allocate a number of pages rather than using RTMem*() and mess with
345 * alignment. The returned address is of course page aligned. Call SUPPageFree()
346 * to free the pages once done with them.
347 *
348 * @returns VBox status.
349 * @param cPages Number of x86 4KB pages to allocate.
350 * Max of 32MB.
351 * @param ppvPages Where to store the base pointer to the allocated pages.
352 */
353SUPR3DECL(int) SUPPageAlloc(size_t cPages, void **ppvPages);
354
355/**
356 * Frees pages allocated with SUPPageAlloc().
357 *
358 * @returns VBox status.
359 * @param pvPages Pointer returned by SUPPageAlloc().
360 */
361SUPR3DECL(int) SUPPageFree(void *pvPages);
362
363/**
364 * Locks down the physical memory backing a virtual memory
365 * range in the current process.
366 *
367 * @returns VBox status code.
368 * @param pvStart Start of virtual memory range.
369 * Must be page aligned.
370 * @param cbMemory Number of bytes.
371 * Must be page aligned.
372 * @param paPages Where to store the physical page addresses returned.
373 * On entry this will point to an array of with cbMemory >> PAGE_SHIFT entries.
374 */
375SUPR3DECL(int) SUPPageLock(void *pvStart, size_t cbMemory, PSUPPAGE paPages);
376
377/**
378 * Releases locked down pages.
379 *
380 * @returns VBox status code.
381 * @param pvStart Start of virtual memory range previously locked
382 * down by SUPPageLock().
383 */
384SUPR3DECL(int) SUPPageUnlock(void *pvStart);
385
386/**
387 * Allocated memory with page aligned memory with a contiguous and locked physical
388 * memory backing below 4GB.
389 *
390 * @returns Pointer to the allocated memory (virtual address).
391 * *pHCPhys is set to the physical address of the memory.
392 * The returned memory must be freed using SUPContFree().
393 * @returns NULL on failure.
394 * @param cb Number of bytes to allocate.
395 * @param pHCPhys Where to store the physical address of the memory block.
396 */
397SUPR3DECL(void *) SUPContAlloc(unsigned cb, PRTHCPHYS pHCPhys);
398
399/**
400 * Allocated memory with page aligned memory with a contiguous and locked physical
401 * memory backing below 4GB.
402 *
403 * @returns Pointer to the allocated memory (virtual address).
404 * *pHCPhys is set to the physical address of the memory.
405 * If ppvR0 isn't NULL, *ppvR0 is set to the ring-0 mapping.
406 * The returned memory must be freed using SUPContFree().
407 * @returns NULL on failure.
408 * @param cb Number of bytes to allocate.
409 * @param pR0Ptr Where to store the ring-0 mapping of the allocation. (optional)
410 * @param pHCPhys Where to store the physical address of the memory block.
411 *
412 * @remark This 2nd version of this API exists because we're not able to map the
413 * ring-3 mapping executable on WIN64. This is a serious problem in regard to
414 * the world switchers.
415 */
416SUPR3DECL(void *) SUPContAlloc2(unsigned cb, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys);
417
418/**
419 * Frees memory allocated with SUPContAlloc().
420 *
421 * @returns VBox status code.
422 * @param pv Pointer to the memory block which should be freed.
423 */
424SUPR3DECL(int) SUPContFree(void *pv);
425
426/**
427 * Allocated non contiguous physical memory below 4GB.
428 *
429 * @returns VBox status code.
430 * @returns NULL on failure.
431 * @param cPages Number of pages to allocate.
432 * @param ppvPages Where to store the pointer to the allocated memory.
433 * The pointer stored here on success must be passed to SUPLowFree when
434 * the memory should be released.
435 * @param ppvPagesR0 Where to store the ring-0 pointer to the allocated memory. optional.
436 * @param paPages Where to store the physical addresses of the individual pages.
437 */
438SUPR3DECL(int) SUPLowAlloc(unsigned cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages);
439
440/**
441 * Frees memory allocated with SUPLowAlloc().
442 *
443 * @returns VBox status code.
444 * @param pv Pointer to the memory block which should be freed.
445 */
446SUPR3DECL(int) SUPLowFree(void *pv);
447
448/**
449 * Load a module into R0 HC.
450 *
451 * @returns VBox status code.
452 * @param pszFilename The path to the image file.
453 * @param pszModule The module name. Max 32 bytes.
454 */
455SUPR3DECL(int) SUPLoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase);
456
457/**
458 * Frees a R0 HC module.
459 *
460 * @returns VBox status code.
461 * @param pszModule The module to free.
462 * @remark This will not actually 'free' the module, there are of course usage counting.
463 */
464SUPR3DECL(int) SUPFreeModule(void *pvImageBase);
465
466/**
467 * Get the address of a symbol in a ring-0 module.
468 *
469 * @returns VBox status code.
470 * @param pszModule The module name.
471 * @param pszSymbol Symbol name. If it's value is less than 64k it's treated like a
472 * ordinal value rather than a string pointer.
473 * @param ppvValue Where to store the symbol value.
474 */
475SUPR3DECL(int) SUPGetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue);
476
477/**
478 * Load R0 HC VMM code.
479 *
480 * @returns VBox status code.
481 * @deprecated Use SUPLoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
482 */
483SUPR3DECL(int) SUPLoadVMM(const char *pszFilename);
484
485/**
486 * Unloads R0 HC VMM code.
487 *
488 * @returns VBox status code.
489 * @deprecated Use SUPFreeModule().
490 */
491SUPR3DECL(int) SUPUnloadVMM(void);
492
493/**
494 * Get the physical address of the GIP.
495 *
496 * @returns VBox status code.
497 * @param pHCPhys Where to store the physical address of the GIP.
498 */
499SUPR3DECL(int) SUPGipGetPhys(PRTHCPHYS pHCPhys);
500
501/** @} */
502#endif /* IN_RING3 */
503
504
505#ifdef IN_RING0
506/** @defgroup grp_sup_r0 SUP Host Context Ring 0 API
507 * @ingroup grp_sup
508 * @{
509 */
510
511/**
512 * Security objectype.
513 */
514typedef enum SUPDRVOBJTYPE
515{
516 /** The usual invalid object. */
517 SUPDRVOBJTYPE_INVALID = 0,
518 /** Internal network. */
519 SUPDRVOBJTYPE_INTERNAL_NETWORK,
520 /** Internal network interface. */
521 SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE,
522 /** The first invalid object type in this end. */
523 SUPDRVOBJTYPE_END,
524 /** The usual 32-bit type size hack. */
525 SUPDRVOBJTYPE_32_BIT_HACK = 0x7ffffff
526} SUPDRVOBJTYPE;
527
528/**
529 * Object destructor callback.
530 * This is called for reference counted objectes when the count reaches 0.
531 *
532 * @param pvObj The object pointer.
533 * @param pvUser1 The first user argument.
534 * @param pvUser2 The second user argument.
535 */
536typedef DECLCALLBACK(void) FNSUPDRVDESTRUCTOR(void *pvObj, void *pvUser1, void *pvUser2);
537/** Pointer to a FNSUPDRVDESTRUCTOR(). */
538typedef FNSUPDRVDESTRUCTOR *PFNSUPDRVDESTRUCTOR;
539
540SUPR0DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2);
541SUPR0DECL(int) SUPR0ObjAddRef(void *pvObj, PSUPDRVSESSION pSession);
542SUPR0DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession);
543SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName);
544
545SUPR0DECL(int) SUPR0LockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t cb, PSUPPAGE paPages);
546SUPR0DECL(int) SUPR0UnlockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3);
547SUPR0DECL(int) SUPR0ContAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys);
548SUPR0DECL(int) SUPR0ContFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
549SUPR0DECL(int) SUPR0LowAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PSUPPAGE paPages);
550SUPR0DECL(int) SUPR0LowFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
551SUPR0DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3);
552SUPR0DECL(int) SUPR0MemGetPhys(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, PSUPPAGE paPages);
553SUPR0DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
554SUPR0DECL(int) SUPR0GipMap(PSUPDRVSESSION pSession, PCSUPGLOBALINFOPAGE *ppGip, PRTHCPHYS pHCPhysGid);
555SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession);
556SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...);
557
558/** @} */
559#endif
560
561/** @} */
562
563__END_DECLS
564
565
566#endif
567
Note: See TracBrowser for help on using the repository browser.

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