VirtualBox

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

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.1 KB
Line 
1/** @file
2 *
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 * Changes the VMMR0Entry() call frame and stack used by the IDT patch code
39 * so that we'll dispatch an interrupt rather than returning directly to Ring-3
40 * when VMMR0Entry() returns.
41 *
42 * @param pVM Pointer to the VM.
43 * @param pvRet Pointer to the return address of VMMR0Entry() on the stack.
44 */
45TRPMR0DECL(void) TRPMR0SetupInterruptDispatcherFrame(PVM pVM, void *pvRet)
46{
47 RTUINT uActiveVector = pVM->trpm.s.uActiveVector;
48 pVM->trpm.s.uActiveVector = ~0;
49 if (uActiveVector >= 256)
50 {
51 AssertMsgFailed(("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n",
52 uActiveVector));
53 return;
54 }
55
56#if HC_ARCH_BITS == 32
57 /*
58 * Get the handler pointer (16:32 ptr).
59 */
60 RTIDTR Idtr;
61 ASMGetIDTR(&Idtr);
62 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector];
63 if (!pIdte->Gen.u1Present)
64 {
65 AssertMsgFailed(("The IDT entry (%d) is not present!\n", uActiveVector));
66 return;
67 }
68 if ( pIdte->Gen.u3Type1 != VBOX_IDTE_TYPE1
69 && pIdte->Gen.u5Type2 != VBOX_IDTE_TYPE2_INT_32)
70 {
71 AssertMsgFailed(("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
72 uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
73 return;
74 }
75
76 RTFAR32 pfnHandler;
77 pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
78 pfnHandler.sel = pIdte->Gen.u16SegSel;
79
80 /*
81 * The stack frame is as follows:
82 *
83 * 1c iret frame
84 * 18 fs
85 * 14 ds
86 * 10 es
87 * c uArg
88 * 8 uOperation
89 * 4 pVM
90 * 0 return address (pvRet points here)
91 *
92 * We'll change the stackframe so that we will not return
93 * to the caller but to a interrupt dispatcher. We'll also
94 * setup the frame so that ds and es are moved to give room
95 * to a far return (to the handler).
96 */
97 unsigned *pau = (unsigned *)pvRet;
98 pau[0] = (unsigned)trpmR0InterruptDispatcher; /* new return address */
99 pau[3] = pau[6]; /* uArg = fs */
100 pau[2] = pau[5]; /* uOperation = ds */
101 pau[5] = pfnHandler.off; /* ds = retf off */
102 pau[6] = pfnHandler.sel; /* fs = retf sel */
103
104#else /* 64-bit: */
105
106 /*
107 * Get the handler pointer (16:48 ptr).
108 */
109 RTIDTR Idtr;
110 ASMGetIDTR(&Idtr);
111 PVBOXIDTE pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector * 2];
112 if (!pIdte->Gen.u1Present)
113 {
114 AssertMsgFailed(("The IDT entry (%d) is not present!\n", uActiveVector));
115 return;
116 }
117 if ( pIdte->Gen.u3Type1 != VBOX_IDTE_TYPE1
118 && pIdte->Gen.u5Type2 != VBOX_IDTE_TYPE2_INT_32)
119 {
120 AssertMsgFailed(("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
121 uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
122 return;
123 }
124
125 RTFAR64 pfnHandler;
126 pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
127 pfnHandler.off |= (uint64_t)(*(uint32_t *)(pIdte + 1)) << 32; //cleanup!
128 pfnHandler.sel = pIdte->Gen.u16SegSel;
129
130 /*
131 * The stack frame is as follows:
132 *
133 * 28 iret frame
134 * 20 dummy
135 * 14 uArg
136 * 10 uOperation
137 * 8 pVM
138 * 0 return address (pvRet points here)
139 *
140 * We'll change the stackframe so that we will not return
141 * to the caller but to a interrupt dispatcher. And we'll create
142 * a 64-bit far return frame where dummy and uArg is.
143 */
144 uint64_t *pau = (uint64_t *)pvRet;
145 pau[0] = (uint64_t)trpmR0InterruptDispatcher; /* new return address */
146 pau[3] = pfnHandler.off; /* retf off */
147 pau[4] = pfnHandler.sel; /* retf sel */
148#endif
149
150// dprintf(("Interrupt: %04x:%08x vector %d\n", pfnHandler.sel, pfnHandler.off, uActiveVector));
151}
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