VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/DevACPI.cpp@ 12428

最後變更 在這個檔案從12428是 12428,由 vboxsync 提交於 17 年 前

more SMP work

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 67.6 KB
 
1/* $Id: DevACPI.cpp 12428 2008-09-12 15:08:00Z vboxsync $ */
2/** @file
3 * DevACPI - Advanced Configuration and Power Interface (ACPI) Device.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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#define LOG_GROUP LOG_GROUP_DEV_ACPI
23#include <VBox/pdmdev.h>
24#include <VBox/log.h>
25#include <iprt/assert.h>
26#include <iprt/asm.h>
27#ifdef IN_RING3
28# include <iprt/alloc.h>
29# include <iprt/string.h>
30#endif /* IN_RING3 */
31
32#include "../Builtins.h"
33
34#ifdef LOG_ENABLED
35# define DEBUG_ACPI
36#endif
37
38/* the compiled DSL */
39#if defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
40#include <vboxaml.hex>
41#endif /* !IN_RING3 */
42
43#define IO_READ_PROTO(name) \
44 PDMBOTHCBDECL(int) name (PPDMDEVINS pDevIns, void *pvUser, \
45 RTIOPORT Port, uint32_t *pu32, unsigned cb)
46
47#define IO_WRITE_PROTO(name) \
48 PDMBOTHCBDECL(int) name (PPDMDEVINS pDevIns, void *pvUser, \
49 RTIOPORT Port, uint32_t u32, unsigned cb)
50
51#define DEBUG_HEX 0x3000
52#define DEBUG_CHR 0x3001
53
54#define PM_TMR_FREQ 3579545
55#define PM1a_EVT_BLK 0x00004000
56#define PM1b_EVT_BLK 0x00000000 /**< not supported */
57#define PM1a_CTL_BLK 0x00004004
58#define PM1b_CTL_BLK 0x00000000 /**< not supported */
59#define PM2_CTL_BLK 0x00000000 /**< not supported */
60#define PM_TMR_BLK 0x00004008
61#define GPE0_BLK 0x00004020
62#define GPE1_BLK 0x00000000 /**< not supported */
63#define BAT_INDEX 0x00004040
64#define BAT_DATA 0x00004044
65#define SYSI_INDEX 0x00004048
66#define SYSI_DATA 0x0000404c
67#define ACPI_RESET_BLK 0x00004050
68#define FDC_STATUS 0x00004054
69
70/* PM1x status register bits */
71#define TMR_STS RT_BIT(0)
72#define RSR1_STS (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
73#define BM_STS RT_BIT(4)
74#define GBL_STS RT_BIT(5)
75#define RSR2_STS (RT_BIT(6) | RT_BIT(7))
76#define PWRBTN_STS RT_BIT(8)
77#define SLPBTN_STS RT_BIT(9)
78#define RTC_STS RT_BIT(10)
79#define IGN_STS RT_BIT(11)
80#define RSR3_STS (RT_BIT(12) | RT_BIT(13) | RT_BIT(14))
81#define WAK_STS RT_BIT(15)
82#define RSR_STS (RSR1_STS | RSR2_STS | RSR3_STS)
83
84/* PM1x enable register bits */
85#define TMR_EN RT_BIT(0)
86#define RSR1_EN (RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
87#define GBL_EN RT_BIT(5)
88#define RSR2_EN (RT_BIT(6) | RT_BIT(7))
89#define PWRBTN_EN RT_BIT(8)
90#define SLPBTN_EN RT_BIT(9)
91#define RTC_EN RT_BIT(10)
92#define RSR3_EN (RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14) | RT_BIT(15))
93#define RSR_EN (RSR1_EN | RSR2_EN | RSR3_EN)
94#define IGN_EN 0
95
96/* PM1x control register bits */
97#define SCI_EN RT_BIT(0)
98#define BM_RLD RT_BIT(1)
99#define GBL_RLS RT_BIT(2)
100#define RSR1_CNT (RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8))
101#define IGN_CNT RT_BIT(9)
102#define SLP_TYPx_SHIFT 10
103#define SLP_TYPx_MASK 7
104#define SLP_EN RT_BIT(13)
105#define RSR2_CNT (RT_BIT(14) | RT_BIT(15))
106#define RSR_CNT (RSR1_CNT | RSR2_CNT)
107
108#define GPE0_BATTERY_INFO_CHANGED RT_BIT(0)
109
110enum
111{
112 BAT_STATUS_STATE = 0x00, /**< BST battery state */
113 BAT_STATUS_PRESENT_RATE = 0x01, /**< BST battery present rate */
114 BAT_STATUS_REMAINING_CAPACITY = 0x02, /**< BST battery remaining capacity */
115 BAT_STATUS_PRESENT_VOLTAGE = 0x03, /**< BST battery present voltage */
116 BAT_INFO_UNITS = 0x04, /**< BIF power unit */
117 BAT_INFO_DESIGN_CAPACITY = 0x05, /**< BIF design capacity */
118 BAT_INFO_LAST_FULL_CHARGE_CAPACITY = 0x06, /**< BIF last full charge capacity */
119 BAT_INFO_TECHNOLOGY = 0x07, /**< BIF battery technology */
120 BAT_INFO_DESIGN_VOLTAGE = 0x08, /**< BIF design voltage */
121 BAT_INFO_DESIGN_CAPACITY_OF_WARNING = 0x09, /**< BIF design capacity of warning */
122 BAT_INFO_DESIGN_CAPACITY_OF_LOW = 0x0A, /**< BIF design capacity of low */
123 BAT_INFO_CAPACITY_GRANULARITY_1 = 0x0B, /**< BIF battery capacity granularity 1 */
124 BAT_INFO_CAPACITY_GRANULARITY_2 = 0x0C, /**< BIF battery capacity granularity 2 */
125 BAT_DEVICE_STATUS = 0x0D, /**< STA device status */
126 BAT_POWER_SOURCE = 0x0E, /**< PSR power source */
127 BAT_INDEX_LAST
128};
129
130enum
131{
132 SYSTEM_INFO_INDEX_MEMORY_LENGTH = 0,
133 SYSTEM_INFO_INDEX_USE_IOAPIC = 1,
134 SYSTEM_INFO_INDEX_LAST = 2,
135 SYSTEM_INFO_INDEX_INVALID = 0x80,
136 SYSTEM_INFO_INDEX_VALID = 0x200
137};
138
139#define AC_OFFLINE 0
140#define AC_ONLINE 1
141
142#define BAT_TECH_PRIMARY 1
143#define BAT_TECH_SECONDARY 2
144
145#define BAT_STATUS_DISCHARGING_MASK RT_BIT(0)
146#define BAT_STATUS_CHARGING_MASK RT_BIT(1)
147#define BAT_STATUS_CRITICAL_MASK RT_BIT(2)
148
149#define STA_DEVICE_PRESENT_MASK RT_BIT(0)
150#define STA_DEVICE_ENABLED_MASK RT_BIT(1)
151#define STA_DEVICE_SHOW_IN_UI_MASK RT_BIT(2)
152#define STA_DEVICE_FUNCTIONING_PROPERLY_MASK RT_BIT(3)
153#define STA_BATTERY_PRESENT_MASK RT_BIT(4)
154
155struct ACPIState
156{
157 PCIDevice dev;
158 uint16_t pm1a_en;
159 uint16_t pm1a_sts;
160 uint16_t pm1a_ctl;
161 /** Number of logical CPUs in guest */
162 uint16_t cCpus;
163 int64_t pm_timer_initial;
164 PTMTIMERR3 tsR3;
165 PTMTIMERR0 tsR0;
166 PTMTIMERRC tsRC;
167
168 uint32_t gpe0_en;
169 uint32_t gpe0_sts;
170
171 unsigned int uBatteryIndex;
172 uint32_t au8BatteryInfo[13];
173
174 unsigned int uSystemInfoIndex;
175 uint64_t u64RamSize;
176
177 /** Current ACPI S* state. We support S0 and S5 */
178 uint32_t uSleepState;
179 uint8_t au8RSDPPage[0x1000];
180 /** This is a workaround for incorrect index field handling by Intels ACPICA.
181 * The system info _INI method writes to offset 0x200. We either observe a
182 * write request to index 0x80 (in that case we don't change the index) or a
183 * write request to offset 0x200 (in that case we divide the index value by
184 * 4. Note that the _STA method is sometimes called prior to the _INI method
185 * (ACPI spec 6.3.7, _STA). See the special case for BAT_DEVICE_STATUS in
186 * acpiBatIndexWrite() for handling this. */
187 uint8_t u8IndexShift;
188 uint8_t u8UseIOApic;
189 uint8_t u8UseFdc;
190 bool fPowerButtonHandled;
191
192 /** ACPI port base interface. */
193 PDMIBASE IBase;
194 /** ACPI port interface. */
195 PDMIACPIPORT IACPIPort;
196 /** Pointer to the device instance. */
197 PPDMDEVINSR3 pDevIns;
198 /** Pointer to the driver base interface */
199 R3PTRTYPE(PPDMIBASE) pDrvBase;
200 /** Pointer to the driver connector interface */
201 R3PTRTYPE(PPDMIACPICONNECTOR) pDrv;
202};
203
204#pragma pack(1)
205
206/** Generic Address Structure (see ACPIspec 3.0, 5.2.3.1) */
207struct ACPIGENADDR
208{
209 uint8_t u8AddressSpaceId; /**< 0=sys, 1=IO, 2=PCICfg, 3=emb, 4=SMBus */
210 uint8_t u8RegisterBitWidth; /**< size in bits of the given register */
211 uint8_t u8RegisterBitOffset; /**< bit offset of register */
212 uint8_t u8AccessSize; /**< 1=byte, 2=word, 3=dword, 4=qword */
213 uint64_t u64Address; /**< 64-bit address of register */
214};
215AssertCompileSize(ACPIGENADDR, 12);
216
217/** Root System Description Pointer */
218struct ACPITBLRSDP
219{
220 uint8_t au8Signature[8]; /**< 'RSD PTR ' */
221 uint8_t u8Checksum; /**< checksum for the first 20 bytes */
222 uint8_t au8OemId[6]; /**< OEM-supplied identifier */
223 uint8_t u8Revision; /**< revision number, currently 2 */
224#define ACPI_REVISION 2 /**< ACPI 3.0 */
225 uint32_t u32RSDT; /**< phys addr of RSDT */
226 uint32_t u32Length; /**< bytes of this table */
227 uint64_t u64XSDT; /**< 64-bit phys addr of XSDT */
228 uint8_t u8ExtChecksum; /**< checksum of entire table */
229 uint8_t u8Reserved[3]; /**< reserved */
230};
231AssertCompileSize(ACPITBLRSDP, 36);
232
233/** System Description Table Header */
234struct ACPITBLHEADER
235{
236 uint8_t au8Signature[4]; /**< table identifier */
237 uint32_t u32Length; /**< length of the table including header */
238 uint8_t u8Revision; /**< revision number */
239 uint8_t u8Checksum; /**< all fields inclusive this add to zero */
240 uint8_t au8OemId[6]; /**< OEM-supplied string */
241 uint8_t au8OemTabId[8]; /**< to identify the particular data table */
242 uint32_t u32OemRevision; /**< OEM-supplied revision number */
243 uint8_t au8CreatorId[4]; /**< ID for the ASL compiler */
244 uint32_t u32CreatorRev; /**< revision for the ASL compiler */
245};
246AssertCompileSize(ACPITBLHEADER, 36);
247
248/** Root System Description Table */
249struct ACPITBLRSDT
250{
251 ACPITBLHEADER header;
252 uint32_t u32Entry[1]; /**< array of phys. addresses to other tables */
253};
254AssertCompileSize(ACPITBLRSDT, 40);
255
256/** Extended System Description Table */
257struct ACPITBLXSDT
258{
259 ACPITBLHEADER header;
260 uint64_t u64Entry[1]; /**< array of phys. addresses to other tables */
261};
262AssertCompileSize(ACPITBLXSDT, 44);
263
264/** Fixed ACPI Description Table */
265struct ACPITBLFADT
266{
267 ACPITBLHEADER header;
268 uint32_t u32FACS; /**< phys. address of FACS */
269 uint32_t u32DSDT; /**< phys. address of DSDT */
270 uint8_t u8IntModel; /**< was eleminated in ACPI 2.0 */
271#define INT_MODEL_DUAL_PIC 1 /**< for ACPI 2+ */
272#define INT_MODEL_MULTIPLE_APIC 2
273 uint8_t u8PreferredPMProfile; /**< preferred power management profile */
274 uint16_t u16SCIInt; /**< system vector the SCI is wired in 8259 mode */
275#define SCI_INT 9
276 uint32_t u32SMICmd; /**< system port address of SMI command port */
277#define SMI_CMD 0x0000442e
278 uint8_t u8AcpiEnable; /**< SMICmd val to disable ownship of ACPIregs */
279#define ACPI_ENABLE 0xa1
280 uint8_t u8AcpiDisable; /**< SMICmd val to re-enable ownship of ACPIregs */
281#define ACPI_DISABLE 0xa0
282 uint8_t u8S4BIOSReq; /**< SMICmd val to enter S4BIOS state */
283 uint8_t u8PStateCnt; /**< SMICmd val to assume processor performance
284 state control responsibility */
285 uint32_t u32PM1aEVTBLK; /**< port addr of PM1a event regs block */
286 uint32_t u32PM1bEVTBLK; /**< port addr of PM1b event regs block */
287 uint32_t u32PM1aCTLBLK; /**< port addr of PM1a control regs block */
288 uint32_t u32PM1bCTLBLK; /**< port addr of PM1b control regs block */
289 uint32_t u32PM2CTLBLK; /**< port addr of PM2 control regs block */
290 uint32_t u32PMTMRBLK; /**< port addr of PMTMR regs block */
291 uint32_t u32GPE0BLK; /**< port addr of gen-purp event 0 regs block */
292 uint32_t u32GPE1BLK; /**< port addr of gen-purp event 1 regs block */
293 uint8_t u8PM1EVTLEN; /**< bytes decoded by PM1a_EVT_BLK. >= 4 */
294 uint8_t u8PM1CTLLEN; /**< bytes decoded by PM1b_CNT_BLK. >= 2 */
295 uint8_t u8PM2CTLLEN; /**< bytes decoded by PM2_CNT_BLK. >= 1 or 0 */
296 uint8_t u8PMTMLEN; /**< bytes decoded by PM_TMR_BLK. ==4 */
297 uint8_t u8GPE0BLKLEN; /**< bytes decoded by GPE0_BLK. %2==0 */
298#define GPE0_BLK_LEN 2
299 uint8_t u8GPE1BLKLEN; /**< bytes decoded by GPE1_BLK. %2==0 */
300#define GPE1_BLK_LEN 0
301 uint8_t u8GPE1BASE; /**< offset of GPE1 based events */
302#define GPE1_BASE 0
303 uint8_t u8CSTCNT; /**< SMICmd val to indicate OS supp for C states */
304 uint16_t u16PLVL2LAT; /**< us to enter/exit C2. >100 => unsupported */
305#define P_LVL2_LAT 101 /**< C2 state not supported */
306 uint16_t u16PLVL3LAT; /**< us to enter/exit C3. >1000 => unsupported */
307#define P_LVL3_LAT 1001 /**< C3 state not supported */
308 uint16_t u16FlushSize; /**< # of flush strides to read to flush dirty
309 lines from any processors memory caches */
310#define FLUSH_SIZE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
311 uint16_t u16FlushStride; /**< cache line width */
312#define FLUSH_STRIDE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
313 uint8_t u8DutyOffset;
314 uint8_t u8DutyWidth;
315 uint8_t u8DayAlarm; /**< RTC CMOS RAM index of day-of-month alarm */
316 uint8_t u8MonAlarm; /**< RTC CMOS RAM index of month-of-year alarm */
317 uint8_t u8Century; /**< RTC CMOS RAM index of century */
318 uint16_t u16IAPCBOOTARCH; /**< IA-PC boot architecture flags */
319#define IAPC_BOOT_ARCH_LEGACY_DEV RT_BIT(0) /**< legacy devices present such as LPT
320 (COM too?) */
321#define IAPC_BOOT_ARCH_8042 RT_BIT(1) /**< legacy keyboard device present */
322#define IAPC_BOOT_ARCH_NO_VGA RT_BIT(2) /**< VGA not present */
323 uint8_t u8Must0_0; /**< must be 0 */
324 uint32_t u32Flags; /**< fixed feature flags */
325#define FADT_FL_WBINVD RT_BIT(0) /**< emulation of WBINVD available */
326#define FADT_FL_WBINVD_FLUSH RT_BIT(1)
327#define FADT_FL_PROC_C1 RT_BIT(2) /**< 1=C1 supported on all processors */
328#define FADT_FL_P_LVL2_UP RT_BIT(3) /**< 1=C2 works on SMP and UNI systems */
329#define FADT_FL_PWR_BUTTON RT_BIT(4) /**< 1=power button handled as ctrl method dev */
330#define FADT_FL_SLP_BUTTON RT_BIT(5) /**< 1=sleep button handled as ctrl method dev */
331#define FADT_FL_FIX_RTC RT_BIT(6) /**< 0=RTC wake status in fixed register */
332#define FADT_FL_RTC_S4 RT_BIT(7) /**< 1=RTC can wake system from S4 */
333#define FADT_FL_TMR_VAL_EXT RT_BIT(8) /**< 1=TMR_VAL implemented as 32 bit */
334#define FADT_FL_DCK_CAP RT_BIT(9) /**< 0=system cannot support docking */
335#define FADT_FL_RESET_REG_SUP RT_BIT(10) /**< 1=system supports system resets */
336#define FADT_FL_SEALED_CASE RT_BIT(11) /**< 1=case is sealed */
337#define FADT_FL_HEADLESS RT_BIT(12) /**< 1=system cannot detect moni/keyb/mouse */
338#define FADT_FL_CPU_SW_SLP RT_BIT(13)
339#define FADT_FL_PCI_EXT_WAK RT_BIT(14) /**< 1=system supports PCIEXP_WAKE_STS */
340#define FADT_FL_USE_PLATFORM_CLOCK RT_BIT(15) /**< 1=system has ACPI PM timer */
341#define FADT_FL_S4_RTC_STS_VALID RT_BIT(16) /**< 1=RTC_STS flag is valid when waking from S4 */
342#define FADT_FL_REMOVE_POWER_ON_CAPABLE RT_BIT(17) /**< 1=platform can remote power on */
343#define FADT_FL_FORCE_APIC_CLUSTER_MODEL RT_BIT(18)
344#define FADT_FL_FORCE_APIC_PHYS_DEST_MODE RT_BIT(19)
345 ACPIGENADDR ResetReg; /**< ext addr of reset register */
346 uint8_t u8ResetVal; /**< ResetReg value to reset the system */
347#define ACPI_RESET_REG_VAL 0x10
348 uint8_t au8Must0_1[3]; /**< must be 0 */
349 uint64_t u64XFACS; /**< 64-bit phys address of FACS */
350 uint64_t u64XDSDT; /**< 64-bit phys address of DSDT */
351 ACPIGENADDR X_PM1aEVTBLK; /**< ext addr of PM1a event regs block */
352 ACPIGENADDR X_PM1bEVTBLK; /**< ext addr of PM1b event regs block */
353 ACPIGENADDR X_PM1aCTLBLK; /**< ext addr of PM1a control regs block */
354 ACPIGENADDR X_PM1bCTLBLK; /**< ext addr of PM1b control regs block */
355 ACPIGENADDR X_PM2CTLBLK; /**< ext addr of PM2 control regs block */
356 ACPIGENADDR X_PMTMRBLK; /**< ext addr of PMTMR control regs block */
357 ACPIGENADDR X_GPE0BLK; /**< ext addr of GPE1 regs block */
358 ACPIGENADDR X_GPE1BLK; /**< ext addr of GPE1 regs block */
359};
360AssertCompileSize(ACPITBLFADT, 244);
361
362/** Firmware ACPI Control Structure */
363struct ACPITBLFACS
364{
365 uint8_t au8Signature[4]; /**< 'FACS' */
366 uint32_t u32Length; /**< bytes of entire FACS structure >= 64 */
367 uint32_t u32HWSignature; /**< systems HW signature at last boot */
368 uint32_t u32FWVector; /**< address of waking vector */
369 uint32_t u32GlobalLock; /**< global lock to sync HW/SW */
370 uint32_t u32Flags; /**< FACS flags */
371 uint64_t u64X_FWVector; /**< 64-bit waking vector */
372 uint8_t u8Version; /**< version of this table */
373 uint8_t au8Reserved[31]; /**< zero */
374};
375AssertCompileSize(ACPITBLFACS, 64);
376
377/** Processor Local APIC Structure */
378struct ACPITBLLAPIC
379{
380 uint8_t u8Type; /**< 0 = LAPIC */
381 uint8_t u8Length; /**< 8 */
382 uint8_t u8ProcId; /**< processor ID */
383 uint8_t u8ApicId; /**< local APIC ID */
384 uint32_t u32Flags; /**< Flags */
385#define LAPIC_ENABLED 0x1
386};
387AssertCompileSize(ACPITBLLAPIC, 8);
388
389/** I/O APIC Structure */
390struct ACPITBLIOAPIC
391{
392 uint8_t u8Type; /**< 1 == I/O APIC */
393 uint8_t u8Length; /**< 12 */
394 uint8_t u8IOApicId; /**< I/O APIC ID */
395 uint8_t u8Reserved; /**< 0 */
396 uint32_t u32Address; /**< phys address to access I/O APIC */
397 uint32_t u32GSIB; /**< global system interrupt number to start */
398};
399AssertCompileSize(ACPITBLIOAPIC, 12);
400
401/** Multiple APIC Description Table */
402#ifdef VBOX_WITH_SMP_GUESTS
403
404#define PCAT_COMPAT 0x1 /**< system has also a dual-8259 setup */
405
406/*
407 * This structure looks somewhat convoluted due layout of MADT table in MP case.
408 * There extpected to be multiple LAPIC records for each CPU, thus we cannot
409 * use regular C structure and proxy to raw memory instead.
410 */
411class ACPITBLMADT
412{
413 /*
414 * All actual data stored in dynamically allocated memory pointed by this field.
415 */
416 uint8_t* pData;
417 /*
418 * Number of CPU entries in this MADT.
419 */
420 uint32_t cCpus;
421
422 public:
423 /*
424 * Address of ACPI header
425 */
426 inline ACPITBLHEADER* header_addr() const
427 {
428 return (ACPITBLHEADER*)pData;
429 }
430
431 /*
432 * Address of local APIC for each CPU. Note that different CPUs address different LAPICs,
433 * although address is the same for all of them.
434 */
435 inline uint32_t* u32LAPIC_addr() const
436 {
437 return (uint32_t*)(header_addr() + 1);
438 }
439
440 /*
441 * Address of APIC flags
442 */
443 inline uint32_t* u32Flags_addr() const
444 {
445 return (uint32_t*)(u32LAPIC_addr() + 1);
446 }
447
448 /*
449 * Address of per-CPU LAPIC descriptions
450 */
451 inline ACPITBLLAPIC* LApics_addr() const
452 {
453 return (ACPITBLLAPIC*)(u32Flags_addr() + 1);
454 }
455
456 /*
457 * Address of IO APIC description
458 */
459 inline ACPITBLIOAPIC* IOApic_addr() const
460 {
461 return (ACPITBLIOAPIC*)(LApics_addr() + cCpus);
462 }
463
464 /*
465 * Size of MADT.
466 * Note that this function assumes IOApic to be the last field in structure.
467 */
468 inline uint32_t size() const
469 {
470 return (uint8_t*)(IOApic_addr() + 1)-(uint8_t*)header_addr();
471 }
472
473 /*
474 * Raw data of MADT.
475 */
476 inline const uint8_t* data() const
477 {
478 return pData;
479 }
480
481 /*
482 * Size of MADT for given ACPI config, useful to compute layout.
483 */
484 static uint32_t sizeFor(ACPIState *s)
485 {
486 return ACPITBLMADT(s->cCpus).size();
487 }
488
489 /*
490 * Constructor, only works in Ring 3, doesn't look like a big deal.
491 */
492 ACPITBLMADT(uint16_t cpus)
493 {
494 cCpus = cpus;
495 pData = 0;
496#ifdef IN_RING3
497 uint32_t sSize = size();
498 pData = (uint8_t*)RTMemAllocZ(sSize);
499#else
500 AssertMsgFailed(("cannot use in inner rings"));
501#endif
502 }
503
504 ~ACPITBLMADT()
505 {
506#ifdef IN_RING3
507 RTMemFree(pData);
508#else
509 AssertMsgFailed(("cannot use in inner rings"));
510#endif
511 }
512};
513#else
514struct ACPITBLMADT
515{
516 ACPITBLHEADER header;
517 uint32_t u32LAPIC; /**< local APIC address */
518 uint32_t u32Flags; /**< Flags */
519#define PCAT_COMPAT 0x1 /**< system has also a dual-8259 setup */
520 ACPITBLLAPIC LApic;
521 ACPITBLIOAPIC IOApic;
522};
523AssertCompileSize(ACPITBLMADT, 64);
524#endif
525
526#pragma pack()
527
528
529#ifndef VBOX_DEVICE_STRUCT_TESTCASE
530__BEGIN_DECLS
531IO_READ_PROTO (acpiPMTmrRead);
532#ifdef IN_RING3
533IO_READ_PROTO (acpiPm1aEnRead);
534IO_WRITE_PROTO (acpiPM1aEnWrite);
535IO_READ_PROTO (acpiPm1aStsRead);
536IO_WRITE_PROTO (acpiPM1aStsWrite);
537IO_READ_PROTO (acpiPm1aCtlRead);
538IO_WRITE_PROTO (acpiPM1aCtlWrite);
539IO_WRITE_PROTO (acpiSmiWrite);
540IO_WRITE_PROTO (acpiBatIndexWrite);
541IO_READ_PROTO (acpiBatDataRead);
542IO_READ_PROTO (acpiFdcStatusRead);
543IO_READ_PROTO (acpiSysInfoDataRead);
544IO_WRITE_PROTO (acpiSysInfoDataWrite);
545IO_READ_PROTO (acpiGpe0EnRead);
546IO_WRITE_PROTO (acpiGpe0EnWrite);
547IO_READ_PROTO (acpiGpe0StsRead);
548IO_WRITE_PROTO (acpiGpe0StsWrite);
549IO_WRITE_PROTO (acpiResetWrite);
550# ifdef DEBUG_ACPI
551IO_WRITE_PROTO (acpiDhexWrite);
552IO_WRITE_PROTO (acpiDchrWrite);
553# endif
554#endif
555__END_DECLS
556
557#ifdef IN_RING3
558
559/* Simple acpiChecksum: all the bytes must add up to 0. */
560static uint8_t acpiChecksum (const uint8_t * const data, uint32_t len)
561{
562 uint8_t sum = 0;
563 for (size_t i = 0; i < len; ++i)
564 sum += data[i];
565 return -sum;
566}
567
568static void acpiPrepareHeader (ACPITBLHEADER *header, const char au8Signature[4],
569 uint32_t u32Length, uint8_t u8Revision)
570{
571 memcpy(header->au8Signature, au8Signature, 4);
572 header->u32Length = RT_H2LE_U32(u32Length);
573 header->u8Revision = u8Revision;
574 memcpy(header->au8OemId, "VBOX ", 6);
575 memcpy(header->au8OemTabId, "VBOX", 4);
576 memcpy(header->au8OemTabId+4, au8Signature, 4);
577 header->u32OemRevision = RT_H2LE_U32(1);
578 memcpy(header->au8CreatorId, "ASL ", 4);
579 header->u32CreatorRev = RT_H2LE_U32(0x61);
580}
581
582static void acpiWriteGenericAddr(ACPIGENADDR *g, uint8_t u8AddressSpaceId,
583 uint8_t u8RegisterBitWidth, uint8_t u8RegisterBitOffset,
584 uint8_t u8AccessSize, uint64_t u64Address)
585{
586 g->u8AddressSpaceId = u8AddressSpaceId;
587 g->u8RegisterBitWidth = u8RegisterBitWidth;
588 g->u8RegisterBitOffset = u8RegisterBitOffset;
589 g->u8AccessSize = u8AccessSize;
590 g->u64Address = RT_H2LE_U64(u64Address);
591}
592
593static void acpiPhyscpy (ACPIState *s, RTGCPHYS32 dst, const void * const src, size_t size)
594{
595 PDMDevHlpPhysWrite (s->pDevIns, dst, src, size);
596}
597
598/* Differentiated System Description Table (DSDT) */
599static void acpiSetupDSDT (ACPIState *s, RTGCPHYS32 addr)
600{
601 acpiPhyscpy (s, addr, AmlCode, sizeof(AmlCode));
602}
603
604/* Firmware ACPI Control Structure (FACS) */
605static void acpiSetupFACS (ACPIState *s, RTGCPHYS32 addr)
606{
607 ACPITBLFACS facs;
608
609 memset (&facs, 0, sizeof(facs));
610 memcpy (facs.au8Signature, "FACS", 4);
611 facs.u32Length = RT_H2LE_U32(sizeof(ACPITBLFACS));
612 facs.u32HWSignature = RT_H2LE_U32(0);
613 facs.u32FWVector = RT_H2LE_U32(0);
614 facs.u32GlobalLock = RT_H2LE_U32(0);
615 facs.u32Flags = RT_H2LE_U32(0);
616 facs.u64X_FWVector = RT_H2LE_U64(0);
617 facs.u8Version = 1;
618
619 acpiPhyscpy (s, addr, (const uint8_t*)&facs, sizeof(facs));
620}
621
622/* Fixed ACPI Description Table (FADT aka FACP) */
623static void acpiSetupFADT (ACPIState *s, RTGCPHYS32 addr, uint32_t facs_addr, uint32_t dsdt_addr)
624{
625 ACPITBLFADT fadt;
626
627 memset (&fadt, 0, sizeof(fadt));
628 acpiPrepareHeader (&fadt.header, "FACP", sizeof(fadt), 4);
629 fadt.u32FACS = RT_H2LE_U32(facs_addr);
630 fadt.u32DSDT = RT_H2LE_U32(dsdt_addr);
631 fadt.u8IntModel = INT_MODEL_DUAL_PIC;
632 fadt.u8PreferredPMProfile = 0; /* unspecified */
633 fadt.u16SCIInt = RT_H2LE_U16(SCI_INT);
634 fadt.u32SMICmd = RT_H2LE_U32(SMI_CMD);
635 fadt.u8AcpiEnable = ACPI_ENABLE;
636 fadt.u8AcpiDisable = ACPI_DISABLE;
637 fadt.u8S4BIOSReq = 0;
638 fadt.u8PStateCnt = 0;
639 fadt.u32PM1aEVTBLK = RT_H2LE_U32(PM1a_EVT_BLK);
640 fadt.u32PM1bEVTBLK = RT_H2LE_U32(PM1b_EVT_BLK);
641 fadt.u32PM1aCTLBLK = RT_H2LE_U32(PM1a_CTL_BLK);
642 fadt.u32PM1bCTLBLK = RT_H2LE_U32(PM1b_CTL_BLK);
643 fadt.u32PM2CTLBLK = RT_H2LE_U32(PM2_CTL_BLK);
644 fadt.u32PMTMRBLK = RT_H2LE_U32(PM_TMR_BLK);
645 fadt.u32GPE0BLK = RT_H2LE_U32(GPE0_BLK);
646 fadt.u32GPE1BLK = RT_H2LE_U32(GPE1_BLK);
647 fadt.u8PM1EVTLEN = 4;
648 fadt.u8PM1CTLLEN = 2;
649 fadt.u8PM2CTLLEN = 0;
650 fadt.u8PMTMLEN = 4;
651 fadt.u8GPE0BLKLEN = GPE0_BLK_LEN;
652 fadt.u8GPE1BLKLEN = GPE1_BLK_LEN;
653 fadt.u8GPE1BASE = GPE1_BASE;
654 fadt.u8CSTCNT = 0;
655 fadt.u16PLVL2LAT = RT_H2LE_U16(P_LVL2_LAT);
656 fadt.u16PLVL3LAT = RT_H2LE_U16(P_LVL3_LAT);
657 fadt.u16FlushSize = RT_H2LE_U16(FLUSH_SIZE);
658 fadt.u16FlushStride = RT_H2LE_U16(FLUSH_STRIDE);
659 fadt.u8DutyOffset = 0;
660 fadt.u8DutyWidth = 0;
661 fadt.u8DayAlarm = 0;
662 fadt.u8MonAlarm = 0;
663 fadt.u8Century = 0;
664 fadt.u16IAPCBOOTARCH = RT_H2LE_U16(IAPC_BOOT_ARCH_LEGACY_DEV | IAPC_BOOT_ARCH_8042);
665 /** @note WBINVD is required for ACPI versions newer than 1.0 */
666 fadt.u32Flags = RT_H2LE_U32( FADT_FL_WBINVD
667 | FADT_FL_FIX_RTC
668 | FADT_FL_TMR_VAL_EXT);
669 acpiWriteGenericAddr(&fadt.ResetReg, 1, 8, 0, 1, ACPI_RESET_BLK);
670 fadt.u8ResetVal = ACPI_RESET_REG_VAL;
671 fadt.u64XFACS = RT_H2LE_U64((uint64_t)facs_addr);
672 fadt.u64XDSDT = RT_H2LE_U64((uint64_t)dsdt_addr);
673 acpiWriteGenericAddr(&fadt.X_PM1aEVTBLK, 1, 32, 0, 2, PM1a_EVT_BLK);
674 acpiWriteGenericAddr(&fadt.X_PM1bEVTBLK, 0, 0, 0, 0, PM1b_EVT_BLK);
675 acpiWriteGenericAddr(&fadt.X_PM1aCTLBLK, 1, 16, 0, 2, PM1a_CTL_BLK);
676 acpiWriteGenericAddr(&fadt.X_PM1bCTLBLK, 0, 0, 0, 0, PM1b_CTL_BLK);
677 acpiWriteGenericAddr(&fadt.X_PM2CTLBLK, 0, 0, 0, 0, PM2_CTL_BLK);
678 acpiWriteGenericAddr(&fadt.X_PMTMRBLK, 1, 32, 0, 3, PM_TMR_BLK);
679 acpiWriteGenericAddr(&fadt.X_GPE0BLK, 1, 16, 0, 1, GPE0_BLK);
680 acpiWriteGenericAddr(&fadt.X_GPE1BLK, 0, 0, 0, 0, GPE1_BLK);
681 fadt.header.u8Checksum = acpiChecksum ((uint8_t*)&fadt, sizeof(fadt));
682 acpiPhyscpy (s, addr, &fadt, sizeof(fadt));
683}
684
685/*
686 * Root System Description Table.
687 * The RSDT and XSDT tables are basically identical. The only difference is 32 vs 64 bits
688 * addresses for description headers. RSDT is for ACPI 1.0. XSDT for ACPI 2.0 and up.
689 */
690static int acpiSetupRSDT (ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
691{
692 ACPITBLRSDT *rsdt;
693 const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(rsdt->u32Entry[0]);
694
695 rsdt = (ACPITBLRSDT*)RTMemAllocZ (size);
696 if (!rsdt)
697 return PDMDEV_SET_ERROR(s->pDevIns, VERR_NO_TMP_MEMORY, N_("Cannot allocate RSDT"));
698
699 acpiPrepareHeader (&rsdt->header, "RSDT", size, 1);
700 for (unsigned int i = 0; i < nb_entries; ++i)
701 {
702 rsdt->u32Entry[i] = RT_H2LE_U32(addrs[i]);
703 Log(("Setup RSDT: [%d] = %x\n", i, rsdt->u32Entry[i]));
704 }
705 rsdt->header.u8Checksum = acpiChecksum ((uint8_t*)rsdt, size);
706 acpiPhyscpy (s, addr, rsdt, size);
707 RTMemFree (rsdt);
708 return VINF_SUCCESS;
709}
710
711/* Extended System Description Table. */
712static int acpiSetupXSDT (ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
713{
714 ACPITBLXSDT *xsdt;
715 const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(xsdt->u64Entry[0]);
716
717 xsdt = (ACPITBLXSDT*)RTMemAllocZ (size);
718 if (!xsdt)
719 return VERR_NO_TMP_MEMORY;
720
721 acpiPrepareHeader (&xsdt->header, "XSDT", size, 1 /* according to ACPI 3.0 specs */);
722 for (unsigned int i = 0; i < nb_entries; ++i)
723 {
724 xsdt->u64Entry[i] = RT_H2LE_U64((uint64_t)addrs[i]);
725 Log(("Setup XSDT: [%d] = %RX64\n", i, xsdt->u64Entry[i]));
726 }
727 xsdt->header.u8Checksum = acpiChecksum ((uint8_t*)xsdt, size);
728 acpiPhyscpy (s, addr, xsdt, size);
729 RTMemFree (xsdt);
730 return VINF_SUCCESS;
731}
732
733/* Root System Description Pointer (RSDP) */
734static void acpiSetupRSDP (ACPITBLRSDP *rsdp, uint32_t rsdt_addr, uint64_t xsdt_addr)
735{
736 memset(rsdp, 0, sizeof(*rsdp));
737
738 /* ACPI 1.0 part (RSDT */
739 memcpy(rsdp->au8Signature, "RSD PTR ", 8);
740 memcpy(rsdp->au8OemId, "VBOX ", 6);
741 rsdp->u8Revision = ACPI_REVISION;
742 rsdp->u32RSDT = RT_H2LE_U32(rsdt_addr);
743 rsdp->u8Checksum = acpiChecksum((uint8_t*)rsdp, RT_OFFSETOF(ACPITBLRSDP, u32Length));
744
745 /* ACPI 2.0 part (XSDT) */
746 rsdp->u32Length = RT_H2LE_U32(sizeof(ACPITBLRSDP));
747 rsdp->u64XSDT = RT_H2LE_U64(xsdt_addr);
748 rsdp->u8ExtChecksum = acpiChecksum ((uint8_t*)rsdp, sizeof(ACPITBLRSDP));
749}
750
751/* Multiple APIC Description Table. */
752/** @todo All hardcoded, should set this up based on the actual VM config!!!!! */
753/** @note APIC without IO-APIC hangs Windows Vista therefore we setup both */
754static void acpiSetupMADT (ACPIState *s, RTGCPHYS32 addr)
755{
756#if VBOX_WITH_SMP_GUESTS
757 uint16_t cpus = s->cCpus;
758 ACPITBLMADT madt(cpus);
759
760 acpiPrepareHeader(madt.header_addr(), "APIC", madt.size(), 2);
761
762 *madt.u32LAPIC_addr() = RT_H2LE_U32(0xfee00000);
763 *madt.u32Flags_addr() = RT_H2LE_U32(PCAT_COMPAT);
764
765 ACPITBLLAPIC* lapic = madt.LApics_addr();
766 for (uint16_t i = 0; i < cpus; i++)
767 {
768 lapic->u8Type = 0;
769 lapic->u8Length = sizeof(ACPITBLLAPIC);
770 lapic->u8ProcId = i;
771 lapic->u8ApicId = i;
772 lapic->u32Flags = RT_H2LE_U32(LAPIC_ENABLED);
773 lapic++;
774 }
775
776 ACPITBLIOAPIC* ioapic = madt.IOApic_addr();
777
778 ioapic->u8Type = 1;
779 ioapic->u8Length = sizeof(ACPITBLIOAPIC);
780 ioapic->u8IOApicId = cpus;
781 ioapic->u8Reserved = 0;
782 ioapic->u32Address = RT_H2LE_U32(0xfec00000);
783 ioapic->u32GSIB = RT_H2LE_U32(0);
784
785 madt.header_addr()->u8Checksum = acpiChecksum (madt.data(), madt.size());
786 acpiPhyscpy (s, addr, madt.data(), madt.size());
787
788#else
789 ACPITBLMADT madt;
790
791 /* Don't call this function if u8UseIOApic==false! */
792 Assert(s->u8UseIOApic);
793
794 memset(&madt, 0, sizeof(madt));
795 acpiPrepareHeader(&madt.header, "APIC", sizeof(madt), 2);
796
797 madt.u32LAPIC = RT_H2LE_U32(0xfee00000);
798 madt.u32Flags = RT_H2LE_U32(PCAT_COMPAT);
799
800 madt.LApic.u8Type = 0;
801 madt.LApic.u8Length = sizeof(ACPITBLLAPIC);
802 madt.LApic.u8ProcId = 0;
803 madt.LApic.u8ApicId = 0;
804 madt.LApic.u32Flags = RT_H2LE_U32(LAPIC_ENABLED);
805
806 madt.IOApic.u8Type = 1;
807 madt.IOApic.u8Length = sizeof(ACPITBLIOAPIC);
808 madt.IOApic.u8IOApicId = 0;
809 madt.IOApic.u8Reserved = 0;
810 madt.IOApic.u32Address = RT_H2LE_U32(0xfec00000);
811 madt.IOApic.u32GSIB = RT_H2LE_U32(0);
812
813 madt.header.u8Checksum = acpiChecksum ((uint8_t*)&madt, sizeof(madt));
814 acpiPhyscpy (s, addr, &madt, sizeof(madt));
815#endif
816}
817
818/* SCI IRQ */
819DECLINLINE(void) acpiSetIrq (ACPIState *s, int level)
820{
821 if (s->pm1a_ctl & SCI_EN)
822 PDMDevHlpPCISetIrq (s->pDevIns, -1, level);
823}
824
825DECLINLINE(uint32_t) pm1a_pure_en (uint32_t en)
826{
827 return en & ~(RSR_EN | IGN_EN);
828}
829
830DECLINLINE(uint32_t) pm1a_pure_sts (uint32_t sts)
831{
832 return sts & ~(RSR_STS | IGN_STS);
833}
834
835DECLINLINE(int) pm1a_level (ACPIState *s)
836{
837 return (pm1a_pure_en (s->pm1a_en) & pm1a_pure_sts (s->pm1a_sts)) != 0;
838}
839
840DECLINLINE(int) gpe0_level (ACPIState *s)
841{
842 return (s->gpe0_en & s->gpe0_sts) != 0;
843}
844
845static void update_pm1a (ACPIState *s, uint32_t sts, uint32_t en)
846{
847 int old_level, new_level;
848
849 if (gpe0_level (s))
850 return;
851
852 old_level = pm1a_level (s);
853 new_level = (pm1a_pure_en (en) & pm1a_pure_sts (sts)) != 0;
854
855 s->pm1a_en = en;
856 s->pm1a_sts = sts;
857
858 if (new_level != old_level)
859 acpiSetIrq (s, new_level);
860}
861
862static void update_gpe0 (ACPIState *s, uint32_t sts, uint32_t en)
863{
864 int old_level, new_level;
865
866 if (pm1a_level (s))
867 return;
868
869 old_level = (s->gpe0_en & s->gpe0_sts) != 0;
870 new_level = (en & sts) != 0;
871
872 s->gpe0_en = en;
873 s->gpe0_sts = sts;
874
875 if (new_level != old_level)
876 acpiSetIrq (s, new_level);
877}
878
879static int acpiPowerDown (ACPIState *s)
880{
881 int rc = PDMDevHlpVMPowerOff(s->pDevIns);
882 if (RT_FAILURE (rc))
883 AssertMsgFailed (("Could not power down the VM. rc = %Rrc\n", rc));
884 return rc;
885}
886
887/** Converts a ACPI port interface pointer to an ACPI state pointer. */
888#define IACPIPORT_2_ACPISTATE(pInterface) ( (ACPIState*)((uintptr_t)pInterface - RT_OFFSETOF(ACPIState, IACPIPort)) )
889
890/**
891 * Send an ACPI power off event.
892 *
893 * @returns VBox status code
894 * @param pInterface Pointer to the interface structure containing the called function pointer.
895 */
896static DECLCALLBACK(int) acpiPowerButtonPress(PPDMIACPIPORT pInterface)
897{
898 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
899 s->fPowerButtonHandled = false;
900 update_pm1a (s, s->pm1a_sts | PWRBTN_STS, s->pm1a_en);
901 return VINF_SUCCESS;
902}
903
904static DECLCALLBACK(int) acpiGetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled)
905{
906 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
907 *pfHandled = s->fPowerButtonHandled;
908 return VINF_SUCCESS;
909}
910
911/**
912 * Send an ACPI sleep button event.
913 *
914 * @returns VBox status code
915 * @param pInterface Pointer to the interface structure containing the called function pointer.
916 */
917static DECLCALLBACK(int) acpiSleepButtonPress(PPDMIACPIPORT pInterface)
918{
919 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
920 update_pm1a (s, s->pm1a_sts | SLPBTN_STS, s->pm1a_en);
921 return VINF_SUCCESS;
922}
923
924/* PM1a_EVT_BLK enable */
925static uint32_t acpiPm1aEnReadw (ACPIState *s, uint32_t addr)
926{
927 uint16_t val = s->pm1a_en;
928 Log (("acpi: acpiPm1aEnReadw -> %#x\n", val));
929 return val;
930}
931
932static void acpiPM1aEnWritew (ACPIState *s, uint32_t addr, uint32_t val)
933{
934 Log (("acpi: acpiPM1aEnWritew <- %#x (%#x)\n", val, val & ~(RSR_EN | IGN_EN)));
935 val &= ~(RSR_EN | IGN_EN);
936 update_pm1a (s, s->pm1a_sts, val);
937}
938
939/* PM1a_EVT_BLK status */
940static uint32_t acpiPm1aStsReadw (ACPIState *s, uint32_t addr)
941{
942 uint16_t val = s->pm1a_sts;
943 Log (("acpi: acpiPm1aStsReadw -> %#x\n", val));
944 return val;
945}
946
947static void acpiPM1aStsWritew (ACPIState *s, uint32_t addr, uint32_t val)
948{
949 Log (("acpi: acpiPM1aStsWritew <- %#x (%#x)\n", val, val & ~(RSR_STS | IGN_STS)));
950 if (val & PWRBTN_STS)
951 s->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */
952 val = s->pm1a_sts & ~(val & ~(RSR_STS | IGN_STS));
953 update_pm1a (s, val, s->pm1a_en);
954}
955
956/* PM1a_CTL_BLK */
957static uint32_t acpiPm1aCtlReadw (ACPIState *s, uint32_t addr)
958{
959 uint16_t val = s->pm1a_ctl;
960 Log (("acpi: acpiPm1aCtlReadw -> %#x\n", val));
961 return val;
962}
963
964static int acpiPM1aCtlWritew (ACPIState *s, uint32_t addr, uint32_t val)
965{
966 uint32_t uSleepState;
967
968 Log (("acpi: acpiPM1aCtlWritew <- %#x (%#x)\n", val, val & ~(RSR_CNT | IGN_CNT)));
969 s->pm1a_ctl = val & ~(RSR_CNT | IGN_CNT);
970
971 uSleepState = (s->pm1a_ctl >> SLP_TYPx_SHIFT) & SLP_TYPx_MASK;
972 if (uSleepState != s->uSleepState)
973 {
974 s->uSleepState = uSleepState;
975 switch (uSleepState)
976 {
977 case 0x00: /* S0 */
978 break;
979 case 0x05: /* S5 */
980 LogRel (("Entering S5 (power down)\n"));
981 return acpiPowerDown (s);
982 default:
983 AssertMsgFailed (("Unknown sleep state %#x\n", uSleepState));
984 break;
985 }
986 }
987 return VINF_SUCCESS;
988}
989
990/* GPE0_BLK */
991static uint32_t acpiGpe0EnReadb (ACPIState *s, uint32_t addr)
992{
993 uint8_t val = s->gpe0_en;
994 Log (("acpi: acpiGpe0EnReadl -> %#x\n", val));
995 return val;
996}
997
998static void acpiGpe0EnWriteb (ACPIState *s, uint32_t addr, uint32_t val)
999{
1000 Log (("acpi: acpiGpe0EnWritel <- %#x\n", val));
1001 update_gpe0 (s, s->gpe0_sts, val);
1002}
1003
1004static uint32_t acpiGpe0StsReadb (ACPIState *s, uint32_t addr)
1005{
1006 uint8_t val = s->gpe0_sts;
1007 Log (("acpi: acpiGpe0StsReadl -> %#x\n", val));
1008 return val;
1009}
1010
1011static void acpiGpe0StsWriteb (ACPIState *s, uint32_t addr, uint32_t val)
1012{
1013 val = s->gpe0_sts & ~val;
1014 update_gpe0 (s, val, s->gpe0_en);
1015 Log (("acpi: acpiGpe0StsWritel <- %#x\n", val));
1016}
1017
1018static int acpiResetWriteU8(ACPIState *s, uint32_t addr, uint32_t val)
1019{
1020 int rc = VINF_SUCCESS;
1021
1022 Log(("ACPI: acpiResetWriteU8: %x %x\n", addr, val));
1023 if (val == ACPI_RESET_REG_VAL)
1024 {
1025# ifndef IN_RING3
1026 rc = VINF_IOM_HC_IOPORT_WRITE;
1027# else /* IN_RING3 */
1028 rc = PDMDevHlpVMReset(s->pDevIns);
1029# endif /* !IN_RING3 */
1030 }
1031 return rc;
1032}
1033
1034/* SMI */
1035static void acpiSmiWriteU8 (ACPIState *s, uint32_t addr, uint32_t val)
1036{
1037 Log (("acpi: acpiSmiWriteU8 %#x\n", val));
1038 if (val == ACPI_ENABLE)
1039 s->pm1a_ctl |= SCI_EN;
1040 else if (val == ACPI_DISABLE)
1041 s->pm1a_ctl &= ~SCI_EN;
1042 else
1043 Log (("acpi: acpiSmiWriteU8 %#x <- unknown value\n", val));
1044}
1045
1046static uint32_t find_rsdp_space (void)
1047{
1048 return 0xe0000;
1049}
1050
1051static void acpiPMTimerReset (ACPIState *s)
1052{
1053 uint64_t interval, freq;
1054
1055 freq = TMTimerGetFreq (s->CTX_SUFF(ts));
1056 interval = ASMMultU64ByU32DivByU32 (0xffffffff, freq, PM_TMR_FREQ);
1057 Log (("interval = %RU64\n", interval));
1058 TMTimerSet (s->CTX_SUFF(ts), TMTimerGet (s->CTX_SUFF(ts)) + interval);
1059}
1060
1061static DECLCALLBACK(void) acpiTimer (PPDMDEVINS pDevIns, PTMTIMER pTimer)
1062{
1063 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1064
1065 Log (("acpi: pm timer sts %#x (%d), en %#x (%d)\n",
1066 s->pm1a_sts, (s->pm1a_sts & TMR_STS) != 0,
1067 s->pm1a_en, (s->pm1a_en & TMR_EN) != 0));
1068
1069 update_pm1a (s, s->pm1a_sts | TMR_STS, s->pm1a_en);
1070 acpiPMTimerReset (s);
1071}
1072
1073/**
1074 * _BST method.
1075 */
1076static void acpiFetchBatteryStatus (ACPIState *s)
1077{
1078 uint32_t *p = s->au8BatteryInfo;
1079 bool fPresent; /* battery present? */
1080 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
1081 PDMACPIBATSTATE hostBatteryState; /* bitfield */
1082 uint32_t hostPresentRate; /* 0..1000 */
1083 int rc;
1084
1085 if (!s->pDrv)
1086 return;
1087 rc = s->pDrv->pfnQueryBatteryStatus (s->pDrv, &fPresent, &hostRemainingCapacity,
1088 &hostBatteryState, &hostPresentRate);
1089 AssertRC (rc);
1090
1091 /* default values */
1092 p[BAT_STATUS_STATE] = hostBatteryState;
1093 p[BAT_STATUS_PRESENT_RATE] = hostPresentRate == ~0U ? 0xFFFFFFFF
1094 : hostPresentRate * 50; /* mW */
1095 p[BAT_STATUS_REMAINING_CAPACITY] = 50000; /* mWh */
1096 p[BAT_STATUS_PRESENT_VOLTAGE] = 10000; /* mV */
1097
1098 /* did we get a valid battery state? */
1099 if (hostRemainingCapacity != PDM_ACPI_BAT_CAPACITY_UNKNOWN)
1100 p[BAT_STATUS_REMAINING_CAPACITY] = hostRemainingCapacity * 500; /* mWh */
1101 if (hostBatteryState == PDM_ACPI_BAT_STATE_CHARGED)
1102 p[BAT_STATUS_PRESENT_RATE] = 0; /* mV */
1103}
1104
1105/**
1106 * _BIF method.
1107 */
1108static void acpiFetchBatteryInfo (ACPIState *s)
1109{
1110 uint32_t *p = s->au8BatteryInfo;
1111
1112 p[BAT_INFO_UNITS] = 0; /* mWh */
1113 p[BAT_INFO_DESIGN_CAPACITY] = 50000; /* mWh */
1114 p[BAT_INFO_LAST_FULL_CHARGE_CAPACITY] = 50000; /* mWh */
1115 p[BAT_INFO_TECHNOLOGY] = BAT_TECH_PRIMARY;
1116 p[BAT_INFO_DESIGN_VOLTAGE] = 10000; /* mV */
1117 p[BAT_INFO_DESIGN_CAPACITY_OF_WARNING] = 100; /* mWh */
1118 p[BAT_INFO_DESIGN_CAPACITY_OF_LOW] = 50; /* mWh */
1119 p[BAT_INFO_CAPACITY_GRANULARITY_1] = 1; /* mWh */
1120 p[BAT_INFO_CAPACITY_GRANULARITY_2] = 1; /* mWh */
1121}
1122
1123/**
1124 * _STA method.
1125 */
1126static uint32_t acpiGetBatteryDeviceStatus (ACPIState *s)
1127{
1128 bool fPresent; /* battery present? */
1129 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
1130 PDMACPIBATSTATE hostBatteryState; /* bitfield */
1131 uint32_t hostPresentRate; /* 0..1000 */
1132 int rc;
1133
1134 if (!s->pDrv)
1135 return 0;
1136 rc = s->pDrv->pfnQueryBatteryStatus (s->pDrv, &fPresent, &hostRemainingCapacity,
1137 &hostBatteryState, &hostPresentRate);
1138 AssertRC (rc);
1139
1140 return fPresent
1141 ? STA_DEVICE_PRESENT_MASK /* present */
1142 | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */
1143 | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */
1144 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */
1145 | STA_BATTERY_PRESENT_MASK /* battery is present */
1146 : 0; /* device not present */
1147}
1148
1149static uint32_t acpiGetPowerSource (ACPIState *s)
1150{
1151 PDMACPIPOWERSOURCE ps;
1152
1153 /* query the current power source from the host driver */
1154 if (!s->pDrv)
1155 return AC_ONLINE;
1156 int rc = s->pDrv->pfnQueryPowerSource (s->pDrv, &ps);
1157 AssertRC (rc);
1158 return ps == PDM_ACPI_POWER_SOURCE_BATTERY ? AC_OFFLINE : AC_ONLINE;
1159}
1160
1161IO_WRITE_PROTO (acpiBatIndexWrite)
1162{
1163 ACPIState *s = (ACPIState *)pvUser;
1164
1165 switch (cb)
1166 {
1167 case 4:
1168 u32 >>= s->u8IndexShift;
1169 /* see comment at the declaration of u8IndexShift */
1170 if (s->u8IndexShift == 0 && u32 == (BAT_DEVICE_STATUS << 2))
1171 {
1172 s->u8IndexShift = 2;
1173 u32 >>= 2;
1174 }
1175 Assert (u32 < BAT_INDEX_LAST);
1176 s->uBatteryIndex = u32;
1177 break;
1178 default:
1179 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1180 break;
1181 }
1182 return VINF_SUCCESS;
1183}
1184
1185IO_READ_PROTO (acpiBatDataRead)
1186{
1187 ACPIState *s = (ACPIState *)pvUser;
1188
1189 switch (cb)
1190 {
1191 case 4:
1192 switch (s->uBatteryIndex)
1193 {
1194 case BAT_STATUS_STATE:
1195 acpiFetchBatteryStatus(s);
1196 case BAT_STATUS_PRESENT_RATE:
1197 case BAT_STATUS_REMAINING_CAPACITY:
1198 case BAT_STATUS_PRESENT_VOLTAGE:
1199 *pu32 = s->au8BatteryInfo[s->uBatteryIndex];
1200 break;
1201
1202 case BAT_INFO_UNITS:
1203 acpiFetchBatteryInfo(s);
1204 case BAT_INFO_DESIGN_CAPACITY:
1205 case BAT_INFO_LAST_FULL_CHARGE_CAPACITY:
1206 case BAT_INFO_TECHNOLOGY:
1207 case BAT_INFO_DESIGN_VOLTAGE:
1208 case BAT_INFO_DESIGN_CAPACITY_OF_WARNING:
1209 case BAT_INFO_DESIGN_CAPACITY_OF_LOW:
1210 case BAT_INFO_CAPACITY_GRANULARITY_1:
1211 case BAT_INFO_CAPACITY_GRANULARITY_2:
1212 *pu32 = s->au8BatteryInfo[s->uBatteryIndex];
1213 break;
1214
1215 case BAT_DEVICE_STATUS:
1216 *pu32 = acpiGetBatteryDeviceStatus(s);
1217 break;
1218
1219 case BAT_POWER_SOURCE:
1220 *pu32 = acpiGetPowerSource(s);
1221 break;
1222
1223 default:
1224 AssertMsgFailed (("Invalid battery index %d\n", s->uBatteryIndex));
1225 break;
1226 }
1227 break;
1228 default:
1229 return VERR_IOM_IOPORT_UNUSED;
1230 }
1231 return VINF_SUCCESS;
1232}
1233
1234IO_READ_PROTO (acpiFdcStatusRead)
1235{
1236 ACPIState *s = (ACPIState *)pvUser;
1237
1238 switch (cb)
1239 {
1240 case 4:
1241 *pu32 = s->u8UseFdc
1242 ? STA_DEVICE_PRESENT_MASK /* present */
1243 | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */
1244 | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */
1245 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */
1246 : 0; /* device not present */
1247 break;
1248 default:
1249 return VERR_IOM_IOPORT_UNUSED;
1250 }
1251 return VINF_SUCCESS;
1252}
1253
1254IO_WRITE_PROTO (acpiSysInfoIndexWrite)
1255{
1256 ACPIState *s = (ACPIState *)pvUser;
1257
1258 Log(("system_index = %d, %d\n", u32, u32 >> 2));
1259 switch (cb) {
1260 case 4:
1261 if (u32 == SYSTEM_INFO_INDEX_VALID || u32 == SYSTEM_INFO_INDEX_INVALID)
1262 s->uSystemInfoIndex = u32;
1263 else
1264 {
1265 u32 >>= s->u8IndexShift;
1266 Assert (u32 < SYSTEM_INFO_INDEX_LAST);
1267 s->uSystemInfoIndex = u32;
1268 }
1269 break;
1270
1271 default:
1272 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1273 break;
1274 }
1275 return VINF_SUCCESS;
1276}
1277
1278IO_READ_PROTO (acpiSysInfoDataRead)
1279{
1280 ACPIState *s = (ACPIState *)pvUser;
1281
1282 switch (cb)
1283 {
1284 case 4:
1285 switch (s->uSystemInfoIndex)
1286 {
1287 case SYSTEM_INFO_INDEX_MEMORY_LENGTH:
1288 *pu32 = s->u64RamSize;
1289 break;
1290
1291 case SYSTEM_INFO_INDEX_USE_IOAPIC:
1292 *pu32 = s->u8UseIOApic;
1293 break;
1294
1295 default:
1296 AssertMsgFailed (("Invalid system info index %d\n", s->uSystemInfoIndex));
1297 break;
1298 }
1299 break;
1300
1301 default:
1302 return VERR_IOM_IOPORT_UNUSED;
1303 }
1304
1305 Log(("index %d val %d\n", s->uSystemInfoIndex, *pu32));
1306 return VINF_SUCCESS;
1307}
1308
1309IO_WRITE_PROTO (acpiSysInfoDataWrite)
1310{
1311 ACPIState *s = (ACPIState *)pvUser;
1312
1313 Log(("addr=%#x cb=%d u32=%#x si=%#x\n", Port, cb, u32, s->uSystemInfoIndex));
1314
1315 if (cb == 4 && u32 == 0xbadc0de)
1316 {
1317 switch (s->uSystemInfoIndex)
1318 {
1319 case SYSTEM_INFO_INDEX_INVALID:
1320 s->u8IndexShift = 0;
1321 break;
1322
1323 case SYSTEM_INFO_INDEX_VALID:
1324 s->u8IndexShift = 2;
1325 break;
1326
1327 default:
1328 AssertMsgFailed(("Port=%#x cb=%d u32=%#x system_index=%#x\n",
1329 Port, cb, u32, s->uSystemInfoIndex));
1330 break;
1331 }
1332 }
1333 else
1334 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1335 return VINF_SUCCESS;
1336}
1337
1338/* IO Helpers */
1339IO_READ_PROTO (acpiPm1aEnRead)
1340{
1341 switch (cb)
1342 {
1343 case 2:
1344 *pu32 = acpiPm1aEnReadw ((ACPIState*)pvUser, Port);
1345 break;
1346 default:
1347 return VERR_IOM_IOPORT_UNUSED;
1348 }
1349 return VINF_SUCCESS;
1350}
1351
1352IO_READ_PROTO (acpiPm1aStsRead)
1353{
1354 switch (cb)
1355 {
1356 case 2:
1357 *pu32 = acpiPm1aStsReadw ((ACPIState*)pvUser, Port);
1358 break;
1359 default:
1360 return VERR_IOM_IOPORT_UNUSED;
1361 }
1362 return VINF_SUCCESS;
1363}
1364
1365IO_READ_PROTO (acpiPm1aCtlRead)
1366{
1367 switch (cb)
1368 {
1369 case 2:
1370 *pu32 = acpiPm1aCtlReadw ((ACPIState*)pvUser, Port);
1371 break;
1372 default:
1373 return VERR_IOM_IOPORT_UNUSED;
1374 }
1375 return VINF_SUCCESS;
1376}
1377
1378IO_WRITE_PROTO (acpiPM1aEnWrite)
1379{
1380 switch (cb)
1381 {
1382 case 2:
1383 acpiPM1aEnWritew ((ACPIState*)pvUser, Port, u32);
1384 break;
1385 default:
1386 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1387 break;
1388 }
1389 return VINF_SUCCESS;
1390}
1391
1392IO_WRITE_PROTO (acpiPM1aStsWrite)
1393{
1394 switch (cb)
1395 {
1396 case 2:
1397 acpiPM1aStsWritew ((ACPIState*)pvUser, Port, u32);
1398 break;
1399 default:
1400 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1401 break;
1402 }
1403 return VINF_SUCCESS;
1404}
1405
1406IO_WRITE_PROTO (acpiPM1aCtlWrite)
1407{
1408 switch (cb)
1409 {
1410 case 2:
1411 return acpiPM1aCtlWritew ((ACPIState*)pvUser, Port, u32);
1412 default:
1413 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1414 break;
1415 }
1416 return VINF_SUCCESS;
1417}
1418
1419#endif /* IN_RING3 */
1420
1421/**
1422 * PMTMR readable from host/guest.
1423 */
1424IO_READ_PROTO (acpiPMTmrRead)
1425{
1426 if (cb == 4)
1427 {
1428 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1429 int64_t now = TMTimerGet (s->CTX_SUFF(ts));
1430 int64_t elapsed = now - s->pm_timer_initial;
1431
1432 *pu32 = ASMMultU64ByU32DivByU32 (elapsed, PM_TMR_FREQ, TMTimerGetFreq (s->CTX_SUFF(ts)));
1433 Log (("acpi: acpiPMTmrRead -> %#x\n", *pu32));
1434 return VINF_SUCCESS;
1435 }
1436 return VERR_IOM_IOPORT_UNUSED;
1437}
1438
1439#ifdef IN_RING3
1440
1441IO_READ_PROTO (acpiGpe0StsRead)
1442{
1443 switch (cb)
1444 {
1445 case 1:
1446 *pu32 = acpiGpe0StsReadb ((ACPIState*)pvUser, Port);
1447 break;
1448 default:
1449 return VERR_IOM_IOPORT_UNUSED;
1450 }
1451 return VINF_SUCCESS;
1452}
1453
1454IO_READ_PROTO (acpiGpe0EnRead)
1455{
1456 switch (cb)
1457 {
1458 case 1:
1459 *pu32 = acpiGpe0EnReadb ((ACPIState*)pvUser, Port);
1460 break;
1461 default:
1462 return VERR_IOM_IOPORT_UNUSED;
1463 }
1464 return VINF_SUCCESS;
1465}
1466
1467IO_WRITE_PROTO (acpiGpe0StsWrite)
1468{
1469 switch (cb)
1470 {
1471 case 1:
1472 acpiGpe0StsWriteb ((ACPIState*)pvUser, Port, u32);
1473 break;
1474 default:
1475 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1476 break;
1477 }
1478 return VINF_SUCCESS;
1479}
1480
1481IO_WRITE_PROTO (acpiGpe0EnWrite)
1482{
1483 switch (cb)
1484 {
1485 case 1:
1486 acpiGpe0EnWriteb ((ACPIState*)pvUser, Port, u32);
1487 break;
1488 default:
1489 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1490 break;
1491 }
1492 return VINF_SUCCESS;
1493}
1494
1495IO_WRITE_PROTO (acpiSmiWrite)
1496{
1497 switch (cb)
1498 {
1499 case 1:
1500 acpiSmiWriteU8 ((ACPIState*)pvUser, Port, u32);
1501 break;
1502 default:
1503 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1504 break;
1505 }
1506 return VINF_SUCCESS;
1507}
1508
1509IO_WRITE_PROTO (acpiResetWrite)
1510{
1511 switch (cb)
1512 {
1513 case 1:
1514 return acpiResetWriteU8 ((ACPIState*)pvUser, Port, u32);
1515 default:
1516 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1517 break;
1518 }
1519 return VINF_SUCCESS;
1520}
1521
1522#ifdef DEBUG_ACPI
1523
1524IO_WRITE_PROTO (acpiDhexWrite)
1525{
1526 switch (cb)
1527 {
1528 case 1:
1529 Log (("%#x\n", u32 & 0xff));
1530 break;
1531 case 2:
1532 Log (("%#6x\n", u32 & 0xffff));
1533 case 4:
1534 Log (("%#10x\n", u32));
1535 break;
1536 default:
1537 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1538 break;
1539 }
1540 return VINF_SUCCESS;
1541}
1542
1543IO_WRITE_PROTO (acpiDchrWrite)
1544{
1545 switch (cb)
1546 {
1547 case 1:
1548 Log (("%c", u32 & 0xff));
1549 break;
1550 default:
1551 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1552 break;
1553 }
1554 return VINF_SUCCESS;
1555}
1556
1557#endif /* DEBUG_ACPI */
1558
1559
1560/**
1561 * Saved state structure description.
1562 */
1563static const SSMFIELD g_AcpiSavedStateFields[] =
1564{
1565 SSMFIELD_ENTRY (ACPIState, pm1a_en),
1566 SSMFIELD_ENTRY (ACPIState, pm1a_sts),
1567 SSMFIELD_ENTRY (ACPIState, pm1a_ctl),
1568 SSMFIELD_ENTRY (ACPIState, pm_timer_initial),
1569 SSMFIELD_ENTRY (ACPIState, gpe0_en),
1570 SSMFIELD_ENTRY (ACPIState, gpe0_sts),
1571 SSMFIELD_ENTRY (ACPIState, uBatteryIndex),
1572 SSMFIELD_ENTRY (ACPIState, uSystemInfoIndex),
1573 SSMFIELD_ENTRY (ACPIState, u64RamSize),
1574 SSMFIELD_ENTRY (ACPIState, u8IndexShift),
1575 SSMFIELD_ENTRY (ACPIState, u8UseIOApic),
1576 SSMFIELD_ENTRY (ACPIState, uSleepState),
1577 SSMFIELD_ENTRY_TERM ()
1578};
1579
1580static DECLCALLBACK(int) acpi_save_state (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1581{
1582 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1583 return SSMR3PutStruct (pSSMHandle, s, &g_AcpiSavedStateFields[0]);
1584}
1585
1586static DECLCALLBACK(int) acpi_load_state (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
1587 uint32_t u32Version)
1588{
1589 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1590 int rc;
1591
1592 if (u32Version != 4)
1593 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1594
1595 rc = SSMR3GetStruct (pSSMHandle, s, &g_AcpiSavedStateFields[0]);
1596 if (RT_SUCCESS (rc))
1597 {
1598 acpiFetchBatteryStatus (s);
1599 acpiFetchBatteryInfo (s);
1600 acpiPMTimerReset (s);
1601 }
1602 return rc;
1603}
1604
1605/**
1606 * Queries an interface to the driver.
1607 *
1608 * @returns Pointer to interface.
1609 * @returns NULL if the interface was not supported by the driver.
1610 * @param pInterface Pointer to this interface structure.
1611 * @param enmInterface The requested interface identification.
1612 * @thread Any thread.
1613 */
1614static DECLCALLBACK(void *) acpiQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
1615{
1616 ACPIState *pThis = (ACPIState*)((uintptr_t)pInterface - RT_OFFSETOF(ACPIState, IBase));
1617 switch (enmInterface)
1618 {
1619 case PDMINTERFACE_BASE:
1620 return &pThis->IBase;
1621 case PDMINTERFACE_ACPI_PORT:
1622 return &pThis->IACPIPort;
1623 default:
1624 return NULL;
1625 }
1626}
1627
1628/**
1629 * Create the ACPI tables.
1630 */
1631static int acpiPlantTables (ACPIState *s)
1632{
1633 int rc;
1634 RTGCPHYS32 rsdt_addr, xsdt_addr, fadt_addr, facs_addr, dsdt_addr, last_addr, apic_addr = 0;
1635 uint32_t addend = 0;
1636 RTGCPHYS32 rsdt_addrs[4];
1637 uint32_t cAddr;
1638 size_t rsdt_tbl_len = sizeof(ACPITBLHEADER);
1639 size_t xsdt_tbl_len = sizeof(ACPITBLHEADER);
1640
1641 cAddr = 1; /* FADT */
1642 if (s->u8UseIOApic)
1643 cAddr++; /* MADT */
1644
1645 rsdt_tbl_len += cAddr*4; /* each entry: 32 bits phys. address. */
1646 xsdt_tbl_len += cAddr*8; /* each entry: 64 bits phys. address. */
1647
1648 rc = CFGMR3QueryU64 (s->pDevIns->pCfgHandle, "RamSize", &s->u64RamSize);
1649 if (RT_FAILURE (rc))
1650 return PDMDEV_SET_ERROR(s->pDevIns, rc,
1651 N_("Configuration error: Querying "
1652 "\"RamSize\" as integer failed"));
1653
1654 if (s->u64RamSize > (0xffffffff - 0x10000))
1655 return PDMDEV_SET_ERROR(s->pDevIns, VERR_OUT_OF_RANGE,
1656 N_("Configuration error: Invalid \"RamSize\", maximum allowed "
1657 "value is 4095MB"));
1658 rsdt_addr = 0;
1659 xsdt_addr = RT_ALIGN_32 (rsdt_addr + rsdt_tbl_len, 16);
1660 fadt_addr = RT_ALIGN_32 (xsdt_addr + xsdt_tbl_len, 16);
1661 facs_addr = RT_ALIGN_32 (fadt_addr + sizeof(ACPITBLFADT), 16);
1662 if (s->u8UseIOApic)
1663 {
1664 apic_addr = RT_ALIGN_32 (facs_addr + sizeof(ACPITBLFACS), 16);
1665#ifdef VBOX_WITH_SMP_GUESTS
1666 /*
1667 * @todo r=nike maybe some refactoring needed to compute tables layout,
1668 * but as this code is executed only once it doesn't make sense to optimize much
1669 */
1670 dsdt_addr = RT_ALIGN_32 (apic_addr + ACPITBLMADT::sizeFor(s), 16);
1671#else
1672 dsdt_addr = RT_ALIGN_32 (apic_addr + sizeof(ACPITBLMADT), 16);
1673#endif
1674 }
1675 else
1676 {
1677 dsdt_addr = RT_ALIGN_32 (facs_addr + sizeof(ACPITBLFACS), 16);
1678 }
1679
1680 last_addr = RT_ALIGN_32 (dsdt_addr + sizeof(AmlCode), 16);
1681 if (last_addr > 0x10000)
1682 return PDMDEV_SET_ERROR(s->pDevIns, VERR_TOO_MUCH_DATA,
1683 N_("Error: ACPI tables > 64KB"));
1684
1685 Log(("RSDP 0x%08X\n", find_rsdp_space()));
1686 addend = (uint32_t) s->u64RamSize - 0x10000;
1687 Log(("RSDT 0x%08X XSDT 0x%08X\n", rsdt_addr + addend, xsdt_addr + addend));
1688 Log(("FACS 0x%08X FADT 0x%08X\n", facs_addr + addend, fadt_addr + addend));
1689 Log(("DSDT 0x%08X\n", dsdt_addr + addend));
1690 acpiSetupRSDP ((ACPITBLRSDP*)s->au8RSDPPage, rsdt_addr + addend, xsdt_addr + addend);
1691 acpiSetupDSDT (s, dsdt_addr + addend);
1692 acpiSetupFACS (s, facs_addr + addend);
1693 acpiSetupFADT (s, fadt_addr + addend, facs_addr + addend, dsdt_addr + addend);
1694
1695 rsdt_addrs[0] = fadt_addr + addend;
1696 if (s->u8UseIOApic)
1697 {
1698 acpiSetupMADT (s, apic_addr + addend);
1699 rsdt_addrs[1] = apic_addr + addend;
1700 }
1701
1702 rc = acpiSetupRSDT (s, rsdt_addr + addend, cAddr, rsdt_addrs);
1703 if (RT_FAILURE(rc))
1704 return rc;
1705 return acpiSetupXSDT (s, xsdt_addr + addend, cAddr, rsdt_addrs);
1706}
1707
1708/**
1709 * Construct a device instance for a VM.
1710 *
1711 * @returns VBox status.
1712 * @param pDevIns The device instance data.
1713 * If the registration structure is needed, pDevIns->pDevReg points to it.
1714 * @param iInstance Instance number. Use this to figure out which registers and such to use.
1715 * The device number is also found in pDevIns->iInstance, but since it's
1716 * likely to be freqently used PDM passes it as parameter.
1717 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
1718 * of the device instance. It's also found in pDevIns->pCfgHandle, but like
1719 * iInstance it's expected to be used a bit in this function.
1720 */
1721static DECLCALLBACK(int) acpiConstruct (PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
1722{
1723 int rc;
1724 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1725 uint32_t rsdp_addr;
1726 PCIDevice *dev;
1727 bool fGCEnabled;
1728 bool fR0Enabled;
1729
1730 /* Validate and read the configuration. */
1731 if (!CFGMR3AreValuesValid (pCfgHandle,
1732 "RamSize\0"
1733 "IOAPIC\0"
1734 "NumCPUs\0"
1735 "GCEnabled\0"
1736 "R0Enabled\0"
1737 "FdcEnabled\0"))
1738 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
1739 N_("Configuration error: Invalid config key for ACPI device"));
1740
1741 s->pDevIns = pDevIns;
1742
1743 /* query whether we are supposed to present an IOAPIC */
1744 rc = CFGMR3QueryU8 (pCfgHandle, "IOAPIC", &s->u8UseIOApic);
1745 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1746 s->u8UseIOApic = 1;
1747 else if (RT_FAILURE (rc))
1748 return PDMDEV_SET_ERROR(pDevIns, rc,
1749 N_("Configuration error: Failed to read \"IOAPIC\""));
1750
1751 rc = CFGMR3QueryU16Def(pCfgHandle, "NumCPUs", &s->cCpus, 1);
1752 if (RT_FAILURE(rc))
1753 return PDMDEV_SET_ERROR(pDevIns, rc,
1754 N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
1755
1756 /* query whether we are supposed to present an FDC controller */
1757 rc = CFGMR3QueryU8 (pCfgHandle, "FdcEnabled", &s->u8UseFdc);
1758 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1759 s->u8UseFdc = 1;
1760 else if (RT_FAILURE (rc))
1761 return PDMDEV_SET_ERROR(pDevIns, rc,
1762 N_("Configuration error: Failed to read \"FdcEnabled\""));
1763
1764 rc = CFGMR3QueryBool (pCfgHandle, "GCEnabled", &fGCEnabled);
1765 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1766 fGCEnabled = true;
1767 else if (RT_FAILURE (rc))
1768 return PDMDEV_SET_ERROR(pDevIns, rc,
1769 N_("Configuration error: Failed to read \"GCEnabled\""));
1770
1771 rc = CFGMR3QueryBool(pCfgHandle, "R0Enabled", &fR0Enabled);
1772 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1773 fR0Enabled = true;
1774 else if (RT_FAILURE(rc))
1775 return PDMDEV_SET_ERROR(pDevIns, rc,
1776 N_("configuration error: failed to read R0Enabled as boolean"));
1777
1778 /* */
1779 rsdp_addr = find_rsdp_space ();
1780 if (!rsdp_addr)
1781 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY,
1782 N_("Can not find space for RSDP. ACPI is disabled"));
1783
1784 rc = acpiPlantTables (s);
1785 if (RT_FAILURE (rc))
1786 return rc;
1787
1788 rc = PDMDevHlpROMRegister (pDevIns, rsdp_addr, 0x1000, s->au8RSDPPage, false /* fShadow */, "ACPI RSDP");
1789 if (RT_FAILURE (rc))
1790 return rc;
1791
1792#define R(addr, cnt, writer, reader, description) \
1793 do { \
1794 rc = PDMDevHlpIOPortRegister (pDevIns, addr, cnt, s, writer, reader, \
1795 NULL, NULL, description); \
1796 if (RT_FAILURE (rc)) \
1797 return rc; \
1798 } while (0)
1799#define L (GPE0_BLK_LEN / 2)
1800
1801 R (PM1a_EVT_BLK+2, 1, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable");
1802 R (PM1a_EVT_BLK, 1, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status");
1803 R (PM1a_CTL_BLK, 1, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control");
1804 R (PM_TMR_BLK, 1, NULL, acpiPMTmrRead, "ACPI PM Timer");
1805 R (SMI_CMD, 1, acpiSmiWrite, NULL, "ACPI SMI");
1806#ifdef DEBUG_ACPI
1807 R (DEBUG_HEX, 1, acpiDhexWrite, NULL, "ACPI Debug hex");
1808 R (DEBUG_CHR, 1, acpiDchrWrite, NULL, "ACPI Debug char");
1809#endif
1810 R (BAT_INDEX, 1, acpiBatIndexWrite, NULL, "ACPI Battery status index");
1811 R (BAT_DATA, 1, NULL, acpiBatDataRead, "ACPI Battery status data");
1812 R (SYSI_INDEX, 1, acpiSysInfoIndexWrite, NULL, "ACPI system info index");
1813 R (SYSI_DATA, 1, acpiSysInfoDataWrite, acpiSysInfoDataRead, "ACPI system info data");
1814 R (FDC_STATUS, 1, NULL, acpiFdcStatusRead, "ACPI FDC status index");
1815 R (GPE0_BLK + L, L, acpiGpe0EnWrite, acpiGpe0EnRead, "ACPI GPE0 Enable");
1816 R (GPE0_BLK, L, acpiGpe0StsWrite, acpiGpe0StsRead, "ACPI GPE0 Status");
1817 R (ACPI_RESET_BLK, 1, acpiResetWrite, NULL, "ACPI Reset");
1818#undef L
1819#undef R
1820
1821 /* register GC stuff */
1822 if (fGCEnabled)
1823 {
1824 rc = PDMDevHlpIOPortRegisterGC (pDevIns, PM_TMR_BLK, 1, 0, NULL, "acpiPMTmrRead",
1825 NULL, NULL, "ACPI PM Timer");
1826 AssertRCReturn(rc, rc);
1827 }
1828
1829 /* register R0 stuff */
1830 if (fR0Enabled)
1831 {
1832 rc = PDMDevHlpIOPortRegisterR0 (pDevIns, PM_TMR_BLK, 1, 0, NULL, "acpiPMTmrRead",
1833 NULL, NULL, "ACPI PM Timer");
1834 AssertRCReturn(rc, rc);
1835 }
1836
1837 rc = PDMDevHlpTMTimerCreate (pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiTimer, "ACPI Timer", &s->tsR3);
1838 if (RT_FAILURE(rc))
1839 {
1840 AssertMsgFailed(("pfnTMTimerCreate -> %Rrc\n", rc));
1841 return rc;
1842 }
1843
1844 s->tsR0 = TMTimerR0Ptr (s->tsR3);
1845 s->tsRC = TMTimerRCPtr (s->tsR3);
1846 s->pm_timer_initial = TMTimerGet (s->tsR3);
1847 acpiPMTimerReset (s);
1848
1849 dev = &s->dev;
1850 dev->config[0x00] = 0x86;
1851 dev->config[0x01] = 0x80;
1852
1853 dev->config[0x02] = 0x13;
1854 dev->config[0x03] = 0x71;
1855
1856 dev->config[0x04] = 0x01;
1857 dev->config[0x05] = 0x00;
1858
1859 dev->config[0x06] = 0x80;
1860 dev->config[0x07] = 0x02;
1861 dev->config[0x08] = 0x08;
1862 dev->config[0x09] = 0x00;
1863
1864 dev->config[0x0a] = 0x80;
1865 dev->config[0x0b] = 0x06;
1866
1867 dev->config[0x0e] = 0x80;
1868 dev->config[0x0f] = 0x00;
1869
1870#if 0 /* The ACPI controller usually has no subsystem ID. */
1871 dev->config[0x2c] = 0x86;
1872 dev->config[0x2d] = 0x80;
1873 dev->config[0x2e] = 0x00;
1874 dev->config[0x2f] = 0x00;
1875#endif
1876 dev->config[0x3c] = SCI_INT;
1877
1878 rc = PDMDevHlpPCIRegister (pDevIns, dev);
1879 if (RT_FAILURE (rc))
1880 return rc;
1881
1882 rc = PDMDevHlpSSMRegister (pDevIns, pDevIns->pDevReg->szDeviceName, iInstance, 4, sizeof(*s),
1883 NULL, acpi_save_state, NULL, NULL, acpi_load_state, NULL);
1884 if (RT_FAILURE(rc))
1885 return rc;
1886
1887 /*
1888 * Interfaces
1889 */
1890 /* IBase */
1891 s->IBase.pfnQueryInterface = acpiQueryInterface;
1892 /* IACPIPort */
1893 s->IACPIPort.pfnSleepButtonPress = acpiSleepButtonPress;
1894 s->IACPIPort.pfnPowerButtonPress = acpiPowerButtonPress;
1895 s->IACPIPort.pfnGetPowerButtonHandled = acpiGetPowerButtonHandled;
1896
1897 /*
1898 * Get the corresponding connector interface
1899 */
1900 rc = PDMDevHlpDriverAttach (pDevIns, 0, &s->IBase, &s->pDrvBase, "ACPI Driver Port");
1901 if (RT_SUCCESS (rc))
1902 {
1903 s->pDrv = (PPDMIACPICONNECTOR)s->pDrvBase->pfnQueryInterface (s->pDrvBase,
1904 PDMINTERFACE_ACPI_CONNECTOR);
1905 if (!s->pDrv)
1906 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_MISSING_INTERFACE,
1907 N_("LUN #0 doesn't have an ACPI connector interface"));
1908 }
1909 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1910 {
1911 Log (("acpi: %s/%d: warning: no driver attached to LUN #0!\n",
1912 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1913 rc = VINF_SUCCESS;
1914 }
1915 else
1916 return PDMDEV_SET_ERROR(pDevIns, rc,
1917 N_("Failed to attach LUN #0"));
1918
1919 return rc;
1920}
1921
1922/**
1923 * Relocates the GC pointer members.
1924 */
1925static DECLCALLBACK(void) acpiRelocate (PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
1926{
1927 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1928 s->tsRC = TMTimerRCPtr (s->CTX_SUFF(ts));
1929}
1930
1931static DECLCALLBACK(void) acpiReset (PPDMDEVINS pDevIns)
1932{
1933 ACPIState *s = PDMINS_2_DATA (pDevIns, ACPIState *);
1934
1935 s->pm1a_en = 0;
1936 s->pm1a_sts = 0;
1937 s->pm1a_ctl = 0;
1938 s->pm_timer_initial = TMTimerGet (s->CTX_SUFF(ts));
1939 acpiPMTimerReset(s);
1940 s->uBatteryIndex = 0;
1941 s->uSystemInfoIndex = 0;
1942 s->gpe0_en = 0;
1943 s->gpe0_sts = 0;
1944 s->uSleepState = 0;
1945
1946 acpiPlantTables(s);
1947}
1948
1949/**
1950 * The device registration structure.
1951 */
1952const PDMDEVREG g_DeviceACPI =
1953{
1954 /* u32Version */
1955 PDM_DEVREG_VERSION,
1956 /* szDeviceName */
1957 "acpi",
1958 /* szGCMod */
1959 "VBoxDDGC.gc",
1960 /* szR0Mod */
1961 "VBoxDDR0.r0",
1962 /* pszDescription */
1963 "Advanced Configuration and Power Interface",
1964 /* fFlags */
1965 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0,
1966 /* fClass */
1967 PDM_DEVREG_CLASS_ACPI,
1968 /* cMaxInstances */
1969 ~0,
1970 /* cbInstance */
1971 sizeof(ACPIState),
1972 /* pfnConstruct */
1973 acpiConstruct,
1974 /* pfnDestruct */
1975 NULL,
1976 /* pfnRelocate */
1977 acpiRelocate,
1978 /* pfnIOCtl */
1979 NULL,
1980 /* pfnPowerOn */
1981 NULL,
1982 /* pfnReset */
1983 acpiReset,
1984 /* pfnSuspend */
1985 NULL,
1986 /* pfnResume */
1987 NULL,
1988 /* pfnAttach */
1989 NULL,
1990 /* pfnDetach */
1991 NULL,
1992 /* pfnQueryInterface. */
1993 NULL
1994};
1995
1996#endif /* IN_RING3 */
1997#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
1998
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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