VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/APICR0.cpp@ 60380

Last change on this file since 60380 was 60377, checked in by vboxsync, 9 years ago

VMM: Fix APIC, CPUM init ordering for the new APIC code while still retaining the old code. Namely, consistent MSR APIC base caching and APIC page dependency on PDM construction, see bugref:8245:46 for more details.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.7 KB
Line 
1/* $Id: APICR0.cpp 60377 2016-04-07 15:53:36Z vboxsync $ */
2/** @file
3 * Advanced Programmable Interrupt Controller (APIC) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2016 Oracle Corporation
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 (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_APIC
23#include "APICInternal.h"
24#include <iprt/mem.h>
25#include <iprt/memobj.h>
26#include <iprt/process.h>
27#include <VBox/vmm/vm.h>
28
29
30/**
31 * Does ring-0 per-VM APIC initialization.
32 *
33 * @returns VBox status code.
34 * @param pVM The cross context VM structure.
35 */
36VMMR0_INT_DECL(int) APICR0InitVM(PVM pVM)
37{
38 /* Paranoia. */
39 PAPIC pApic = VM_TO_APIC(pVM);
40 Assert(pApic->hMapObjApicPibR0 == NIL_RTR0MEMOBJ);
41 Assert(pApic->hMapObjApicPibR0 == NIL_RTR0MEMOBJ);
42
43 /* Init. non-zero members. */
44 pApic->HCPhysApicPib = NIL_RTHCPHYS;
45
46 /*
47 * Allocate and map the pending-interrupt bitmap (PIB).
48 *
49 * We allocate all the VCPUs' PIBs contiguously in order to save space
50 * as physically contiguous allocations are rounded to a multiple of page size.
51 */
52 size_t const cbApicPib = RT_ALIGN_Z(pVM->cCpus * sizeof(APICPIB), PAGE_SIZE);
53 int rc = RTR0MemObjAllocCont(&pApic->hMemObjApicPibR0, cbApicPib, false /* fExecutable */);
54 if (RT_SUCCESS(rc))
55 {
56 pApic->cbApicPib = cbApicPib;
57 pApic->pvApicPibR0 = RTR0MemObjAddress(pApic->hMemObjApicPibR0);
58 pApic->HCPhysApicPib = RTR0MemObjGetPagePhysAddr(pApic->hMemObjApicPibR0, 0 /* iPage */);
59 ASMMemZero32(pApic->pvApicPibR0, cbApicPib);
60
61 rc = RTR0MemObjMapUser(&pApic->hMapObjApicPibR0, pApic->hMemObjApicPibR0, (RTR3PTR)-1, 0 /* uAlignment */,
62 RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf());
63 if (RT_SUCCESS(rc))
64 pApic->pvApicPibR3 = RTR0MemObjAddressR3(pApic->hMapObjApicPibR0);
65 else
66 {
67 LogRel(("APICR0InitVM: Failed to map pending-interrupt bitmap of %u bytes. rc=%Rrc\n", cbApicPib, rc));
68 return rc;
69 }
70 }
71 else
72 {
73 LogRel(("APICR0InitVM: Failed to allocate pending-interrupt bitmap of %u bytes. rc=%Rrc\n", cbApicPib, rc));
74 return rc;
75 }
76
77 /*
78 * Allocate and map the virtual-APIC pages.
79 */
80 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
81 {
82 PVMCPU pVCpu = &pVM->aCpus[idCpu];
83 PAPICCPU pApicCpu = VMCPU_TO_APICCPU(pVCpu);
84 size_t const cbApicPage = PAGE_SIZE;
85
86 /* Paranoia. */
87 Assert(pApicCpu->hMapObjApicPageR0 == NIL_RTR0MEMOBJ);
88 Assert(pApicCpu->hMapObjApicPageR0 == NIL_RTR0MEMOBJ);
89
90 /* Init. non-zero members. */
91 pApicCpu->HCPhysApicPage = NIL_RTHCPHYS;
92
93 rc = RTR0MemObjAllocCont(&pApicCpu->hMemObjApicPageR0, cbApicPage, false /* fExecutable */);
94 if (RT_SUCCESS(rc))
95 {
96 pApicCpu->cbApicPage = cbApicPage;
97 pApicCpu->pvApicPageR0 = RTR0MemObjAddress(pApicCpu->hMemObjApicPageR0);
98 pApicCpu->HCPhysApicPage = RTR0MemObjGetPagePhysAddr(pApicCpu->hMemObjApicPageR0, 0 /* iPage */);
99 ASMMemZero32(pApicCpu->pvApicPageR0, cbApicPage);
100
101 rc = RTR0MemObjMapUser(&pApicCpu->hMapObjApicPageR0, pApicCpu->hMemObjApicPageR0, (RTR3PTR)-1, 0 /* uAlignment */,
102 RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf());
103 if (RT_SUCCESS(rc))
104 {
105 pApicCpu->pvApicPageR3 = RTR0MemObjAddressR3(pApicCpu->hMapObjApicPageR0);
106
107 /*
108 * Associate the per-VCPU PIB pointers to the per-VM PIB allocation.
109 */
110 const size_t offApicPib = idCpu * sizeof(APICPIB);
111 pApicCpu->HCPhysApicPib = pApic->HCPhysApicPib + offApicPib;
112 pApicCpu->pvApicPibR0 = (RTR0PTR)((const uint8_t *)pApic->pvApicPibR0 + offApicPib);
113 pApicCpu->pvApicPibR3 = (RTR3PTR)((const uint8_t *)pApic->pvApicPibR3 + offApicPib);
114 }
115 else
116 {
117 LogRel(("APICR0InitVM: VCPU[%u]: Failed to map APIC page of %u bytes. rc=%Rrc\n", idCpu, cbApicPib, rc));
118 return rc;
119 }
120 }
121 else
122 {
123 LogRel(("APICR0InitVM: VCPU[%u]: Failed to allocate APIC page of %u bytes. rc=%Rrc\n", idCpu, cbApicPib, rc));
124 return rc;
125 }
126 }
127
128 LogFlow(("APICR0InitVM: Completed successfully\n"));
129 return VINF_SUCCESS;
130}
131
132
133/**
134 * Does ring-0 per-VM APIC termination.
135 *
136 * @returns VBox status code.
137 * @param pVM The cross context VM structure.
138 */
139VMMR0_INT_DECL(int) APICR0TermVM(PVM pVM)
140{
141 PAPIC pApic = VM_TO_APIC(pVM);
142 if (pApic->hMapObjApicPibR0 != NIL_RTR0MEMOBJ)
143 {
144 RTR0MemObjFree(pApic->hMapObjApicPibR0, true /* fFreeMappings */);
145 pApic->hMapObjApicPibR0 = NIL_RTR0MEMOBJ;
146 pApic->pvApicPibR3 = NULL;
147 }
148 if (pApic->hMemObjApicPibR0 != NIL_RTR0MEMOBJ)
149 {
150 RTR0MemObjFree(pApic->hMemObjApicPibR0, true /* fFreeMappings */);
151 pApic->hMemObjApicPibR0 = NIL_RTR0MEMOBJ;
152 pApic->pvApicPibR0 = NULL;
153 pApic->HCPhysApicPib = NIL_RTHCPHYS;
154 }
155
156 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
157 {
158 PVMCPU pVCpu = &pVM->aCpus[idCpu];
159 PAPICCPU pApicCpu = &pVCpu->apic.s;
160
161 if (pApicCpu->hMapObjApicPageR0 != NIL_RTR0MEMOBJ)
162 {
163 RTR0MemObjFree(pApicCpu->hMapObjApicPageR0, true /* fFreeMappings */);
164 pApicCpu->hMapObjApicPageR0 = NIL_RTR0MEMOBJ;
165 pApicCpu->pvApicPageR3 = NULL;
166 }
167 if (pApicCpu->hMemObjApicPageR0 != NIL_RTR0MEMOBJ)
168 {
169 RTR0MemObjFree(pApicCpu->hMemObjApicPageR0, true /* fFreeMappings */);
170 pApicCpu->hMemObjApicPageR0 = NIL_RTR0MEMOBJ;
171 pApicCpu->pvApicPageR0 = NULL;
172 pApicCpu->HCPhysApicPage = NIL_RTHCPHYS;
173 }
174 }
175
176 LogFlow(("APICR0TermVM: Completed successfully\n"));
177 return VINF_SUCCESS;
178}
179
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