Commit ab1e34add6735b5d2c1300426e8143399bc27dd8
1 parent
3b21e03e
moved ACPI table init to BIOS - preliminary SMM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2170 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
113 additions
and
379 deletions
hw/acpi.c
| ... | ... | @@ -19,13 +19,11 @@ |
| 19 | 19 | #include "vl.h" |
| 20 | 20 | |
| 21 | 21 | //#define DEBUG |
| 22 | +#define USE_SMM | |
| 22 | 23 | |
| 23 | 24 | /* i82731AB (PIIX4) compatible power management function */ |
| 24 | 25 | #define PM_FREQ 3579545 |
| 25 | 26 | |
| 26 | -/* XXX: make them variable */ | |
| 27 | -#define PM_IO_BASE 0xb000 | |
| 28 | -#define SMI_CMD_IO_ADDR 0xb040 | |
| 29 | 27 | #define ACPI_DBG_IO_ADDR 0xb044 |
| 30 | 28 | |
| 31 | 29 | typedef struct PIIX4PMState { |
| ... | ... | @@ -33,6 +31,8 @@ typedef struct PIIX4PMState { |
| 33 | 31 | uint16_t pmsts; |
| 34 | 32 | uint16_t pmen; |
| 35 | 33 | uint16_t pmcntrl; |
| 34 | + uint8_t apmc; | |
| 35 | + uint8_t apms; | |
| 36 | 36 | QEMUTimer *tmr_timer; |
| 37 | 37 | int64_t tmr_overflow_time; |
| 38 | 38 | } PIIX4PMState; |
| ... | ... | @@ -46,10 +46,6 @@ typedef struct PIIX4PMState { |
| 46 | 46 | |
| 47 | 47 | #define SUS_EN (1 << 13) |
| 48 | 48 | |
| 49 | -/* Note: only used for ACPI bios init. Could be deleted when ACPI init | |
| 50 | - is integrated in Bochs BIOS */ | |
| 51 | -static PIIX4PMState *piix4_pm_state; | |
| 52 | - | |
| 53 | 49 | static uint32_t get_pmtmr(PIIX4PMState *s) |
| 54 | 50 | { |
| 55 | 51 | uint32_t d; |
| ... | ... | @@ -195,22 +191,50 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr) |
| 195 | 191 | return val; |
| 196 | 192 | } |
| 197 | 193 | |
| 198 | -static void smi_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) | |
| 194 | +static void pm_smi_writeb(void *opaque, uint32_t addr, uint32_t val) | |
| 199 | 195 | { |
| 200 | 196 | PIIX4PMState *s = opaque; |
| 197 | + addr &= 1; | |
| 201 | 198 | #ifdef DEBUG |
| 202 | - printf("SMI cmd val=0x%02x\n", val); | |
| 199 | + printf("pm_smi_writeb addr=0x%x val=0x%02x\n", addr, val); | |
| 203 | 200 | #endif |
| 204 | - switch(val) { | |
| 205 | - case 0xf0: /* ACPI disable */ | |
| 206 | - s->pmcntrl &= ~SCI_EN; | |
| 207 | - break; | |
| 208 | - case 0xf1: /* ACPI enable */ | |
| 209 | - s->pmcntrl |= SCI_EN; | |
| 210 | - break; | |
| 201 | + if (addr == 0) { | |
| 202 | + s->apmc = val; | |
| 203 | +#ifdef USE_SMM | |
| 204 | + cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI); | |
| 205 | +#else | |
| 206 | + /* emulation of what the SMM BIOS should do */ | |
| 207 | + switch(val) { | |
| 208 | + case 0xf0: /* ACPI disable */ | |
| 209 | + s->pmcntrl &= ~SCI_EN; | |
| 210 | + break; | |
| 211 | + case 0xf1: /* ACPI enable */ | |
| 212 | + s->pmcntrl |= SCI_EN; | |
| 213 | + break; | |
| 214 | + } | |
| 215 | +#endif | |
| 216 | + } else { | |
| 217 | + s->apms = val; | |
| 211 | 218 | } |
| 212 | 219 | } |
| 213 | 220 | |
| 221 | +static uint32_t pm_smi_readb(void *opaque, uint32_t addr) | |
| 222 | +{ | |
| 223 | + PIIX4PMState *s = opaque; | |
| 224 | + uint32_t val; | |
| 225 | + | |
| 226 | + addr &= 1; | |
| 227 | + if (addr == 0) { | |
| 228 | + val = s->apmc; | |
| 229 | + } else { | |
| 230 | + val = s->apms; | |
| 231 | + } | |
| 232 | +#ifdef DEBUG | |
| 233 | + printf("pm_smi_readb addr=0x%x val=0x%02x\n", addr, val); | |
| 234 | +#endif | |
| 235 | + return val; | |
| 236 | +} | |
| 237 | + | |
| 214 | 238 | static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val) |
| 215 | 239 | { |
| 216 | 240 | #if defined(DEBUG) |
| ... | ... | @@ -218,17 +242,81 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val) |
| 218 | 242 | #endif |
| 219 | 243 | } |
| 220 | 244 | |
| 221 | -/* XXX: we still add it to the PIIX3 and we count on the fact that | |
| 222 | - OSes are smart enough to accept this strange configuration */ | |
| 245 | +static void pm_io_space_update(PIIX4PMState *s) | |
| 246 | +{ | |
| 247 | + uint32_t pm_io_base; | |
| 248 | + | |
| 249 | + if (s->dev.config[0x80] & 1) { | |
| 250 | + pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40)); | |
| 251 | + pm_io_base &= 0xfffe; | |
| 252 | + | |
| 253 | + /* XXX: need to improve memory and ioport allocation */ | |
| 254 | +#if defined(DEBUG) | |
| 255 | + printf("PM: mapping to 0x%x\n", pm_io_base); | |
| 256 | +#endif | |
| 257 | + register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s); | |
| 258 | + register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s); | |
| 259 | + register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s); | |
| 260 | + register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s); | |
| 261 | + } | |
| 262 | +} | |
| 263 | + | |
| 264 | +static void pm_write_config(PCIDevice *d, | |
| 265 | + uint32_t address, uint32_t val, int len) | |
| 266 | +{ | |
| 267 | + pci_default_write_config(d, address, val, len); | |
| 268 | + if (address == 0x80) | |
| 269 | + pm_io_space_update((PIIX4PMState *)d); | |
| 270 | +} | |
| 271 | + | |
| 272 | +static void pm_save(QEMUFile* f,void *opaque) | |
| 273 | +{ | |
| 274 | + PIIX4PMState *s = opaque; | |
| 275 | + | |
| 276 | + pci_device_save(&s->dev, f); | |
| 277 | + | |
| 278 | + qemu_put_be16s(f, &s->pmsts); | |
| 279 | + qemu_put_be16s(f, &s->pmen); | |
| 280 | + qemu_put_be16s(f, &s->pmcntrl); | |
| 281 | + qemu_put_8s(f, &s->apmc); | |
| 282 | + qemu_put_8s(f, &s->apms); | |
| 283 | + qemu_put_timer(f, s->tmr_timer); | |
| 284 | + qemu_put_be64s(f, &s->tmr_overflow_time); | |
| 285 | +} | |
| 286 | + | |
| 287 | +static int pm_load(QEMUFile* f,void* opaque,int version_id) | |
| 288 | +{ | |
| 289 | + PIIX4PMState *s = opaque; | |
| 290 | + int ret; | |
| 291 | + | |
| 292 | + if (version_id > 1) | |
| 293 | + return -EINVAL; | |
| 294 | + | |
| 295 | + ret = pci_device_load(&s->dev, f); | |
| 296 | + if (ret < 0) | |
| 297 | + return ret; | |
| 298 | + | |
| 299 | + qemu_get_be16s(f, &s->pmsts); | |
| 300 | + qemu_get_be16s(f, &s->pmen); | |
| 301 | + qemu_get_be16s(f, &s->pmcntrl); | |
| 302 | + qemu_get_8s(f, &s->apmc); | |
| 303 | + qemu_get_8s(f, &s->apms); | |
| 304 | + qemu_get_timer(f, s->tmr_timer); | |
| 305 | + qemu_get_be64s(f, &s->tmr_overflow_time); | |
| 306 | + | |
| 307 | + pm_io_space_update(s); | |
| 308 | + | |
| 309 | + return 0; | |
| 310 | +} | |
| 311 | + | |
| 223 | 312 | void piix4_pm_init(PCIBus *bus, int devfn) |
| 224 | 313 | { |
| 225 | 314 | PIIX4PMState *s; |
| 226 | 315 | uint8_t *pci_conf; |
| 227 | - uint32_t pm_io_base; | |
| 228 | 316 | |
| 229 | 317 | s = (PIIX4PMState *)pci_register_device(bus, |
| 230 | 318 | "PM", sizeof(PIIX4PMState), |
| 231 | - devfn, NULL, NULL); | |
| 319 | + devfn, NULL, pm_write_config); | |
| 232 | 320 | pci_conf = s->dev.config; |
| 233 | 321 | pci_conf[0x00] = 0x86; |
| 234 | 322 | pci_conf[0x01] = 0x80; |
| ... | ... | @@ -241,15 +329,11 @@ void piix4_pm_init(PCIBus *bus, int devfn) |
| 241 | 329 | pci_conf[0x0e] = 0x00; // header_type |
| 242 | 330 | pci_conf[0x3d] = 0x01; // interrupt pin 1 |
| 243 | 331 | |
| 244 | - pm_io_base = PM_IO_BASE; | |
| 245 | - pci_conf[0x40] = pm_io_base | 1; | |
| 246 | - pci_conf[0x41] = pm_io_base >> 8; | |
| 247 | - register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s); | |
| 248 | - register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s); | |
| 249 | - register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s); | |
| 250 | - register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s); | |
| 332 | + pci_conf[0x40] = 0x01; /* PM io base read only bit */ | |
| 251 | 333 | |
| 252 | - register_ioport_write(SMI_CMD_IO_ADDR, 1, 1, smi_cmd_writeb, s); | |
| 334 | + register_ioport_write(0xb2, 2, 1, pm_smi_writeb, s); | |
| 335 | + register_ioport_read(0xb2, 2, 1, pm_smi_readb, s); | |
| 336 | + | |
| 253 | 337 | register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s); |
| 254 | 338 | |
| 255 | 339 | /* XXX: which specification is used ? The i82731AB has different |
| ... | ... | @@ -260,356 +344,6 @@ void piix4_pm_init(PCIBus *bus, int devfn) |
| 260 | 344 | (serial_hds[1] != NULL ? 0x90 : 0); |
| 261 | 345 | |
| 262 | 346 | s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s); |
| 263 | - piix4_pm_state = s; | |
| 264 | -} | |
| 265 | - | |
| 266 | -/* ACPI tables */ | |
| 267 | -/* XXX: move them in the Bochs BIOS ? */ | |
| 268 | - | |
| 269 | -/*************************************************/ | |
| 270 | - | |
| 271 | -/* Table structure from Linux kernel (the ACPI tables are under the | |
| 272 | - BSD license) */ | |
| 273 | - | |
| 274 | -#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ | |
| 275 | - uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\ | |
| 276 | - uint32_t length; /* Length of table, in bytes, including header */\ | |
| 277 | - uint8_t revision; /* ACPI Specification minor version # */\ | |
| 278 | - uint8_t checksum; /* To make sum of entire table == 0 */\ | |
| 279 | - uint8_t oem_id [6]; /* OEM identification */\ | |
| 280 | - uint8_t oem_table_id [8]; /* OEM table identification */\ | |
| 281 | - uint32_t oem_revision; /* OEM revision number */\ | |
| 282 | - uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\ | |
| 283 | - uint32_t asl_compiler_revision; /* ASL compiler revision number */ | |
| 284 | - | |
| 285 | - | |
| 286 | -struct acpi_table_header /* ACPI common table header */ | |
| 287 | -{ | |
| 288 | - ACPI_TABLE_HEADER_DEF | |
| 289 | -}; | |
| 290 | - | |
| 291 | -struct rsdp_descriptor /* Root System Descriptor Pointer */ | |
| 292 | -{ | |
| 293 | - uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */ | |
| 294 | - uint8_t checksum; /* To make sum of struct == 0 */ | |
| 295 | - uint8_t oem_id [6]; /* OEM identification */ | |
| 296 | - uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */ | |
| 297 | - uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */ | |
| 298 | - uint32_t length; /* XSDT Length in bytes including hdr */ | |
| 299 | - uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */ | |
| 300 | - uint8_t extended_checksum; /* Checksum of entire table */ | |
| 301 | - uint8_t reserved [3]; /* Reserved field must be 0 */ | |
| 302 | -}; | |
| 303 | 347 | |
| 304 | -/* | |
| 305 | - * ACPI 1.0 Root System Description Table (RSDT) | |
| 306 | - */ | |
| 307 | -struct rsdt_descriptor_rev1 | |
| 308 | -{ | |
| 309 | - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ | |
| 310 | - uint32_t table_offset_entry [2]; /* Array of pointers to other */ | |
| 311 | - /* ACPI tables */ | |
| 312 | -}; | |
| 313 | - | |
| 314 | -/* | |
| 315 | - * ACPI 1.0 Firmware ACPI Control Structure (FACS) | |
| 316 | - */ | |
| 317 | -struct facs_descriptor_rev1 | |
| 318 | -{ | |
| 319 | - uint8_t signature[4]; /* ACPI Signature */ | |
| 320 | - uint32_t length; /* Length of structure, in bytes */ | |
| 321 | - uint32_t hardware_signature; /* Hardware configuration signature */ | |
| 322 | - uint32_t firmware_waking_vector; /* ACPI OS waking vector */ | |
| 323 | - uint32_t global_lock; /* Global Lock */ | |
| 324 | - uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */ | |
| 325 | - uint32_t reserved1 : 31; /* Must be 0 */ | |
| 326 | - uint8_t resverved3 [40]; /* Reserved - must be zero */ | |
| 327 | -}; | |
| 328 | - | |
| 329 | - | |
| 330 | -/* | |
| 331 | - * ACPI 1.0 Fixed ACPI Description Table (FADT) | |
| 332 | - */ | |
| 333 | -struct fadt_descriptor_rev1 | |
| 334 | -{ | |
| 335 | - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ | |
| 336 | - uint32_t firmware_ctrl; /* Physical address of FACS */ | |
| 337 | - uint32_t dsdt; /* Physical address of DSDT */ | |
| 338 | - uint8_t model; /* System Interrupt Model */ | |
| 339 | - uint8_t reserved1; /* Reserved */ | |
| 340 | - uint16_t sci_int; /* System vector of SCI interrupt */ | |
| 341 | - uint32_t smi_cmd; /* Port address of SMI command port */ | |
| 342 | - uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */ | |
| 343 | - uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */ | |
| 344 | - uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ | |
| 345 | - uint8_t reserved2; /* Reserved - must be zero */ | |
| 346 | - uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ | |
| 347 | - uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ | |
| 348 | - uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ | |
| 349 | - uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ | |
| 350 | - uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ | |
| 351 | - uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ | |
| 352 | - uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ | |
| 353 | - uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ | |
| 354 | - uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ | |
| 355 | - uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ | |
| 356 | - uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ | |
| 357 | - uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ | |
| 358 | - uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ | |
| 359 | - uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ | |
| 360 | - uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */ | |
| 361 | - uint8_t reserved3; /* Reserved */ | |
| 362 | - uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ | |
| 363 | - uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ | |
| 364 | - uint16_t flush_size; /* Size of area read to flush caches */ | |
| 365 | - uint16_t flush_stride; /* Stride used in flushing caches */ | |
| 366 | - uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */ | |
| 367 | - uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */ | |
| 368 | - uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ | |
| 369 | - uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ | |
| 370 | - uint8_t century; /* Index to century in RTC CMOS RAM */ | |
| 371 | - uint8_t reserved4; /* Reserved */ | |
| 372 | - uint8_t reserved4a; /* Reserved */ | |
| 373 | - uint8_t reserved4b; /* Reserved */ | |
| 374 | -#if 0 | |
| 375 | - uint32_t wb_invd : 1; /* The wbinvd instruction works properly */ | |
| 376 | - uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ | |
| 377 | - uint32_t proc_c1 : 1; /* All processors support C1 state */ | |
| 378 | - uint32_t plvl2_up : 1; /* C2 state works on MP system */ | |
| 379 | - uint32_t pwr_button : 1; /* Power button is handled as a generic feature */ | |
| 380 | - uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ | |
| 381 | - uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ | |
| 382 | - uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ | |
| 383 | - uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */ | |
| 384 | - uint32_t reserved5 : 23; /* Reserved - must be zero */ | |
| 385 | -#else | |
| 386 | - uint32_t flags; | |
| 387 | -#endif | |
| 388 | -}; | |
| 389 | - | |
| 390 | -/* | |
| 391 | - * MADT values and structures | |
| 392 | - */ | |
| 393 | - | |
| 394 | -/* Values for MADT PCATCompat */ | |
| 395 | - | |
| 396 | -#define DUAL_PIC 0 | |
| 397 | -#define MULTIPLE_APIC 1 | |
| 398 | - | |
| 399 | - | |
| 400 | -/* Master MADT */ | |
| 401 | - | |
| 402 | -struct multiple_apic_table | |
| 403 | -{ | |
| 404 | - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ | |
| 405 | - uint32_t local_apic_address; /* Physical address of local APIC */ | |
| 406 | -#if 0 | |
| 407 | - uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */ | |
| 408 | - uint32_t reserved1 : 31; | |
| 409 | -#else | |
| 410 | - uint32_t flags; | |
| 411 | -#endif | |
| 412 | -}; | |
| 413 | - | |
| 414 | - | |
| 415 | -/* Values for Type in APIC_HEADER_DEF */ | |
| 416 | - | |
| 417 | -#define APIC_PROCESSOR 0 | |
| 418 | -#define APIC_IO 1 | |
| 419 | -#define APIC_XRUPT_OVERRIDE 2 | |
| 420 | -#define APIC_NMI 3 | |
| 421 | -#define APIC_LOCAL_NMI 4 | |
| 422 | -#define APIC_ADDRESS_OVERRIDE 5 | |
| 423 | -#define APIC_IO_SAPIC 6 | |
| 424 | -#define APIC_LOCAL_SAPIC 7 | |
| 425 | -#define APIC_XRUPT_SOURCE 8 | |
| 426 | -#define APIC_RESERVED 9 /* 9 and greater are reserved */ | |
| 427 | - | |
| 428 | -/* | |
| 429 | - * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) | |
| 430 | - */ | |
| 431 | -#define APIC_HEADER_DEF /* Common APIC sub-structure header */\ | |
| 432 | - uint8_t type; \ | |
| 433 | - uint8_t length; | |
| 434 | - | |
| 435 | -/* Sub-structures for MADT */ | |
| 436 | - | |
| 437 | -struct madt_processor_apic | |
| 438 | -{ | |
| 439 | - APIC_HEADER_DEF | |
| 440 | - uint8_t processor_id; /* ACPI processor id */ | |
| 441 | - uint8_t local_apic_id; /* Processor's local APIC id */ | |
| 442 | -#if 0 | |
| 443 | - uint32_t processor_enabled: 1; /* Processor is usable if set */ | |
| 444 | - uint32_t reserved2 : 31; /* Reserved, must be zero */ | |
| 445 | -#else | |
| 446 | - uint32_t flags; | |
| 447 | -#endif | |
| 448 | -}; | |
| 449 | - | |
| 450 | -struct madt_io_apic | |
| 451 | -{ | |
| 452 | - APIC_HEADER_DEF | |
| 453 | - uint8_t io_apic_id; /* I/O APIC ID */ | |
| 454 | - uint8_t reserved; /* Reserved - must be zero */ | |
| 455 | - uint32_t address; /* APIC physical address */ | |
| 456 | - uint32_t interrupt; /* Global system interrupt where INTI | |
| 457 | - * lines start */ | |
| 458 | -}; | |
| 459 | - | |
| 460 | -#include "acpi-dsdt.hex" | |
| 461 | - | |
| 462 | -static int acpi_checksum(const uint8_t *data, int len) | |
| 463 | -{ | |
| 464 | - int sum, i; | |
| 465 | - sum = 0; | |
| 466 | - for(i = 0; i < len; i++) | |
| 467 | - sum += data[i]; | |
| 468 | - return (-sum) & 0xff; | |
| 469 | -} | |
| 470 | - | |
| 471 | -static void acpi_build_table_header(struct acpi_table_header *h, | |
| 472 | - char *sig, int len) | |
| 473 | -{ | |
| 474 | - memcpy(h->signature, sig, 4); | |
| 475 | - h->length = cpu_to_le32(len); | |
| 476 | - h->revision = 0; | |
| 477 | - memcpy(h->oem_id, "QEMU ", 6); | |
| 478 | - memcpy(h->oem_table_id, "QEMU", 4); | |
| 479 | - memcpy(h->oem_table_id + 4, sig, 4); | |
| 480 | - h->oem_revision = cpu_to_le32(1); | |
| 481 | - memcpy(h->asl_compiler_id, "QEMU", 4); | |
| 482 | - h->asl_compiler_revision = cpu_to_le32(1); | |
| 483 | - h->checksum = acpi_checksum((void *)h, len); | |
| 484 | -} | |
| 485 | - | |
| 486 | -#define ACPI_TABLES_BASE 0x000e8000 | |
| 487 | - | |
| 488 | -/* base_addr must be a multiple of 4KB */ | |
| 489 | -void acpi_bios_init(void) | |
| 490 | -{ | |
| 491 | - struct rsdp_descriptor *rsdp; | |
| 492 | - struct rsdt_descriptor_rev1 *rsdt; | |
| 493 | - struct fadt_descriptor_rev1 *fadt; | |
| 494 | - struct facs_descriptor_rev1 *facs; | |
| 495 | - struct multiple_apic_table *madt; | |
| 496 | - uint8_t *dsdt; | |
| 497 | - uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr; | |
| 498 | - uint32_t pm_io_base, acpi_tables_size, madt_addr, madt_size; | |
| 499 | - int i; | |
| 500 | - | |
| 501 | - /* compute PCI I/O addresses */ | |
| 502 | - pm_io_base = (piix4_pm_state->dev.config[0x40] | | |
| 503 | - (piix4_pm_state->dev.config[0x41] << 8)) & ~0x3f; | |
| 504 | - | |
| 505 | - base_addr = ACPI_TABLES_BASE; | |
| 506 | - | |
| 507 | - /* reserve memory space for tables */ | |
| 508 | - addr = base_addr; | |
| 509 | - rsdp = (void *)(phys_ram_base + addr); | |
| 510 | - addr += sizeof(*rsdp); | |
| 511 | - | |
| 512 | - rsdt_addr = addr; | |
| 513 | - rsdt = (void *)(phys_ram_base + addr); | |
| 514 | - addr += sizeof(*rsdt); | |
| 515 | - | |
| 516 | - fadt_addr = addr; | |
| 517 | - fadt = (void *)(phys_ram_base + addr); | |
| 518 | - addr += sizeof(*fadt); | |
| 519 | - | |
| 520 | - /* XXX: FACS should be in RAM */ | |
| 521 | - addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */ | |
| 522 | - facs_addr = addr; | |
| 523 | - facs = (void *)(phys_ram_base + addr); | |
| 524 | - addr += sizeof(*facs); | |
| 525 | - | |
| 526 | - dsdt_addr = addr; | |
| 527 | - dsdt = (void *)(phys_ram_base + addr); | |
| 528 | - addr += sizeof(AmlCode); | |
| 529 | - | |
| 530 | - addr = (addr + 7) & ~7; | |
| 531 | - madt_addr = addr; | |
| 532 | - madt_size = sizeof(*madt) + | |
| 533 | - sizeof(struct madt_processor_apic) * smp_cpus + | |
| 534 | - sizeof(struct madt_io_apic); | |
| 535 | - madt = (void *)(phys_ram_base + addr); | |
| 536 | - addr += madt_size; | |
| 537 | - | |
| 538 | - acpi_tables_size = addr - base_addr; | |
| 539 | - | |
| 540 | - cpu_register_physical_memory(base_addr, acpi_tables_size, | |
| 541 | - base_addr | IO_MEM_ROM); | |
| 542 | - | |
| 543 | - /* RSDP */ | |
| 544 | - memset(rsdp, 0, sizeof(*rsdp)); | |
| 545 | - memcpy(rsdp->signature, "RSD PTR ", 8); | |
| 546 | - memcpy(rsdp->oem_id, "QEMU ", 6); | |
| 547 | - rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr); | |
| 548 | - rsdp->checksum = acpi_checksum((void *)rsdp, 20); | |
| 549 | - | |
| 550 | - /* RSDT */ | |
| 551 | - rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); | |
| 552 | - rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); | |
| 553 | - acpi_build_table_header((struct acpi_table_header *)rsdt, | |
| 554 | - "RSDT", sizeof(*rsdt)); | |
| 555 | - | |
| 556 | - /* FADT */ | |
| 557 | - memset(fadt, 0, sizeof(*fadt)); | |
| 558 | - fadt->firmware_ctrl = cpu_to_le32(facs_addr); | |
| 559 | - fadt->dsdt = cpu_to_le32(dsdt_addr); | |
| 560 | - fadt->model = 1; | |
| 561 | - fadt->reserved1 = 0; | |
| 562 | - fadt->sci_int = cpu_to_le16(piix4_pm_state->dev.config[0x3c]); | |
| 563 | - fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR); | |
| 564 | - fadt->acpi_enable = 0xf1; | |
| 565 | - fadt->acpi_disable = 0xf0; | |
| 566 | - fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base); | |
| 567 | - fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04); | |
| 568 | - fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08); | |
| 569 | - fadt->pm1_evt_len = 4; | |
| 570 | - fadt->pm1_cnt_len = 2; | |
| 571 | - fadt->pm_tmr_len = 4; | |
| 572 | - fadt->plvl2_lat = cpu_to_le16(50); | |
| 573 | - fadt->plvl3_lat = cpu_to_le16(50); | |
| 574 | - fadt->plvl3_lat = cpu_to_le16(50); | |
| 575 | - /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */ | |
| 576 | - fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6)); | |
| 577 | - acpi_build_table_header((struct acpi_table_header *)fadt, "FACP", | |
| 578 | - sizeof(*fadt)); | |
| 579 | - | |
| 580 | - /* FACS */ | |
| 581 | - memset(facs, 0, sizeof(*facs)); | |
| 582 | - memcpy(facs->signature, "FACS", 4); | |
| 583 | - facs->length = cpu_to_le32(sizeof(*facs)); | |
| 584 | - | |
| 585 | - /* DSDT */ | |
| 586 | - memcpy(dsdt, AmlCode, sizeof(AmlCode)); | |
| 587 | - | |
| 588 | - /* MADT */ | |
| 589 | - { | |
| 590 | - struct madt_processor_apic *apic; | |
| 591 | - struct madt_io_apic *io_apic; | |
| 592 | - | |
| 593 | - memset(madt, 0, madt_size); | |
| 594 | - madt->local_apic_address = cpu_to_le32(0xfee00000); | |
| 595 | - madt->flags = cpu_to_le32(1); | |
| 596 | - apic = (void *)(madt + 1); | |
| 597 | - for(i=0;i<smp_cpus;i++) { | |
| 598 | - apic->type = APIC_PROCESSOR; | |
| 599 | - apic->length = sizeof(*apic); | |
| 600 | - apic->processor_id = i; | |
| 601 | - apic->local_apic_id = i; | |
| 602 | - apic->flags = cpu_to_le32(1); | |
| 603 | - apic++; | |
| 604 | - } | |
| 605 | - io_apic = (void *)apic; | |
| 606 | - io_apic->type = APIC_IO; | |
| 607 | - io_apic->length = sizeof(*io_apic); | |
| 608 | - io_apic->io_apic_id = smp_cpus; | |
| 609 | - io_apic->address = cpu_to_le32(0xfec00000); | |
| 610 | - io_apic->interrupt = cpu_to_le32(0); | |
| 611 | - | |
| 612 | - acpi_build_table_header((struct acpi_table_header *)madt, | |
| 613 | - "APIC", madt_size); | |
| 614 | - } | |
| 348 | + register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s); | |
| 615 | 349 | } | ... | ... |