[38954] | 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 | /*
|
---|
[98103] | 10 | * Copyright (C) 2011-2023 Oracle and/or its affiliates.
|
---|
[38954] | 11 | *
|
---|
[96407] | 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
|
---|
[38954] | 29 | */
|
---|
| 30 |
|
---|
[57358] | 31 |
|
---|
| 32 | /*********************************************************************************************************************************
|
---|
| 33 | * Header Files *
|
---|
| 34 | *********************************************************************************************************************************/
|
---|
[38954] | 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 |
|
---|
[57358] | 47 | /*********************************************************************************************************************************
|
---|
| 48 | * Global Variables *
|
---|
| 49 | *********************************************************************************************************************************/
|
---|
[38954] | 50 | static RTR0MEMOBJ g_hMemPage0;
|
---|
| 51 | static RTR0MEMOBJ g_hMapPage0;
|
---|
| 52 | static uint8_t *g_pbPage0;
|
---|
| 53 |
|
---|
| 54 | static RTR0MEMOBJ g_hMemLowCore;
|
---|
| 55 | static RTR0MEMOBJ g_hMapLowCore;
|
---|
| 56 | static uint8_t *g_pbLowCore;
|
---|
| 57 | static RTHCPHYS g_HCPhysLowCore;
|
---|
| 58 |
|
---|
| 59 | /** @name For restoring memory we've overwritten.
|
---|
| 60 | * @{ */
|
---|
| 61 | static uint32_t g_u32SavedVector;
|
---|
| 62 | static uint16_t g_u16SavedCadIndicator;
|
---|
| 63 | static void *g_pvSavedLowCore;
|
---|
| 64 | /** @} */
|
---|
| 65 |
|
---|
| 66 |
|
---|
[57358] | 67 | /*********************************************************************************************************************************
|
---|
| 68 | * Internal Functions *
|
---|
| 69 | *********************************************************************************************************************************/
|
---|
[38954] | 70 | /* VMMR0TripleFaultHackA.asm */
|
---|
| 71 | DECLASM(void) vmmR0TripleFaultHackStart(void);
|
---|
| 72 | DECLASM(void) vmmR0TripleFaultHackEnd(void);
|
---|
| 73 | DECLASM(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 | */
|
---|
| 83 | int vmmR0TripleFaultHackInit(void)
|
---|
| 84 | {
|
---|
| 85 | /*
|
---|
| 86 | * Map the first page.
|
---|
| 87 | */
|
---|
[93554] | 88 | int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, HOST_PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
|
---|
[38954] | 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 | */
|
---|
[93554] | 98 | //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, HOST_PAGE_SIZE, _1M - 1);
|
---|
[38954] | 99 | //__debugbreak();
|
---|
[93554] | 100 | rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, HOST_PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
|
---|
[38954] | 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 | */
|
---|
[93554] | 111 | g_pvSavedLowCore = RTMemAlloc(HOST_PAGE_SIZE);
|
---|
[38954] | 112 | AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY);
|
---|
[93554] | 113 | memcpy(g_pvSavedLowCore, g_pbLowCore, HOST_PAGE_SIZE);
|
---|
[38954] | 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;
|
---|
[93554] | 122 | AssertLogRelReturn(cbCode <= HOST_PAGE_SIZE, VERR_OUT_OF_RANGE);
|
---|
[38954] | 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 | */
|
---|
| 163 | void vmmR0TripleFaultHackTerm(void)
|
---|
| 164 | {
|
---|
| 165 | /*
|
---|
| 166 | * Restore overwritten memory.
|
---|
| 167 | */
|
---|
| 168 | if ( g_pvSavedLowCore
|
---|
| 169 | && g_pbLowCore)
|
---|
[93554] | 170 | memcpy(g_pbLowCore, g_pvSavedLowCore, HOST_PAGE_SIZE);
|
---|
[38954] | 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 |
|
---|