Annotation of qemu/roms/seabios/src/acpi.c, revision 1.1

1.1     ! root        1: // Support for generating ACPI tables (on emulators)
        !             2: //
        !             3: // Copyright (C) 2008,2009  Kevin O'Connor <[email protected]>
        !             4: // Copyright (C) 2006 Fabrice Bellard
        !             5: //
        !             6: // This file may be distributed under the terms of the GNU LGPLv3 license.
        !             7: 
        !             8: #include "acpi.h" // struct rsdp_descriptor
        !             9: #include "util.h" // memcpy
        !            10: #include "pci.h" // pci_find_device
        !            11: #include "biosvar.h" // GET_EBDA
        !            12: #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
        !            13: #include "pci_regs.h" // PCI_INTERRUPT_LINE
        !            14: #include "paravirt.h"
        !            15: 
        !            16: /****************************************************/
        !            17: /* ACPI tables init */
        !            18: 
        !            19: /* Table structure from Linux kernel (the ACPI tables are under the
        !            20:    BSD license) */
        !            21: 
        !            22: #define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
        !            23:     u32 signature;          /* ACPI signature (4 ASCII characters) */ \
        !            24:     u32 length;                 /* Length of table, in bytes, including header */ \
        !            25:     u8  revision;               /* ACPI Specification minor version # */ \
        !            26:     u8  checksum;               /* To make sum of entire table == 0 */ \
        !            27:     u8  oem_id [6];             /* OEM identification */ \
        !            28:     u8  oem_table_id [8];       /* OEM table identification */ \
        !            29:     u32 oem_revision;           /* OEM revision number */ \
        !            30:     u8  asl_compiler_id [4];    /* ASL compiler vendor ID */ \
        !            31:     u32 asl_compiler_revision;  /* ASL compiler revision number */
        !            32: 
        !            33: 
        !            34: struct acpi_table_header         /* ACPI common table header */
        !            35: {
        !            36:     ACPI_TABLE_HEADER_DEF
        !            37: } PACKED;
        !            38: 
        !            39: /*
        !            40:  * ACPI 1.0 Root System Description Table (RSDT)
        !            41:  */
        !            42: #define RSDT_SIGNATURE 0x54445352 // RSDT
        !            43: struct rsdt_descriptor_rev1
        !            44: {
        !            45:     ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
        !            46:     u32 table_offset_entry[0];  /* Array of pointers to other */
        !            47:     /* ACPI tables */
        !            48: } PACKED;
        !            49: 
        !            50: /*
        !            51:  * ACPI 1.0 Firmware ACPI Control Structure (FACS)
        !            52:  */
        !            53: #define FACS_SIGNATURE 0x53434146 // FACS
        !            54: struct facs_descriptor_rev1
        !            55: {
        !            56:     u32 signature;           /* ACPI Signature */
        !            57:     u32 length;                 /* Length of structure, in bytes */
        !            58:     u32 hardware_signature;     /* Hardware configuration signature */
        !            59:     u32 firmware_waking_vector; /* ACPI OS waking vector */
        !            60:     u32 global_lock;            /* Global Lock */
        !            61:     u32 S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
        !            62:     u32 reserved1       : 31;   /* Must be 0 */
        !            63:     u8  resverved3 [40];        /* Reserved - must be zero */
        !            64: } PACKED;
        !            65: 
        !            66: 
        !            67: /*
        !            68:  * ACPI 1.0 Fixed ACPI Description Table (FADT)
        !            69:  */
        !            70: #define FACP_SIGNATURE 0x50434146 // FACP
        !            71: struct fadt_descriptor_rev1
        !            72: {
        !            73:     ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
        !            74:     u32 firmware_ctrl;          /* Physical address of FACS */
        !            75:     u32 dsdt;                   /* Physical address of DSDT */
        !            76:     u8  model;                  /* System Interrupt Model */
        !            77:     u8  reserved1;              /* Reserved */
        !            78:     u16 sci_int;                /* System vector of SCI interrupt */
        !            79:     u32 smi_cmd;                /* Port address of SMI command port */
        !            80:     u8  acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
        !            81:     u8  acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
        !            82:     u8  S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
        !            83:     u8  reserved2;              /* Reserved - must be zero */
        !            84:     u32 pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
        !            85:     u32 pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
        !            86:     u32 pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
        !            87:     u32 pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
        !            88:     u32 pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
        !            89:     u32 pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
        !            90:     u32 gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
        !            91:     u32 gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
        !            92:     u8  pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
        !            93:     u8  pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
        !            94:     u8  pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
        !            95:     u8  pm_tmr_len;             /* Byte Length of ports at pm_tm_blk */
        !            96:     u8  gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
        !            97:     u8  gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
        !            98:     u8  gpe1_base;              /* Offset in gpe model where gpe1 events start */
        !            99:     u8  reserved3;              /* Reserved */
        !           100:     u16 plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
        !           101:     u16 plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
        !           102:     u16 flush_size;             /* Size of area read to flush caches */
        !           103:     u16 flush_stride;           /* Stride used in flushing caches */
        !           104:     u8  duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
        !           105:     u8  duty_width;             /* Bit width of duty cycle field in p_cnt reg */
        !           106:     u8  day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
        !           107:     u8  mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
        !           108:     u8  century;                /* Index to century in RTC CMOS RAM */
        !           109:     u8  reserved4;              /* Reserved */
        !           110:     u8  reserved4a;             /* Reserved */
        !           111:     u8  reserved4b;             /* Reserved */
        !           112: #if 0
        !           113:     u32 wb_invd         : 1;    /* The wbinvd instruction works properly */
        !           114:     u32 wb_invd_flush   : 1;    /* The wbinvd flushes but does not invalidate */
        !           115:     u32 proc_c1         : 1;    /* All processors support C1 state */
        !           116:     u32 plvl2_up        : 1;    /* C2 state works on MP system */
        !           117:     u32 pwr_button      : 1;    /* Power button is handled as a generic feature */
        !           118:     u32 sleep_button    : 1;    /* Sleep button is handled as a generic feature, or not present */
        !           119:     u32 fixed_rTC       : 1;    /* RTC wakeup stat not in fixed register space */
        !           120:     u32 rtcs4           : 1;    /* RTC wakeup stat not possible from S4 */
        !           121:     u32 tmr_val_ext     : 1;    /* The tmr_val width is 32 bits (0 = 24 bits) */
        !           122:     u32 reserved5       : 23;   /* Reserved - must be zero */
        !           123: #else
        !           124:     u32 flags;
        !           125: #endif
        !           126: } PACKED;
        !           127: 
        !           128: /*
        !           129:  * MADT values and structures
        !           130:  */
        !           131: 
        !           132: /* Values for MADT PCATCompat */
        !           133: 
        !           134: #define DUAL_PIC                0
        !           135: #define MULTIPLE_APIC           1
        !           136: 
        !           137: 
        !           138: /* Master MADT */
        !           139: 
        !           140: #define APIC_SIGNATURE 0x43495041 // APIC
        !           141: struct multiple_apic_table
        !           142: {
        !           143:     ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
        !           144:     u32 local_apic_address;     /* Physical address of local APIC */
        !           145: #if 0
        !           146:     u32 PCATcompat      : 1;    /* A one indicates system also has dual 8259s */
        !           147:     u32 reserved1       : 31;
        !           148: #else
        !           149:     u32 flags;
        !           150: #endif
        !           151: } PACKED;
        !           152: 
        !           153: 
        !           154: /* Values for Type in APIC sub-headers */
        !           155: 
        !           156: #define APIC_PROCESSOR          0
        !           157: #define APIC_IO                 1
        !           158: #define APIC_XRUPT_OVERRIDE     2
        !           159: #define APIC_NMI                3
        !           160: #define APIC_LOCAL_NMI          4
        !           161: #define APIC_ADDRESS_OVERRIDE   5
        !           162: #define APIC_IO_SAPIC           6
        !           163: #define APIC_LOCAL_SAPIC        7
        !           164: #define APIC_XRUPT_SOURCE       8
        !           165: #define APIC_RESERVED           9           /* 9 and greater are reserved */
        !           166: 
        !           167: /*
        !           168:  * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
        !           169:  */
        !           170: #define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
        !           171:     u8  type;                               \
        !           172:     u8  length;
        !           173: 
        !           174: /* Sub-structures for MADT */
        !           175: 
        !           176: struct madt_processor_apic
        !           177: {
        !           178:     ACPI_SUB_HEADER_DEF
        !           179:     u8  processor_id;           /* ACPI processor id */
        !           180:     u8  local_apic_id;          /* Processor's local APIC id */
        !           181: #if 0
        !           182:     u32 processor_enabled: 1;   /* Processor is usable if set */
        !           183:     u32 reserved2       : 31;   /* Reserved, must be zero */
        !           184: #else
        !           185:     u32 flags;
        !           186: #endif
        !           187: } PACKED;
        !           188: 
        !           189: struct madt_io_apic
        !           190: {
        !           191:     ACPI_SUB_HEADER_DEF
        !           192:     u8  io_apic_id;             /* I/O APIC ID */
        !           193:     u8  reserved;               /* Reserved - must be zero */
        !           194:     u32 address;                /* APIC physical address */
        !           195:     u32 interrupt;              /* Global system interrupt where INTI
        !           196:                                  * lines start */
        !           197: } PACKED;
        !           198: 
        !           199: /* IRQs 5,9,10,11 */
        !           200: #define PCI_ISA_IRQ_MASK    0x0e20
        !           201: 
        !           202: struct madt_intsrcovr {
        !           203:     ACPI_SUB_HEADER_DEF
        !           204:     u8  bus;
        !           205:     u8  source;
        !           206:     u32 gsi;
        !           207:     u16 flags;
        !           208: } PACKED;
        !           209: 
        !           210: /*
        !           211:  * ACPI 2.0 Generic Address Space definition.
        !           212:  */
        !           213: struct acpi_20_generic_address {
        !           214:     u8  address_space_id;
        !           215:     u8  register_bit_width;
        !           216:     u8  register_bit_offset;
        !           217:     u8  reserved;
        !           218:     u64 address;
        !           219: } PACKED;
        !           220: 
        !           221: /*
        !           222:  * HPET Description Table
        !           223:  */
        !           224: struct acpi_20_hpet {
        !           225:     ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
        !           226:     u32           timer_block_id;
        !           227:     struct acpi_20_generic_address addr;
        !           228:     u8            hpet_number;
        !           229:     u16           min_tick;
        !           230:     u8            page_protect;
        !           231: } PACKED;
        !           232: #define ACPI_HPET_ADDRESS 0xFED00000UL
        !           233: 
        !           234: /*
        !           235:  * SRAT (NUMA topology description) table
        !           236:  */
        !           237: 
        !           238: #define SRAT_PROCESSOR          0
        !           239: #define SRAT_MEMORY             1
        !           240: 
        !           241: struct system_resource_affinity_table
        !           242: {
        !           243:     ACPI_TABLE_HEADER_DEF
        !           244:     u32    reserved1;
        !           245:     u32    reserved2[2];
        !           246: } PACKED;
        !           247: 
        !           248: struct srat_processor_affinity
        !           249: {
        !           250:     ACPI_SUB_HEADER_DEF
        !           251:     u8     proximity_lo;
        !           252:     u8     local_apic_id;
        !           253:     u32    flags;
        !           254:     u8     local_sapic_eid;
        !           255:     u8     proximity_hi[3];
        !           256:     u32    reserved;
        !           257: } PACKED;
        !           258: 
        !           259: struct srat_memory_affinity
        !           260: {
        !           261:     ACPI_SUB_HEADER_DEF
        !           262:     u8     proximity[4];
        !           263:     u16    reserved1;
        !           264:     u32    base_addr_low,base_addr_high;
        !           265:     u32    length_low,length_high;
        !           266:     u32    reserved2;
        !           267:     u32    flags;
        !           268:     u32    reserved3[2];
        !           269: } PACKED;
        !           270: 
        !           271: #include "acpi-dsdt.hex"
        !           272: 
        !           273: static inline u16 cpu_to_le16(u16 x)
        !           274: {
        !           275:     return x;
        !           276: }
        !           277: 
        !           278: static inline u32 cpu_to_le32(u32 x)
        !           279: {
        !           280:     return x;
        !           281: }
        !           282: 
        !           283: static void
        !           284: build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
        !           285: {
        !           286:     h->signature = sig;
        !           287:     h->length = cpu_to_le32(len);
        !           288:     h->revision = rev;
        !           289:     memcpy(h->oem_id, CONFIG_APPNAME6, 6);
        !           290:     memcpy(h->oem_table_id, CONFIG_APPNAME4, 4);
        !           291:     memcpy(h->asl_compiler_id, CONFIG_APPNAME4, 4);
        !           292:     memcpy(h->oem_table_id + 4, (void*)&sig, 4);
        !           293:     h->oem_revision = cpu_to_le32(1);
        !           294:     h->asl_compiler_revision = cpu_to_le32(1);
        !           295:     h->checksum -= checksum(h, len);
        !           296: }
        !           297: 
        !           298: static void*
        !           299: build_fadt(int bdf)
        !           300: {
        !           301:     struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
        !           302:     struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
        !           303:     void *dsdt = malloc_high(sizeof(AmlCode));
        !           304: 
        !           305:     if (!fadt || !facs || !dsdt) {
        !           306:         dprintf(1, "Not enough memory for fadt!\n");
        !           307:         return NULL;
        !           308:     }
        !           309: 
        !           310:     /* FACS */
        !           311:     memset(facs, 0, sizeof(*facs));
        !           312:     facs->signature = FACS_SIGNATURE;
        !           313:     facs->length = cpu_to_le32(sizeof(*facs));
        !           314: 
        !           315:     /* DSDT */
        !           316:     memcpy(dsdt, AmlCode, sizeof(AmlCode));
        !           317: 
        !           318:     /* FADT */
        !           319:     memset(fadt, 0, sizeof(*fadt));
        !           320:     fadt->firmware_ctrl = cpu_to_le32((u32)facs);
        !           321:     fadt->dsdt = cpu_to_le32((u32)dsdt);
        !           322:     fadt->model = 1;
        !           323:     fadt->reserved1 = 0;
        !           324:     int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
        !           325:     fadt->sci_int = cpu_to_le16(pm_sci_int);
        !           326:     fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
        !           327:     fadt->acpi_enable = 0xf1;
        !           328:     fadt->acpi_disable = 0xf0;
        !           329:     fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
        !           330:     fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
        !           331:     fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
        !           332:     fadt->pm1_evt_len = 4;
        !           333:     fadt->pm1_cnt_len = 2;
        !           334:     fadt->pm_tmr_len = 4;
        !           335:     fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
        !           336:     fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
        !           337:     fadt->gpe0_blk = cpu_to_le32(0xafe0);
        !           338:     fadt->gpe0_blk_len = 4;
        !           339:     /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
        !           340:     fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
        !           341: 
        !           342:     build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1);
        !           343: 
        !           344:     return fadt;
        !           345: }
        !           346: 
        !           347: static void*
        !           348: build_madt(void)
        !           349: {
        !           350:     int madt_size = (sizeof(struct multiple_apic_table)
        !           351:                      + sizeof(struct madt_processor_apic) * MaxCountCPUs
        !           352:                      + sizeof(struct madt_io_apic)
        !           353:                      + sizeof(struct madt_intsrcovr) * 16);
        !           354:     struct multiple_apic_table *madt = malloc_high(madt_size);
        !           355:     if (!madt) {
        !           356:         dprintf(1, "Not enough memory for madt!\n");
        !           357:         return NULL;
        !           358:     }
        !           359:     memset(madt, 0, madt_size);
        !           360:     madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
        !           361:     madt->flags = cpu_to_le32(1);
        !           362:     struct madt_processor_apic *apic = (void*)&madt[1];
        !           363:     int i;
        !           364:     for (i=0; i<MaxCountCPUs; i++) {
        !           365:         apic->type = APIC_PROCESSOR;
        !           366:         apic->length = sizeof(*apic);
        !           367:         apic->processor_id = i;
        !           368:         apic->local_apic_id = i;
        !           369:         if (i < CountCPUs)
        !           370:             apic->flags = cpu_to_le32(1);
        !           371:         else
        !           372:             apic->flags = cpu_to_le32(0);
        !           373:         apic++;
        !           374:     }
        !           375:     struct madt_io_apic *io_apic = (void*)apic;
        !           376:     io_apic->type = APIC_IO;
        !           377:     io_apic->length = sizeof(*io_apic);
        !           378:     io_apic->io_apic_id = CountCPUs;
        !           379:     io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
        !           380:     io_apic->interrupt = cpu_to_le32(0);
        !           381: 
        !           382:     struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
        !           383:     if (qemu_cfg_irq0_override()) {
        !           384:         memset(intsrcovr, 0, sizeof(*intsrcovr));
        !           385:         intsrcovr->type   = APIC_XRUPT_OVERRIDE;
        !           386:         intsrcovr->length = sizeof(*intsrcovr);
        !           387:         intsrcovr->source = 0;
        !           388:         intsrcovr->gsi    = 2;
        !           389:         intsrcovr->flags  = 0; /* conforms to bus specifications */
        !           390:         intsrcovr++;
        !           391:     }
        !           392:     for (i = 1; i < 16; i++) {
        !           393:         if (!(PCI_ISA_IRQ_MASK & (1 << i)))
        !           394:             /* No need for a INT source override structure. */
        !           395:             continue;
        !           396:         memset(intsrcovr, 0, sizeof(*intsrcovr));
        !           397:         intsrcovr->type   = APIC_XRUPT_OVERRIDE;
        !           398:         intsrcovr->length = sizeof(*intsrcovr);
        !           399:         intsrcovr->source = i;
        !           400:         intsrcovr->gsi    = i;
        !           401:         intsrcovr->flags  = 0xd; /* active high, level triggered */
        !           402:         intsrcovr++;
        !           403:     }
        !           404: 
        !           405:     build_header((void*)madt, APIC_SIGNATURE, (void*)intsrcovr - (void*)madt, 1);
        !           406:     return madt;
        !           407: }
        !           408: 
        !           409: #define SSDT_SIGNATURE 0x54445353 // SSDT
        !           410: static void*
        !           411: build_ssdt(void)
        !           412: {
        !           413:     int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
        !           414:     // calculate the length of processor block and scope block
        !           415:     // excluding PkgLength
        !           416:     int cpu_length = 13 * acpi_cpus + 4;
        !           417: 
        !           418:     int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
        !           419:     u8 *ssdt = malloc_high(length);
        !           420:     if (! ssdt) {
        !           421:         dprintf(1, "No space for ssdt!\n");
        !           422:         return NULL;
        !           423:     }
        !           424: 
        !           425:     u8 *ssdt_ptr = ssdt;
        !           426:     ssdt_ptr[9] = 0; // checksum;
        !           427:     ssdt_ptr += sizeof(struct acpi_table_header);
        !           428: 
        !           429:     // build processor scope header
        !           430:     *(ssdt_ptr++) = 0x10; // ScopeOp
        !           431:     if (cpu_length <= 0x3e) {
        !           432:         *(ssdt_ptr++) = cpu_length + 1;
        !           433:     } else {
        !           434:         *(ssdt_ptr++) = 0x7F;
        !           435:         *(ssdt_ptr++) = (cpu_length + 2) >> 6;
        !           436:     }
        !           437:     *(ssdt_ptr++) = '_'; // Name
        !           438:     *(ssdt_ptr++) = 'P';
        !           439:     *(ssdt_ptr++) = 'R';
        !           440:     *(ssdt_ptr++) = '_';
        !           441: 
        !           442:     // build object for each processor
        !           443:     int i;
        !           444:     for (i=0; i<acpi_cpus; i++) {
        !           445:         *(ssdt_ptr++) = 0x5B; // ProcessorOp
        !           446:         *(ssdt_ptr++) = 0x83;
        !           447:         *(ssdt_ptr++) = 0x0B; // Length
        !           448:         *(ssdt_ptr++) = 'C';  // Name (CPUxx)
        !           449:         *(ssdt_ptr++) = 'P';
        !           450:         if ((i & 0xf0) != 0)
        !           451:             *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
        !           452:         else
        !           453:             *(ssdt_ptr++) = 'U';
        !           454:         *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
        !           455:         *(ssdt_ptr++) = i;
        !           456:         *(ssdt_ptr++) = 0x10; // Processor block address
        !           457:         *(ssdt_ptr++) = 0xb0;
        !           458:         *(ssdt_ptr++) = 0;
        !           459:         *(ssdt_ptr++) = 0;
        !           460:         *(ssdt_ptr++) = 6;    // Processor block length
        !           461:     }
        !           462: 
        !           463:     build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
        !           464: 
        !           465:     return ssdt;
        !           466: }
        !           467: 
        !           468: #define HPET_SIGNATURE 0x54455048 //HPET
        !           469: static void*
        !           470: build_hpet(void)
        !           471: {
        !           472:     struct acpi_20_hpet *hpet = malloc_high(sizeof(*hpet));
        !           473:     if (!hpet) {
        !           474:         dprintf(1, "Not enough memory for hpet!\n");
        !           475:         return NULL;
        !           476:     }
        !           477: 
        !           478:     memset(hpet, 0, sizeof(*hpet));
        !           479:     /* Note timer_block_id value must be kept in sync with value advertised by
        !           480:      * emulated hpet
        !           481:      */
        !           482:     hpet->timer_block_id = cpu_to_le32(0x8086a201);
        !           483:     hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
        !           484:     build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1);
        !           485: 
        !           486:     return hpet;
        !           487: }
        !           488: 
        !           489: static void
        !           490: acpi_build_srat_memory(struct srat_memory_affinity *numamem,
        !           491:                        u64 base, u64 len, int node, int enabled)
        !           492: {
        !           493:     numamem->type = SRAT_MEMORY;
        !           494:     numamem->length = sizeof(*numamem);
        !           495:     memset (numamem->proximity, 0 ,4);
        !           496:     numamem->proximity[0] = node;
        !           497:     numamem->flags = cpu_to_le32(!!enabled);
        !           498:     numamem->base_addr_low = base & 0xFFFFFFFF;
        !           499:     numamem->base_addr_high = base >> 32;
        !           500:     numamem->length_low = len & 0xFFFFFFFF;
        !           501:     numamem->length_high = len >> 32;
        !           502: }
        !           503: 
        !           504: #define SRAT_SIGNATURE 0x54415253 //HPET
        !           505: static void *
        !           506: build_srat(void)
        !           507: {
        !           508:     int nb_numa_nodes = qemu_cfg_get_numa_nodes();
        !           509: 
        !           510:     if (nb_numa_nodes == 0)
        !           511:         return NULL;
        !           512: 
        !           513:     u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes));
        !           514:     if (!numadata) {
        !           515:         dprintf(1, "Not enough memory for read numa data from VM!\n");
        !           516:         return NULL;
        !           517:     }
        !           518: 
        !           519:     qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes);
        !           520: 
        !           521:     struct system_resource_affinity_table *srat;
        !           522:     int srat_size = sizeof(*srat) +
        !           523:         sizeof(struct srat_processor_affinity) * MaxCountCPUs +
        !           524:         sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
        !           525: 
        !           526:     srat = malloc_high(srat_size);
        !           527:     if (!srat) {
        !           528:         dprintf(1, "Not enough memory for srat table!\n");
        !           529:         return NULL;
        !           530:     }
        !           531: 
        !           532:     memset(srat, 0, srat_size);
        !           533:     srat->reserved1=1;
        !           534:     struct srat_processor_affinity *core = (void*)(srat + 1);
        !           535:     int i;
        !           536:     u64 curnode;
        !           537: 
        !           538:     for (i = 0; i < MaxCountCPUs; ++i) {
        !           539:         core->type = SRAT_PROCESSOR;
        !           540:         core->length = sizeof(*core);
        !           541:         core->local_apic_id = i;
        !           542:         curnode = *numadata++;
        !           543:         core->proximity_lo = curnode;
        !           544:         memset(core->proximity_hi, 0, 3);
        !           545:         core->local_sapic_eid = 0;
        !           546:         if (i < CountCPUs)
        !           547:             core->flags = cpu_to_le32(1);
        !           548:         else
        !           549:             core->flags = 0;
        !           550:         core++;
        !           551:     }
        !           552: 
        !           553: 
        !           554:     /* the memory map is a bit tricky, it contains at least one hole
        !           555:      * from 640k-1M and possibly another one from 3.5G-4G.
        !           556:      */
        !           557:     struct srat_memory_affinity *numamem = (void*)core;
        !           558:     int slots = 0;
        !           559:     u64 mem_len, mem_base, next_base = 0;
        !           560: 
        !           561:     acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
        !           562:     next_base = 1024 * 1024;
        !           563:     numamem++;
        !           564:     slots++;
        !           565:     for (i = 1; i < nb_numa_nodes + 1; ++i) {
        !           566:         mem_base = next_base;
        !           567:         mem_len = *numadata++;
        !           568:         if (i == 1)
        !           569:             mem_len -= 1024 * 1024;
        !           570:         next_base = mem_base + mem_len;
        !           571: 
        !           572:         /* Cut out the PCI hole */
        !           573:         if (mem_base <= RamSize && next_base > RamSize) {
        !           574:             mem_len -= next_base - RamSize;
        !           575:             if (mem_len > 0) {
        !           576:                 acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
        !           577:                 numamem++;
        !           578:                 slots++;
        !           579:             }
        !           580:             mem_base = 1ULL << 32;
        !           581:             mem_len = next_base - RamSize;
        !           582:             next_base += (1ULL << 32) - RamSize;
        !           583:         }
        !           584:         acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
        !           585:         numamem++;
        !           586:         slots++;
        !           587:     }
        !           588:     for (; slots < nb_numa_nodes + 2; slots++) {
        !           589:         acpi_build_srat_memory(numamem, 0, 0, 0, 0);
        !           590:         numamem++;
        !           591:     }
        !           592: 
        !           593:     build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1);
        !           594: 
        !           595:     return srat;
        !           596: }
        !           597: 
        !           598: struct rsdp_descriptor *RsdpAddr;
        !           599: 
        !           600: #define MAX_ACPI_TABLES 20
        !           601: void
        !           602: acpi_bios_init(void)
        !           603: {
        !           604:     if (! CONFIG_ACPI)
        !           605:         return;
        !           606: 
        !           607:     dprintf(3, "init ACPI tables\n");
        !           608: 
        !           609:     // This code is hardcoded for PIIX4 Power Management device.
        !           610:     int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
        !           611:                               , PCI_DEVICE_ID_INTEL_82371AB_3);
        !           612:     if (bdf < 0)
        !           613:         // Device not found
        !           614:         return;
        !           615: 
        !           616:     // Create initial rsdt table
        !           617:     struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp));
        !           618:     if (!rsdp) {
        !           619:         dprintf(1, "Not enough memory for acpi rsdp table!\n");
        !           620:         return;
        !           621:     }
        !           622: 
        !           623:     u32 tables[MAX_ACPI_TABLES], tbl_idx = 0;
        !           624: 
        !           625: #define ACPI_INIT_TABLE(X)                                   \
        !           626:     do {                                                     \
        !           627:         tables[tbl_idx] = (u32)(X);                          \
        !           628:         if (tables[tbl_idx])                                 \
        !           629:             tbl_idx++;                                       \
        !           630:     } while(0)
        !           631: 
        !           632:     // Add tables
        !           633:     ACPI_INIT_TABLE(build_fadt(bdf));
        !           634:     ACPI_INIT_TABLE(build_ssdt());
        !           635:     ACPI_INIT_TABLE(build_madt());
        !           636:     ACPI_INIT_TABLE(build_hpet());
        !           637:     ACPI_INIT_TABLE(build_srat());
        !           638: 
        !           639:     u16 i, external_tables = qemu_cfg_acpi_additional_tables();
        !           640: 
        !           641:     for(i = 0; i < external_tables; i++) {
        !           642:         u16 len = qemu_cfg_next_acpi_table_len();
        !           643:         void *addr = malloc_high(len);
        !           644:         if (!addr) {
        !           645:             dprintf(1, "Not enough memory for ext acpi table of size %d!\n"
        !           646:                     , len);
        !           647:             continue;
        !           648:         }
        !           649:         ACPI_INIT_TABLE(qemu_cfg_next_acpi_table_load(addr, len));
        !           650:         if (tbl_idx == MAX_ACPI_TABLES) {
        !           651:             dprintf(1, "Too many external tables!\n");
        !           652:             break;
        !           653:         }
        !           654:     }
        !           655: 
        !           656:     struct rsdt_descriptor_rev1 *rsdt;
        !           657:     size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;
        !           658:     rsdt = malloc_high(rsdt_len);
        !           659: 
        !           660:     if (!rsdt) {
        !           661:         dprintf(1, "Not enough memory for acpi rsdt table!\n");
        !           662:         return;
        !           663:     }
        !           664:     memset(rsdt, 0, rsdt_len);
        !           665:     memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx);
        !           666: 
        !           667:     build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1);
        !           668: 
        !           669:     // Build rsdp pointer table
        !           670:     memset(rsdp, 0, sizeof(*rsdp));
        !           671:     rsdp->signature = RSDP_SIGNATURE;
        !           672:     memcpy(rsdp->oem_id, CONFIG_APPNAME6, 6);
        !           673:     rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt);
        !           674:     rsdp->checksum -= checksum(rsdp, 20);
        !           675:     RsdpAddr = rsdp;
        !           676:     dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt);
        !           677: }
        !           678: 
        !           679: u32
        !           680: find_resume_vector()
        !           681: {
        !           682:     dprintf(4, "rsdp=%p\n", RsdpAddr);
        !           683:     if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE)
        !           684:         return 0;
        !           685:     struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address;
        !           686:     dprintf(4, "rsdt=%p\n", rsdt);
        !           687:     if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
        !           688:         return 0;
        !           689:     void *end = (void*)rsdt + rsdt->length;
        !           690:     int i;
        !           691:     for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
        !           692:         struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i];
        !           693:         if (!fadt || fadt->signature != FACP_SIGNATURE)
        !           694:             continue;
        !           695:         dprintf(4, "fadt=%p\n", fadt);
        !           696:         struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
        !           697:         dprintf(4, "facs=%p\n", facs);
        !           698:         if (! facs || facs->signature != FACS_SIGNATURE)
        !           699:             return 0;
        !           700:         // Found it.
        !           701:         dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector);
        !           702:         return facs->firmware_waking_vector;
        !           703:     }
        !           704:     return 0;
        !           705: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.