VirtualBox

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

Last change on this file since 35853 was 35773, checked in by vboxsync, 14 years ago

dev/acpi: fix index_end value

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 109.0 KB
Line 
1/* $Id: DevACPI.cpp 35773 2011-01-28 20:18:17Z vboxsync $ */
2/** @file
3 * DevACPI - Advanced Configuration and Power Interface (ACPI) Device.
4 */
5
6/*
7 * Copyright (C) 2006-2009 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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DEV_ACPI
22#include <VBox/vmm/pdmdev.h>
23#include <VBox/vmm/pgm.h>
24#include <VBox/log.h>
25#include <VBox/param.h>
26#include <iprt/assert.h>
27#include <iprt/asm.h>
28#include <iprt/asm-math.h>
29#ifdef IN_RING3
30# include <iprt/alloc.h>
31# include <iprt/string.h>
32# include <iprt/uuid.h>
33#endif /* IN_RING3 */
34
35#include "VBoxDD.h"
36
37#ifdef LOG_ENABLED
38# define DEBUG_ACPI
39#endif
40
41#if defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
42int acpiPrepareDsdt(PPDMDEVINS pDevIns, void* *ppPtr, size_t *puDsdtLen);
43int acpiCleanupDsdt(PPDMDEVINS pDevIns, void* pPtr);
44
45int acpiPrepareSsdt(PPDMDEVINS pDevIns, void* *ppPtr, size_t *puSsdtLen);
46int acpiCleanupSsdt(PPDMDEVINS pDevIns, void* pPtr);
47#endif /* !IN_RING3 */
48
49
50
51/*******************************************************************************
52* Defined Constants And Macros *
53*******************************************************************************/
54#define DEBUG_HEX 0x3000
55#define DEBUG_CHR 0x3001
56
57#define PM_TMR_FREQ 3579545
58/* Default base for PM PIIX4 device */
59#define PM_PORT_BASE 0x4000
60/* Port offsets in PM device */
61enum
62{
63 PM1a_EVT_OFFSET = 0x00,
64 PM1b_EVT_OFFSET = -1, /**< not supported */
65 PM1a_CTL_OFFSET = 0x04,
66 PM1b_CTL_OFFSET = -1, /**< not supported */
67 PM2_CTL_OFFSET = -1, /**< not supported */
68 PM_TMR_OFFSET = 0x08,
69 GPE0_OFFSET = 0x20,
70 GPE1_OFFSET = -1 /**< not supported */
71};
72
73#define BAT_INDEX 0x00004040
74#define BAT_DATA 0x00004044
75#define SYSI_INDEX 0x00004048
76#define SYSI_DATA 0x0000404c
77#define ACPI_RESET_BLK 0x00004050
78
79/* PM1x status register bits */
80#define TMR_STS RT_BIT(0)
81#define RSR1_STS (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
82#define BM_STS RT_BIT(4)
83#define GBL_STS RT_BIT(5)
84#define RSR2_STS (RT_BIT(6) | RT_BIT(7))
85#define PWRBTN_STS RT_BIT(8)
86#define SLPBTN_STS RT_BIT(9)
87#define RTC_STS RT_BIT(10)
88#define IGN_STS RT_BIT(11)
89#define RSR3_STS (RT_BIT(12) | RT_BIT(13) | RT_BIT(14))
90#define WAK_STS RT_BIT(15)
91#define RSR_STS (RSR1_STS | RSR2_STS | RSR3_STS)
92
93/* PM1x enable register bits */
94#define TMR_EN RT_BIT(0)
95#define RSR1_EN (RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
96#define GBL_EN RT_BIT(5)
97#define RSR2_EN (RT_BIT(6) | RT_BIT(7))
98#define PWRBTN_EN RT_BIT(8)
99#define SLPBTN_EN RT_BIT(9)
100#define RTC_EN RT_BIT(10)
101#define RSR3_EN (RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14) | RT_BIT(15))
102#define RSR_EN (RSR1_EN | RSR2_EN | RSR3_EN)
103#define IGN_EN 0
104
105/* PM1x control register bits */
106#define SCI_EN RT_BIT(0)
107#define BM_RLD RT_BIT(1)
108#define GBL_RLS RT_BIT(2)
109#define RSR1_CNT (RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8))
110#define IGN_CNT RT_BIT(9)
111#define SLP_TYPx_SHIFT 10
112#define SLP_TYPx_MASK 7
113#define SLP_EN RT_BIT(13)
114#define RSR2_CNT (RT_BIT(14) | RT_BIT(15))
115#define RSR_CNT (RSR1_CNT | RSR2_CNT)
116
117#define GPE0_BATTERY_INFO_CHANGED RT_BIT(0)
118
119enum
120{
121 BAT_STATUS_STATE = 0x00, /**< BST battery state */
122 BAT_STATUS_PRESENT_RATE = 0x01, /**< BST battery present rate */
123 BAT_STATUS_REMAINING_CAPACITY = 0x02, /**< BST battery remaining capacity */
124 BAT_STATUS_PRESENT_VOLTAGE = 0x03, /**< BST battery present voltage */
125 BAT_INFO_UNITS = 0x04, /**< BIF power unit */
126 BAT_INFO_DESIGN_CAPACITY = 0x05, /**< BIF design capacity */
127 BAT_INFO_LAST_FULL_CHARGE_CAPACITY = 0x06, /**< BIF last full charge capacity */
128 BAT_INFO_TECHNOLOGY = 0x07, /**< BIF battery technology */
129 BAT_INFO_DESIGN_VOLTAGE = 0x08, /**< BIF design voltage */
130 BAT_INFO_DESIGN_CAPACITY_OF_WARNING = 0x09, /**< BIF design capacity of warning */
131 BAT_INFO_DESIGN_CAPACITY_OF_LOW = 0x0A, /**< BIF design capacity of low */
132 BAT_INFO_CAPACITY_GRANULARITY_1 = 0x0B, /**< BIF battery capacity granularity 1 */
133 BAT_INFO_CAPACITY_GRANULARITY_2 = 0x0C, /**< BIF battery capacity granularity 2 */
134 BAT_DEVICE_STATUS = 0x0D, /**< STA device status */
135 BAT_POWER_SOURCE = 0x0E, /**< PSR power source */
136 BAT_INDEX_LAST
137};
138
139enum
140{
141 CPU_EVENT_TYPE_ADD = 0x01, /**< Event type add */
142 CPU_EVENT_TYPE_REMOVE = 0x03 /**< Event type remove */
143};
144
145enum
146{
147 SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH = 0,
148 SYSTEM_INFO_INDEX_USE_IOAPIC = 1,
149 SYSTEM_INFO_INDEX_HPET_STATUS = 2,
150 SYSTEM_INFO_INDEX_SMC_STATUS = 3,
151 SYSTEM_INFO_INDEX_FDC_STATUS = 4,
152 SYSTEM_INFO_INDEX_CPU0_STATUS = 5, /**< For compatibility with older saved states. */
153 SYSTEM_INFO_INDEX_CPU1_STATUS = 6, /**< For compatibility with older saved states. */
154 SYSTEM_INFO_INDEX_CPU2_STATUS = 7, /**< For compatibility with older saved states. */
155 SYSTEM_INFO_INDEX_CPU3_STATUS = 8, /**< For compatibility with older saved states. */
156 SYSTEM_INFO_INDEX_HIGH_MEMORY_LENGTH= 9,
157 SYSTEM_INFO_INDEX_RTC_STATUS = 10,
158 SYSTEM_INFO_INDEX_CPU_LOCKED = 11, /**< Contains a flag indicating whether the CPU is locked or not */
159 SYSTEM_INFO_INDEX_CPU_LOCK_CHECK = 12, /**< For which CPU the lock status should be checked */
160 SYSTEM_INFO_INDEX_CPU_EVENT_TYPE = 13, /**< Type of the CPU hot-plug event */
161 SYSTEM_INFO_INDEX_CPU_EVENT = 14, /**< The CPU id the event is for */
162 SYSTEM_INFO_INDEX_NIC_ADDRESS = 15, /**< NIC PCI address, or 0 */
163 SYSTEM_INFO_INDEX_AUDIO_ADDRESS = 16, /**< Audio card PCI address, or 0 */
164 SYSTEM_INFO_INDEX_POWER_STATES = 17,
165 SYSTEM_INFO_INDEX_IOC_ADDRESS = 18, /**< IO controller PCI address */
166 SYSTEM_INFO_INDEX_HBC_ADDRESS = 19, /**< host bus controller PCI address */
167 SYSTEM_INFO_INDEX_PCI_BASE = 20, /**< PCI bus MCFG MMIO range base */
168 SYSTEM_INFO_INDEX_PCI_LENGTH = 21, /**< PCI bus MCFG MMIO range length */
169 SYSTEM_INFO_INDEX_SERIAL0_IOBASE = 22,
170 SYSTEM_INFO_INDEX_SERIAL0_IRQ = 23,
171 SYSTEM_INFO_INDEX_SERIAL1_IOBASE = 24,
172 SYSTEM_INFO_INDEX_SERIAL1_IRQ = 25,
173 SYSTEM_INFO_INDEX_END = 26,
174 SYSTEM_INFO_INDEX_INVALID = 0x80,
175 SYSTEM_INFO_INDEX_VALID = 0x200
176};
177
178#define AC_OFFLINE 0
179#define AC_ONLINE 1
180
181#define BAT_TECH_PRIMARY 1
182#define BAT_TECH_SECONDARY 2
183
184#define STA_DEVICE_PRESENT_MASK RT_BIT(0) /**< present */
185#define STA_DEVICE_ENABLED_MASK RT_BIT(1) /**< enabled and decodes its resources */
186#define STA_DEVICE_SHOW_IN_UI_MASK RT_BIT(2) /**< should be shown in UI */
187#define STA_DEVICE_FUNCTIONING_PROPERLY_MASK RT_BIT(3) /**< functioning properly */
188#define STA_BATTERY_PRESENT_MASK RT_BIT(4) /**< the battery is present */
189
190
191/*******************************************************************************
192* Structures and Typedefs *
193*******************************************************************************/
194/**
195 * The ACPI device state.
196 */
197typedef struct ACPIState
198{
199 PCIDevice dev;
200 uint16_t pm1a_en;
201 uint16_t pm1a_sts;
202 uint16_t pm1a_ctl;
203 /** Number of logical CPUs in guest */
204 uint16_t cCpus;
205 int64_t pm_timer_initial;
206 PTMTIMERR3 tsR3;
207 PTMTIMERR0 tsR0;
208 PTMTIMERRC tsRC;
209
210 uint32_t gpe0_en;
211 uint32_t gpe0_sts;
212
213 unsigned int uBatteryIndex;
214 uint32_t au8BatteryInfo[13];
215
216 unsigned int uSystemInfoIndex;
217 uint64_t u64RamSize;
218 /** The number of bytes above 4GB. */
219 uint64_t cbRamHigh;
220 /** The number of bytes below 4GB. */
221 uint32_t cbRamLow;
222
223 /** Current ACPI S* state. We support S0 and S5. */
224 uint32_t uSleepState;
225 uint8_t au8RSDPPage[0x1000];
226 /** This is a workaround for incorrect index field handling by Intels ACPICA.
227 * The system info _INI method writes to offset 0x200. We either observe a
228 * write request to index 0x80 (in that case we don't change the index) or a
229 * write request to offset 0x200 (in that case we divide the index value by
230 * 4. Note that the _STA method is sometimes called prior to the _INI method
231 * (ACPI spec 6.3.7, _STA). See the special case for BAT_DEVICE_STATUS in
232 * acpiBatIndexWrite() for handling this. */
233 uint8_t u8IndexShift;
234 /** provide an I/O-APIC */
235 uint8_t u8UseIOApic;
236 /** provide a floppy controller */
237 bool fUseFdc;
238 /** If High Precision Event Timer device should be supported */
239 bool fUseHpet;
240 /** If System Management Controller device should be supported */
241 bool fUseSmc;
242 /** the guest handled the last power button event */
243 bool fPowerButtonHandled;
244 /** If ACPI CPU device should be shown */
245 bool fShowCpu;
246 /** If Real Time Clock ACPI object to be shown */
247 bool fShowRtc;
248 /** I/O port address of PM device. */
249 RTIOPORT uPmIoPortBase;
250 /** Flag whether the GC part of the device is enabled. */
251 bool fGCEnabled;
252 /** Flag whether the R0 part of the device is enabled. */
253 bool fR0Enabled;
254 /** Array of flags of attached CPUs */
255 VMCPUSET CpuSetAttached;
256 /** Which CPU to check for the locked status. */
257 uint32_t idCpuLockCheck;
258 /** Mask of locked CPUs (used by the guest). */
259 VMCPUSET CpuSetLocked;
260 /** The CPU event type. */
261 uint32_t u32CpuEventType;
262 /** The CPU id affected. */
263 uint32_t u32CpuEvent;
264 /** Flag whether CPU hot plugging is enabled. */
265 bool fCpuHotPlug;
266 /** If MCFG ACPI table shown to the guest */
267 bool fUseMcfg;
268 /** Primary NIC PCI address. */
269 uint32_t u32NicPciAddress;
270 /** Primary audio card PCI address. */
271 uint32_t u32AudioPciAddress;
272 /** Flag whether S1 power state is enabled. */
273 bool fS1Enabled;
274 /** Flag whether S4 power state is enabled. */
275 bool fS4Enabled;
276 /** Flag whether S1 triggers a state save. */
277 bool fSuspendToSavedState;
278 /** Flag whether to set WAK_STS on resume (restore included). */
279 bool fSetWakeupOnResume;
280 /** PCI address of the IO controller device. */
281 uint32_t u32IocPciAddress;
282 /** PCI address of the host bus controller device. */
283 uint32_t u32HbcPciAddress;
284 /* Physical address of PCI config space MMIO region */
285 uint64_t u64PciConfigMMioAddress;
286 /* Length of PCI config space MMIO region */
287 uint64_t u64PciConfigMMioLength;
288 /** Serial 0 IRQ number */
289 uint8_t uSerial0Irq;
290 /** Serial 1 IRQ number */
291 uint8_t uSerial1Irq;
292 /** Serial 0 IO port base */
293 RTIOPORT uSerial0IoPortBase;
294 /** Serial 1 IO port base */
295 RTIOPORT uSerial1IoPortBase;
296 /** ACPI port base interface. */
297 PDMIBASE IBase;
298 /** ACPI port interface. */
299 PDMIACPIPORT IACPIPort;
300 /** Pointer to the device instance. */
301 PPDMDEVINSR3 pDevIns;
302 /** Pointer to the driver base interface. */
303 R3PTRTYPE(PPDMIBASE) pDrvBase;
304 /** Pointer to the driver connector interface. */
305 R3PTRTYPE(PPDMIACPICONNECTOR) pDrv;
306
307 /** Pointer to default PCI config read function. */
308 R3PTRTYPE(PFNPCICONFIGREAD) pfnAcpiPciConfigRead;
309 /** Pointer to default PCI config write function. */
310 R3PTRTYPE(PFNPCICONFIGWRITE) pfnAcpiPciConfigWrite;
311} ACPIState;
312
313#pragma pack(1)
314
315/** Generic Address Structure (see ACPIspec 3.0, 5.2.3.1) */
316struct ACPIGENADDR
317{
318 uint8_t u8AddressSpaceId; /**< 0=sys, 1=IO, 2=PCICfg, 3=emb, 4=SMBus */
319 uint8_t u8RegisterBitWidth; /**< size in bits of the given register */
320 uint8_t u8RegisterBitOffset; /**< bit offset of register */
321 uint8_t u8AccessSize; /**< 1=byte, 2=word, 3=dword, 4=qword */
322 uint64_t u64Address; /**< 64-bit address of register */
323};
324AssertCompileSize(ACPIGENADDR, 12);
325
326/** Root System Description Pointer */
327struct ACPITBLRSDP
328{
329 uint8_t au8Signature[8]; /**< 'RSD PTR ' */
330 uint8_t u8Checksum; /**< checksum for the first 20 bytes */
331 uint8_t au8OemId[6]; /**< OEM-supplied identifier */
332 uint8_t u8Revision; /**< revision number, currently 2 */
333#define ACPI_REVISION 2 /**< ACPI 3.0 */
334 uint32_t u32RSDT; /**< phys addr of RSDT */
335 uint32_t u32Length; /**< bytes of this table */
336 uint64_t u64XSDT; /**< 64-bit phys addr of XSDT */
337 uint8_t u8ExtChecksum; /**< checksum of entire table */
338 uint8_t u8Reserved[3]; /**< reserved */
339};
340AssertCompileSize(ACPITBLRSDP, 36);
341
342/** System Description Table Header */
343struct ACPITBLHEADER
344{
345 uint8_t au8Signature[4]; /**< table identifier */
346 uint32_t u32Length; /**< length of the table including header */
347 uint8_t u8Revision; /**< revision number */
348 uint8_t u8Checksum; /**< all fields inclusive this add to zero */
349 uint8_t au8OemId[6]; /**< OEM-supplied string */
350 uint8_t au8OemTabId[8]; /**< to identify the particular data table */
351 uint32_t u32OemRevision; /**< OEM-supplied revision number */
352 uint8_t au8CreatorId[4]; /**< ID for the ASL compiler */
353 uint32_t u32CreatorRev; /**< revision for the ASL compiler */
354};
355AssertCompileSize(ACPITBLHEADER, 36);
356
357/** Root System Description Table */
358struct ACPITBLRSDT
359{
360 ACPITBLHEADER header;
361 uint32_t u32Entry[1]; /**< array of phys. addresses to other tables */
362};
363AssertCompileSize(ACPITBLRSDT, 40);
364
365/** Extended System Description Table */
366struct ACPITBLXSDT
367{
368 ACPITBLHEADER header;
369 uint64_t u64Entry[1]; /**< array of phys. addresses to other tables */
370};
371AssertCompileSize(ACPITBLXSDT, 44);
372
373/** Fixed ACPI Description Table */
374struct ACPITBLFADT
375{
376 ACPITBLHEADER header;
377 uint32_t u32FACS; /**< phys. address of FACS */
378 uint32_t u32DSDT; /**< phys. address of DSDT */
379 uint8_t u8IntModel; /**< was eleminated in ACPI 2.0 */
380#define INT_MODEL_DUAL_PIC 1 /**< for ACPI 2+ */
381#define INT_MODEL_MULTIPLE_APIC 2
382 uint8_t u8PreferredPMProfile; /**< preferred power management profile */
383 uint16_t u16SCIInt; /**< system vector the SCI is wired in 8259 mode */
384#define SCI_INT 9
385 uint32_t u32SMICmd; /**< system port address of SMI command port */
386#define SMI_CMD 0x0000442e
387 uint8_t u8AcpiEnable; /**< SMICmd val to disable ownership of ACPIregs */
388#define ACPI_ENABLE 0xa1
389 uint8_t u8AcpiDisable; /**< SMICmd val to re-enable ownership of ACPIregs */
390#define ACPI_DISABLE 0xa0
391 uint8_t u8S4BIOSReq; /**< SMICmd val to enter S4BIOS state */
392 uint8_t u8PStateCnt; /**< SMICmd val to assume processor performance
393 state control responsibility */
394 uint32_t u32PM1aEVTBLK; /**< port addr of PM1a event regs block */
395 uint32_t u32PM1bEVTBLK; /**< port addr of PM1b event regs block */
396 uint32_t u32PM1aCTLBLK; /**< port addr of PM1a control regs block */
397 uint32_t u32PM1bCTLBLK; /**< port addr of PM1b control regs block */
398 uint32_t u32PM2CTLBLK; /**< port addr of PM2 control regs block */
399 uint32_t u32PMTMRBLK; /**< port addr of PMTMR regs block */
400 uint32_t u32GPE0BLK; /**< port addr of gen-purp event 0 regs block */
401 uint32_t u32GPE1BLK; /**< port addr of gen-purp event 1 regs block */
402 uint8_t u8PM1EVTLEN; /**< bytes decoded by PM1a_EVT_BLK. >= 4 */
403 uint8_t u8PM1CTLLEN; /**< bytes decoded by PM1b_CNT_BLK. >= 2 */
404 uint8_t u8PM2CTLLEN; /**< bytes decoded by PM2_CNT_BLK. >= 1 or 0 */
405 uint8_t u8PMTMLEN; /**< bytes decoded by PM_TMR_BLK. ==4 */
406 uint8_t u8GPE0BLKLEN; /**< bytes decoded by GPE0_BLK. %2==0 */
407#define GPE0_BLK_LEN 2
408 uint8_t u8GPE1BLKLEN; /**< bytes decoded by GPE1_BLK. %2==0 */
409#define GPE1_BLK_LEN 0
410 uint8_t u8GPE1BASE; /**< offset of GPE1 based events */
411#define GPE1_BASE 0
412 uint8_t u8CSTCNT; /**< SMICmd val to indicate OS supp for C states */
413 uint16_t u16PLVL2LAT; /**< us to enter/exit C2. >100 => unsupported */
414#define P_LVL2_LAT 101 /**< C2 state not supported */
415 uint16_t u16PLVL3LAT; /**< us to enter/exit C3. >1000 => unsupported */
416#define P_LVL3_LAT 1001 /**< C3 state not supported */
417 uint16_t u16FlushSize; /**< # of flush strides to read to flush dirty
418 lines from any processors memory caches */
419#define FLUSH_SIZE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
420 uint16_t u16FlushStride; /**< cache line width */
421#define FLUSH_STRIDE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
422 uint8_t u8DutyOffset;
423 uint8_t u8DutyWidth;
424 uint8_t u8DayAlarm; /**< RTC CMOS RAM index of day-of-month alarm */
425 uint8_t u8MonAlarm; /**< RTC CMOS RAM index of month-of-year alarm */
426 uint8_t u8Century; /**< RTC CMOS RAM index of century */
427 uint16_t u16IAPCBOOTARCH; /**< IA-PC boot architecture flags */
428#define IAPC_BOOT_ARCH_LEGACY_DEV RT_BIT(0) /**< legacy devices present such as LPT
429 (COM too?) */
430#define IAPC_BOOT_ARCH_8042 RT_BIT(1) /**< legacy keyboard device present */
431#define IAPC_BOOT_ARCH_NO_VGA RT_BIT(2) /**< VGA not present */
432 uint8_t u8Must0_0; /**< must be 0 */
433 uint32_t u32Flags; /**< fixed feature flags */
434#define FADT_FL_WBINVD RT_BIT(0) /**< emulation of WBINVD available */
435#define FADT_FL_WBINVD_FLUSH RT_BIT(1)
436#define FADT_FL_PROC_C1 RT_BIT(2) /**< 1=C1 supported on all processors */
437#define FADT_FL_P_LVL2_UP RT_BIT(3) /**< 1=C2 works on SMP and UNI systems */
438#define FADT_FL_PWR_BUTTON RT_BIT(4) /**< 1=power button handled as ctrl method dev */
439#define FADT_FL_SLP_BUTTON RT_BIT(5) /**< 1=sleep button handled as ctrl method dev */
440#define FADT_FL_FIX_RTC RT_BIT(6) /**< 0=RTC wake status in fixed register */
441#define FADT_FL_RTC_S4 RT_BIT(7) /**< 1=RTC can wake system from S4 */
442#define FADT_FL_TMR_VAL_EXT RT_BIT(8) /**< 1=TMR_VAL implemented as 32 bit */
443#define FADT_FL_DCK_CAP RT_BIT(9) /**< 0=system cannot support docking */
444#define FADT_FL_RESET_REG_SUP RT_BIT(10) /**< 1=system supports system resets */
445#define FADT_FL_SEALED_CASE RT_BIT(11) /**< 1=case is sealed */
446#define FADT_FL_HEADLESS RT_BIT(12) /**< 1=system cannot detect moni/keyb/mouse */
447#define FADT_FL_CPU_SW_SLP RT_BIT(13)
448#define FADT_FL_PCI_EXT_WAK RT_BIT(14) /**< 1=system supports PCIEXP_WAKE_STS */
449#define FADT_FL_USE_PLATFORM_CLOCK RT_BIT(15) /**< 1=system has ACPI PM timer */
450#define FADT_FL_S4_RTC_STS_VALID RT_BIT(16) /**< 1=RTC_STS flag is valid when waking from S4 */
451#define FADT_FL_REMOVE_POWER_ON_CAPABLE RT_BIT(17) /**< 1=platform can remote power on */
452#define FADT_FL_FORCE_APIC_CLUSTER_MODEL RT_BIT(18)
453#define FADT_FL_FORCE_APIC_PHYS_DEST_MODE RT_BIT(19)
454
455 /** Start of the ACPI 2.0 extension. */
456 ACPIGENADDR ResetReg; /**< ext addr of reset register */
457 uint8_t u8ResetVal; /**< ResetReg value to reset the system */
458#define ACPI_RESET_REG_VAL 0x10
459 uint8_t au8Must0_1[3]; /**< must be 0 */
460 uint64_t u64XFACS; /**< 64-bit phys address of FACS */
461 uint64_t u64XDSDT; /**< 64-bit phys address of DSDT */
462 ACPIGENADDR X_PM1aEVTBLK; /**< ext addr of PM1a event regs block */
463 ACPIGENADDR X_PM1bEVTBLK; /**< ext addr of PM1b event regs block */
464 ACPIGENADDR X_PM1aCTLBLK; /**< ext addr of PM1a control regs block */
465 ACPIGENADDR X_PM1bCTLBLK; /**< ext addr of PM1b control regs block */
466 ACPIGENADDR X_PM2CTLBLK; /**< ext addr of PM2 control regs block */
467 ACPIGENADDR X_PMTMRBLK; /**< ext addr of PMTMR control regs block */
468 ACPIGENADDR X_GPE0BLK; /**< ext addr of GPE1 regs block */
469 ACPIGENADDR X_GPE1BLK; /**< ext addr of GPE1 regs block */
470};
471AssertCompileSize(ACPITBLFADT, 244);
472#define ACPITBLFADT_VERSION1_SIZE RT_OFFSETOF(ACPITBLFADT, ResetReg)
473
474/** Firmware ACPI Control Structure */
475struct ACPITBLFACS
476{
477 uint8_t au8Signature[4]; /**< 'FACS' */
478 uint32_t u32Length; /**< bytes of entire FACS structure >= 64 */
479 uint32_t u32HWSignature; /**< systems HW signature at last boot */
480 uint32_t u32FWVector; /**< address of waking vector */
481 uint32_t u32GlobalLock; /**< global lock to sync HW/SW */
482 uint32_t u32Flags; /**< FACS flags */
483 uint64_t u64X_FWVector; /**< 64-bit waking vector */
484 uint8_t u8Version; /**< version of this table */
485 uint8_t au8Reserved[31]; /**< zero */
486};
487AssertCompileSize(ACPITBLFACS, 64);
488
489/** Processor Local APIC Structure */
490struct ACPITBLLAPIC
491{
492 uint8_t u8Type; /**< 0 = LAPIC */
493 uint8_t u8Length; /**< 8 */
494 uint8_t u8ProcId; /**< processor ID */
495 uint8_t u8ApicId; /**< local APIC ID */
496 uint32_t u32Flags; /**< Flags */
497#define LAPIC_ENABLED 0x1
498};
499AssertCompileSize(ACPITBLLAPIC, 8);
500
501/** I/O APIC Structure */
502struct ACPITBLIOAPIC
503{
504 uint8_t u8Type; /**< 1 == I/O APIC */
505 uint8_t u8Length; /**< 12 */
506 uint8_t u8IOApicId; /**< I/O APIC ID */
507 uint8_t u8Reserved; /**< 0 */
508 uint32_t u32Address; /**< phys address to access I/O APIC */
509 uint32_t u32GSIB; /**< global system interrupt number to start */
510};
511AssertCompileSize(ACPITBLIOAPIC, 12);
512
513/** Interrupt Source Override Structure */
514struct ACPITBLISO
515{
516 uint8_t u8Type; /**< 2 == Interrupt Source Override*/
517 uint8_t u8Length; /**< 10 */
518 uint8_t u8Bus; /**< Bus */
519 uint8_t u8Source; /**< Bus-relative interrupt source (IRQ) */
520 uint32_t u32GSI; /**< Global System Interrupt */
521 uint16_t u16Flags; /**< MPS INTI flags Global */
522};
523AssertCompileSize(ACPITBLISO, 10);
524#define NUMBER_OF_IRQ_SOURCE_OVERRIDES 2
525
526/** HPET Descriptor Structure */
527struct ACPITBLHPET
528{
529 ACPITBLHEADER aHeader;
530 uint32_t u32Id; /**< hardware ID of event timer block
531 [31:16] PCI vendor ID of first timer block
532 [15] legacy replacement IRQ routing capable
533 [14] reserved
534 [13] COUNT_SIZE_CAP counter size
535 [12:8] number of comparators in first timer block
536 [7:0] hardware rev ID */
537 ACPIGENADDR HpetAddr; /**< lower 32-bit base address */
538 uint8_t u32Number; /**< sequence number starting at 0 */
539 uint16_t u32MinTick; /**< minimum clock ticks which can be set without
540 lost interrupts while the counter is programmed
541 to operate in periodic mode. Unit: clock tick. */
542 uint8_t u8Attributes; /**< page protection and OEM attribute. */
543};
544AssertCompileSize(ACPITBLHPET, 56);
545
546/** MCFG Descriptor Structure */
547typedef struct ACPITBLMCFG
548{
549 ACPITBLHEADER aHeader;
550 uint64_t u64Reserved;
551} ACPITBLMCFG;
552AssertCompileSize(ACPITBLMCFG, 44);
553
554/** Number of such entries can be computed from the whole table length in header */
555typedef struct ACPITBLMCFGENTRY
556{
557 uint64_t u64BaseAddress;
558 uint16_t u16PciSegmentGroup;
559 uint8_t u8StartBus;
560 uint8_t u8EndBus;
561 uint32_t u32Reserved;
562} ACPITBLMCFGENTRY;
563AssertCompileSize(ACPITBLMCFGENTRY, 16);
564
565# ifdef IN_RING3 /** @todo r=bird: Move this down to where it's used. */
566
567# define PCAT_COMPAT 0x1 /**< system has also a dual-8259 setup */
568
569/**
570 * Multiple APIC Description Table.
571 *
572 * This structure looks somewhat convoluted due layout of MADT table in MP case.
573 * There extpected to be multiple LAPIC records for each CPU, thus we cannot
574 * use regular C structure and proxy to raw memory instead.
575 */
576class AcpiTableMADT
577{
578 /**
579 * All actual data stored in dynamically allocated memory pointed by this field.
580 */
581 uint8_t *m_pbData;
582 /**
583 * Number of CPU entries in this MADT.
584 */
585 uint32_t m_cCpus;
586
587 /**
588 * Number of interrupt overrides.
589 */
590 uint32_t m_cIsos;
591
592public:
593 /**
594 * Address of ACPI header
595 */
596 inline ACPITBLHEADER *header_addr(void) const
597 {
598 return (ACPITBLHEADER *)m_pbData;
599 }
600
601 /**
602 * Address of local APIC for each CPU. Note that different CPUs address different LAPICs,
603 * although address is the same for all of them.
604 */
605 inline uint32_t *u32LAPIC_addr(void) const
606 {
607 return (uint32_t *)(header_addr() + 1);
608 }
609
610 /**
611 * Address of APIC flags
612 */
613 inline uint32_t *u32Flags_addr(void) const
614 {
615 return (uint32_t *)(u32LAPIC_addr() + 1);
616 }
617
618 /**
619 * Address of ISO description
620 */
621 inline ACPITBLISO *ISO_addr(void) const
622 {
623 return (ACPITBLISO *)(u32Flags_addr() + 1);
624 }
625
626 /**
627 * Address of per-CPU LAPIC descriptions
628 */
629 inline ACPITBLLAPIC *LApics_addr(void) const
630 {
631 return (ACPITBLLAPIC *)(ISO_addr() + m_cIsos);
632 }
633
634 /**
635 * Address of IO APIC description
636 */
637 inline ACPITBLIOAPIC *IOApic_addr(void) const
638 {
639 return (ACPITBLIOAPIC *)(LApics_addr() + m_cCpus);
640 }
641
642 /**
643 * Size of MADT.
644 * Note that this function assumes IOApic to be the last field in structure.
645 */
646 inline uint32_t size(void) const
647 {
648 return (uint8_t *)(IOApic_addr() + 1) - (uint8_t *)header_addr();
649 }
650
651 /**
652 * Raw data of MADT.
653 */
654 inline const uint8_t *data(void) const
655 {
656 return m_pbData;
657 }
658
659 /**
660 * Size of MADT for given ACPI config, useful to compute layout.
661 */
662 static uint32_t sizeFor(ACPIState *s, uint32_t cIsos)
663 {
664 return AcpiTableMADT(s->cCpus, cIsos).size();
665 }
666
667 /*
668 * Constructor, only works in Ring 3, doesn't look like a big deal.
669 */
670 AcpiTableMADT(uint32_t cCpus, uint32_t cIsos)
671 {
672 m_cCpus = cCpus;
673 m_cIsos = cIsos;
674 m_pbData = NULL; /* size() uses this and gcc will complain if not initialized. */
675 uint32_t cb = size();
676 m_pbData = (uint8_t *)RTMemAllocZ(cb);
677 }
678
679 ~AcpiTableMADT()
680 {
681 RTMemFree(m_pbData);
682 }
683};
684# endif /* IN_RING3 */
685
686#pragma pack()
687
688
689#ifndef VBOX_DEVICE_STRUCT_TESTCASE /* exclude the rest of the file */
690/*******************************************************************************
691* Internal Functions *
692*******************************************************************************/
693RT_C_DECLS_BEGIN
694PDMBOTHCBDECL(int) acpiPMTmrRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
695#ifdef IN_RING3
696PDMBOTHCBDECL(int) acpiPm1aEnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
697PDMBOTHCBDECL(int) acpiPM1aEnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
698PDMBOTHCBDECL(int) acpiPm1aStsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
699PDMBOTHCBDECL(int) acpiPM1aStsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
700PDMBOTHCBDECL(int) acpiPm1aCtlRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
701PDMBOTHCBDECL(int) acpiPM1aCtlWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
702PDMBOTHCBDECL(int) acpiSmiWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
703PDMBOTHCBDECL(int) acpiBatIndexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
704PDMBOTHCBDECL(int) acpiBatDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
705PDMBOTHCBDECL(int) acpiSysInfoDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
706PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
707PDMBOTHCBDECL(int) acpiGpe0EnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
708PDMBOTHCBDECL(int) acpiGpe0EnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
709PDMBOTHCBDECL(int) acpiGpe0StsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
710PDMBOTHCBDECL(int) acpiGpe0StsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
711PDMBOTHCBDECL(int) acpiResetWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
712# ifdef DEBUG_ACPI
713PDMBOTHCBDECL(int) acpiDhexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
714PDMBOTHCBDECL(int) acpiDchrWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
715# endif
716#endif /* IN_RING3 */
717RT_C_DECLS_END
718
719
720#ifdef IN_RING3
721
722static RTIOPORT acpiPmPort(ACPIState* pAcpi, int32_t offset)
723{
724 Assert(pAcpi->uPmIoPortBase != 0);
725
726 if (offset == -1)
727 return 0;
728
729 return RTIOPORT(pAcpi->uPmIoPortBase + offset);
730}
731
732/* Simple acpiChecksum: all the bytes must add up to 0. */
733static uint8_t acpiChecksum(const uint8_t * const data, size_t len)
734{
735 uint8_t sum = 0;
736 for (size_t i = 0; i < len; ++i)
737 sum += data[i];
738 return -sum;
739}
740
741static void acpiPrepareHeader(ACPITBLHEADER *header, const char au8Signature[4],
742 uint32_t u32Length, uint8_t u8Revision)
743{
744 memcpy(header->au8Signature, au8Signature, 4);
745 header->u32Length = RT_H2LE_U32(u32Length);
746 header->u8Revision = u8Revision;
747 memcpy(header->au8OemId, "VBOX ", 6);
748 memcpy(header->au8OemTabId, "VBOX", 4);
749 memcpy(header->au8OemTabId+4, au8Signature, 4);
750 header->u32OemRevision = RT_H2LE_U32(1);
751 memcpy(header->au8CreatorId, "ASL ", 4);
752 header->u32CreatorRev = RT_H2LE_U32(0x61);
753}
754
755static void acpiWriteGenericAddr(ACPIGENADDR *g, uint8_t u8AddressSpaceId,
756 uint8_t u8RegisterBitWidth, uint8_t u8RegisterBitOffset,
757 uint8_t u8AccessSize, uint64_t u64Address)
758{
759 g->u8AddressSpaceId = u8AddressSpaceId;
760 g->u8RegisterBitWidth = u8RegisterBitWidth;
761 g->u8RegisterBitOffset = u8RegisterBitOffset;
762 g->u8AccessSize = u8AccessSize;
763 g->u64Address = RT_H2LE_U64(u64Address);
764}
765
766static void acpiPhyscpy(ACPIState *s, RTGCPHYS32 dst, const void * const src, size_t size)
767{
768 PDMDevHlpPhysWrite(s->pDevIns, dst, src, size);
769}
770
771/** Differentiated System Description Table (DSDT) */
772
773static void acpiSetupDSDT(ACPIState *s, RTGCPHYS32 addr,
774 void* pPtr, size_t uDsdtLen)
775{
776 acpiPhyscpy(s, addr, pPtr, uDsdtLen);
777}
778
779/** Secondary System Description Table (SSDT) */
780
781static void acpiSetupSSDT(ACPIState *s, RTGCPHYS32 addr,
782 void* pPtr, size_t uSsdtLen)
783{
784 acpiPhyscpy(s, addr, pPtr, uSsdtLen);
785}
786
787/** Firmware ACPI Control Structure (FACS) */
788static void acpiSetupFACS(ACPIState *s, RTGCPHYS32 addr)
789{
790 ACPITBLFACS facs;
791
792 memset(&facs, 0, sizeof(facs));
793 memcpy(facs.au8Signature, "FACS", 4);
794 facs.u32Length = RT_H2LE_U32(sizeof(ACPITBLFACS));
795 facs.u32HWSignature = RT_H2LE_U32(0);
796 facs.u32FWVector = RT_H2LE_U32(0);
797 facs.u32GlobalLock = RT_H2LE_U32(0);
798 facs.u32Flags = RT_H2LE_U32(0);
799 facs.u64X_FWVector = RT_H2LE_U64(0);
800 facs.u8Version = 1;
801
802 acpiPhyscpy(s, addr, (const uint8_t *)&facs, sizeof(facs));
803}
804
805/** Fixed ACPI Description Table (FADT aka FACP) */
806static void acpiSetupFADT(ACPIState *s, RTGCPHYS32 GCPhysAcpi1, RTGCPHYS32 GCPhysAcpi2, RTGCPHYS32 GCPhysFacs, RTGCPHYS GCPhysDsdt)
807{
808 ACPITBLFADT fadt;
809
810 /* First the ACPI version 2+ version of the structure. */
811 memset(&fadt, 0, sizeof(fadt));
812 acpiPrepareHeader(&fadt.header, "FACP", sizeof(fadt), 4);
813 fadt.u32FACS = RT_H2LE_U32(GCPhysFacs);
814 fadt.u32DSDT = RT_H2LE_U32(GCPhysDsdt);
815 fadt.u8IntModel = 0; /* dropped from the ACPI 2.0 spec. */
816 fadt.u8PreferredPMProfile = 0; /* unspecified */
817 fadt.u16SCIInt = RT_H2LE_U16(SCI_INT);
818 fadt.u32SMICmd = RT_H2LE_U32(SMI_CMD);
819 fadt.u8AcpiEnable = ACPI_ENABLE;
820 fadt.u8AcpiDisable = ACPI_DISABLE;
821 fadt.u8S4BIOSReq = 0;
822 fadt.u8PStateCnt = 0;
823 fadt.u32PM1aEVTBLK = RT_H2LE_U32(acpiPmPort(s, PM1a_EVT_OFFSET));
824 fadt.u32PM1bEVTBLK = RT_H2LE_U32(acpiPmPort(s, PM1b_EVT_OFFSET));
825 fadt.u32PM1aCTLBLK = RT_H2LE_U32(acpiPmPort(s, PM1a_CTL_OFFSET));
826 fadt.u32PM1bCTLBLK = RT_H2LE_U32(acpiPmPort(s, PM1b_CTL_OFFSET));
827 fadt.u32PM2CTLBLK = RT_H2LE_U32(acpiPmPort(s, PM2_CTL_OFFSET));
828 fadt.u32PMTMRBLK = RT_H2LE_U32(acpiPmPort(s, PM_TMR_OFFSET));
829 fadt.u32GPE0BLK = RT_H2LE_U32(acpiPmPort(s, GPE0_OFFSET));
830 fadt.u32GPE1BLK = RT_H2LE_U32(acpiPmPort(s, GPE1_OFFSET));
831 fadt.u8PM1EVTLEN = 4;
832 fadt.u8PM1CTLLEN = 2;
833 fadt.u8PM2CTLLEN = 0;
834 fadt.u8PMTMLEN = 4;
835 fadt.u8GPE0BLKLEN = GPE0_BLK_LEN;
836 fadt.u8GPE1BLKLEN = GPE1_BLK_LEN;
837 fadt.u8GPE1BASE = GPE1_BASE;
838 fadt.u8CSTCNT = 0;
839 fadt.u16PLVL2LAT = RT_H2LE_U16(P_LVL2_LAT);
840 fadt.u16PLVL3LAT = RT_H2LE_U16(P_LVL3_LAT);
841 fadt.u16FlushSize = RT_H2LE_U16(FLUSH_SIZE);
842 fadt.u16FlushStride = RT_H2LE_U16(FLUSH_STRIDE);
843 fadt.u8DutyOffset = 0;
844 fadt.u8DutyWidth = 0;
845 fadt.u8DayAlarm = 0;
846 fadt.u8MonAlarm = 0;
847 fadt.u8Century = 0;
848 fadt.u16IAPCBOOTARCH = RT_H2LE_U16(IAPC_BOOT_ARCH_LEGACY_DEV | IAPC_BOOT_ARCH_8042);
849 /** @note WBINVD is required for ACPI versions newer than 1.0 */
850 fadt.u32Flags = RT_H2LE_U32( FADT_FL_WBINVD
851 | FADT_FL_FIX_RTC
852 | FADT_FL_TMR_VAL_EXT
853 | FADT_FL_RESET_REG_SUP);
854
855 /* We have to force physical APIC mode or Linux can't use more than 8 CPUs */
856 if (s->fCpuHotPlug)
857 fadt.u32Flags |= RT_H2LE_U32(FADT_FL_FORCE_APIC_PHYS_DEST_MODE);
858
859 acpiWriteGenericAddr(&fadt.ResetReg, 1, 8, 0, 1, ACPI_RESET_BLK);
860 fadt.u8ResetVal = ACPI_RESET_REG_VAL;
861 fadt.u64XFACS = RT_H2LE_U64((uint64_t)GCPhysFacs);
862 fadt.u64XDSDT = RT_H2LE_U64((uint64_t)GCPhysDsdt);
863 acpiWriteGenericAddr(&fadt.X_PM1aEVTBLK, 1, 32, 0, 2, acpiPmPort(s, PM1a_EVT_OFFSET));
864 acpiWriteGenericAddr(&fadt.X_PM1bEVTBLK, 0, 0, 0, 0, acpiPmPort(s, PM1b_EVT_OFFSET));
865 acpiWriteGenericAddr(&fadt.X_PM1aCTLBLK, 1, 16, 0, 2, acpiPmPort(s, PM1a_CTL_OFFSET));
866 acpiWriteGenericAddr(&fadt.X_PM1bCTLBLK, 0, 0, 0, 0, acpiPmPort(s, PM1b_CTL_OFFSET));
867 acpiWriteGenericAddr(&fadt.X_PM2CTLBLK, 0, 0, 0, 0, acpiPmPort(s, PM2_CTL_OFFSET));
868 acpiWriteGenericAddr(&fadt.X_PMTMRBLK, 1, 32, 0, 3, acpiPmPort(s, PM_TMR_OFFSET));
869 acpiWriteGenericAddr(&fadt.X_GPE0BLK, 1, 16, 0, 1, acpiPmPort(s, GPE0_OFFSET));
870 acpiWriteGenericAddr(&fadt.X_GPE1BLK, 0, 0, 0, 0, acpiPmPort(s, GPE1_OFFSET));
871 fadt.header.u8Checksum = acpiChecksum((uint8_t *)&fadt, sizeof(fadt));
872 acpiPhyscpy(s, GCPhysAcpi2, &fadt, sizeof(fadt));
873
874 /* Now the ACPI 1.0 version. */
875 fadt.header.u32Length = ACPITBLFADT_VERSION1_SIZE;
876 fadt.u8IntModel = INT_MODEL_DUAL_PIC;
877 fadt.header.u8Checksum = 0; /* Must be zeroed before recalculating checksum! */
878 fadt.header.u8Checksum = acpiChecksum((uint8_t *)&fadt, ACPITBLFADT_VERSION1_SIZE);
879 acpiPhyscpy(s, GCPhysAcpi1, &fadt, ACPITBLFADT_VERSION1_SIZE);
880}
881
882/**
883 * Root System Description Table.
884 * The RSDT and XSDT tables are basically identical. The only difference is 32 vs 64 bits
885 * addresses for description headers. RSDT is for ACPI 1.0. XSDT for ACPI 2.0 and up.
886 */
887static int acpiSetupRSDT(ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
888{
889 ACPITBLRSDT *rsdt;
890 const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(rsdt->u32Entry[0]);
891
892 rsdt = (ACPITBLRSDT*)RTMemAllocZ(size);
893 if (!rsdt)
894 return PDMDEV_SET_ERROR(s->pDevIns, VERR_NO_TMP_MEMORY, N_("Cannot allocate RSDT"));
895
896 acpiPrepareHeader(&rsdt->header, "RSDT", (uint32_t)size, 1);
897 for (unsigned int i = 0; i < nb_entries; ++i)
898 {
899 rsdt->u32Entry[i] = RT_H2LE_U32(addrs[i]);
900 Log(("Setup RSDT: [%d] = %x\n", i, rsdt->u32Entry[i]));
901 }
902 rsdt->header.u8Checksum = acpiChecksum((uint8_t*)rsdt, size);
903 acpiPhyscpy(s, addr, rsdt, size);
904 RTMemFree(rsdt);
905 return VINF_SUCCESS;
906}
907
908/** Extended System Description Table. */
909static int acpiSetupXSDT(ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
910{
911 ACPITBLXSDT *xsdt;
912 const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(xsdt->u64Entry[0]);
913
914 xsdt = (ACPITBLXSDT*)RTMemAllocZ(size);
915 if (!xsdt)
916 return VERR_NO_TMP_MEMORY;
917
918 acpiPrepareHeader(&xsdt->header, "XSDT", (uint32_t)size, 1 /* according to ACPI 3.0 specs */);
919 for (unsigned int i = 0; i < nb_entries; ++i)
920 {
921 xsdt->u64Entry[i] = RT_H2LE_U64((uint64_t)addrs[i]);
922 Log(("Setup XSDT: [%d] = %RX64\n", i, xsdt->u64Entry[i]));
923 }
924 xsdt->header.u8Checksum = acpiChecksum((uint8_t*)xsdt, size);
925 acpiPhyscpy(s, addr, xsdt, size);
926 RTMemFree(xsdt);
927 return VINF_SUCCESS;
928}
929
930/** Root System Description Pointer (RSDP) */
931static void acpiSetupRSDP(ACPITBLRSDP *rsdp, RTGCPHYS32 GCPhysRsdt, RTGCPHYS GCPhysXsdt)
932{
933 memset(rsdp, 0, sizeof(*rsdp));
934
935 /* ACPI 1.0 part (RSDT */
936 memcpy(rsdp->au8Signature, "RSD PTR ", 8);
937 memcpy(rsdp->au8OemId, "VBOX ", 6);
938 rsdp->u8Revision = ACPI_REVISION;
939 rsdp->u32RSDT = RT_H2LE_U32(GCPhysRsdt);
940 rsdp->u8Checksum = acpiChecksum((uint8_t*)rsdp, RT_OFFSETOF(ACPITBLRSDP, u32Length));
941
942 /* ACPI 2.0 part (XSDT) */
943 rsdp->u32Length = RT_H2LE_U32(sizeof(ACPITBLRSDP));
944 rsdp->u64XSDT = RT_H2LE_U64(GCPhysXsdt);
945 rsdp->u8ExtChecksum = acpiChecksum((uint8_t*)rsdp, sizeof(ACPITBLRSDP));
946}
947
948/**
949 * Multiple APIC Description Table.
950 *
951 * @note APIC without IO-APIC hangs Windows Vista therefore we setup both
952 *
953 * @todo All hardcoded, should set this up based on the actual VM config!!!!!
954 */
955static void acpiSetupMADT(ACPIState *s, RTGCPHYS32 addr)
956{
957 uint16_t cpus = s->cCpus;
958 AcpiTableMADT madt(cpus, NUMBER_OF_IRQ_SOURCE_OVERRIDES);
959
960 acpiPrepareHeader(madt.header_addr(), "APIC", madt.size(), 2);
961
962 *madt.u32LAPIC_addr() = RT_H2LE_U32(0xfee00000);
963 *madt.u32Flags_addr() = RT_H2LE_U32(PCAT_COMPAT);
964
965 /* LAPICs records */
966 ACPITBLLAPIC* lapic = madt.LApics_addr();
967 for (uint16_t i = 0; i < cpus; i++)
968 {
969 lapic->u8Type = 0;
970 lapic->u8Length = sizeof(ACPITBLLAPIC);
971 lapic->u8ProcId = i;
972 /** Must match numbering convention in MPTABLES */
973 lapic->u8ApicId = i;
974 lapic->u32Flags = VMCPUSET_IS_PRESENT(&s->CpuSetAttached, i) ? RT_H2LE_U32(LAPIC_ENABLED) : 0;
975 lapic++;
976 }
977
978 /* IO-APIC record */
979 ACPITBLIOAPIC* ioapic = madt.IOApic_addr();
980 ioapic->u8Type = 1;
981 ioapic->u8Length = sizeof(ACPITBLIOAPIC);
982 /** Must match MP tables ID */
983 ioapic->u8IOApicId = cpus;
984 ioapic->u8Reserved = 0;
985 ioapic->u32Address = RT_H2LE_U32(0xfec00000);
986 ioapic->u32GSIB = RT_H2LE_U32(0);
987
988 /* Interrupt Source Overrides */
989 /* Flags:
990 bits[3:2]:
991 00 conforms to the bus
992 01 edge-triggered
993 10 reserved
994 11 level-triggered
995 bits[1:0]
996 00 conforms to the bus
997 01 active-high
998 10 reserved
999 11 active-low */
1000 /* If changing, also update PDMIsaSetIrq() and MPS */
1001 ACPITBLISO* isos = madt.ISO_addr();
1002 /* Timer interrupt rule IRQ0 to GSI2 */
1003 isos[0].u8Type = 2;
1004 isos[0].u8Length = sizeof(ACPITBLISO);
1005 isos[0].u8Bus = 0; /* Must be 0 */
1006 isos[0].u8Source = 0; /* IRQ0 */
1007 isos[0].u32GSI = 2; /* connected to pin 2 */
1008 isos[0].u16Flags = 0; /* conform to the bus */
1009
1010 /* ACPI interrupt rule - IRQ9 to GSI9 */
1011 isos[1].u8Type = 2;
1012 isos[1].u8Length = sizeof(ACPITBLISO);
1013 isos[1].u8Bus = 0; /* Must be 0 */
1014 isos[1].u8Source = 9; /* IRQ9 */
1015 isos[1].u32GSI = 9; /* connected to pin 9 */
1016 isos[1].u16Flags = 0xd; /* active high, level triggered */
1017 Assert(NUMBER_OF_IRQ_SOURCE_OVERRIDES == 2);
1018
1019 madt.header_addr()->u8Checksum = acpiChecksum(madt.data(), madt.size());
1020 acpiPhyscpy(s, addr, madt.data(), madt.size());
1021}
1022
1023
1024/** High Performance Event Timer (HPET) descriptor */
1025static void acpiSetupHPET(ACPIState *s, RTGCPHYS32 addr)
1026{
1027 ACPITBLHPET hpet;
1028
1029 memset(&hpet, 0, sizeof(hpet));
1030
1031 acpiPrepareHeader(&hpet.aHeader, "HPET", sizeof(hpet), 1);
1032 /* Keep base address consistent with appropriate DSDT entry (vbox.dsl) */
1033 acpiWriteGenericAddr(&hpet.HpetAddr,
1034 0 /* Memory address space */,
1035 64 /* Register bit width */,
1036 0 /* Bit offset */,
1037 0, /* Register access size, is it correct? */
1038 0xfed00000 /* Address */);
1039
1040 hpet.u32Id = 0x8086a201; /* must match what HPET ID returns, is it correct ? */
1041 hpet.u32Number = 0;
1042 hpet.u32MinTick = 4096;
1043 hpet.u8Attributes = 0;
1044
1045 hpet.aHeader.u8Checksum = acpiChecksum((uint8_t *)&hpet, sizeof(hpet));
1046
1047 acpiPhyscpy(s, addr, (const uint8_t *)&hpet, sizeof(hpet));
1048}
1049
1050/** MMCONFIG PCI config space access (MCFG) descriptor */
1051static void acpiSetupMCFG(ACPIState *s, RTGCPHYS32 addr)
1052{
1053 struct {
1054 ACPITBLMCFG hdr;
1055 ACPITBLMCFGENTRY entry;
1056 } tbl;
1057
1058 uint8_t u8StartBus = 0;
1059 uint8_t u8EndBus = (s->u64PciConfigMMioLength >> 20) - 1;
1060
1061 memset(&tbl, 0, sizeof(tbl));
1062
1063 acpiPrepareHeader(&tbl.hdr.aHeader, "MCFG", sizeof(tbl), 1);
1064 tbl.entry.u64BaseAddress = s->u64PciConfigMMioAddress;
1065 tbl.entry.u8StartBus = u8StartBus;
1066 tbl.entry.u8EndBus = u8EndBus;
1067 // u16PciSegmentGroup must match _SEG in ACPI table
1068
1069 tbl.hdr.aHeader.u8Checksum = acpiChecksum((uint8_t *)&tbl, sizeof(tbl));
1070
1071 acpiPhyscpy(s, addr, (const uint8_t *)&tbl, sizeof(tbl));
1072}
1073
1074/* SCI IRQ */
1075DECLINLINE(void) acpiSetIrq(ACPIState *s, int level)
1076{
1077 if (s->pm1a_ctl & SCI_EN)
1078 PDMDevHlpPCISetIrq(s->pDevIns, -1, level);
1079}
1080
1081DECLINLINE(uint32_t) pm1a_pure_en(uint32_t en)
1082{
1083 return en & ~(RSR_EN | IGN_EN);
1084}
1085
1086DECLINLINE(uint32_t) pm1a_pure_sts(uint32_t sts)
1087{
1088 return sts & ~(RSR_STS | IGN_STS);
1089}
1090
1091DECLINLINE(int) pm1a_level(ACPIState *s)
1092{
1093 return (pm1a_pure_en(s->pm1a_en) & pm1a_pure_sts(s->pm1a_sts)) != 0;
1094}
1095
1096DECLINLINE(int) gpe0_level(ACPIState *s)
1097{
1098 return (s->gpe0_en & s->gpe0_sts) != 0;
1099}
1100
1101static void update_pm1a(ACPIState *s, uint32_t sts, uint32_t en)
1102{
1103 int old_level, new_level;
1104
1105 if (gpe0_level(s))
1106 return;
1107
1108 old_level = pm1a_level(s);
1109 new_level = (pm1a_pure_en(en) & pm1a_pure_sts(sts)) != 0;
1110
1111 Log(("update_pm1a() old=%x new=%x\n", old_level, new_level));
1112
1113 s->pm1a_en = en;
1114 s->pm1a_sts = sts;
1115
1116 if (new_level != old_level)
1117 acpiSetIrq(s, new_level);
1118}
1119
1120static void update_gpe0(ACPIState *s, uint32_t sts, uint32_t en)
1121{
1122 int old_level, new_level;
1123
1124 if (pm1a_level(s))
1125 return;
1126
1127 old_level = (s->gpe0_en & s->gpe0_sts) != 0;
1128 new_level = (en & sts) != 0;
1129
1130 s->gpe0_en = en;
1131 s->gpe0_sts = sts;
1132
1133 if (new_level != old_level)
1134 acpiSetIrq(s, new_level);
1135}
1136
1137static int acpiPowerDown(ACPIState *s)
1138{
1139 int rc = PDMDevHlpVMPowerOff(s->pDevIns);
1140 if (RT_FAILURE(rc))
1141 AssertMsgFailed(("Could not power down the VM. rc = %Rrc\n", rc));
1142 return rc;
1143}
1144
1145static int acpiSleep(ACPIState *pThis)
1146{
1147 int rc;
1148
1149 /* We must set WAK_STS on resume (includes restore) so the guest knows that
1150 we've woken up and can continue executing code. The guest is probably
1151 reading the PMSTS register in a loop to check this. */
1152 pThis->fSetWakeupOnResume = true;
1153 if (pThis->fSuspendToSavedState)
1154 {
1155 rc = PDMDevHlpVMSuspendSaveAndPowerOff(pThis->pDevIns);
1156 if (rc != VERR_NOT_SUPPORTED)
1157 AssertRC(rc);
1158 else
1159 {
1160 LogRel(("ACPI: PDMDevHlpVMSuspendSaveAndPowerOff is not supported, falling back to suspend-only\n"));
1161 rc = PDMDevHlpVMSuspend(pThis->pDevIns);
1162 AssertRC(rc);
1163 }
1164 }
1165 else
1166 {
1167 rc = PDMDevHlpVMSuspend(pThis->pDevIns);
1168 AssertRC(rc);
1169 }
1170 return rc;
1171}
1172
1173/** Converts a ACPI port interface pointer to an ACPI state pointer. */
1174#define IACPIPORT_2_ACPISTATE(pInterface) ( (ACPIState*)((uintptr_t)pInterface - RT_OFFSETOF(ACPIState, IACPIPort)) )
1175
1176/**
1177 * Send an ACPI power off event.
1178 *
1179 * @returns VBox status code
1180 * @param pInterface Pointer to the interface structure containing the called function pointer.
1181 */
1182static DECLCALLBACK(int) acpiPowerButtonPress(PPDMIACPIPORT pInterface)
1183{
1184 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
1185 Log(("acpiPowerButtonPress: handled=%d status=%x\n", s->fPowerButtonHandled, s->pm1a_sts));
1186 s->fPowerButtonHandled = false;
1187 update_pm1a(s, s->pm1a_sts | PWRBTN_STS, s->pm1a_en);
1188 return VINF_SUCCESS;
1189}
1190
1191/**
1192 * Check if the ACPI power button event was handled.
1193 *
1194 * @returns VBox status code
1195 * @param pInterface Pointer to the interface structure containing the called function pointer.
1196 * @param pfHandled Return true if the power button event was handled by the guest.
1197 */
1198static DECLCALLBACK(int) acpiGetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled)
1199{
1200 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
1201 *pfHandled = s->fPowerButtonHandled;
1202 return VINF_SUCCESS;
1203}
1204
1205/**
1206 * Check if the Guest entered into G0 (working) or G1 (sleeping).
1207 *
1208 * @returns VBox status code
1209 * @param pInterface Pointer to the interface structure containing the called function pointer.
1210 * @param pfEntered Return true if the guest entered the ACPI mode.
1211 */
1212static DECLCALLBACK(int) acpiGetGuestEnteredACPIMode(PPDMIACPIPORT pInterface, bool *pfEntered)
1213{
1214 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
1215 *pfEntered = (s->pm1a_ctl & SCI_EN) != 0;
1216 return VINF_SUCCESS;
1217}
1218
1219static DECLCALLBACK(int) acpiGetCpuStatus(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked)
1220{
1221 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
1222 *pfLocked = VMCPUSET_IS_PRESENT(&s->CpuSetLocked, uCpu);
1223 return VINF_SUCCESS;
1224}
1225
1226/**
1227 * Send an ACPI sleep button event.
1228 *
1229 * @returns VBox status code
1230 * @param pInterface Pointer to the interface structure containing the called function pointer.
1231 */
1232static DECLCALLBACK(int) acpiSleepButtonPress(PPDMIACPIPORT pInterface)
1233{
1234 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
1235 update_pm1a(s, s->pm1a_sts | SLPBTN_STS, s->pm1a_en);
1236 return VINF_SUCCESS;
1237}
1238
1239/* PM1a_EVT_BLK enable */
1240static uint32_t acpiPm1aEnReadw(ACPIState *s, uint32_t addr)
1241{
1242 uint16_t val = s->pm1a_en;
1243 Log(("acpi: acpiPm1aEnReadw -> %#x\n", val));
1244 return val;
1245}
1246
1247static void acpiPM1aEnWritew(ACPIState *s, uint32_t addr, uint32_t val)
1248{
1249 Log(("acpi: acpiPM1aEnWritew <- %#x (%#x)\n", val, val & ~(RSR_EN | IGN_EN)));
1250 val &= ~(RSR_EN | IGN_EN);
1251 update_pm1a(s, s->pm1a_sts, val);
1252}
1253
1254/* PM1a_EVT_BLK status */
1255static uint32_t acpiPm1aStsReadw(ACPIState *s, uint32_t addr)
1256{
1257 uint16_t val = s->pm1a_sts;
1258 Log(("acpi: acpiPm1aStsReadw -> %#x\n", val));
1259 return val;
1260}
1261
1262static void acpiPM1aStsWritew(ACPIState *s, uint32_t addr, uint32_t val)
1263{
1264 Log(("acpi: acpiPM1aStsWritew <- %#x (%#x)\n", val, val & ~(RSR_STS | IGN_STS)));
1265 if (val & PWRBTN_STS)
1266 s->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */
1267 val = s->pm1a_sts & ~(val & ~(RSR_STS | IGN_STS));
1268 update_pm1a(s, val, s->pm1a_en);
1269}
1270
1271/* PM1a_CTL_BLK */
1272static uint32_t acpiPm1aCtlReadw(ACPIState *s, uint32_t addr)
1273{
1274 uint16_t val = s->pm1a_ctl;
1275 Log(("acpi: acpiPm1aCtlReadw -> %#x\n", val));
1276 return val;
1277}
1278
1279static int acpiPM1aCtlWritew(ACPIState *s, uint32_t addr, uint32_t val)
1280{
1281 uint32_t uSleepState;
1282
1283 Log(("acpi: acpiPM1aCtlWritew <- %#x (%#x)\n", val, val & ~(RSR_CNT | IGN_CNT)));
1284 s->pm1a_ctl = val & ~(RSR_CNT | IGN_CNT);
1285
1286 uSleepState = (s->pm1a_ctl >> SLP_TYPx_SHIFT) & SLP_TYPx_MASK;
1287 if (uSleepState != s->uSleepState)
1288 {
1289 s->uSleepState = uSleepState;
1290 switch (uSleepState)
1291 {
1292 case 0x00: /* S0 */
1293 break;
1294 case 0x01: /* S1 */
1295 if (s->fS1Enabled)
1296 {
1297 LogRel(("Entering S1 power state (powered-on suspend)\n"));
1298 return acpiSleep(s);
1299 }
1300 else
1301 LogRel(("Ignoring guest attempt to enter S1 power state (powered-on suspend)!\n"));
1302 case 0x04: /* S4 */
1303 if (s->fS4Enabled)
1304 {
1305 LogRel(("Entering S4 power state (suspend to disk)\n"));
1306 return acpiPowerDown(s);/* Same behavior as S5 */
1307 }
1308 else
1309 LogRel(("Ignoring guest attempt to enter S4 power state (suspend to disk)!\n"));
1310 case 0x05: /* S5 */
1311 LogRel(("Entering S5 power state (power down)\n"));
1312 return acpiPowerDown(s);
1313 default:
1314 AssertMsgFailed(("Unknown sleep state %#x\n", uSleepState));
1315 break;
1316 }
1317 }
1318 return VINF_SUCCESS;
1319}
1320
1321/* GPE0_BLK */
1322static uint32_t acpiGpe0EnReadb(ACPIState *s, uint32_t addr)
1323{
1324 uint8_t val = s->gpe0_en;
1325 Log(("acpi: acpiGpe0EnReadl -> %#x\n", val));
1326 return val;
1327}
1328
1329static void acpiGpe0EnWriteb(ACPIState *s, uint32_t addr, uint32_t val)
1330{
1331 Log(("acpi: acpiGpe0EnWritel <- %#x\n", val));
1332 update_gpe0(s, s->gpe0_sts, val);
1333}
1334
1335static uint32_t acpiGpe0StsReadb(ACPIState *s, uint32_t addr)
1336{
1337 uint8_t val = s->gpe0_sts;
1338 Log(("acpi: acpiGpe0StsReadl -> %#x\n", val));
1339 return val;
1340}
1341
1342static void acpiGpe0StsWriteb(ACPIState *s, uint32_t addr, uint32_t val)
1343{
1344 val = s->gpe0_sts & ~val;
1345 update_gpe0(s, val, s->gpe0_en);
1346 Log(("acpi: acpiGpe0StsWritel <- %#x\n", val));
1347}
1348
1349static int acpiResetWriteU8(ACPIState *s, uint32_t addr, uint32_t val)
1350{
1351 int rc = VINF_SUCCESS;
1352
1353 Log(("ACPI: acpiResetWriteU8: %x %x\n", addr, val));
1354 if (val == ACPI_RESET_REG_VAL)
1355 {
1356# ifndef IN_RING3
1357 rc = VINF_IOM_HC_IOPORT_WRITE;
1358# else /* IN_RING3 */
1359 rc = PDMDevHlpVMReset(s->pDevIns);
1360# endif /* !IN_RING3 */
1361 }
1362 return rc;
1363}
1364
1365/* SMI */
1366static void acpiSmiWriteU8(ACPIState *s, uint32_t addr, uint32_t val)
1367{
1368 Log(("acpi: acpiSmiWriteU8 %#x\n", val));
1369 if (val == ACPI_ENABLE)
1370 s->pm1a_ctl |= SCI_EN;
1371 else if (val == ACPI_DISABLE)
1372 s->pm1a_ctl &= ~SCI_EN;
1373 else
1374 Log(("acpi: acpiSmiWriteU8 %#x <- unknown value\n", val));
1375}
1376
1377static uint32_t find_rsdp_space(void)
1378{
1379 return 0xe0000;
1380}
1381
1382static int acpiPMTimerReset(ACPIState *s)
1383{
1384 uint64_t interval, freq;
1385
1386 freq = TMTimerGetFreq(s->CTX_SUFF(ts));
1387 interval = ASMMultU64ByU32DivByU32(0xffffffff, freq, PM_TMR_FREQ);
1388 Log(("interval = %RU64\n", interval));
1389 TMTimerSet(s->CTX_SUFF(ts), TMTimerGet(s->CTX_SUFF(ts)) + interval);
1390
1391 return VINF_SUCCESS;
1392}
1393
1394static DECLCALLBACK(void) acpiTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
1395{
1396 ACPIState *s = (ACPIState *)pvUser;
1397
1398 Log(("acpi: pm timer sts %#x (%d), en %#x (%d)\n",
1399 s->pm1a_sts, (s->pm1a_sts & TMR_STS) != 0,
1400 s->pm1a_en, (s->pm1a_en & TMR_EN) != 0));
1401
1402 update_pm1a(s, s->pm1a_sts | TMR_STS, s->pm1a_en);
1403 acpiPMTimerReset(s);
1404}
1405
1406/**
1407 * _BST method.
1408 */
1409static int acpiFetchBatteryStatus(ACPIState *s)
1410{
1411 uint32_t *p = s->au8BatteryInfo;
1412 bool fPresent; /* battery present? */
1413 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
1414 PDMACPIBATSTATE hostBatteryState; /* bitfield */
1415 uint32_t hostPresentRate; /* 0..1000 */
1416 int rc;
1417
1418 if (!s->pDrv)
1419 return VINF_SUCCESS;
1420 rc = s->pDrv->pfnQueryBatteryStatus(s->pDrv, &fPresent, &hostRemainingCapacity,
1421 &hostBatteryState, &hostPresentRate);
1422 AssertRC(rc);
1423
1424 /* default values */
1425 p[BAT_STATUS_STATE] = hostBatteryState;
1426 p[BAT_STATUS_PRESENT_RATE] = hostPresentRate == ~0U ? 0xFFFFFFFF
1427 : hostPresentRate * 50; /* mW */
1428 p[BAT_STATUS_REMAINING_CAPACITY] = 50000; /* mWh */
1429 p[BAT_STATUS_PRESENT_VOLTAGE] = 10000; /* mV */
1430
1431 /* did we get a valid battery state? */
1432 if (hostRemainingCapacity != PDM_ACPI_BAT_CAPACITY_UNKNOWN)
1433 p[BAT_STATUS_REMAINING_CAPACITY] = hostRemainingCapacity * 500; /* mWh */
1434 if (hostBatteryState == PDM_ACPI_BAT_STATE_CHARGED)
1435 p[BAT_STATUS_PRESENT_RATE] = 0; /* mV */
1436
1437 return VINF_SUCCESS;
1438}
1439
1440/**
1441 * _BIF method.
1442 */
1443static int acpiFetchBatteryInfo(ACPIState *s)
1444{
1445 uint32_t *p = s->au8BatteryInfo;
1446
1447 p[BAT_INFO_UNITS] = 0; /* mWh */
1448 p[BAT_INFO_DESIGN_CAPACITY] = 50000; /* mWh */
1449 p[BAT_INFO_LAST_FULL_CHARGE_CAPACITY] = 50000; /* mWh */
1450 p[BAT_INFO_TECHNOLOGY] = BAT_TECH_PRIMARY;
1451 p[BAT_INFO_DESIGN_VOLTAGE] = 10000; /* mV */
1452 p[BAT_INFO_DESIGN_CAPACITY_OF_WARNING] = 100; /* mWh */
1453 p[BAT_INFO_DESIGN_CAPACITY_OF_LOW] = 50; /* mWh */
1454 p[BAT_INFO_CAPACITY_GRANULARITY_1] = 1; /* mWh */
1455 p[BAT_INFO_CAPACITY_GRANULARITY_2] = 1; /* mWh */
1456
1457 return VINF_SUCCESS;
1458}
1459
1460/**
1461 * _STA method.
1462 */
1463static uint32_t acpiGetBatteryDeviceStatus(ACPIState *s)
1464{
1465 bool fPresent; /* battery present? */
1466 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
1467 PDMACPIBATSTATE hostBatteryState; /* bitfield */
1468 uint32_t hostPresentRate; /* 0..1000 */
1469 int rc;
1470
1471 if (!s->pDrv)
1472 return 0;
1473 rc = s->pDrv->pfnQueryBatteryStatus(s->pDrv, &fPresent, &hostRemainingCapacity,
1474 &hostBatteryState, &hostPresentRate);
1475 AssertRC(rc);
1476
1477 return fPresent
1478 ? STA_DEVICE_PRESENT_MASK /* present */
1479 | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */
1480 | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */
1481 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */
1482 | STA_BATTERY_PRESENT_MASK /* battery is present */
1483 : 0; /* device not present */
1484}
1485
1486static uint32_t acpiGetPowerSource(ACPIState *s)
1487{
1488 PDMACPIPOWERSOURCE ps;
1489
1490 /* query the current power source from the host driver */
1491 if (!s->pDrv)
1492 return AC_ONLINE;
1493 int rc = s->pDrv->pfnQueryPowerSource(s->pDrv, &ps);
1494 AssertRC(rc);
1495 return ps == PDM_ACPI_POWER_SOURCE_BATTERY ? AC_OFFLINE : AC_ONLINE;
1496}
1497
1498PDMBOTHCBDECL(int) acpiBatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1499{
1500 ACPIState *s = (ACPIState *)pvUser;
1501
1502 switch (cb)
1503 {
1504 case 4:
1505 u32 >>= s->u8IndexShift;
1506 /* see comment at the declaration of u8IndexShift */
1507 if (s->u8IndexShift == 0 && u32 == (BAT_DEVICE_STATUS << 2))
1508 {
1509 s->u8IndexShift = 2;
1510 u32 >>= 2;
1511 }
1512 Assert(u32 < BAT_INDEX_LAST);
1513 s->uBatteryIndex = u32;
1514 break;
1515 default:
1516 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1517 break;
1518 }
1519 return VINF_SUCCESS;
1520}
1521
1522PDMBOTHCBDECL(int) acpiBatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1523{
1524 ACPIState *s = (ACPIState *)pvUser;
1525
1526 switch (cb)
1527 {
1528 case 4:
1529 switch (s->uBatteryIndex)
1530 {
1531 case BAT_STATUS_STATE:
1532 acpiFetchBatteryStatus(s);
1533 case BAT_STATUS_PRESENT_RATE:
1534 case BAT_STATUS_REMAINING_CAPACITY:
1535 case BAT_STATUS_PRESENT_VOLTAGE:
1536 *pu32 = s->au8BatteryInfo[s->uBatteryIndex];
1537 break;
1538
1539 case BAT_INFO_UNITS:
1540 acpiFetchBatteryInfo(s);
1541 case BAT_INFO_DESIGN_CAPACITY:
1542 case BAT_INFO_LAST_FULL_CHARGE_CAPACITY:
1543 case BAT_INFO_TECHNOLOGY:
1544 case BAT_INFO_DESIGN_VOLTAGE:
1545 case BAT_INFO_DESIGN_CAPACITY_OF_WARNING:
1546 case BAT_INFO_DESIGN_CAPACITY_OF_LOW:
1547 case BAT_INFO_CAPACITY_GRANULARITY_1:
1548 case BAT_INFO_CAPACITY_GRANULARITY_2:
1549 *pu32 = s->au8BatteryInfo[s->uBatteryIndex];
1550 break;
1551
1552 case BAT_DEVICE_STATUS:
1553 *pu32 = acpiGetBatteryDeviceStatus(s);
1554 break;
1555
1556 case BAT_POWER_SOURCE:
1557 *pu32 = acpiGetPowerSource(s);
1558 break;
1559
1560 default:
1561 AssertMsgFailed(("Invalid battery index %d\n", s->uBatteryIndex));
1562 break;
1563 }
1564 break;
1565 default:
1566 return VERR_IOM_IOPORT_UNUSED;
1567 }
1568 return VINF_SUCCESS;
1569}
1570
1571PDMBOTHCBDECL(int) acpiSysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1572{
1573 ACPIState *s = (ACPIState *)pvUser;
1574
1575 Log(("system_index = %d, %d\n", u32, u32 >> 2));
1576 switch (cb)
1577 {
1578 case 4:
1579 if (u32 == SYSTEM_INFO_INDEX_VALID || u32 == SYSTEM_INFO_INDEX_INVALID)
1580 s->uSystemInfoIndex = u32;
1581 else
1582 {
1583 /* see comment at the declaration of u8IndexShift */
1584 if ((u32 > SYSTEM_INFO_INDEX_END) && (s->u8IndexShift == 0))
1585 {
1586 if (((u32 >> 2) < SYSTEM_INFO_INDEX_END) && ((u32 & 0x3)) == 0)
1587 {
1588 s->u8IndexShift = 2;
1589 }
1590 }
1591
1592 u32 >>= s->u8IndexShift;
1593 Assert(u32 < SYSTEM_INFO_INDEX_END);
1594 s->uSystemInfoIndex = u32;
1595 }
1596 break;
1597
1598 default:
1599 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1600 break;
1601 }
1602 return VINF_SUCCESS;
1603}
1604
1605PDMBOTHCBDECL(int) acpiSysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1606{
1607 ACPIState *s = (ACPIState *)pvUser;
1608
1609 switch (cb)
1610 {
1611 case 4:
1612 switch (s->uSystemInfoIndex)
1613 {
1614 case SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH:
1615 *pu32 = s->cbRamLow;
1616 break;
1617
1618 case SYSTEM_INFO_INDEX_HIGH_MEMORY_LENGTH:
1619 *pu32 = s->cbRamHigh >> 16; /* 64KB units */
1620 Assert(((uint64_t)*pu32 << 16) == s->cbRamHigh);
1621 break;
1622
1623 case SYSTEM_INFO_INDEX_USE_IOAPIC:
1624 *pu32 = s->u8UseIOApic;
1625 break;
1626
1627 case SYSTEM_INFO_INDEX_HPET_STATUS:
1628 *pu32 = s->fUseHpet ? ( STA_DEVICE_PRESENT_MASK
1629 | STA_DEVICE_ENABLED_MASK
1630 | STA_DEVICE_SHOW_IN_UI_MASK
1631 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
1632 : 0;
1633 break;
1634
1635 case SYSTEM_INFO_INDEX_SMC_STATUS:
1636 *pu32 = s->fUseSmc ? ( STA_DEVICE_PRESENT_MASK
1637 | STA_DEVICE_ENABLED_MASK
1638 /* no need to show this device in the UI */
1639 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
1640 : 0;
1641 break;
1642
1643 case SYSTEM_INFO_INDEX_FDC_STATUS:
1644 *pu32 = s->fUseFdc ? ( STA_DEVICE_PRESENT_MASK
1645 | STA_DEVICE_ENABLED_MASK
1646 | STA_DEVICE_SHOW_IN_UI_MASK
1647 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
1648 : 0;
1649 break;
1650
1651 case SYSTEM_INFO_INDEX_NIC_ADDRESS:
1652 *pu32 = s->u32NicPciAddress;
1653 break;
1654
1655 case SYSTEM_INFO_INDEX_AUDIO_ADDRESS:
1656 *pu32 = s->u32AudioPciAddress;
1657 break;
1658
1659 case SYSTEM_INFO_INDEX_POWER_STATES:
1660 *pu32 = RT_BIT(0) | RT_BIT(5); /* S1 and S5 always exposed */
1661 if (s->fS1Enabled) /* Optionally expose S1 and S4 */
1662 *pu32 |= RT_BIT(1);
1663 if (s->fS4Enabled)
1664 *pu32 |= RT_BIT(4);
1665 break;
1666
1667 case SYSTEM_INFO_INDEX_IOC_ADDRESS:
1668 *pu32 = s->u32IocPciAddress;
1669 break;
1670
1671 case SYSTEM_INFO_INDEX_HBC_ADDRESS:
1672 *pu32 = s->u32HbcPciAddress;
1673 break;
1674
1675 case SYSTEM_INFO_INDEX_PCI_BASE:
1676 /** @todo: couldn't MCFG be in 64-bit range? */
1677 Assert(s->u64PciConfigMMioAddress < 0xffffffff);
1678 *pu32 = (uint32_t)s->u64PciConfigMMioAddress;
1679 break;
1680
1681 case SYSTEM_INFO_INDEX_PCI_LENGTH:
1682 /** @todo: couldn't MCFG be in 64-bit range? */
1683 Assert(s->u64PciConfigMMioLength< 0xffffffff);
1684 *pu32 = (uint32_t)s->u64PciConfigMMioLength;
1685 break;
1686
1687 /* This is only for compatibility with older saved states that
1688 may include ACPI code that read these values. Legacy is
1689 a wonderful thing, isn't it? :-) */
1690 case SYSTEM_INFO_INDEX_CPU0_STATUS:
1691 case SYSTEM_INFO_INDEX_CPU1_STATUS:
1692 case SYSTEM_INFO_INDEX_CPU2_STATUS:
1693 case SYSTEM_INFO_INDEX_CPU3_STATUS:
1694 *pu32 = ( s->fShowCpu
1695 && s->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS < s->cCpus
1696 && VMCPUSET_IS_PRESENT(&s->CpuSetAttached,
1697 s->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS))
1698 ? ( STA_DEVICE_PRESENT_MASK
1699 | STA_DEVICE_ENABLED_MASK
1700 | STA_DEVICE_SHOW_IN_UI_MASK
1701 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
1702 : 0;
1703 break;
1704
1705 case SYSTEM_INFO_INDEX_RTC_STATUS:
1706 *pu32 = s->fShowRtc ? ( STA_DEVICE_PRESENT_MASK
1707 | STA_DEVICE_ENABLED_MASK
1708 | STA_DEVICE_SHOW_IN_UI_MASK
1709 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
1710 : 0;
1711 break;
1712
1713 case SYSTEM_INFO_INDEX_CPU_LOCKED:
1714 {
1715 if (s->idCpuLockCheck < VMM_MAX_CPU_COUNT)
1716 {
1717 *pu32 = VMCPUSET_IS_PRESENT(&s->CpuSetLocked, s->idCpuLockCheck);
1718 s->idCpuLockCheck = UINT32_C(0xffffffff); /* Make the entry invalid */
1719 }
1720 else
1721 {
1722 AssertMsgFailed(("ACPI: CPU lock check protocol violation\n"));
1723 /* Always return locked status just to be safe */
1724 *pu32 = 1;
1725 }
1726 break;
1727 }
1728
1729 case SYSTEM_INFO_INDEX_CPU_EVENT_TYPE:
1730 *pu32 = s->u32CpuEventType;
1731 break;
1732
1733 case SYSTEM_INFO_INDEX_CPU_EVENT:
1734 *pu32 = s->u32CpuEvent;
1735 break;
1736
1737 case SYSTEM_INFO_INDEX_SERIAL0_IOBASE:
1738 *pu32 = s->uSerial0IoPortBase;
1739 break;
1740
1741 case SYSTEM_INFO_INDEX_SERIAL0_IRQ:
1742 *pu32 = s->uSerial0Irq;
1743 break;
1744
1745 case SYSTEM_INFO_INDEX_SERIAL1_IOBASE:
1746 *pu32 = s->uSerial1IoPortBase;
1747 break;
1748
1749 case SYSTEM_INFO_INDEX_SERIAL1_IRQ:
1750 *pu32 = s->uSerial1Irq;
1751 break;
1752
1753 case SYSTEM_INFO_INDEX_END:
1754 break;
1755
1756 /* Solaris 9 tries to read from this index */
1757 case SYSTEM_INFO_INDEX_INVALID:
1758 *pu32 = 0;
1759 break;
1760
1761 default:
1762 AssertMsgFailed(("Invalid system info index %d\n", s->uSystemInfoIndex));
1763 break;
1764 }
1765 break;
1766
1767 default:
1768 return VERR_IOM_IOPORT_UNUSED;
1769 }
1770
1771 Log(("index %d val %d\n", s->uSystemInfoIndex, *pu32));
1772 return VINF_SUCCESS;
1773}
1774
1775PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1776{
1777 ACPIState *s = (ACPIState *)pvUser;
1778
1779 Log(("addr=%#x cb=%d u32=%#x si=%#x\n", Port, cb, u32, s->uSystemInfoIndex));
1780
1781 if (cb == 4)
1782 {
1783 switch (s->uSystemInfoIndex)
1784 {
1785 case SYSTEM_INFO_INDEX_INVALID:
1786 AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32));
1787 s->u8IndexShift = 0;
1788 break;
1789
1790 case SYSTEM_INFO_INDEX_VALID:
1791 AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32));
1792 s->u8IndexShift = 2;
1793 break;
1794
1795 case SYSTEM_INFO_INDEX_CPU_LOCK_CHECK:
1796 s->idCpuLockCheck = u32;
1797 break;
1798
1799 case SYSTEM_INFO_INDEX_CPU_LOCKED:
1800 if (u32 < s->cCpus)
1801 VMCPUSET_DEL(&s->CpuSetLocked, u32); /* Unlock the CPU */
1802 else
1803 LogRel(("ACPI: CPU %u does not exist\n", u32));
1804 break;
1805
1806 default:
1807 AssertMsgFailed(("Port=%#x cb=%d u32=%#x system_index=%#x\n",
1808 Port, cb, u32, s->uSystemInfoIndex));
1809 break;
1810 }
1811 }
1812 else
1813 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1814 return VINF_SUCCESS;
1815}
1816
1817/** @todo Don't call functions, but do the job in the read/write handlers
1818 * here! */
1819
1820/* IO Helpers */
1821PDMBOTHCBDECL(int) acpiPm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1822{
1823 switch (cb)
1824 {
1825 case 2:
1826 *pu32 = acpiPm1aEnReadw((ACPIState*)pvUser, Port);
1827 break;
1828 default:
1829 return VERR_IOM_IOPORT_UNUSED;
1830 }
1831 return VINF_SUCCESS;
1832}
1833
1834PDMBOTHCBDECL(int) acpiPm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1835{
1836 switch (cb)
1837 {
1838 case 2:
1839 *pu32 = acpiPm1aStsReadw((ACPIState*)pvUser, Port);
1840 break;
1841 default:
1842 AssertMsgFailed(("PM1 status read: width %d\n", cb));
1843 return VERR_IOM_IOPORT_UNUSED;
1844 }
1845 return VINF_SUCCESS;
1846}
1847
1848PDMBOTHCBDECL(int) acpiPm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1849{
1850 switch (cb)
1851 {
1852 case 2:
1853 *pu32 = acpiPm1aCtlReadw((ACPIState*)pvUser, Port);
1854 break;
1855 default:
1856 AssertMsgFailed(("PM1 control read: width %d\n", cb));
1857 return VERR_IOM_IOPORT_UNUSED;
1858 }
1859 return VINF_SUCCESS;
1860}
1861
1862PDMBOTHCBDECL(int) acpiPM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1863{
1864 switch (cb)
1865 {
1866 case 2:
1867 acpiPM1aEnWritew((ACPIState*)pvUser, Port, u32);
1868 break;
1869 case 4:
1870 acpiPM1aEnWritew((ACPIState*)pvUser, Port, u32 & 0xffff);
1871 break;
1872 default:
1873 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1874 break;
1875 }
1876 return VINF_SUCCESS;
1877}
1878
1879PDMBOTHCBDECL(int) acpiPM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1880{
1881 switch (cb)
1882 {
1883 case 2:
1884 acpiPM1aStsWritew((ACPIState*)pvUser, Port, u32);
1885 break;
1886 case 4:
1887 acpiPM1aStsWritew((ACPIState*)pvUser, Port, u32 & 0xffff);
1888 break;
1889 default:
1890 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1891 break;
1892 }
1893 return VINF_SUCCESS;
1894}
1895
1896PDMBOTHCBDECL(int) acpiPM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1897{
1898 switch (cb)
1899 {
1900 case 2:
1901 return acpiPM1aCtlWritew((ACPIState*)pvUser, Port, u32);
1902 case 4:
1903 return acpiPM1aCtlWritew((ACPIState*)pvUser, Port, u32 & 0xffff);
1904 default:
1905 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1906 break;
1907 }
1908 return VINF_SUCCESS;
1909}
1910
1911#endif /* IN_RING3 */
1912
1913/**
1914 * PMTMR readable from host/guest.
1915 */
1916PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1917{
1918 if (cb == 4)
1919 {
1920 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
1921 int64_t now = TMTimerGet(s->CTX_SUFF(ts));
1922 int64_t elapsed = now - s->pm_timer_initial;
1923
1924 *pu32 = ASMMultU64ByU32DivByU32(elapsed, PM_TMR_FREQ, TMTimerGetFreq(s->CTX_SUFF(ts)));
1925 Log(("acpi: acpiPMTmrRead -> %#x\n", *pu32));
1926 return VINF_SUCCESS;
1927 }
1928 return VERR_IOM_IOPORT_UNUSED;
1929}
1930
1931#ifdef IN_RING3
1932
1933PDMBOTHCBDECL(int) acpiGpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1934{
1935 switch (cb)
1936 {
1937 case 1:
1938 *pu32 = acpiGpe0StsReadb((ACPIState*)pvUser, Port);
1939 break;
1940 default:
1941 return VERR_IOM_IOPORT_UNUSED;
1942 }
1943 return VINF_SUCCESS;
1944}
1945
1946PDMBOTHCBDECL(int) acpiGpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1947{
1948 switch (cb)
1949 {
1950 case 1:
1951 *pu32 = acpiGpe0EnReadb((ACPIState*)pvUser, Port);
1952 break;
1953 default:
1954 return VERR_IOM_IOPORT_UNUSED;
1955 }
1956 return VINF_SUCCESS;
1957}
1958
1959PDMBOTHCBDECL(int) acpiGpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1960{
1961 switch (cb)
1962 {
1963 case 1:
1964 acpiGpe0StsWriteb((ACPIState*)pvUser, Port, u32);
1965 break;
1966 default:
1967 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1968 break;
1969 }
1970 return VINF_SUCCESS;
1971}
1972
1973PDMBOTHCBDECL(int) acpiGpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1974{
1975 switch (cb)
1976 {
1977 case 1:
1978 acpiGpe0EnWriteb((ACPIState*)pvUser, Port, u32);
1979 break;
1980 default:
1981 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1982 break;
1983 }
1984 return VINF_SUCCESS;
1985}
1986
1987PDMBOTHCBDECL(int) acpiSmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1988{
1989 switch (cb)
1990 {
1991 case 1:
1992 acpiSmiWriteU8((ACPIState*)pvUser, Port, u32);
1993 break;
1994 default:
1995 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1996 break;
1997 }
1998 return VINF_SUCCESS;
1999}
2000
2001PDMBOTHCBDECL(int) acpiResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2002{
2003 switch (cb)
2004 {
2005 case 1:
2006 return acpiResetWriteU8((ACPIState*)pvUser, Port, u32);
2007 default:
2008 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
2009 break;
2010 }
2011 return VINF_SUCCESS;
2012}
2013
2014#ifdef DEBUG_ACPI
2015
2016PDMBOTHCBDECL(int) acpiDhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2017{
2018 switch (cb)
2019 {
2020 case 1:
2021 Log(("%#x\n", u32 & 0xff));
2022 break;
2023 case 2:
2024 Log(("%#6x\n", u32 & 0xffff));
2025 case 4:
2026 Log(("%#10x\n", u32));
2027 break;
2028 default:
2029 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
2030 break;
2031 }
2032 return VINF_SUCCESS;
2033}
2034
2035PDMBOTHCBDECL(int) acpiDchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2036{
2037 switch (cb)
2038 {
2039 case 1:
2040 Log(("%c", u32 & 0xff));
2041 break;
2042 default:
2043 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
2044 break;
2045 }
2046 return VINF_SUCCESS;
2047}
2048
2049#endif /* DEBUG_ACPI */
2050
2051static int acpiRegisterPmHandlers(ACPIState* pThis)
2052{
2053 int rc = VINF_SUCCESS;
2054
2055#define R(offset, cnt, writer, reader, description) \
2056 do { \
2057 rc = PDMDevHlpIOPortRegister(pThis->pDevIns, acpiPmPort(pThis, offset), cnt, pThis, writer, reader, \
2058 NULL, NULL, description); \
2059 if (RT_FAILURE(rc)) \
2060 return rc; \
2061 } while (0)
2062#define L (GPE0_BLK_LEN / 2)
2063
2064 R(PM1a_EVT_OFFSET+2, 1, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable");
2065 R(PM1a_EVT_OFFSET, 1, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status");
2066 R(PM1a_CTL_OFFSET, 1, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control");
2067 R(PM_TMR_OFFSET, 1, NULL, acpiPMTmrRead, "ACPI PM Timer");
2068 R(GPE0_OFFSET + L, L, acpiGpe0EnWrite, acpiGpe0EnRead, "ACPI GPE0 Enable");
2069 R(GPE0_OFFSET, L, acpiGpe0StsWrite, acpiGpe0StsRead, "ACPI GPE0 Status");
2070#undef L
2071#undef R
2072
2073 /* register RC stuff */
2074 if (pThis->fGCEnabled)
2075 {
2076 rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, acpiPmPort(pThis, PM_TMR_OFFSET),
2077 1, 0, NULL, "acpiPMTmrRead",
2078 NULL, NULL, "ACPI PM Timer");
2079 AssertRCReturn(rc, rc);
2080 }
2081
2082 /* register R0 stuff */
2083 if (pThis->fR0Enabled)
2084 {
2085 rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, acpiPmPort(pThis, PM_TMR_OFFSET),
2086 1, 0, NULL, "acpiPMTmrRead",
2087 NULL, NULL, "ACPI PM Timer");
2088 AssertRCReturn(rc, rc);
2089 }
2090
2091 return rc;
2092}
2093
2094static int acpiUnregisterPmHandlers(ACPIState *pThis)
2095{
2096#define U(offset, cnt) \
2097 do { \
2098 int rc = PDMDevHlpIOPortDeregister(pThis->pDevIns, acpiPmPort(pThis, offset), cnt); \
2099 AssertRCReturn(rc, rc); \
2100 } while (0)
2101#define L (GPE0_BLK_LEN / 2)
2102
2103 U(PM1a_EVT_OFFSET+2, 1);
2104 U(PM1a_EVT_OFFSET, 1);
2105 U(PM1a_CTL_OFFSET, 1);
2106 U(PM_TMR_OFFSET, 1);
2107 U(GPE0_OFFSET + L, L);
2108 U(GPE0_OFFSET, L);
2109#undef L
2110#undef U
2111
2112 return VINF_SUCCESS;
2113}
2114
2115/**
2116 * Saved state structure description, version 4.
2117 */
2118static const SSMFIELD g_AcpiSavedStateFields4[] =
2119{
2120 SSMFIELD_ENTRY(ACPIState, pm1a_en),
2121 SSMFIELD_ENTRY(ACPIState, pm1a_sts),
2122 SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
2123 SSMFIELD_ENTRY(ACPIState, pm_timer_initial),
2124 SSMFIELD_ENTRY(ACPIState, gpe0_en),
2125 SSMFIELD_ENTRY(ACPIState, gpe0_sts),
2126 SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
2127 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
2128 SSMFIELD_ENTRY(ACPIState, u64RamSize),
2129 SSMFIELD_ENTRY(ACPIState, u8IndexShift),
2130 SSMFIELD_ENTRY(ACPIState, u8UseIOApic),
2131 SSMFIELD_ENTRY(ACPIState, uSleepState),
2132 SSMFIELD_ENTRY_TERM()
2133};
2134
2135/**
2136 * Saved state structure description, version 5.
2137 */
2138static const SSMFIELD g_AcpiSavedStateFields5[] =
2139{
2140 SSMFIELD_ENTRY(ACPIState, pm1a_en),
2141 SSMFIELD_ENTRY(ACPIState, pm1a_sts),
2142 SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
2143 SSMFIELD_ENTRY(ACPIState, pm_timer_initial),
2144 SSMFIELD_ENTRY(ACPIState, gpe0_en),
2145 SSMFIELD_ENTRY(ACPIState, gpe0_sts),
2146 SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
2147 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
2148 SSMFIELD_ENTRY(ACPIState, uSleepState),
2149 SSMFIELD_ENTRY(ACPIState, u8IndexShift),
2150 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
2151 SSMFIELD_ENTRY_TERM()
2152};
2153
2154/**
2155 * Saved state structure description, version 6.
2156 */
2157static const SSMFIELD g_AcpiSavedStateFields6[] =
2158{
2159 SSMFIELD_ENTRY(ACPIState, pm1a_en),
2160 SSMFIELD_ENTRY(ACPIState, pm1a_sts),
2161 SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
2162 SSMFIELD_ENTRY(ACPIState, pm_timer_initial),
2163 SSMFIELD_ENTRY(ACPIState, gpe0_en),
2164 SSMFIELD_ENTRY(ACPIState, gpe0_sts),
2165 SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
2166 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
2167 SSMFIELD_ENTRY(ACPIState, uSleepState),
2168 SSMFIELD_ENTRY(ACPIState, u8IndexShift),
2169 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
2170 SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState),
2171 SSMFIELD_ENTRY_TERM()
2172};
2173
2174
2175/**
2176 * @callback_method_impl{FNSSMDEVSAVEEXEC}
2177 */
2178static DECLCALLBACK(int) acpiSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2179{
2180 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
2181 return SSMR3PutStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields6[0]);
2182}
2183
2184/**
2185 * @callback_method_impl{FNSSMDEVLOADEXEC}
2186 */
2187static DECLCALLBACK(int) acpiLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
2188 uint32_t uVersion, uint32_t uPass)
2189{
2190 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
2191 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
2192
2193 /*
2194 * Unregister PM handlers, will register with actual base after state
2195 * successfully loaded.
2196 */
2197 int rc = acpiUnregisterPmHandlers(pThis);
2198 if (RT_FAILURE(rc))
2199 return rc;
2200
2201 switch (uVersion)
2202 {
2203 case 4:
2204 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields4[0]);
2205 break;
2206 case 5:
2207 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields5[0]);
2208 break;
2209 case 6:
2210 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields6[0]);
2211 break;
2212 default:
2213 rc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
2214 break;
2215 }
2216 if (RT_SUCCESS(rc))
2217 {
2218 rc = acpiRegisterPmHandlers(pThis);
2219 if (RT_FAILURE(rc))
2220 return rc;
2221 rc = acpiFetchBatteryStatus(pThis);
2222 if (RT_FAILURE(rc))
2223 return rc;
2224 rc = acpiFetchBatteryInfo(pThis);
2225 if (RT_FAILURE(rc))
2226 return rc;
2227 rc = acpiPMTimerReset(pThis);
2228 if (RT_FAILURE(rc))
2229 return rc;
2230 }
2231 return rc;
2232}
2233
2234/**
2235 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2236 */
2237static DECLCALLBACK(void *) acpiQueryInterface(PPDMIBASE pInterface, const char *pszIID)
2238{
2239 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IBase);
2240 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
2241 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIACPIPORT, &pThis->IACPIPort);
2242 return NULL;
2243}
2244
2245/**
2246 * Create the ACPI tables.
2247 */
2248static int acpiPlantTables(ACPIState *s)
2249{
2250 int rc;
2251 RTGCPHYS32 GCPhysCur, GCPhysRsdt, GCPhysXsdt, GCPhysFadtAcpi1, GCPhysFadtAcpi2, GCPhysFacs, GCPhysDsdt;
2252 RTGCPHYS32 GCPhysHpet = 0, GCPhysApic = 0, GCPhysSsdt = 0, GCPhysMcfg = 0;
2253 uint32_t addend = 0;
2254 RTGCPHYS32 aGCPhysRsdt[8];
2255 RTGCPHYS32 aGCPhysXsdt[8];
2256 uint32_t cAddr, iMadt = 0, iHpet = 0, iSsdt = 0, iMcfg = 0;
2257 size_t cbRsdt = sizeof(ACPITBLHEADER);
2258 size_t cbXsdt = sizeof(ACPITBLHEADER);
2259
2260 cAddr = 1; /* FADT */
2261 if (s->u8UseIOApic)
2262 iMadt = cAddr++; /* MADT */
2263
2264 if (s->fUseHpet)
2265 iHpet = cAddr++; /* HPET */
2266
2267 if (s->fUseMcfg)
2268 iMcfg = cAddr++; /* MCFG */
2269
2270 iSsdt = cAddr++; /* SSDT */
2271
2272 Assert(cAddr < RT_ELEMENTS(aGCPhysRsdt));
2273 Assert(cAddr < RT_ELEMENTS(aGCPhysXsdt));
2274
2275 cbRsdt += cAddr*sizeof(uint32_t); /* each entry: 32 bits phys. address. */
2276 cbXsdt += cAddr*sizeof(uint64_t); /* each entry: 64 bits phys. address. */
2277
2278 rc = CFGMR3QueryU64(s->pDevIns->pCfg, "RamSize", &s->u64RamSize);
2279 if (RT_FAILURE(rc))
2280 return PDMDEV_SET_ERROR(s->pDevIns, rc,
2281 N_("Configuration error: Querying \"RamSize\" as integer failed"));
2282
2283 uint32_t cbRamHole;
2284 rc = CFGMR3QueryU32Def(s->pDevIns->pCfg, "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
2285 if (RT_FAILURE(rc))
2286 return PDMDEV_SET_ERROR(s->pDevIns, rc,
2287 N_("Configuration error: Querying \"RamHoleSize\" as integer failed"));
2288
2289 /*
2290 * Calculate the sizes for the high and low regions.
2291 */
2292 const uint64_t offRamHole = _4G - cbRamHole;
2293 s->cbRamHigh = offRamHole < s->u64RamSize ? s->u64RamSize - offRamHole : 0;
2294 uint64_t cbRamLow = offRamHole < s->u64RamSize ? offRamHole : s->u64RamSize;
2295 if (cbRamLow > UINT32_C(0xffe00000)) /* See MEM3. */
2296 {
2297 /* Note: This is also enforced by DevPcBios.cpp. */
2298 LogRel(("DevACPI: Clipping cbRamLow=%#RX64 down to 0xffe00000.\n", cbRamLow));
2299 cbRamLow = UINT32_C(0xffe00000);
2300 }
2301 s->cbRamLow = (uint32_t)cbRamLow;
2302
2303 GCPhysCur = 0;
2304 GCPhysRsdt = GCPhysCur;
2305
2306 GCPhysCur = RT_ALIGN_32(GCPhysCur + cbRsdt, 16);
2307 GCPhysXsdt = GCPhysCur;
2308
2309 GCPhysCur = RT_ALIGN_32(GCPhysCur + cbXsdt, 16);
2310 GCPhysFadtAcpi1 = GCPhysCur;
2311
2312 GCPhysCur = RT_ALIGN_32(GCPhysCur + ACPITBLFADT_VERSION1_SIZE, 16);
2313 GCPhysFadtAcpi2 = GCPhysCur;
2314
2315 GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLFADT), 64);
2316 GCPhysFacs = GCPhysCur;
2317
2318 GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLFACS), 16);
2319 if (s->u8UseIOApic)
2320 {
2321 GCPhysApic = GCPhysCur;
2322 GCPhysCur = RT_ALIGN_32(GCPhysCur + AcpiTableMADT::sizeFor(s, NUMBER_OF_IRQ_SOURCE_OVERRIDES), 16);
2323 }
2324 if (s->fUseHpet)
2325 {
2326 GCPhysHpet = GCPhysCur;
2327 GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLHPET), 16);
2328 }
2329 if (s->fUseMcfg)
2330 {
2331 GCPhysMcfg = GCPhysCur;
2332 /* Assume one entry */
2333 GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLMCFG) + sizeof(ACPITBLMCFGENTRY), 16);
2334 }
2335
2336 void* pSsdtCode = NULL;
2337 size_t cbSsdtSize = 0;
2338 rc = acpiPrepareSsdt(s->pDevIns, &pSsdtCode, &cbSsdtSize);
2339 if (RT_FAILURE(rc))
2340 return rc;
2341
2342 GCPhysSsdt = GCPhysCur;
2343 GCPhysCur = RT_ALIGN_32(GCPhysCur + cbSsdtSize, 16);
2344
2345 GCPhysDsdt = GCPhysCur;
2346
2347 void* pDsdtCode = NULL;
2348 size_t cbDsdtSize = 0;
2349 rc = acpiPrepareDsdt(s->pDevIns, &pDsdtCode, &cbDsdtSize);
2350 if (RT_FAILURE(rc))
2351 return rc;
2352
2353 GCPhysCur = RT_ALIGN_32(GCPhysCur + cbDsdtSize, 16);
2354
2355 if (GCPhysCur > 0x10000)
2356 return PDMDEV_SET_ERROR(s->pDevIns, VERR_TOO_MUCH_DATA,
2357 N_("Error: ACPI tables bigger than 64KB"));
2358
2359 Log(("RSDP 0x%08X\n", find_rsdp_space()));
2360 addend = s->cbRamLow - 0x10000;
2361 Log(("RSDT 0x%08X XSDT 0x%08X\n", GCPhysRsdt + addend, GCPhysXsdt + addend));
2362 Log(("FACS 0x%08X FADT (1.0) 0x%08X, FADT (2+) 0x%08X\n", GCPhysFacs + addend, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend));
2363 Log(("DSDT 0x%08X", GCPhysDsdt + addend));
2364 if (s->u8UseIOApic)
2365 Log((" MADT 0x%08X", GCPhysApic + addend));
2366 if (s->fUseHpet)
2367 Log((" HPET 0x%08X", GCPhysHpet + addend));
2368 if (s->fUseMcfg)
2369 Log((" MCFG 0x%08X", GCPhysMcfg + addend));
2370 Log((" SSDT 0x%08X", GCPhysSsdt + addend));
2371 Log(("\n"));
2372
2373 acpiSetupRSDP((ACPITBLRSDP*)s->au8RSDPPage, GCPhysRsdt + addend, GCPhysXsdt + addend);
2374 acpiSetupDSDT(s, GCPhysDsdt + addend, pDsdtCode, cbDsdtSize);
2375 acpiCleanupDsdt(s->pDevIns, pDsdtCode);
2376 acpiSetupFACS(s, GCPhysFacs + addend);
2377 acpiSetupFADT(s, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend, GCPhysFacs + addend, GCPhysDsdt + addend);
2378
2379 aGCPhysRsdt[0] = GCPhysFadtAcpi1 + addend;
2380 aGCPhysXsdt[0] = GCPhysFadtAcpi2 + addend;
2381 if (s->u8UseIOApic)
2382 {
2383 acpiSetupMADT(s, GCPhysApic + addend);
2384 aGCPhysRsdt[iMadt] = GCPhysApic + addend;
2385 aGCPhysXsdt[iMadt] = GCPhysApic + addend;
2386 }
2387 if (s->fUseHpet)
2388 {
2389 acpiSetupHPET(s, GCPhysHpet + addend);
2390 aGCPhysRsdt[iHpet] = GCPhysHpet + addend;
2391 aGCPhysXsdt[iHpet] = GCPhysHpet + addend;
2392 }
2393 if (s->fUseMcfg)
2394 {
2395 acpiSetupMCFG(s, GCPhysMcfg + addend);
2396 aGCPhysRsdt[iMcfg] = GCPhysMcfg + addend;
2397 aGCPhysXsdt[iMcfg] = GCPhysMcfg + addend;
2398 }
2399
2400 acpiSetupSSDT(s, GCPhysSsdt + addend, pSsdtCode, cbSsdtSize);
2401 acpiCleanupSsdt(s->pDevIns, pSsdtCode);
2402 aGCPhysRsdt[iSsdt] = GCPhysSsdt + addend;
2403 aGCPhysXsdt[iSsdt] = GCPhysSsdt + addend;
2404
2405 rc = acpiSetupRSDT(s, GCPhysRsdt + addend, cAddr, aGCPhysRsdt);
2406 if (RT_FAILURE(rc))
2407 return rc;
2408 return acpiSetupXSDT(s, GCPhysXsdt + addend, cAddr, aGCPhysXsdt);
2409}
2410
2411static int acpiUpdatePmHandlers(ACPIState *pThis, RTIOPORT uNewBase)
2412{
2413 Log(("acpi: rebasing PM 0x%x -> 0x%x\n", pThis->uPmIoPortBase, uNewBase));
2414 if (uNewBase != pThis->uPmIoPortBase)
2415 {
2416 int rc;
2417
2418 rc = acpiUnregisterPmHandlers(pThis);
2419 if (RT_FAILURE(rc))
2420 return rc;
2421
2422 pThis->uPmIoPortBase = uNewBase;
2423
2424 rc = acpiRegisterPmHandlers(pThis);
2425 if (RT_FAILURE(rc))
2426 return rc;
2427
2428 /* We have to update FADT table acccording to the new base */
2429 rc = acpiPlantTables(pThis);
2430 AssertRC(rc);
2431 if (RT_FAILURE(rc))
2432 return rc;
2433 }
2434
2435 return VINF_SUCCESS;
2436}
2437
2438static uint32_t acpiPciConfigRead(PPCIDEVICE pPciDev, uint32_t Address, unsigned cb)
2439{
2440 PPDMDEVINS pDevIns = pPciDev->pDevIns;
2441 ACPIState* pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
2442
2443 Log2(("acpi: PCI config read: 0x%x (%d)\n", Address, cb));
2444
2445 return pThis->pfnAcpiPciConfigRead(pPciDev, Address, cb);
2446}
2447
2448static void acpiPciConfigWrite(PPCIDEVICE pPciDev, uint32_t Address, uint32_t u32Value, unsigned cb)
2449{
2450 PPDMDEVINS pDevIns = pPciDev->pDevIns;
2451 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
2452
2453 Log2(("acpi: PCI config write: 0x%x -> 0x%x (%d)\n", u32Value, Address, cb));
2454
2455
2456 if (Address == VBOX_PCI_INTERRUPT_LINE)
2457 {
2458 Log(("acpi: ignore interrupt line settings: %d, we'll use hardcoded value %d\n", u32Value, SCI_INT));
2459 u32Value = SCI_INT;
2460 }
2461
2462 pThis->pfnAcpiPciConfigWrite(pPciDev, Address, u32Value, cb);
2463
2464 /* PMREGMISC written */
2465 if (Address == 0x80)
2466 {
2467 /* Check Power Management IO Space Enable (PMIOSE) bit */
2468 if (pPciDev->config[0x80] & 0x1)
2469 {
2470 int rc;
2471
2472 RTIOPORT uNewBase = RTIOPORT(PCIDevGetDWord(pPciDev, 0x40));
2473 uNewBase &= 0xffc0;
2474
2475 rc = acpiUpdatePmHandlers(pThis, uNewBase);
2476 AssertRC(rc);
2477 }
2478 }
2479}
2480
2481/**
2482 * Attach a new CPU.
2483 *
2484 * @returns VBox status code.
2485 * @param pDevIns The device instance.
2486 * @param iLUN The logical unit which is being attached.
2487 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
2488 *
2489 * @remarks This code path is not used during construction.
2490 */
2491static DECLCALLBACK(int) acpiAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
2492{
2493 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
2494
2495 LogFlow(("acpiAttach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags));
2496
2497 AssertMsgReturn(!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
2498 ("Hot-plug flag is not set\n"),
2499 VERR_NOT_SUPPORTED);
2500 AssertReturn(iLUN < VMM_MAX_CPU_COUNT, VERR_PDM_NO_SUCH_LUN);
2501
2502 /* Check if it was already attached */
2503 if (VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN))
2504 return VINF_SUCCESS;
2505
2506 PPDMIBASE IBaseTmp;
2507 int rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &s->IBase, &IBaseTmp, "ACPI CPU");
2508
2509 if (RT_SUCCESS(rc))
2510 {
2511 /* Enable the CPU */
2512 VMCPUSET_ADD(&s->CpuSetAttached, iLUN);
2513
2514 /*
2515 * Lock the CPU because we don't know if the guest will use it or not.
2516 * Prevents ejection while the CPU is still used
2517 */
2518 VMCPUSET_ADD(&s->CpuSetLocked, iLUN);
2519 s->u32CpuEventType = CPU_EVENT_TYPE_ADD;
2520 s->u32CpuEvent = iLUN;
2521 /* Notify the guest */
2522 update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en);
2523 }
2524 return rc;
2525}
2526
2527/**
2528 * Detach notification.
2529 *
2530 * @param pDevIns The device instance.
2531 * @param iLUN The logical unit which is being detached.
2532 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
2533 */
2534static DECLCALLBACK(void) acpiDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
2535{
2536 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
2537
2538 LogFlow(("acpiDetach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags));
2539
2540 AssertMsgReturnVoid(!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
2541 ("Hot-plug flag is not set\n"));
2542
2543 /* Check if it was already detached */
2544 if (VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN))
2545 {
2546 AssertMsgReturnVoid(!(VMCPUSET_IS_PRESENT(&s->CpuSetLocked, iLUN)), ("CPU is still locked by the guest\n"));
2547
2548 /* Disable the CPU */
2549 VMCPUSET_DEL(&s->CpuSetAttached, iLUN);
2550 s->u32CpuEventType = CPU_EVENT_TYPE_REMOVE;
2551 s->u32CpuEvent = iLUN;
2552 /* Notify the guest */
2553 update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en);
2554 }
2555}
2556
2557/**
2558 * @interface_method_impl{PDMDEVREG,pfnResume}
2559 */
2560static DECLCALLBACK(void) acpiResume(PPDMDEVINS pDevIns)
2561{
2562 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
2563 if (pThis->fSetWakeupOnResume)
2564 {
2565 Log(("acpiResume: setting WAK_STS\n"));
2566 pThis->fSetWakeupOnResume = false;
2567 pThis->pm1a_sts |= WAK_STS;
2568 }
2569}
2570
2571/**
2572 * @interface_method_impl{PDMDEVREG,pfnReset}
2573 */
2574static DECLCALLBACK(void) acpiReset(PPDMDEVINS pDevIns)
2575{
2576 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
2577
2578 s->pm1a_en = 0;
2579 s->pm1a_sts = 0;
2580 s->pm1a_ctl = 0;
2581 s->pm_timer_initial = TMTimerGet(s->CTX_SUFF(ts));
2582 acpiPMTimerReset(s);
2583 s->uBatteryIndex = 0;
2584 s->uSystemInfoIndex = 0;
2585 s->gpe0_en = 0;
2586 s->gpe0_sts = 0;
2587 s->uSleepState = 0;
2588
2589 /** @todo Should we really reset PM base? */
2590 acpiUpdatePmHandlers(s, PM_PORT_BASE);
2591
2592 acpiPlantTables(s);
2593}
2594
2595/**
2596 * @interface_method_impl{PDMDEVREG,pfnRelocate}
2597 */
2598static DECLCALLBACK(void) acpiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
2599{
2600 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
2601 s->tsRC = TMTimerRCPtr(s->CTX_SUFF(ts));
2602}
2603
2604/**
2605 * @interface_method_impl{PDMDEVREG,pfnConstruct}
2606 */
2607static DECLCALLBACK(int) acpiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
2608{
2609 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
2610 PCIDevice *dev = &s->dev;
2611 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2612
2613 /* Validate and read the configuration. */
2614 if (!CFGMR3AreValuesValid(pCfg,
2615 "RamSize\0"
2616 "RamHoleSize\0"
2617 "IOAPIC\0"
2618 "NumCPUs\0"
2619 "GCEnabled\0"
2620 "R0Enabled\0"
2621 "HpetEnabled\0"
2622 "McfgEnabled\0"
2623 "McfgBase\0"
2624 "McfgLength\0"
2625 "SmcEnabled\0"
2626 "FdcEnabled\0"
2627 "ShowRtc\0"
2628 "ShowCpu\0"
2629 "NicPciAddress\0"
2630 "AudioPciAddress\0"
2631 "IocPciAddress\0"
2632 "HostBusPciAddress\0"
2633 "EnableSuspendToDisk\0"
2634 "PowerS1Enabled\0"
2635 "PowerS4Enabled\0"
2636 "CpuHotPlug\0"
2637 "AmlFilePath\0"
2638 "Serial0IoPortBase\0"
2639 "Serial1IoPortBase\0"
2640 "Serial0Irq\0"
2641 "Serial1Irq\0"
2642 ))
2643 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2644 N_("Configuration error: Invalid config key for ACPI device"));
2645
2646 s->pDevIns = pDevIns;
2647
2648 /* query whether we are supposed to present an IOAPIC */
2649 int rc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &s->u8UseIOApic, 1);
2650 if (RT_FAILURE(rc))
2651 return PDMDEV_SET_ERROR(pDevIns, rc,
2652 N_("Configuration error: Failed to read \"IOAPIC\""));
2653
2654 rc = CFGMR3QueryU16Def(pCfg, "NumCPUs", &s->cCpus, 1);
2655 if (RT_FAILURE(rc))
2656 return PDMDEV_SET_ERROR(pDevIns, rc,
2657 N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
2658
2659 /* query whether we are supposed to present an FDC controller */
2660 rc = CFGMR3QueryBoolDef(pCfg, "FdcEnabled", &s->fUseFdc, true);
2661 if (RT_FAILURE(rc))
2662 return PDMDEV_SET_ERROR(pDevIns, rc,
2663 N_("Configuration error: Failed to read \"FdcEnabled\""));
2664
2665 /* query whether we are supposed to present HPET */
2666 rc = CFGMR3QueryBoolDef(pCfg, "HpetEnabled", &s->fUseHpet, false);
2667 if (RT_FAILURE(rc))
2668 return PDMDEV_SET_ERROR(pDevIns, rc,
2669 N_("Configuration error: Failed to read \"HpetEnabled\""));
2670 /* query MCFG configuration */
2671 rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &s->u64PciConfigMMioAddress, 0);
2672 if (RT_FAILURE(rc))
2673 return PDMDEV_SET_ERROR(pDevIns, rc,
2674 N_("Configuration error: Failed to read \"McfgBase\""));
2675 rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &s->u64PciConfigMMioLength, 0);
2676 if (RT_FAILURE(rc))
2677 return PDMDEV_SET_ERROR(pDevIns, rc,
2678 N_("Configuration error: Failed to read \"McfgLength\""));
2679 s->fUseMcfg = (s->u64PciConfigMMioAddress != 0) && (s->u64PciConfigMMioLength != 0);
2680
2681 /* query whether we are supposed to present SMC */
2682 rc = CFGMR3QueryBoolDef(pCfg, "SmcEnabled", &s->fUseSmc, false);
2683 if (RT_FAILURE(rc))
2684 return PDMDEV_SET_ERROR(pDevIns, rc,
2685 N_("Configuration error: Failed to read \"SmcEnabled\""));
2686
2687 /* query whether we are supposed to present RTC object */
2688 rc = CFGMR3QueryBoolDef(pCfg, "ShowRtc", &s->fShowRtc, false);
2689 if (RT_FAILURE(rc))
2690 return PDMDEV_SET_ERROR(pDevIns, rc,
2691 N_("Configuration error: Failed to read \"ShowRtc\""));
2692
2693 /* query whether we are supposed to present CPU objects */
2694 rc = CFGMR3QueryBoolDef(pCfg, "ShowCpu", &s->fShowCpu, false);
2695 if (RT_FAILURE(rc))
2696 return PDMDEV_SET_ERROR(pDevIns, rc,
2697 N_("Configuration error: Failed to read \"ShowCpu\""));
2698
2699 /* query primary NIC PCI address */
2700 rc = CFGMR3QueryU32Def(pCfg, "NicPciAddress", &s->u32NicPciAddress, 0);
2701 if (RT_FAILURE(rc))
2702 return PDMDEV_SET_ERROR(pDevIns, rc,
2703 N_("Configuration error: Failed to read \"NicPciAddress\""));
2704
2705 /* query primary NIC PCI address */
2706 rc = CFGMR3QueryU32Def(pCfg, "AudioPciAddress", &s->u32AudioPciAddress, 0);
2707 if (RT_FAILURE(rc))
2708 return PDMDEV_SET_ERROR(pDevIns, rc,
2709 N_("Configuration error: Failed to read \"AudioPciAddress\""));
2710
2711 /* query IO controller (southbridge) PCI address */
2712 rc = CFGMR3QueryU32Def(pCfg, "IocPciAddress", &s->u32IocPciAddress, 0);
2713 if (RT_FAILURE(rc))
2714 return PDMDEV_SET_ERROR(pDevIns, rc,
2715 N_("Configuration error: Failed to read \"IocPciAddress\""));
2716
2717 /* query host bus controller PCI address */
2718 rc = CFGMR3QueryU32Def(pCfg, "HostBusPciAddress", &s->u32HbcPciAddress, 0);
2719 if (RT_FAILURE(rc))
2720 return PDMDEV_SET_ERROR(pDevIns, rc,
2721 N_("Configuration error: Failed to read \"HostBusPciAddress\""));
2722
2723 /* query whether S1 power state should be exposed */
2724 rc = CFGMR3QueryBoolDef(pCfg, "PowerS1Enabled", &s->fS1Enabled, false);
2725 if (RT_FAILURE(rc))
2726 return PDMDEV_SET_ERROR(pDevIns, rc,
2727 N_("Configuration error: Failed to read \"PowerS1Enabled\""));
2728
2729 /* query whether S4 power state should be exposed */
2730 rc = CFGMR3QueryBoolDef(pCfg, "PowerS4Enabled", &s->fS4Enabled, false);
2731 if (RT_FAILURE(rc))
2732 return PDMDEV_SET_ERROR(pDevIns, rc,
2733 N_("Configuration error: Failed to read \"PowerS4Enabled\""));
2734
2735 /* query whether S1 power state should save the VM state */
2736 rc = CFGMR3QueryBoolDef(pCfg, "EnableSuspendToDisk", &s->fSuspendToSavedState, false);
2737 if (RT_FAILURE(rc))
2738 return PDMDEV_SET_ERROR(pDevIns, rc,
2739 N_("Configuration error: Failed to read \"EnableSuspendToDisk\""));
2740
2741 /* query whether we are allow CPU hot plugging */
2742 rc = CFGMR3QueryBoolDef(pCfg, "CpuHotPlug", &s->fCpuHotPlug, false);
2743 if (RT_FAILURE(rc))
2744 return PDMDEV_SET_ERROR(pDevIns, rc,
2745 N_("Configuration error: Failed to read \"CpuHotPlug\""));
2746
2747 rc = CFGMR3QueryBool(pCfg, "GCEnabled", &s->fGCEnabled);
2748 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
2749 s->fGCEnabled = true;
2750 else if (RT_FAILURE(rc))
2751 return PDMDEV_SET_ERROR(pDevIns, rc,
2752 N_("Configuration error: Failed to read \"GCEnabled\""));
2753
2754 rc = CFGMR3QueryBool(pCfg, "R0Enabled", &s->fR0Enabled);
2755 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
2756 s->fR0Enabled = true;
2757 else if (RT_FAILURE(rc))
2758 return PDMDEV_SET_ERROR(pDevIns, rc,
2759 N_("configuration error: failed to read R0Enabled as boolean"));
2760
2761 /* query serial info */
2762 rc = CFGMR3QueryU8Def(pCfg, "Serial0Irq", &s->uSerial0Irq, 4);
2763 if (RT_FAILURE(rc))
2764 return PDMDEV_SET_ERROR(pDevIns, rc,
2765 N_("Configuration error: Failed to read \"Serial0Irq\""));
2766
2767 rc = CFGMR3QueryU16Def(pCfg, "Serial0IoPortBase", &s->uSerial0IoPortBase, 0x3f8);
2768 if (RT_FAILURE(rc))
2769 return PDMDEV_SET_ERROR(pDevIns, rc,
2770 N_("Configuration error: Failed to read \"Serial0IoPortBase\""));
2771
2772 /* Serial 1 is enabled, get config data */
2773 rc = CFGMR3QueryU8Def(pCfg, "Serial1Irq", &s->uSerial1Irq, 3);
2774 if (RT_FAILURE(rc))
2775 return PDMDEV_SET_ERROR(pDevIns, rc,
2776 N_("Configuration error: Failed to read \"Serial1Irq\""));
2777
2778 rc = CFGMR3QueryU16Def(pCfg, "Serial1IoPortBase", &s->uSerial1IoPortBase, 0x2f8);
2779 if (RT_FAILURE(rc))
2780 return PDMDEV_SET_ERROR(pDevIns, rc,
2781 N_("Configuration error: Failed to read \"Serial1IoPortBase\""));
2782
2783 /*
2784 * Interfaces
2785 */
2786 /* IBase */
2787 s->IBase.pfnQueryInterface = acpiQueryInterface;
2788 /* IACPIPort */
2789 s->IACPIPort.pfnSleepButtonPress = acpiSleepButtonPress;
2790 s->IACPIPort.pfnPowerButtonPress = acpiPowerButtonPress;
2791 s->IACPIPort.pfnGetPowerButtonHandled = acpiGetPowerButtonHandled;
2792 s->IACPIPort.pfnGetGuestEnteredACPIMode = acpiGetGuestEnteredACPIMode;
2793 s->IACPIPort.pfnGetCpuStatus = acpiGetCpuStatus;
2794
2795 VMCPUSET_EMPTY(&s->CpuSetAttached);
2796 VMCPUSET_EMPTY(&s->CpuSetLocked);
2797 s->idCpuLockCheck = UINT32_C(0xffffffff);
2798 s->u32CpuEventType = 0;
2799 s->u32CpuEvent = UINT32_C(0xffffffff);
2800
2801 /* The first CPU can't be attached/detached */
2802 VMCPUSET_ADD(&s->CpuSetAttached, 0);
2803 VMCPUSET_ADD(&s->CpuSetLocked, 0);
2804
2805 /* Try to attach the other CPUs */
2806 for (unsigned i = 1; i < s->cCpus; i++)
2807 {
2808 if (s->fCpuHotPlug)
2809 {
2810 PPDMIBASE IBaseTmp;
2811 rc = PDMDevHlpDriverAttach(pDevIns, i, &s->IBase, &IBaseTmp, "ACPI CPU");
2812
2813 if (RT_SUCCESS(rc))
2814 {
2815 VMCPUSET_ADD(&s->CpuSetAttached, i);
2816 VMCPUSET_ADD(&s->CpuSetLocked, i);
2817 Log(("acpi: Attached CPU %u\n", i));
2818 }
2819 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2820 Log(("acpi: CPU %u not attached yet\n", i));
2821 else
2822 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach CPU object\n"));
2823 }
2824 else
2825 {
2826 /* CPU is always attached if hot-plug is not enabled. */
2827 VMCPUSET_ADD(&s->CpuSetAttached, i);
2828 VMCPUSET_ADD(&s->CpuSetLocked, i);
2829 }
2830 }
2831
2832
2833 /* Set default port base */
2834 s->uPmIoPortBase = PM_PORT_BASE;
2835
2836 /*
2837 * FDC and SMC try to use the same non-shareable interrupt (6),
2838 * enable only one device.
2839 */
2840 if (s->fUseSmc)
2841 s->fUseFdc = false;
2842
2843 /* */
2844 RTGCPHYS32 GCPhysRsdp = find_rsdp_space();
2845 if (!GCPhysRsdp)
2846 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY,
2847 N_("Can not find space for RSDP. ACPI is disabled"));
2848
2849 rc = acpiPlantTables(s);
2850 if (RT_FAILURE(rc))
2851 return rc;
2852
2853 rc = PDMDevHlpROMRegister(pDevIns, GCPhysRsdp, 0x1000, s->au8RSDPPage, 0x1000,
2854 PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "ACPI RSDP");
2855 if (RT_FAILURE(rc))
2856 return rc;
2857
2858 rc = acpiRegisterPmHandlers(s);
2859 if (RT_FAILURE(rc))
2860 return rc;
2861
2862#define R(addr, cnt, writer, reader, description) \
2863 do { \
2864 rc = PDMDevHlpIOPortRegister(pDevIns, addr, cnt, s, writer, reader, \
2865 NULL, NULL, description); \
2866 if (RT_FAILURE(rc)) \
2867 return rc; \
2868 } while (0)
2869 R(SMI_CMD, 1, acpiSmiWrite, NULL, "ACPI SMI");
2870#ifdef DEBUG_ACPI
2871 R(DEBUG_HEX, 1, acpiDhexWrite, NULL, "ACPI Debug hex");
2872 R(DEBUG_CHR, 1, acpiDchrWrite, NULL, "ACPI Debug char");
2873#endif
2874 R(BAT_INDEX, 1, acpiBatIndexWrite, NULL, "ACPI Battery status index");
2875 R(BAT_DATA, 1, NULL, acpiBatDataRead, "ACPI Battery status data");
2876 R(SYSI_INDEX, 1, acpiSysInfoIndexWrite, NULL, "ACPI system info index");
2877 R(SYSI_DATA, 1, acpiSysInfoDataWrite, acpiSysInfoDataRead, "ACPI system info data");
2878 R(ACPI_RESET_BLK, 1, acpiResetWrite, NULL, "ACPI Reset");
2879#undef R
2880
2881 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiTimer, dev,
2882 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "ACPI Timer", &s->tsR3);
2883 if (RT_FAILURE(rc))
2884 {
2885 AssertMsgFailed(("pfnTMTimerCreate -> %Rrc\n", rc));
2886 return rc;
2887 }
2888
2889 s->tsR0 = TMTimerR0Ptr(s->tsR3);
2890 s->tsRC = TMTimerRCPtr(s->tsR3);
2891 s->pm_timer_initial = TMTimerGet(s->tsR3);
2892 acpiPMTimerReset(s);
2893
2894 PCIDevSetVendorId(dev, 0x8086); /* Intel */
2895 PCIDevSetDeviceId(dev, 0x7113); /* 82371AB */
2896
2897 /* See p. 50 of PIIX4 manual */
2898 PCIDevSetCommand(dev, 0x01);
2899 PCIDevSetStatus(dev, 0x0280);
2900
2901 PCIDevSetRevisionId(dev, 0x08);
2902
2903 PCIDevSetClassProg(dev, 0x00);
2904 PCIDevSetClassSub(dev, 0x80);
2905 PCIDevSetClassBase(dev, 0x06);
2906
2907 PCIDevSetHeaderType(dev, 0x80);
2908
2909 PCIDevSetBIST(dev, 0x00);
2910
2911 PCIDevSetInterruptLine(dev, SCI_INT);
2912 PCIDevSetInterruptPin (dev, 0x01);
2913
2914 dev->config[0x40] = 0x01; /* PM base address, this bit marks it as IO range, not PA */
2915
2916#if 0
2917 int smb_io_base = 0xb100;
2918 dev->config[0x90] = smb_io_base | 1; /* SMBus base address */
2919 dev->config[0x90] = smb_io_base >> 8;
2920#endif
2921
2922 rc = PDMDevHlpPCIRegister(pDevIns, dev);
2923 if (RT_FAILURE(rc))
2924 return rc;
2925
2926 PDMDevHlpPCISetConfigCallbacks(pDevIns, dev,
2927 acpiPciConfigRead, &s->pfnAcpiPciConfigRead,
2928 acpiPciConfigWrite, &s->pfnAcpiPciConfigWrite);
2929
2930 rc = PDMDevHlpSSMRegister(pDevIns, 6, sizeof(*s), acpiSaveState, acpiLoadState);
2931 if (RT_FAILURE(rc))
2932 return rc;
2933
2934 /*
2935 * Get the corresponding connector interface
2936 */
2937 rc = PDMDevHlpDriverAttach(pDevIns, 0, &s->IBase, &s->pDrvBase, "ACPI Driver Port");
2938 if (RT_SUCCESS(rc))
2939 {
2940 s->pDrv = PDMIBASE_QUERY_INTERFACE(s->pDrvBase, PDMIACPICONNECTOR);
2941 if (!s->pDrv)
2942 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_MISSING_INTERFACE,
2943 N_("LUN #0 doesn't have an ACPI connector interface"));
2944 }
2945 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2946 {
2947 Log(("acpi: %s/%d: warning: no driver attached to LUN #0!\n",
2948 pDevIns->pReg->szName, pDevIns->iInstance));
2949 rc = VINF_SUCCESS;
2950 }
2951 else
2952 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach LUN #0"));
2953
2954 return rc;
2955}
2956
2957/**
2958 * The device registration structure.
2959 */
2960const PDMDEVREG g_DeviceACPI =
2961{
2962 /* u32Version */
2963 PDM_DEVREG_VERSION,
2964 /* szName */
2965 "acpi",
2966 /* szRCMod */
2967 "VBoxDDGC.gc",
2968 /* szR0Mod */
2969 "VBoxDDR0.r0",
2970 /* pszDescription */
2971 "Advanced Configuration and Power Interface",
2972 /* fFlags */
2973 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
2974 /* fClass */
2975 PDM_DEVREG_CLASS_ACPI,
2976 /* cMaxInstances */
2977 ~0,
2978 /* cbInstance */
2979 sizeof(ACPIState),
2980 /* pfnConstruct */
2981 acpiConstruct,
2982 /* pfnDestruct */
2983 NULL,
2984 /* pfnRelocate */
2985 acpiRelocate,
2986 /* pfnIOCtl */
2987 NULL,
2988 /* pfnPowerOn */
2989 NULL,
2990 /* pfnReset */
2991 acpiReset,
2992 /* pfnSuspend */
2993 NULL,
2994 /* pfnResume */
2995 acpiResume,
2996 /* pfnAttach */
2997 acpiAttach,
2998 /* pfnDetach */
2999 acpiDetach,
3000 /* pfnQueryInterface. */
3001 NULL,
3002 /* pfnInitComplete */
3003 NULL,
3004 /* pfnPowerOff */
3005 NULL,
3006 /* pfnSoftReset */
3007 NULL,
3008 /* u32VersionEnd */
3009 PDM_DEVREG_VERSION
3010};
3011
3012#endif /* IN_RING3 */
3013#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
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