VirtualBox

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

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

VMM: APIC R0 init/term ordering and nits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: APICR0.cpp 60364 2016-04-06 16:08:15Z 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 page.
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)((uint8_t *)pApic->pvApicPibR0 + offApicPib);
113 pApicCpu->pvApicPibR3 = (RTR3PTR)((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.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette