1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* $Id: bs3-apic-1-32.c32 $ */
/** @file
* BS3Kit - bs3-apic-1, 32-bit C code.
*/
/*
* Copyright (C) 2022-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
/*********************************************************************************************************************************
* Header Files *
*********************************************************************************************************************************/
#include <bs3kit.h>
#include <iprt/asm-amd64-x86.h>
#include <iprt/x86.h>
#include <VBox/apic.h>
static void printBitmap(const char BS3_FAR *pszName, uint32_t BS3_FAR volatile *pau32Bitmap)
{
unsigned off;
Bs3TestPrintf("%s:", pszName);
for (off = 0; off < 0x80; off += 0x10)
{
uint32_t uVal = pau32Bitmap[off / sizeof(uint32_t)];
Bs3TestPrintf(off != 0 ? "'%08x" : "%08x", uVal);
}
Bs3TestPrintf("\n");
}
BS3_DECL(void) ProtModeApicTests(void)
{
uint64_t uApicBase2, uApicBase;
Bs3TestSub("protected mode");
uApicBase = ASMRdMsr(MSR_IA32_APICBASE);
/* Disable the APIC (according to wiki.osdev.org/APIC, disabling the
APIC could require a CPU reset to re-enable it, but it works for us): */
ASMWrMsr(MSR_IA32_APICBASE, uApicBase & ~(uint64_t)MSR_IA32_APICBASE_EN);
uApicBase2 = ASMRdMsr(MSR_IA32_APICBASE);
if (uApicBase2 == (uApicBase & ~(uint64_t)MSR_IA32_APICBASE_EN))
Bs3TestPrintf("Disabling worked.\n");
else
Bs3TestFailedF("Disabling the APIC did not work (%#RX64)", uApicBase2);
/* Enabling the APIC: */
ASMWrMsr(MSR_IA32_APICBASE, uApicBase | MSR_IA32_APICBASE_EN);
uApicBase2 = ASMRdMsr(MSR_IA32_APICBASE);
if (uApicBase2 == (uApicBase | MSR_IA32_APICBASE_EN))
{
uint8_t BS3_FAR volatile * const pabApic = (uint8_t BS3_FAR volatile *)((uintptr_t)uApicBase & X86_PAGE_4K_BASE_MASK);
uint32_t BS3_FAR volatile * const pau32Apic = (uint32_t BS3_FAR volatile *)pabApic;
uint32_t i, uVal, uVal2;
Bs3TestPrintf("Enabling worked.\n");
/*
* Do some register reads and such.
*/
uVal = pau32Apic[XAPIC_OFF_VERSION / sizeof(uint32_t)];
Bs3TestPrintf("APIC version: %#x\n", uVal);
if ( APIC_REG_VERSION_GET_VER(uVal) != XAPIC_HARDWARE_VERSION_P4
&& APIC_REG_VERSION_GET_VER(uVal) != XAPIC_HARDWARE_VERSION_P6)
Bs3TestFailedF("Unexpected APIC version: %#x (%#x)", APIC_REG_VERSION_GET_VER(uVal), uVal);
Bs3TestPrintf("APIC ID: %#x\n", pau32Apic[XAPIC_OFF_ID / sizeof(uint32_t)]);
Bs3TestPrintf("TPR: %#x\n", pau32Apic[XAPIC_OFF_TPR / sizeof(uint32_t)]);
for (i = 0; i < 5; i++)
{
Bs3TestPrintf("TPR write test iteration #%u\n", i + 1);
uVal = 256;
while (uVal-- > 0)
{
pau32Apic[XAPIC_OFF_TPR / sizeof(uint32_t)] = uVal;
uVal2 = pau32Apic[XAPIC_OFF_TPR / sizeof(uint32_t)];
if (uVal2 != uVal)
Bs3TestFailedF("Setting TPR to %#x failed, read back %#x", uVal, uVal2);
}
}
Bs3TestPrintf("APR: %#x\n", pau32Apic[XAPIC_OFF_APR / sizeof(uint32_t)]);
Bs3TestPrintf("PPR: %#x\n", pau32Apic[XAPIC_OFF_PPR / sizeof(uint32_t)]);
printBitmap("ISR", &pau32Apic[XAPIC_OFF_ISR0 / sizeof(uint32_t)]);
printBitmap("TMR", &pau32Apic[XAPIC_OFF_TMR0 / sizeof(uint32_t)]);
printBitmap("IRR", &pau32Apic[XAPIC_OFF_IRR0 / sizeof(uint32_t)]);
}
else
Bs3TestFailedF("Enabling the APIC did not work (%#RX64)", uApicBase2);
}
|