VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/TRPMR0.cpp@ 397

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

Completed most of VBOX_WITHOUT_IDT_PATCHING. (hope I didn't break anything...) TODO: IST support on AMD64.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/* $Id: TRPMR0.cpp 397 2007-01-28 02:34:06Z vboxsync $ */
2/** @file
3 * TRPM - The Trap Monitor - HC Ring 0
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_TRPM
27#include <VBox/trpm.h>
28#include "TRPMInternal.h"
29#include <VBox/vm.h>
30#include <VBox/err.h>
31#include <VBox/log.h>
32#include <iprt/assert.h>
33#include <iprt/asm.h>
34
35
36
37
38/**
39 * Dispatches an interrupt that arrived while we were in the guest context.
40 *
41 * It's assumes we're invoked with interrupts disabled.
42 * When this function returns, interrupts will be enabled.
43 *
44 * @param pVM The VM handle.
45 */
46TRPMR0DECL(void) TRPMR0DispatchHostInterrupt(PVM pVM)
47{
48 RTUINT uActiveVector = pVM->trpm.s.uActiveVector;
49 pVM->trpm.s.uActiveVector = ~0;
50 AssertMsgReturnVoid(uActiveVector < 256, ("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n", uActiveVector));
51
52 /*
53 * Get the handler pointer (16:32 ptr) / (16:48 ptr).
54 */
55 RTIDTR Idtr;
56 ASMGetIDTR(&Idtr);
57#if HC_ARCH_BITS == 32
58 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector];
59#else
60 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector * 2];
61#endif
62 AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
63 AssertMsgReturnVoid( pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
64 || pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32,
65 ("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
66 uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
67#if HC_ARCH_BITS == 32
68 RTFAR32 pfnHandler;
69 pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
70 pfnHandler.sel = pIdte->Gen.u16SegSel;
71
72 const RTR0UINTREG uRSP = ~(RTR0UINTREG)0;
73
74#else /* 64-bit: */
75 RTFAR64 pfnHandler;
76 pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
77 pfnHandler.off |= (uint64_t)(*(uint32_t *)(pIdte + 1)) << 32; //cleanup!
78 pfnHandler.sel = pIdte->Gen.u16SegSel;
79
80 RTR0UINTREG uRSP = ~(RTR0UINTREG)0;
81 if (pIdte->au32[1] & 0x7 /*IST*/)
82 {
83 /** @todo implement IST */
84 }
85
86#endif
87
88 /*
89 * Dispatch it.
90 */
91 trpmR0DispatchHostInterrupt(pfnHandler.off, pfnHandler.sel, uRSP);
92}
93
94#ifndef VBOX_WITHOUT_IDT_PATCHING
95
96/**
97 * Changes the VMMR0Entry() call frame and stack used by the IDT patch code
98 * so that we'll dispatch an interrupt rather than returning directly to Ring-3
99 * when VMMR0Entry() returns.
100 *
101 * @param pVM Pointer to the VM.
102 * @param pvRet Pointer to the return address of VMMR0Entry() on the stack.
103 */
104TRPMR0DECL(void) TRPMR0SetupInterruptDispatcherFrame(PVM pVM, void *pvRet)
105{
106 RTUINT uActiveVector = pVM->trpm.s.uActiveVector;
107 pVM->trpm.s.uActiveVector = ~0;
108 AssertMsgReturnVoid(uActiveVector < 256, ("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n", uActiveVector));
109
110#if HC_ARCH_BITS == 32
111 /*
112 * Get the handler pointer (16:32 ptr).
113 */
114 RTIDTR Idtr;
115 ASMGetIDTR(&Idtr);
116 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector];
117 AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
118 AssertMsgReturnVoid( pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
119 && pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32,
120 ("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
121 uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
122
123 RTFAR32 pfnHandler;
124 pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
125 pfnHandler.sel = pIdte->Gen.u16SegSel;
126
127 /*
128 * The stack frame is as follows:
129 *
130 * 1c iret frame
131 * 18 fs
132 * 14 ds
133 * 10 es
134 * c uArg
135 * 8 uOperation
136 * 4 pVM
137 * 0 return address (pvRet points here)
138 *
139 * We'll change the stackframe so that we will not return
140 * to the caller but to a interrupt dispatcher. We'll also
141 * setup the frame so that ds and es are moved to give room
142 * to a far return (to the handler).
143 */
144 unsigned *pau = (unsigned *)pvRet;
145 pau[0] = (unsigned)trpmR0InterruptDispatcher; /* new return address */
146 pau[3] = pau[6]; /* uArg = fs */
147 pau[2] = pau[5]; /* uOperation = ds */
148 pau[5] = pfnHandler.off; /* ds = retf off */
149 pau[6] = pfnHandler.sel; /* fs = retf sel */
150
151#else /* 64-bit: */
152
153 /*
154 * Get the handler pointer (16:48 ptr).
155 */
156 RTIDTR Idtr;
157 ASMGetIDTR(&Idtr);
158 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector * 2];
159
160 AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
161 AssertMsgReturnVoid( pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
162 && pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32, /* == 64 */
163 ("The IDT entry (%d) is not 64-bit int gate! type1=%#x type2=%#x\n",
164 uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
165
166 RTFAR64 pfnHandler;
167 pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
168 pfnHandler.off |= (uint64_t)(*(uint32_t *)(pIdte + 1)) << 32; //cleanup!
169 pfnHandler.sel = pIdte->Gen.u16SegSel;
170
171 if (pIdte->au32[1] & 0x7 /*IST*/)
172 {
173 /** @todo implement IST */
174 }
175
176 /*
177 * The stack frame is as follows:
178 *
179 * 28 iret frame
180 * 20 dummy
181 * 14 uArg
182 * 10 uOperation
183 * 8 pVM
184 * 0 return address (pvRet points here)
185 *
186 * We'll change the stackframe so that we will not return
187 * to the caller but to a interrupt dispatcher. And we'll create
188 * a 64-bit far return frame where dummy and uArg is.
189 */
190 uint64_t *pau = (uint64_t *)pvRet;
191 pau[0] = (uint64_t)trpmR0InterruptDispatcher; /* new return address */
192 pau[3] = pfnHandler.off; /* retf off */
193 pau[4] = pfnHandler.sel; /* retf sel */
194#endif
195
196// dprintf(("Interrupt: %04x:%08x vector %d\n", pfnHandler.sel, pfnHandler.off, uActiveVector));
197}
198
199#endif /* !VBOX_WITHOUT_IDT_PATCHING */
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