diff options
Diffstat (limited to 'src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c')
-rw-r--r-- | src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c new file mode 100644 index 00000000..a556c5b0 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c @@ -0,0 +1,149 @@ +/* $Id: bs3-cmn-PagingQueryAddressInfo.c $ */ +/** @file + * BS3Kit - Bs3PagingQueryAddressInfo + */ + +/* + * Copyright (C) 2007-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> +#include <iprt/asm-amd64-x86.h> +#include <VBox/err.h> + + +#undef Bs3PagingQueryAddressInfo +BS3_CMN_DEF(int, Bs3PagingQueryAddressInfo,(uint64_t uFlat, PBS3PAGINGINFO4ADDR pPgInfo)) +{ + RTCCUINTXREG const cr3 = ASMGetCR3(); + RTCCUINTXREG const cr4 = g_uBs3CpuDetected & BS3CPU_F_CPUID ? ASMGetCR4() : 0; + bool const fLegacyPTs = !(cr4 & X86_CR4_PAE); + int rc = VERR_OUT_OF_RANGE; + + + pPgInfo->fFlags = 0; + pPgInfo->u.apbEntries[0] = NULL; + pPgInfo->u.apbEntries[1] = NULL; + pPgInfo->u.apbEntries[2] = NULL; + pPgInfo->u.apbEntries[3] = NULL; + + if (!fLegacyPTs) + { +#if TMPL_BITS == 16 + uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1; +#else + uintptr_t const uMaxAddr = ~(uintptr_t)0; +#endif + uint64_t const fEfer = g_uBs3CpuDetected & BS3CPU_F_LONG_MODE ? ASMRdMsr(MSR_K6_EFER) : 0; + + pPgInfo->cEntries = fEfer & MSR_K6_EFER_LMA ? 4 : 3; + pPgInfo->cbEntry = sizeof(X86PTEPAE); + if ((cr3 & X86_CR3_AMD64_PAGE_MASK) <= uMaxAddr) + { + if ( (fEfer & MSR_K6_EFER_LMA) + && X86_IS_CANONICAL(uFlat)) + { + /* 48-bit long mode paging. */ + pPgInfo->u.Pae.pPml4e = (X86PML4E BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_AMD64_PAGE_MASK); + pPgInfo->u.Pae.pPml4e += (uFlat >> X86_PML4_SHIFT) & X86_PML4_MASK; + if (!pPgInfo->u.Pae.pPml4e->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if ((pPgInfo->u.Pae.pPml4e->u & X86_PML4E_PG_MASK) <= uMaxAddr) + { + pPgInfo->u.Pae.pPdpe = (X86PDPE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPml4e->u & X86_PML4E_PG_MASK); + pPgInfo->u.Pae.pPdpe += (uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64; + if (!pPgInfo->u.Pae.pPdpe->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if (pPgInfo->u.Pae.pPdpe->b.u1Size) + rc = VINF_SUCCESS; + else + rc = VINF_TRY_AGAIN; + } + } + else if ( !(fEfer & MSR_K6_EFER_LMA) + && uFlat <= _4G) + { + /* 32-bit PAE paging. */ + pPgInfo->u.Pae.pPdpe = (X86PDPE BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAE_PAGE_MASK); + pPgInfo->u.Pae.pPdpe += ((uint32_t)uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE; + if (!pPgInfo->u.Pae.pPdpe->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else + rc = VINF_TRY_AGAIN; + } + + /* Common code for the PD and PT levels. */ + if ( rc == VINF_TRY_AGAIN + && (pPgInfo->u.Pae.pPdpe->u & X86_PDPE_PG_MASK) <= uMaxAddr) + { + rc = VERR_OUT_OF_RANGE; + pPgInfo->u.Pae.pPde = (X86PDEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPdpe->u & X86_PDPE_PG_MASK); + pPgInfo->u.Pae.pPde += (uFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK; + if (!pPgInfo->u.Pae.pPde->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if (pPgInfo->u.Pae.pPde->b.u1Size) + rc = VINF_SUCCESS; + else if ((pPgInfo->u.Pae.pPde->u & X86_PDE_PAE_PG_MASK) <= uMaxAddr) + { + pPgInfo->u.Pae.pPte = (X86PTEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPde->u & X86_PDE_PAE_PG_MASK); + rc = VINF_SUCCESS; + } + } + else if (rc == VINF_TRY_AGAIN) + rc = VERR_OUT_OF_RANGE; + } + } + else + { +#if TMPL_BITS == 16 + uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1; +#else + uint32_t const uMaxAddr = UINT32_MAX; +#endif + + pPgInfo->cEntries = 2; + pPgInfo->cbEntry = sizeof(X86PTE); + if ( uFlat < _4G + && cr3 <= uMaxAddr) + { + pPgInfo->u.Legacy.pPde = (X86PDE BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAGE_MASK); + pPgInfo->u.Legacy.pPde += ((uint32_t)uFlat >> X86_PD_SHIFT) & X86_PD_MASK; + if (!pPgInfo->u.Legacy.pPde->b.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if (pPgInfo->u.Legacy.pPde->b.u1Size) + rc = VINF_SUCCESS; + else if (pPgInfo->u.Legacy.pPde->u <= uMaxAddr) + { + pPgInfo->u.Legacy.pPte = (X86PTE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Legacy.pPde->u & X86_PDE_PG_MASK); + pPgInfo->u.Legacy.pPte += ((uint32_t)uFlat >> X86_PT_SHIFT) & X86_PT_MASK; + if (pPgInfo->u.Legacy.pPte->n.u1Present) + rc = VINF_SUCCESS; + else + rc = VERR_PAGE_NOT_PRESENT; + } + } + } + return rc; +} + |