summaryrefslogtreecommitdiffstats
path: root/src/VBox/VMM/VMMR0/GVMMR0Internal.h
blob: 52aecdf1c580812241d06c4058d6f815abd730a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* $Id: GVMMR0Internal.h $ */
/** @file
 * GVMM - The Global VM Manager, Internal header.
 */

/*
 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#ifndef VMM_INCLUDED_SRC_VMMR0_GVMMR0Internal_h
#define VMM_INCLUDED_SRC_VMMR0_GVMMR0Internal_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <iprt/mem.h>
#include <iprt/timer.h>


/**
 * The GVMM per VM data.
 */
typedef struct GVMMPERVCPU
{
    /** The time the halted EMT thread expires.
     * 0 if the EMT thread is blocked here. */
    uint64_t volatile   u64HaltExpire;
    /** The event semaphore the EMT thread is blocking on. */
    RTSEMEVENTMULTI     HaltEventMulti;
    /** High resolution wake-up timer, NIL_RTTIMER if not used. */
    PRTTIMER            hHrWakeUpTimer;
    /** The ID of the CPU we ran on when halting (debug only). */
    RTCPUID             idHaltedOnCpu;
    /** Set if hHrWakeUpTimer is armed. */
    bool volatile       fHrWakeUptimerArmed;
    uint8_t             abPadding[1];
    /** The EMT hash table index for this VCpu. */
    uint16_t            idxEmtHash;
    /** The ring-3 mapping of the VMCPU structure. */
    RTR0MEMOBJ          VMCpuMapObj;
    /** Statistics. */
    GVMMSTATSVMCPU      Stats;
} GVMMPERVCPU;
/** Pointer to the GVMM per VCPU data. */
typedef GVMMPERVCPU *PGVMMPERVCPU;


/**
 * EMT hash table entry.
 */
typedef struct GVMMEMTHASHENTRY
{
    /** The key. */
    RTNATIVETHREAD      hNativeEmt;
    /** The VCpu index. */
    VMCPUID             idVCpu;
#if HC_ARCH_BITS == 64
    uint32_t            u32Padding;
#endif
} GVMMEMTHASHENTRY;
AssertCompileSize(GVMMEMTHASHENTRY, sizeof(void *) * 2);

/** The EMT hash table size. */
#define GVMM_EMT_HASH_SIZE                  (VMM_MAX_CPU_COUNT * 4)
/** Primary EMT hash table hash function, sans range limit.
 * @note We assume the native ring-0 thread handle is a pointer to a pretty big
 *       structure of at least 1 KiB.
 *          - NT AMD64 6.0 ETHREAD: 0x450. See
 *            https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ps/ethread/index.htm
 *            for more details.
 *          - Solaris kthread_t is at least 0x370 in Solaris 10.
 *          - Linux task_struct looks pretty big too.
 *          - As does struct thread in xnu.
 * @todo Make platform specific adjustment as needed. */
#define GVMM_EMT_HASH_CORE(a_hNativeSelf)   ( (uintptr_t)(a_hNativeSelf) >> 10 )
/** Primary EMT hash table function. */
#define GVMM_EMT_HASH_1(a_hNativeSelf)      ( GVMM_EMT_HASH_CORE(a_hNativeSelf) % GVMM_EMT_HASH_SIZE )
/** Secondary EMT hash table function, added to the primary one on collision.
 * This uses the bits above the primary hash.
 * @note It is always odd, which guarantees that we'll visit all hash table
 *       entries in case of a collision. */
#define GVMM_EMT_HASH_2(a_hNativeSelf)      ( ((GVMM_EMT_HASH_CORE(a_hNativeSelf) / GVMM_EMT_HASH_SIZE) | 1) % GVMM_EMT_HASH_SIZE )

/**
 * The GVMM per VM data.
 */
typedef struct GVMMPERVM
{
    /** The shared VM data structure allocation object (PVMR0). */
    RTR0MEMOBJ          VMMemObj;
    /** The Ring-3 mapping of the shared VM data structure (PVMR3). */
    RTR0MEMOBJ          VMMapObj;
    /** The allocation object for the VM pages. */
    RTR0MEMOBJ          VMPagesMemObj;
    /** The ring-3 mapping of the VM pages. */
    RTR0MEMOBJ          VMPagesMapObj;

    /** The scheduler statistics. */
    GVMMSTATSSCHED      StatsSched;

    /** Whether the per-VM ring-0 initialization has been performed. */
    bool                fDoneVMMR0Init;
    /** Whether the per-VM ring-0 termination is being or has been performed. */
    bool                fDoneVMMR0Term;
    bool                afPadding[6];

    /** Worker thread registrations. */
    struct
    {
        /** The native ring-0 thread handle. */
        RTNATIVETHREAD  hNativeThread;
        /** The native ring-3 thread handle. */
        RTNATIVETHREAD  hNativeThreadR3;
    } aWorkerThreads[GVMMWORKERTHREAD_END];

    /** EMT lookup hash table. */
    GVMMEMTHASHENTRY    aEmtHash[GVMM_EMT_HASH_SIZE];
} GVMMPERVM;
/** Pointer to the GVMM per VM data. */
typedef GVMMPERVM *PGVMMPERVM;


#endif /* !VMM_INCLUDED_SRC_VMMR0_GVMMR0Internal_h */