VirtualBox

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

Last change on this file since 26277 was 26277, checked in by vboxsync, 15 years ago

VMM: more RC/GC warnings - CSAMDoesPageNeedScanning and CSAMMarkPage now takes RTRCUINTPTR instead of RTRCPTR to ease the pain using them in RC.

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