VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/VMMR0TripleFaultHack.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.2 KB
Line 
1/* $Id: VMMR0TripleFaultHack.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VMM - Host Context Ring 0, Triple Fault Debugging Hack.
4 *
5 * Only use this when desperate. May not work on all systems, esp. newer ones,
6 * since it require BIOS support for the warm reset vector at 0467h.
7 */
8
9/*
10 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
11 *
12 * This file is part of VirtualBox base platform packages, as
13 * available from https://www.virtualbox.org.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, in version 3 of the
18 * License.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <https://www.gnu.org/licenses>.
27 *
28 * SPDX-License-Identifier: GPL-3.0-only
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#define LOG_GROUP LOG_GROUP_VMM
36#include <VBox/vmm/vmm.h>
37#include "VMMInternal.h"
38#include <VBox/param.h>
39
40#include <iprt/asm-amd64-x86.h>
41#include <iprt/assert.h>
42#include <iprt/memobj.h>
43#include <iprt/mem.h>
44#include <iprt/string.h>
45
46
47/*********************************************************************************************************************************
48* Global Variables *
49*********************************************************************************************************************************/
50static RTR0MEMOBJ g_hMemPage0;
51static RTR0MEMOBJ g_hMapPage0;
52static uint8_t *g_pbPage0;
53
54static RTR0MEMOBJ g_hMemLowCore;
55static RTR0MEMOBJ g_hMapLowCore;
56static uint8_t *g_pbLowCore;
57static RTHCPHYS g_HCPhysLowCore;
58
59/** @name For restoring memory we've overwritten.
60 * @{ */
61static uint32_t g_u32SavedVector;
62static uint16_t g_u16SavedCadIndicator;
63static void *g_pvSavedLowCore;
64/** @} */
65
66
67/*********************************************************************************************************************************
68* Internal Functions *
69*********************************************************************************************************************************/
70/* VMMR0TripleFaultHackA.asm */
71DECLASM(void) vmmR0TripleFaultHackStart(void);
72DECLASM(void) vmmR0TripleFaultHackEnd(void);
73DECLASM(void) vmmR0TripleFaultHackTripleFault(void);
74
75
76/**
77 * Initalizes the triple fault / boot hack.
78 *
79 * Always call vmmR0TripleFaultHackTerm to clean up, even when this call fails.
80 *
81 * @returns VBox status code.
82 */
83int vmmR0TripleFaultHackInit(void)
84{
85 /*
86 * Map the first page.
87 */
88 int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, HOST_PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
89 AssertRCReturn(rc, rc);
90 rc = RTR0MemObjMapKernel(&g_hMapPage0, g_hMemPage0, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
91 AssertRCReturn(rc, rc);
92 g_pbPage0 = (uint8_t *)RTR0MemObjAddress(g_hMapPage0);
93 LogRel(("0040:0067 = %04x:%04x\n", RT_MAKE_U16(g_pbPage0[0x467+2], g_pbPage0[0x467+3]), RT_MAKE_U16(g_pbPage0[0x467+0], g_pbPage0[0x467+1]) ));
94
95 /*
96 * Allocate some "low core" memory. If that fails, just grab some memory.
97 */
98 //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, HOST_PAGE_SIZE, _1M - 1);
99 //__debugbreak();
100 rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, HOST_PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
101 AssertRCReturn(rc, rc);
102 rc = RTR0MemObjMapKernel(&g_hMapLowCore, g_hMemLowCore, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
103 AssertRCReturn(rc, rc);
104 g_pbLowCore = (uint8_t *)RTR0MemObjAddress(g_hMapLowCore);
105 g_HCPhysLowCore = RTR0MemObjGetPagePhysAddr(g_hMapLowCore, 0);
106 LogRel(("Low core at %RHp mapped at %p\n", g_HCPhysLowCore, g_pbLowCore));
107
108 /*
109 * Save memory we'll be overwriting.
110 */
111 g_pvSavedLowCore = RTMemAlloc(HOST_PAGE_SIZE);
112 AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY);
113 memcpy(g_pvSavedLowCore, g_pbLowCore, HOST_PAGE_SIZE);
114
115 g_u32SavedVector = RT_MAKE_U32_FROM_U8(g_pbPage0[0x467], g_pbPage0[0x467+1], g_pbPage0[0x467+2], g_pbPage0[0x467+3]);
116 g_u16SavedCadIndicator = RT_MAKE_U16(g_pbPage0[0x472], g_pbPage0[0x472+1]);
117
118 /*
119 * Install the code.
120 */
121 size_t cbCode = (uintptr_t)&vmmR0TripleFaultHackEnd - (uintptr_t)&vmmR0TripleFaultHackStart;
122 AssertLogRelReturn(cbCode <= HOST_PAGE_SIZE, VERR_OUT_OF_RANGE);
123 memcpy(g_pbLowCore, &vmmR0TripleFaultHackStart, cbCode);
124
125 g_pbPage0[0x467+0] = 0x00;
126 g_pbPage0[0x467+1] = 0x70;
127 g_pbPage0[0x467+2] = 0x00;
128 g_pbPage0[0x467+3] = 0x00;
129
130 g_pbPage0[0x472+0] = 0x34;
131 g_pbPage0[0x472+1] = 0x12;
132
133 /*
134 * Configure the status port and cmos shutdown command.
135 */
136 uint32_t fSaved = ASMIntDisableFlags();
137
138 ASMOutU8(0x70, 0x0f);
139 ASMOutU8(0x71, 0x0a);
140
141 ASMOutU8(0x70, 0x05);
142 ASMInU8(0x71);
143
144 ASMReloadCR3();
145 ASMWriteBackAndInvalidateCaches();
146
147 ASMSetFlags(fSaved);
148
149#if 1 /* For testing & debugging. */
150 vmmR0TripleFaultHackTripleFault();
151#endif
152
153 return VINF_SUCCESS;
154}
155
156
157/**
158 * Try undo the harm done by the init function.
159 *
160 * This may leave the system in an unstable state since we might have been
161 * hijacking memory below 1MB that is in use by the kernel.
162 */
163void vmmR0TripleFaultHackTerm(void)
164{
165 /*
166 * Restore overwritten memory.
167 */
168 if ( g_pvSavedLowCore
169 && g_pbLowCore)
170 memcpy(g_pbLowCore, g_pvSavedLowCore, HOST_PAGE_SIZE);
171
172 if (g_pbPage0)
173 {
174 g_pbPage0[0x467+0] = RT_BYTE1(g_u32SavedVector);
175 g_pbPage0[0x467+1] = RT_BYTE2(g_u32SavedVector);
176 g_pbPage0[0x467+2] = RT_BYTE3(g_u32SavedVector);
177 g_pbPage0[0x467+3] = RT_BYTE4(g_u32SavedVector);
178
179 g_pbPage0[0x472+0] = RT_BYTE1(g_u16SavedCadIndicator);
180 g_pbPage0[0x472+1] = RT_BYTE2(g_u16SavedCadIndicator);
181 }
182
183 /*
184 * Fix the CMOS.
185 */
186 if (g_pvSavedLowCore)
187 {
188 uint32_t fSaved = ASMIntDisableFlags();
189
190 ASMOutU8(0x70, 0x0f);
191 ASMOutU8(0x71, 0x0a);
192
193 ASMOutU8(0x70, 0x00);
194 ASMInU8(0x71);
195
196 ASMReloadCR3();
197 ASMWriteBackAndInvalidateCaches();
198
199 ASMSetFlags(fSaved);
200 }
201
202 /*
203 * Release resources.
204 */
205 RTMemFree(g_pvSavedLowCore);
206 g_pvSavedLowCore = NULL;
207
208 RTR0MemObjFree(g_hMemLowCore, true /*fFreeMappings*/);
209 g_hMemLowCore = NIL_RTR0MEMOBJ;
210 g_hMapLowCore = NIL_RTR0MEMOBJ;
211 g_pbLowCore = NULL;
212 g_HCPhysLowCore = NIL_RTHCPHYS;
213
214 RTR0MemObjFree(g_hMemPage0, true /*fFreeMappings*/);
215 g_hMemPage0 = NIL_RTR0MEMOBJ;
216 g_hMapPage0 = NIL_RTR0MEMOBJ;
217 g_pbPage0 = NULL;
218}
219
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use