VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp@ 25817

Last change on this file since 25817 was 25817, checked in by vboxsync, 15 years ago

CPU hotplug: Merge the second patch. ACPI changes to support CPU hotplugging. ACPI table changes are in a separate file which is used if CPU hotplugging is enabled for a VM to not break untested guests

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.8 KB
Line 
1/* $Id: VBoxAcpi.cpp 25817 2010-01-13 22:08:17Z vboxsync $ */
2/** @file
3 * VBoxAcpi - VirtualBox ACPI maniputation functionality.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#if !defined(IN_RING3)
23#error Pure R3 code
24#endif
25
26#define LOG_GROUP LOG_GROUP_DEV_ACPI
27#include <VBox/pdmdev.h>
28#include <VBox/pgm.h>
29#include <VBox/log.h>
30#include <VBox/param.h>
31#include <VBox/cfgm.h>
32#include <iprt/assert.h>
33#include <iprt/alloc.h>
34#include <iprt/string.h>
35
36#ifdef VBOX_WITH_DYNAMIC_DSDT
37/* vbox.dsl - input to generate proper DSDT on the fly */
38# include <vboxdsl.hex>
39#else
40/* Statically compiled AML */
41# include <vboxaml.hex>
42# include <vboxaml-cpuhotplug.hex>
43#endif
44
45#ifdef VBOX_WITH_DYNAMIC_DSDT
46static int prepareDynamicDsdt(PPDMDEVINS pDevIns,
47 void* *ppPtr,
48 size_t *puDsdtLen)
49{
50 *ppPtr = NULL;
51 *puDsdtLen = 0;
52 return 0;
53}
54
55static int cleanupDynamicDsdt(PPDMDEVINS pDevIns,
56 void* pPtr)
57{
58 return 0;
59}
60
61#else
62static int patchAml(PPDMDEVINS pDevIns, uint8_t* pAml, size_t uAmlLen)
63{
64 uint16_t cNumCpus;
65 int rc;
66
67 rc = CFGMR3QueryU16Def(pDevIns->pCfgHandle, "NumCPUs", &cNumCpus, 1);
68
69 if (RT_FAILURE(rc))
70 return rc;
71
72 /* Clear CPU objects at all, if needed */
73 bool fShowCpu;
74 rc = CFGMR3QueryBoolDef(pDevIns->pCfgHandle, "ShowCpu", &fShowCpu, false);
75 if (RT_FAILURE(rc))
76 return rc;
77
78 if (!fShowCpu)
79 cNumCpus = 0;
80
81 /**
82 * Now search AML for:
83 * AML_PROCESSOR_OP (UINT16) 0x5b83
84 * and replace whole block with
85 * AML_NOOP_OP (UINT16) 0xa3
86 * for VCPU not configured
87 */
88 for (uint32_t i = 0; i < uAmlLen - 7; i++)
89 {
90 /*
91 * AML_PROCESSOR_OP
92 *
93 * DefProcessor := ProcessorOp PkgLength NameString ProcID
94 PblkAddr PblkLen ObjectList
95 * ProcessorOp := ExtOpPrefix 0x83
96 * ProcID := ByteData
97 * PblkAddr := DwordData
98 * PblkLen := ByteData
99 */
100 if ((pAml[i] == 0x5b) && (pAml[i+1] == 0x83))
101 {
102 if ((pAml[i+3] != 'C') || (pAml[i+4] != 'P'))
103 /* false alarm, not named starting CP */
104 continue;
105
106 /* Processor ID */
107 if (pAml[i+7] < cNumCpus)
108 continue;
109
110 /* Will fill unwanted CPU block with NOOPs */
111 /*
112 * See 18.2.4 Package Length Encoding in ACPI spec
113 * for full format
114 */
115 uint32_t cBytes = pAml[i + 2];
116 AssertReleaseMsg((cBytes >> 6) == 0,
117 ("So far, we only understand simple package length"));
118
119 /* including AML_PROCESSOR_OP itself */
120 for (uint32_t j = 0; j < cBytes + 2; j++)
121 pAml[i+j] = 0xa3;
122
123 /* Can increase i by cBytes + 1, but not really worth it */
124 }
125 }
126
127 /* now recompute checksum, whole file byte sum must be 0 */
128 pAml[9] = 0;
129 uint8_t aSum = 0;
130 for (uint32_t i = 0; i < uAmlLen; i++)
131 aSum = aSum + (uint8_t)pAml[i];
132 pAml[9] = (uint8_t) (0 - aSum);
133
134 return 0;
135}
136#endif
137
138/* Two only public functions */
139int acpiPrepareDsdt(PPDMDEVINS pDevIns, void * *ppPtr, size_t *puDsdtLen)
140{
141#ifdef VBOX_WITH_DYNAMIC_DSDT
142 return prepareDynamicDsdt(pDevIns, ppPtr, puDsdtLen);
143#else
144 unsigned char *pbAmlCode = NULL;
145 size_t cbAmlCode = 0;
146 bool fCpuHotplug = false;
147 int rc = CFGMR3QueryBoolDef(pDevIns->pCfgHandle, "CpuHotplug", &fCpuHotplug, false);
148 if (RT_FAILURE(rc))
149 return PDMDEV_SET_ERROR(pDevIns, rc,
150 N_("Configuration error: Failed to read \"CpuHotplug\""));
151
152 if (fCpuHotplug)
153 {
154 pbAmlCode = AmlCodeCpuHotplug;
155 cbAmlCode = sizeof(AmlCodeCpuHotplug);
156 }
157 else
158 {
159 pbAmlCode = AmlCode;
160 cbAmlCode = sizeof(AmlCode);
161 }
162
163 patchAml(pDevIns, pbAmlCode, cbAmlCode);
164 *ppPtr = pbAmlCode;
165 *puDsdtLen = cbAmlCode;
166 return 0;
167#endif
168}
169
170int acpiCleanupDsdt(PPDMDEVINS pDevIns, void * pPtr)
171{
172#ifdef VBOX_WITH_DYNAMIC_DSDT
173 return cleanupDynamicDsdt(pDevIns, pPtr);
174#else
175 /* Do nothing */
176 return 0;
177#endif
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