The first three of these are cloned from Linux counterparts, and the last one adjusts behavior we would have needed for v4 already. 1: ACPI 5.0: Basic support for FADT version 5 2: ACPI 5.0: Implement hardware-reduced option 3: ACPICA: Update for larger ACPI 5 FADT size 4: ACPI: support v5 (reduced HW) sleep interface 5: x86: honor ACPI indicating absence of CMOS RTC 6: honor ACPI v4 FADT flags Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/drivers/acpi/tables/tbfadt.c +++ b/xen/drivers/acpi/tables/tbfadt.c @@ -222,12 +222,13 @@ void __init acpi_tb_create_local_fadt(st /* * Check if the FADT is larger than the largest table that we expect - * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue + * (the ACPI 5.0 version). If so, truncate the table, and issue * a warning. */ if (length > sizeof(struct acpi_table_fadt)) { ACPI_WARNING((AE_INFO, - "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX", + "FADT (revision %u) is longer than ACPI 5.0 version," + " truncating length %u to %zu", table->revision, (unsigned)length, sizeof(struct acpi_table_fadt))); } --- a/xen/include/acpi/actbl.h +++ b/xen/include/acpi/actbl.h @@ -255,6 +255,8 @@ struct acpi_table_fadt { struct acpi_generic_address xpm_timer_block; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ struct acpi_generic_address xgpe0_block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */ struct acpi_generic_address xgpe1_block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ + struct acpi_generic_address sleep_control; /* 64-bit Sleep Control register */ + struct acpi_generic_address sleep_status; /* 64-bit Sleep Status register */ }; /* Masks for FADT Boot Architecture Flags (boot_flags) */ @@ -264,6 +266,7 @@ struct acpi_table_fadt { #define ACPI_FADT_NO_VGA (1<<2) /* 02: [V4] It is not safe to probe for VGA hardware */ #define ACPI_FADT_NO_MSI (1<<3) /* 03: [V4] Message Signaled Interrupts (MSI) must not be enabled */ #define ACPI_FADT_NO_ASPM (1<<4) /* 04: [V4] PCIe ASPM control must not be enabled */ +#define ACPI_FADT_NO_CMOS_RTC (1<<5) /* 05: [V5] No CMOS real-time clock present */ #define FADT2_REVISION_ID 3 @@ -289,6 +292,8 @@ struct acpi_table_fadt { #define ACPI_FADT_REMOTE_POWER_ON (1<<17) /* 17: [V4] System is compatible with remote power on (ACPI 3.0) */ #define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: [V4] All local APICs must use cluster model (ACPI 3.0) */ #define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: [V4] All local x_aPICs must use physical dest mode (ACPI 3.0) */ +#define ACPI_FADT_HW_REDUCED (1<<20) /* 20: [V5] ACPI hardware is not implemented (ACPI 5.0) */ +#define ACPI_FADT_LOW_POWER_S0 (1<<21) /* 21: [V5] S0 power savings are equal or better than S3 (ACPI 5.0) */ /* Values for preferred_profile (Preferred Power Management Profiles) */ @@ -299,14 +304,16 @@ enum acpi_prefered_pm_profiles { PM_WORKSTATION = 3, PM_ENTERPRISE_SERVER = 4, PM_SOHO_SERVER = 5, - PM_APPLIANCE_PC = 6 + PM_APPLIANCE_PC = 6, + PM_PERFORMANCE_SERVER = 7, + PM_TABLET = 8 }; /* Reset to default packing */ #pragma pack() -#define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_fadt, f) +#define ACPI_FADT_OFFSET(f) (u16) ACPI_OFFSET (struct acpi_table_fadt, f) /* * Get the remaining ACPI tables @@ -324,12 +331,15 @@ enum acpi_prefered_pm_profiles { * FADT is the bottom line as to what the version really is. * * For reference, the values below are as follows: - * FADT V1 size: 0x74 - * FADT V2 size: 0x84 - * FADT V3+ size: 0xF4 + * FADT V1 size: 0x074 + * FADT V2 size: 0x084 + * FADT V3 size: 0x0F4 + * FADT V4 size: 0x0F4 + * FADT V5 size: 0x10C */ #define ACPI_FADT_V1_SIZE (u32) (ACPI_FADT_OFFSET (flags) + 4) #define ACPI_FADT_V2_SIZE (u32) (ACPI_FADT_OFFSET (reserved4[0]) + 3) -#define ACPI_FADT_V3_SIZE (u32) (sizeof (struct acpi_table_fadt)) +#define ACPI_FADT_V3_SIZE (u32) (ACPI_FADT_OFFSET (sleep_control)) +#define ACPI_FADT_V5_SIZE (u32) (sizeof (struct acpi_table_fadt)) #endif /* __ACTBL_H__ */
If HW-reduced flag is set in the FADT, do not attempt to access or initialize any ACPI hardware, including SCI and global lock. No FACS will be present. Signed-off-by: Bob Moore <robert.moore@intel.com> Also adjust acpi_fadt_parse_sleep_info(). Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/acpi/boot.c +++ b/xen/arch/x86/acpi/boot.c @@ -328,6 +328,9 @@ acpi_fadt_parse_sleep_info(struct acpi_t struct acpi_table_facs *facs = NULL; uint64_t facs_pa; + if (fadt->flags & ACPI_FADT_HW_REDUCED) + goto bad; + acpi_fadt_copy_address(pm1a_cnt, pm1a_control, pm1_control); acpi_fadt_copy_address(pm1b_cnt, pm1b_control, pm1_control); acpi_fadt_copy_address(pm1a_evt, pm1a_event, pm1_event); @@ -351,6 +354,8 @@ acpi_fadt_parse_sleep_info(struct acpi_t fadt->facs, facs_pa); facs_pa = (uint64_t)fadt->facs; } + if (!facs_pa) + goto bad; facs = (struct acpi_table_facs *) __acpi_map_table(facs_pa, sizeof(struct acpi_table_facs)); --- a/xen/include/acpi/acglobal.h +++ b/xen/include/acpi/acglobal.h @@ -78,6 +78,13 @@ ACPI_EXTERN struct acpi_table_fadt acpi_ ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; +/* + * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning + * that the ACPI hardware is no longer required. A flag in the FADT indicates + * a reduced HW machine, and that flag is duplicated here for convenience. + */ +ACPI_EXTERN u8 acpi_gbl_reduced_hardware; + /***************************************************************************** * * Miscellaneous globals --- a/xen/drivers/acpi/tables/tbfadt.c +++ b/xen/drivers/acpi/tables/tbfadt.c @@ -197,8 +197,13 @@ void __init acpi_tb_parse_fadt(acpi_nati acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, - flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); + /* If Hardware Reduced flag is set, there is no FACS */ + + if (!acpi_gbl_reduced_hardware) { + acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT. + Xfacs, flags, ACPI_SIG_FACS, + ACPI_TABLE_INDEX_FACS); + } } /******************************************************************************* @@ -242,6 +247,13 @@ void __init acpi_tb_create_local_fadt(st ACPI_MEMCPY(&acpi_gbl_FADT, table, ACPI_MIN(length, sizeof(struct acpi_table_fadt))); + /* Take a copy of the Hardware Reduced flag */ + + acpi_gbl_reduced_hardware = FALSE; + if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) { + acpi_gbl_reduced_hardware = TRUE; + } + /* * 1) Convert the local copy of the FADT to the common internal format * 2) Validate some of the important values within the FADT @@ -401,6 +413,12 @@ static void __init acpi_tb_validate_fadt u8 length; acpi_native_uint i; + /* If Hardware Reduced flag is set, we are all done */ + + if (acpi_gbl_reduced_hardware) { + return; + } + /* Examine all of the 64-bit extended address fields (X fields) */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
FADT is now larger than 256 bytes, so all FADT offsets must be changed from 8 bits to 16 bits. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/drivers/acpi/tables/tbfadt.c +++ b/xen/drivers/acpi/tables/tbfadt.c @@ -62,13 +62,14 @@ static void acpi_tb_validate_fadt(void); typedef struct acpi_fadt_info { char *name; - u8 target; - u8 source; - u8 length; + u16 target; + u16 source; + u16 length; u8 type; } acpi_fadt_info; +#define ACPI_FADT_OPTIONAL 0 #define ACPI_FADT_REQUIRED 1 #define ACPI_FADT_SEPARATE_LENGTH 2 @@ -79,7 +80,7 @@ static struct acpi_fadt_info __initdata {"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block), ACPI_FADT_OFFSET(pm1b_event_block), - ACPI_FADT_OFFSET(pm1_event_length), 0}, + ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_OPTIONAL}, {"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block), ACPI_FADT_OFFSET(pm1a_control_block), @@ -87,7 +88,7 @@ static struct acpi_fadt_info __initdata {"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block), ACPI_FADT_OFFSET(pm1b_control_block), - ACPI_FADT_OFFSET(pm1_control_length), 0}, + ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_OPTIONAL}, {"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block), ACPI_FADT_OFFSET(pm2_control_block), _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Jan Beulich
2013-Feb-21 13:00 UTC
[PATCH 4/6] ACPI: support v5 (reduced HW) sleep interface
Note that this also fixes a broken input check in acpi_enter_sleep() (previously validating the sleep->pm1[ab]_cnt_val relationship based on acpi_sinfo.pm1b_cnt_val, which however gets set only subsequently). Also adjust a few minor issues with the pre-v5 handling in acpi_fadt_parse_sleep_info(). Signed-off-by: Jan Beulich <jbeulich@suse.com> --- A question is whether, rather than passing the raw values read from _Sx to XENPF_enter_acpi_sleep, we should again have Dom0 pass the values ready to be written into the registers - that would make things consistent with the legacy case, but add further dependency of the hypervisor on Dom0 behavior where it''s not really needed. I think that it was a mistake for the original variant to have Dom0 pass massaged values to the hypervisor. --- a/xen/arch/x86/acpi/boot.c +++ b/xen/arch/x86/acpi/boot.c @@ -310,14 +310,15 @@ static int __init acpi_invalidate_bgrt(s #ifdef CONFIG_ACPI_SLEEP #define acpi_fadt_copy_address(dst, src, len) do { \ - if (fadt->header.revision >= FADT2_REVISION_ID) \ + if (fadt->header.revision >= FADT2_REVISION_ID && \ + fadt->header.length >= ACPI_FADT_V2_SIZE) \ acpi_sinfo.dst##_blk = fadt->x##src##_block; \ if (!acpi_sinfo.dst##_blk.address) { \ acpi_sinfo.dst##_blk.address = fadt->src##_block; \ acpi_sinfo.dst##_blk.space_id = ACPI_ADR_SPACE_SYSTEM_IO; \ acpi_sinfo.dst##_blk.bit_width = fadt->len##_length << 3; \ acpi_sinfo.dst##_blk.bit_offset = 0; \ - acpi_sinfo.dst##_blk.access_width = 0; \ + acpi_sinfo.dst##_blk.access_width = fadt->len##_length; \ } \ } while (0) @@ -328,6 +329,41 @@ acpi_fadt_parse_sleep_info(struct acpi_t struct acpi_table_facs *facs = NULL; uint64_t facs_pa; + if (fadt->header.revision >= 5 && + fadt->header.length >= ACPI_FADT_V5_SIZE) { + acpi_sinfo.sleep_control = fadt->sleep_control; + acpi_sinfo.sleep_status = fadt->sleep_status; + + printk(KERN_INFO PREFIX + "v5 SLEEP INFO: control[%d:%"PRIx64"]," + " status[%d:%"PRIx64"]\n", + acpi_sinfo.sleep_control.space_id, + acpi_sinfo.sleep_control.address, + acpi_sinfo.sleep_status.space_id, + acpi_sinfo.sleep_status.address); + + if ((fadt->sleep_control.address && + (fadt->sleep_control.bit_offset || + fadt->sleep_control.bit_width !+ fadt->sleep_control.access_width * 8)) || + (fadt->sleep_status.address && + (fadt->sleep_status.bit_offset || + fadt->sleep_status.bit_width !+ fadt->sleep_status.access_width * 8))) { + printk(KERN_WARNING PREFIX + "Invalid sleep control/status register data:" + " %#x:%#x:%#x %#x:%#x:%#x\n", + fadt->sleep_control.bit_offset, + fadt->sleep_control.bit_width, + fadt->sleep_control.access_width, + fadt->sleep_status.bit_offset, + fadt->sleep_status.bit_width, + fadt->sleep_status.access_width); + fadt->sleep_control.address = 0; + fadt->sleep_status.address = 0; + } + } + if (fadt->flags & ACPI_FADT_HW_REDUCED) goto bad; @@ -337,7 +373,7 @@ acpi_fadt_parse_sleep_info(struct acpi_t acpi_fadt_copy_address(pm1b_evt, pm1b_event, pm1_event); printk(KERN_INFO PREFIX - "ACPI SLEEP INFO: pm1x_cnt[%"PRIx64",%"PRIx64"], " + "SLEEP INFO: pm1x_cnt[%"PRIx64",%"PRIx64"], " "pm1x_evt[%"PRIx64",%"PRIx64"]\n", acpi_sinfo.pm1a_cnt_blk.address, acpi_sinfo.pm1b_cnt_blk.address, @@ -384,11 +420,14 @@ acpi_fadt_parse_sleep_info(struct acpi_t acpi_sinfo.vector_width = 32; printk(KERN_INFO PREFIX - " wakeup_vec[%"PRIx64"], vec_size[%x]\n", + " wakeup_vec[%"PRIx64"], vec_size[%x]\n", acpi_sinfo.wakeup_vector, acpi_sinfo.vector_width); return; bad: - memset(&acpi_sinfo, 0, sizeof(acpi_sinfo)); + memset(&acpi_sinfo, 0, + offsetof(struct acpi_sleep_info, sleep_control)); + memset(&acpi_sinfo.sleep_status + 1, 0, + (long)(&acpi_sinfo + 1) - (long)(&acpi_sinfo.sleep_status + 1)); } #endif --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -239,23 +239,47 @@ static long enter_state_helper(void *dat */ int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep) { - if ( !acpi_sinfo.pm1a_cnt_blk.address ) + if ( sleep->flags & XENPF_ACPI_SLEEP_EXTENDED ) + { + if ( !acpi_sinfo.sleep_control.address || + !acpi_sinfo.sleep_status.address ) + return -EPERM; + + if ( sleep->flags & ~XENPF_ACPI_SLEEP_EXTENDED ) + return -EINVAL; + + if ( sleep->val_a > ACPI_SLEEP_TYPE_MAX || + (sleep->val_b != ACPI_SLEEP_TYPE_INVALID && + sleep->val_b > ACPI_SLEEP_TYPE_MAX) ) + return -ERANGE; + + acpi_sinfo.sleep_type_a = sleep->val_a; + acpi_sinfo.sleep_type_b = sleep->val_b; + + acpi_sinfo.sleep_extended = 1; + } + + else if ( !acpi_sinfo.pm1a_cnt_blk.address ) return -EPERM; /* Sanity check */ - if ( acpi_sinfo.pm1b_cnt_val && - ((sleep->pm1a_cnt_val ^ sleep->pm1b_cnt_val) & - ACPI_BITMASK_SLEEP_ENABLE) ) + else if ( sleep->val_b && + ((sleep->val_a ^ sleep->val_b) & ACPI_BITMASK_SLEEP_ENABLE) ) { gdprintk(XENLOG_ERR, "Mismatched pm1a/pm1b setting."); return -EINVAL; } - if ( sleep->flags ) + else if ( sleep->flags ) return -EINVAL; - acpi_sinfo.pm1a_cnt_val = sleep->pm1a_cnt_val; - acpi_sinfo.pm1b_cnt_val = sleep->pm1b_cnt_val; + else + { + acpi_sinfo.pm1a_cnt_val = sleep->val_a; + acpi_sinfo.pm1b_cnt_val = sleep->val_b; + acpi_sinfo.sleep_extended = 0; + } + acpi_sinfo.sleep_state = sleep->sleep_state; return continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo); @@ -266,6 +290,13 @@ static int acpi_get_wake_status(void) uint32_t val; acpi_status status; + if ( acpi_sinfo.sleep_extended ) + { + status = acpi_hw_register_read(ACPI_REGISTER_SLEEP_STATUS, &val); + + return ACPI_FAILURE(status) ? 0 : val & ACPI_X_WAKE_STATUS; + } + /* Wake status is the 15th bit of PM1 status register. (ACPI spec 3.0) */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &val); if ( ACPI_FAILURE(status) ) @@ -335,19 +366,33 @@ acpi_status acpi_enter_sleep_state(u8 sl ACPI_FLUSH_CPU_CACHE(); - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - acpi_sinfo.pm1a_cnt_val); - if ( ACPI_FAILURE(status) ) - return_ACPI_STATUS(AE_ERROR); - - if ( acpi_sinfo.pm1b_cnt_blk.address ) + if ( acpi_sinfo.sleep_extended ) { - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - acpi_sinfo.pm1b_cnt_val); - if ( ACPI_FAILURE(status) ) - return_ACPI_STATUS(AE_ERROR); + /* + * Set the SLP_TYP and SLP_EN bits. + * + * Note: We only use the first value returned by the \_Sx method + * (acpi_sinfo.sleep_type_a) - As per ACPI specification. + */ + u8 sleep_type_value + ((acpi_sinfo.sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE; + + status = acpi_hw_register_write(ACPI_REGISTER_SLEEP_CONTROL, + sleep_type_value); + } + else + { + status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, + acpi_sinfo.pm1a_cnt_val); + if ( !ACPI_FAILURE(status) && acpi_sinfo.pm1b_cnt_blk.address ) + status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, + acpi_sinfo.pm1b_cnt_val); } + if ( ACPI_FAILURE(status) ) + return_ACPI_STATUS(AE_ERROR); + /* Wait until we enter sleep state, and spin until we wake */ while ( !acpi_get_wake_status() ) continue; --- a/xen/drivers/acpi/hwregs.c +++ b/xen/drivers/acpi/hwregs.c @@ -365,6 +365,14 @@ acpi_hw_register_read(u32 register_id, u acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); break; + case ACPI_REGISTER_SLEEP_STATUS: + + status + acpi_hw_low_level_read(acpi_gbl_FADT.sleep_status.bit_width, + &value1, + &acpi_gbl_FADT.sleep_status); + break; + default: ACPI_DEBUG_PRINT((AE_INFO, "Unknown Register ID: %X", register_id)); status = AE_BAD_PARAMETER; @@ -525,6 +533,14 @@ acpi_status acpi_hw_register_write(u32 r acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); break; + case ACPI_REGISTER_SLEEP_CONTROL: + + status + acpi_hw_low_level_write(acpi_gbl_FADT.sleep_control.bit_width, + value, + &acpi_gbl_FADT.sleep_control); + break; + default: status = AE_BAD_PARAMETER; break; --- a/xen/include/acpi/aclocal.h +++ b/xen/include/acpi/aclocal.h @@ -128,6 +128,8 @@ struct acpi_bit_register_info { #define ACPI_REGISTER_PM_TIMER 0x07 #define ACPI_REGISTER_PROCESSOR_BLOCK 0x08 #define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x09 +#define ACPI_REGISTER_SLEEP_CONTROL 0x0a +#define ACPI_REGISTER_SLEEP_STATUS 0x0b /* Masks used to access the bit_registers */ --- a/xen/include/acpi/actbl.h +++ b/xen/include/acpi/actbl.h @@ -309,6 +309,13 @@ enum acpi_prefered_pm_profiles { PM_TABLET = 8 }; +/* Values for sleep_status and sleep_control registers (V5 FADT) */ + +#define ACPI_X_WAKE_STATUS 0x80 +#define ACPI_X_SLEEP_TYPE_MASK 0x1C +#define ACPI_X_SLEEP_TYPE_POSITION 0x02 +#define ACPI_X_SLEEP_ENABLE 0x20 + /* Reset to default packing */ #pragma pack() --- a/xen/include/asm-x86/acpi.h +++ b/xen/include/asm-x86/acpi.h @@ -126,11 +126,20 @@ struct acpi_sleep_info { struct acpi_generic_address pm1b_cnt_blk; struct acpi_generic_address pm1a_evt_blk; struct acpi_generic_address pm1b_evt_blk; - uint16_t pm1a_cnt_val; - uint16_t pm1b_cnt_val; + struct acpi_generic_address sleep_control; + struct acpi_generic_address sleep_status; + union { + uint16_t pm1a_cnt_val; + uint8_t sleep_type_a; + }; + union { + uint16_t pm1b_cnt_val; + uint8_t sleep_type_b; + }; uint32_t sleep_state; uint64_t wakeup_vector; uint32_t vector_width; + bool_t sleep_extended; }; #endif /* CONFIG_ACPI_SLEEP */ --- a/xen/include/public/platform.h +++ b/xen/include/public/platform.h @@ -290,10 +290,16 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_i #define XENPF_enter_acpi_sleep 51 struct xenpf_enter_acpi_sleep { /* IN variables */ +#if __XEN_INTERFACE_VERSION__ < 0x00040300 uint16_t pm1a_cnt_val; /* PM1a control value. */ uint16_t pm1b_cnt_val; /* PM1b control value. */ +#else + uint16_t val_a; /* PM1a control / sleep type A. */ + uint16_t val_b; /* PM1b control / sleep type B. */ +#endif uint32_t sleep_state; /* Which state to enter (Sn). */ - uint32_t flags; /* Must be zero. */ +#define XENPF_ACPI_SLEEP_EXTENDED 0x00000001 + uint32_t flags; /* XENPF_ACPI_SLEEP_*. */ }; typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t; DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Jan Beulich
2013-Feb-21 13:01 UTC
[PATCH 5/6] x86: honor ACPI indicating absence of CMOS RTC
On such systems we can boot through EFI only. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -754,6 +754,9 @@ static unsigned long get_cmos_time(void) return res; } + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) ) + panic("System without CMOS RTC must be booted from EFI\n"); + spin_lock_irqsave(&rtc_lock, flags); /* read RTC exactly on falling edge of update flag */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
- force use of physical APIC mode if indicated so (as we don''t support xAPIC cluster mode, the respective flag is taken to force physical mode too) - don''t use MSI if indicated so (implies no IOMMU) Both can be overridden on the command line, for the MSI case this at once adds a new command line option allowing to turn off PCI MSI (IOMMU and HPET are unaffected by this). Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -639,6 +639,13 @@ limit is ignored by Xen. Specify if the MMConfig space should be enabled. +### msi +> `= <boolean>` + +> Default: `true` + +Force Xen to (not) use PCI-MSI, even if ACPI FADT says otherwise. + ### mwait-idle > `= <boolean>` --- a/xen/arch/x86/genapic/bigsmp.c +++ b/xen/arch/x86/genapic/bigsmp.c @@ -40,7 +40,14 @@ static struct dmi_system_id __initdata b static __init int probe_bigsmp(void) { - if (!def_to_bigsmp) + /* + * We don''t implement cluster mode, so force use of + * physical mode in both cases. + */ + if (acpi_gbl_FADT.flags & + (ACPI_FADT_APIC_CLUSTER | ACPI_FADT_APIC_PHYSICAL)) + def_to_bigsmp = 1; + else if (!def_to_bigsmp) dmi_check_system(bigsmp_dmi_table); return def_to_bigsmp; } --- a/xen/arch/x86/genapic/x2apic.c +++ b/xen/arch/x86/genapic/x2apic.c @@ -30,9 +30,6 @@ #include <xen/smp.h> #include <asm/mach-default/mach_mpparse.h> -static bool_t __initdata x2apic_phys; /* By default we use logical cluster mode. */ -boolean_param("x2apic_phys", x2apic_phys); - static DEFINE_PER_CPU_READ_MOSTLY(u32, cpu_2_logical_apicid); static DEFINE_PER_CPU_READ_MOSTLY(cpumask_t *, cluster_cpus); static cpumask_t *cluster_cpus_spare; @@ -223,8 +220,14 @@ static struct notifier_block x2apic_cpu_ .notifier_call = update_clusterinfo }; +static s8 __initdata x2apic_phys = -1; /* By default we use logical cluster mode. */ +boolean_param("x2apic_phys", x2apic_phys); + const struct genapic *__init apic_x2apic_probe(void) { + if ( x2apic_phys < 0 ) + x2apic_phys = !!(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL); + if ( x2apic_phys ) return &apic_x2apic_phys; --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -381,6 +381,9 @@ static void __init hpet_fsb_cap_lookup(v u32 id; unsigned int i, num_chs; + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) + return; + id = hpet_read32(HPET_ID); num_chs = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -32,6 +32,9 @@ #include <xen/iommu.h> #include <xsm/xsm.h> +static s8 __read_mostly use_msi = -1; +boolean_param("msi", use_msi); + /* bitmap indicate which fixed map is free */ static DEFINE_SPINLOCK(msix_fixmap_lock); static DECLARE_BITMAP(msix_fixmap_pages, FIX_MSIX_MAX_PAGES); @@ -994,6 +997,9 @@ int pci_prepare_msix(u16 seg, u8 bus, u8 unsigned int pos = pci_find_cap_offset(seg, bus, slot, func, PCI_CAP_ID_MSIX); + if ( !use_msi ) + return 0; + if ( !pos ) return -ENODEV; @@ -1029,6 +1035,9 @@ int pci_enable_msi(struct msi_info *msi, { ASSERT(spin_is_locked(&pcidevs_lock)); + if ( !use_msi ) + return -EPERM; + return msi->table_base ? __pci_enable_msix(msi, desc) : __pci_enable_msi(msi, desc); } @@ -1074,7 +1083,10 @@ int pci_restore_msi_state(struct pci_dev ASSERT(spin_is_locked(&pcidevs_lock)); - if (!pdev) + if ( !use_msi ) + return -EOPNOTSUPP; + + if ( !pdev ) return -EINVAL; ret = xsm_resource_setup_pci(XSM_PRIV, (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn); @@ -1133,7 +1145,7 @@ unsigned int pci_msix_get_table_len(stru func = PCI_FUNC(pdev->devfn); pos = pci_find_cap_offset(seg, bus, slot, func, PCI_CAP_ID_MSIX); - if ( !pos ) + if ( !pos || !use_msi ) return 0; control = pci_conf_read16(seg, bus, slot, func, msix_control_reg(pos)); @@ -1170,6 +1182,11 @@ static struct notifier_block msi_cpu_nfb void __init early_msi_init(void) { + if ( use_msi < 0 ) + use_msi = !(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI); + if ( !use_msi ) + return; + register_cpu_notifier(&msi_cpu_nfb); if ( msi_cpu_callback(&msi_cpu_nfb, CPU_UP_PREPARE, NULL) & NOTIFY_STOP_MASK ) --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -1094,5 +1094,8 @@ int __init amd_iommu_get_ivrs_dev_entrie int __init amd_iommu_update_ivrs_mapping_acpi(void) { + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) + return -EPERM; + return acpi_table_parse(ACPI_SIG_IVRS, parse_ivrs_table); } --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -2115,6 +2115,12 @@ int __init intel_vtd_setup(void) goto error; } + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) + { + ret = -EPERM; + goto error; + } + platform_quirks_init(); /* We enable the following features only if they are supported by all VT-d _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Jan Beulich
2013-Feb-21 13:03 UTC
Re: [PATCH 1/6] ACPI 5.0: Basic support for FADT version 5
>>> On 21.02.13 at 13:58, "Jan Beulich" <JBeulich@suse.com> wrote: > Signed-off-by: Bob Moore <robert.moore@intel.com> > Signed-off-by: Jan Beulich <jbeulich@suse.com>Patch now also attached, if needed by anyone. Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
On 21/02/2013 12:49, "Jan Beulich" <JBeulich@suse.com> wrote:> The first three of these are cloned from Linux counterparts, and the > last one adjusts behavior we would have needed for v4 already. > > 1: ACPI 5.0: Basic support for FADT version 5 > 2: ACPI 5.0: Implement hardware-reduced option > 3: ACPICA: Update for larger ACPI 5 FADT size > 4: ACPI: support v5 (reduced HW) sleep interface > 5: x86: honor ACPI indicating absence of CMOS RTC > 6: honor ACPI v4 FADT flags > > Signed-off-by: Jan Beulich <jbeulich@suse.com>Looks alright to me. Acked-by: Keir Fraser <keir@xen.org>> > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel