VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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