VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/CSAMAll.cpp@ 46474

Last change on this file since 46474 was 45620, checked in by vboxsync, 12 years ago

CSAM,PATM: Don't bother initializing anything if HMIsEnabled(). Also, don't allow the components to be enabled.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.0 KB
Line 
1/* $Id: CSAMAll.cpp 45620 2013-04-18 20:07:14Z vboxsync $ */
2/** @file
3 * CSAM - Guest OS Code Scanning and Analysis Manager - Any Context
4 */
5
6/*
7 * Copyright (C) 2006-2013 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
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_CSAM
23#include <VBox/vmm/cpum.h>
24#include <VBox/vmm/stam.h>
25#include <VBox/vmm/patm.h>
26#include <VBox/vmm/csam.h>
27#include <VBox/vmm/pgm.h>
28#include <VBox/vmm/em.h>
29#include <VBox/vmm/hm.h>
30#include <VBox/vmm/mm.h>
31#include <VBox/sup.h>
32#include <VBox/vmm/mm.h>
33#include <VBox/param.h>
34#include <iprt/avl.h>
35#include "CSAMInternal.h"
36#include <VBox/vmm/vm.h>
37#include <VBox/vmm/vmm.h>
38#include <VBox/dbg.h>
39#include <VBox/err.h>
40#include <VBox/log.h>
41#include <VBox/dis.h>
42#include <VBox/disopcode.h>
43#include <iprt/assert.h>
44#include <iprt/asm.h>
45#include <iprt/string.h>
46
47/**
48 * Check if this page needs to be analysed by CSAM
49 *
50 * @returns VBox status code
51 * @param pVM Pointer to the VM.
52 * @param pvFault Fault address
53 */
54VMM_INT_DECL(int) CSAMExecFault(PVM pVM, RTRCPTR pvFault)
55{
56 Assert(!HMIsEnabled(pVM));
57 if (!CSAMIsEnabled(pVM))
58 return VINF_SUCCESS;
59
60 LogFlow(("CSAMGCExecFault: for page %08X scanned=%d\n", pvFault, CSAMIsPageScanned(pVM, pvFault)));
61
62 if (CSAMIsPageScanned(pVM, pvFault))
63 {
64 // Already checked!
65 STAM_COUNTER_ADD(&pVM->csam.s.StatNrKnownPagesGC, 1);
66 return VINF_SUCCESS;
67 }
68
69 STAM_COUNTER_ADD(&pVM->csam.s.StatNrTraps, 1);
70 VMCPU_FF_SET(VMMGetCpu0(pVM), VMCPU_FF_CSAM_SCAN_PAGE);
71 return VINF_CSAM_PENDING_ACTION;
72}
73
74
75/**
76 * Check if this page was previously scanned by CSAM
77 *
78 * @returns true -> scanned, false -> not scanned
79 * @param pVM Pointer to the VM.
80 * @param pPage GC page address
81 */
82VMM_INT_DECL(bool) CSAMIsPageScanned(PVM pVM, RTRCPTR pPage)
83{
84 int pgdir, bit;
85 uintptr_t page;
86 Assert(!HMIsEnabled(pVM));
87
88 page = (uintptr_t)pPage;
89 pgdir = page >> X86_PAGE_4M_SHIFT;
90 bit = (page & X86_PAGE_4M_OFFSET_MASK) >> X86_PAGE_4K_SHIFT;
91
92 Assert(pgdir < CSAM_PGDIRBMP_CHUNKS);
93 Assert(bit < PAGE_SIZE);
94
95 return pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir] && ASMBitTest((void *)pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit);
96}
97
98
99
100/**
101 * Mark a page as scanned/not scanned
102 *
103 * @note: we always mark it as scanned, even if we haven't completely done so
104 *
105 * @returns VBox status code.
106 * @param pVM Pointer to the VM.
107 * @param pPage GC page address (not necessarily aligned)
108 * @param fScanned Mark as scanned or not scanned
109 *
110 */
111VMM_INT_DECL(int) CSAMMarkPage(PVM pVM, RTRCUINTPTR pPage, bool fScanned)
112{
113 int pgdir, bit;
114 uintptr_t page;
115
116#ifdef LOG_ENABLED
117 if (fScanned && !CSAMIsPageScanned(pVM, (RTRCPTR)pPage))
118 Log(("CSAMMarkPage %RRv\n", pPage));
119#endif
120
121 if (!CSAMIsEnabled(pVM))
122 return VINF_SUCCESS;
123 Assert(!HMIsEnabled(pVM));
124
125 page = (uintptr_t)pPage;
126 pgdir = page >> X86_PAGE_4M_SHIFT;
127 bit = (page & X86_PAGE_4M_OFFSET_MASK) >> X86_PAGE_4K_SHIFT;
128
129 Assert(pgdir < CSAM_PGDIRBMP_CHUNKS);
130 Assert(bit < PAGE_SIZE);
131
132 if(!CTXSUFF(pVM->csam.s.pPDBitmap)[pgdir])
133 {
134 STAM_COUNTER_INC(&pVM->csam.s.StatBitmapAlloc);
135 int rc = MMHyperAlloc(pVM, CSAM_PAGE_BITMAP_SIZE, 0, MM_TAG_CSAM, (void **)&pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir]);
136 if (RT_FAILURE(rc))
137 {
138 Log(("MMHyperAlloc failed with %Rrc\n", rc));
139 return rc;
140 }
141#ifdef IN_RC
142 pVM->csam.s.pPDHCBitmapGC[pgdir] = MMHyperRCToR3(pVM, (RCPTRTYPE(void*))pVM->csam.s.pPDBitmapGC[pgdir]);
143 if (!pVM->csam.s.pPDHCBitmapGC[pgdir])
144 {
145 Log(("MMHyperHC2GC failed for %RRv\n", pVM->csam.s.pPDBitmapGC[pgdir]));
146 return rc;
147 }
148#else
149 pVM->csam.s.pPDGCBitmapHC[pgdir] = MMHyperR3ToRC(pVM, pVM->csam.s.pPDBitmapHC[pgdir]);
150 if (!pVM->csam.s.pPDGCBitmapHC[pgdir])
151 {
152 Log(("MMHyperHC2GC failed for %RHv\n", pVM->csam.s.pPDBitmapHC[pgdir]));
153 return rc;
154 }
155#endif
156 }
157 if(fScanned)
158 ASMBitSet((void *)pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit);
159 else
160 ASMBitClear((void *)pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit);
161
162 return VINF_SUCCESS;
163}
164
165/**
166 * Check if this page needs to be analysed by CSAM.
167 *
168 * This function should only be called for supervisor pages and
169 * only when CSAM is enabled. Leaving these selection criteria
170 * to the caller simplifies the interface (PTE passing).
171 *
172 * Note that the page has not yet been synced, so the TLB trick
173 * (which wasn't ever active anyway) cannot be applied.
174 *
175 * @returns true if the page should be marked not present because
176 * CSAM want need to scan it.
177 * @returns false if the page was already scanned.
178 * @param pVM Pointer to the VM.
179 * @param GCPtr GC pointer of page
180 */
181VMM_INT_DECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTRCUINTPTR GCPtr)
182{
183 if (!CSAMIsEnabled(pVM))
184 return false;
185 Assert(!HMIsEnabled(pVM));
186
187 if(CSAMIsPageScanned(pVM, (RTRCPTR)GCPtr))
188 {
189 /* Already checked! */
190 STAM_COUNTER_ADD(&CTXSUFF(pVM->csam.s.StatNrKnownPages), 1);
191 return false;
192 }
193 STAM_COUNTER_ADD(&CTXSUFF(pVM->csam.s.StatNrPageNP), 1);
194 return true;
195}
196
197
198/**
199 * Remember a possible code page for later inspection
200 *
201 * @returns VBox status code.
202 * @param pVM Pointer to the VM.
203 * @param GCPtr GC pointer of page
204 */
205VMM_INT_DECL(void) CSAMMarkPossibleCodePage(PVM pVM, RTRCPTR GCPtr)
206{
207 Assert(!HMIsEnabled(pVM));
208 if (pVM->csam.s.cPossibleCodePages < RT_ELEMENTS(pVM->csam.s.pvPossibleCodePage))
209 {
210 pVM->csam.s.pvPossibleCodePage[pVM->csam.s.cPossibleCodePages++] = (RTRCPTR)GCPtr;
211 VMCPU_FF_SET(VMMGetCpu0(pVM), VMCPU_FF_CSAM_PENDING_ACTION);
212 }
213 return;
214}
215
216
217/**
218 * Turn on code scanning
219 *
220 * @returns VBox status code.
221 * @param pVM Pointer to the VM.
222 */
223VMM_INT_DECL(int) CSAMEnableScanning(PVM pVM)
224{
225 AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
226 pVM->fCSAMEnabled = true;
227 return VINF_SUCCESS;
228}
229
230/**
231 * Turn off code scanning
232 *
233 * @returns VBox status code.
234 * @param pVM Pointer to the VM.
235 */
236VMM_INT_DECL(int) CSAMDisableScanning(PVM pVM)
237{
238 pVM->fCSAMEnabled = false;
239 return VINF_SUCCESS;
240}
241
242
243/**
244 * Check if we've scanned this instruction before. If true, then we can emulate
245 * it instead of returning to ring 3.
246 *
247 * Using a simple array here as there are generally few mov crx instructions and
248 * tree lookup is likely to be more expensive. (as it would also have to be offset based)
249 *
250 * @returns boolean
251 * @param pVM Pointer to the VM.
252 * @param GCPtr GC pointer of page table entry
253 */
254VMM_INT_DECL(bool) CSAMIsKnownDangerousInstr(PVM pVM, RTRCUINTPTR GCPtr)
255{
256 Assert(!HMIsEnabled(pVM));
257
258 for (uint32_t i=0;i<pVM->csam.s.cDangerousInstr;i++)
259 {
260 if (pVM->csam.s.aDangerousInstr[i] == (RTRCPTR)GCPtr)
261 {
262 STAM_COUNTER_INC(&pVM->csam.s.StatInstrCacheHit);
263 return true;
264 }
265 }
266 /* Record that we're about to process it in ring 3. */
267 pVM->csam.s.aDangerousInstr[pVM->csam.s.iDangerousInstr++] = (RTRCPTR)GCPtr;
268 pVM->csam.s.iDangerousInstr &= CSAM_MAX_DANGR_INSTR_MASK;
269
270 if (++pVM->csam.s.cDangerousInstr > CSAM_MAX_DANGR_INSTR)
271 pVM->csam.s.cDangerousInstr = CSAM_MAX_DANGR_INSTR;
272
273 STAM_COUNTER_INC(&pVM->csam.s.StatInstrCacheMiss);
274 return false;
275}
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