VirtualBox

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

Last change on this file since 1122 was 23, checked in by vboxsync, 18 years ago

string.h & stdio.h + header cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1/* $Id: CSAMAll.cpp 23 2007-01-15 14:08:28Z vboxsync $ */
2/** @file
3 * CSAM - Guest OS Code Scanning and Analysis Manager - Any Context
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
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/dbg.h>
40#include <VBox/err.h>
41#include <VBox/log.h>
42#include <iprt/assert.h>
43#include <VBox/dis.h>
44#include <VBox/disopcode.h>
45#include <iprt/string.h>
46#include <iprt/asm.h>
47
48/**
49 * Check if this page needs to be analysed by CSAM
50 *
51 * @returns VBox status code
52 * @param pVM The VM to operate on.
53 * @param pvFault Fault address
54 */
55CSAMDECL(int) CSAMExecFault(PVM pVM, RTGCPTR pvFault)
56{
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 VM_FF_SET(pVM, VM_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 The VM to operate on.
80 * @param pPage GC page address
81 */
82CSAMDECL(bool) CSAMIsPageScanned(PVM pVM, RTGCPTR pPage)
83{
84 int pgdir, bit;
85 uintptr_t page;
86
87 page = (uintptr_t)pPage;
88 pgdir = page >> X86_PAGE_4M_SHIFT;
89 bit = (page & X86_PAGE_4M_OFFSET_MASK) >> X86_PAGE_4K_SHIFT;
90
91 Assert(pgdir < CSAM_PGDIRBMP_CHUNKS);
92 Assert(bit < PAGE_SIZE);
93
94 return pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir] && ASMBitTest(pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit);
95}
96
97
98
99/**
100 * Mark a page as scanned/not scanned
101 *
102 * @note: we always mark it as scanned, even if we haven't completely done so
103 *
104 * @returns VBox status code.
105 * @param pVM The VM to operate on.
106 * @param pPage GC page address (not necessarily aligned)
107 * @param fScanned Mark as scanned or not scanned
108 *
109 */
110CSAMDECL(int) CSAMMarkPage(PVM pVM, RTGCPTR pPage, bool fScanned)
111{
112 int pgdir, bit;
113 uintptr_t page;
114
115#ifdef LOG_ENABLED
116 if (fScanned && !CSAMIsPageScanned(pVM, pPage))
117 Log(("CSAMMarkPage %VGv\n", pPage));
118#endif
119
120 if(!CSAMIsEnabled(pVM))
121 return VINF_SUCCESS;
122
123 page = (uintptr_t)pPage;
124 pgdir = page >> X86_PAGE_4M_SHIFT;
125 bit = (page & X86_PAGE_4M_OFFSET_MASK) >> X86_PAGE_4K_SHIFT;
126
127 Assert(pgdir < CSAM_PGDIRBMP_CHUNKS);
128 Assert(bit < PAGE_SIZE);
129
130 if(!CTXSUFF(pVM->csam.s.pPDBitmap)[pgdir])
131 {
132 STAM_COUNTER_INC(&pVM->csam.s.StatBitmapAlloc);
133 int rc = MMHyperAlloc(pVM, CSAM_PAGE_BITMAP_SIZE, 0, MM_TAG_CSAM, (void **)&pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir]);
134 if (VBOX_FAILURE(rc))
135 {
136 Log(("MMR3HyperAlloc failed with %d\n", rc));
137 return rc;
138 }
139#ifdef IN_GC
140 pVM->csam.s.pPDHCBitmapGC[pgdir] = MMHyperGC2HC(pVM, pVM->csam.s.pPDBitmapGC[pgdir]);
141 if (!pVM->csam.s.pPDHCBitmapGC[pgdir])
142 {
143 Log(("MMHyperHC2GC failed for %VGv\n", pVM->csam.s.pPDBitmapGC[pgdir]));
144 return rc;
145 }
146#else
147 pVM->csam.s.pPDGCBitmapHC[pgdir] = MMHyperHC2GC(pVM, pVM->csam.s.pPDBitmapHC[pgdir]);
148 if (!pVM->csam.s.pPDGCBitmapHC[pgdir])
149 {
150 Log(("MMHyperHC2GC failed for %VHv\n", pVM->csam.s.pPDBitmapHC[pgdir]));
151 return rc;
152 }
153#endif
154 }
155 if(fScanned)
156 ASMBitSet(pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit);
157 else
158 ASMBitClear(pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit);
159
160 return VINF_SUCCESS;
161}
162
163/**
164 * Check if this page needs to be analysed by CSAM.
165 *
166 * This function should only be called for supervisor pages and
167 * only when CSAM is enabled. Leaving these selection criteria
168 * to the caller simplifies the interface (PTE passing).
169 *
170 * Note the the page has not yet been synced, so the TLB trick
171 * (which wasn't ever active anyway) cannot be applied.
172 *
173 * @returns true if the page should be marked not present because
174 * CSAM want need to scan it.
175 * @returns false if the page was already scanned.
176 * @param pVM The VM to operate on.
177 * @param GCPtr GC pointer of page table entry
178 */
179CSAMDECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTGCPTR GCPtr)
180{
181 if(CSAMIsPageScanned(pVM, 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 * Turn on code scanning
193 *
194 * @returns VBox status code.
195 * @param pVM The VM to operate on.
196 */
197CSAMDECL(int) CSAMEnableScanning(PVM pVM)
198{
199 pVM->fCSAMEnabled = true;
200 return VINF_SUCCESS;
201}
202
203/**
204 * Turn off code scanning
205 *
206 * @returns VBox status code.
207 * @param pVM The VM to operate on.
208 */
209CSAMDECL(int) CSAMDisableScanning(PVM pVM)
210{
211 pVM->fCSAMEnabled = false;
212 return VINF_SUCCESS;
213}
214
215
216/**
217 * Check if we've scanned this instruction before. If true, then we can emulate
218 * it instead of returning to ring 3.
219 *
220 * Using a simple array here as there are generally few mov crx instructions and
221 * tree lookup is likely to be more expensive. (as it would also have to be offset based)
222 *
223 * @returns boolean
224 * @param pVM The VM to operate on.
225 * @param GCPtr GC pointer of page table entry
226 */
227CSAMDECL(bool) CSAMIsKnownDangerousInstr(PVM pVM, RTGCPTR GCPtr)
228{
229 for (uint32_t i=0;i<pVM->csam.s.cDangerousInstr;i++)
230 {
231 if (pVM->csam.s.aDangerousInstr[i] == GCPtr)
232 {
233 STAM_COUNTER_INC(&pVM->csam.s.StatInstrCacheHit);
234 return true;
235 }
236 }
237 /* Record that we're about to process it in ring 3. */
238 pVM->csam.s.aDangerousInstr[pVM->csam.s.iDangerousInstr++] = GCPtr;
239 pVM->csam.s.iDangerousInstr &= CSAM_MAX_DANGR_INSTR_MASK;
240
241 if (++pVM->csam.s.cDangerousInstr > CSAM_MAX_DANGR_INSTR)
242 pVM->csam.s.cDangerousInstr = CSAM_MAX_DANGR_INSTR;
243
244 STAM_COUNTER_INC(&pVM->csam.s.StatInstrCacheMiss);
245 return false;
246}
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