[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v3 1/3] acpi: Call acpi_os_prepare_sleep hook in reduced hardware sleep path



> From: Konrad Rzeszutek Wilk [mailto:konrad.wilk@xxxxxxxxxx]
> Sent: Thursday, July 25, 2013 8:04 PM
> 
> CC-ing some of the tboot maintainers.
> > As what I've said, it's up to the others to determine if the patch is OK.
> > I just need to make my concerns visible in the community. :-)
> 
> If I understand your concerns you don't want the hook to depend on any
> of the bit manipulations the existing code does for the pm1 values. The
> hook should do it itself case it needs to tweak them or what not.
> 
> And it also frees you from altering the ACPICA code without having to
> worry about being dependent on what the input values the hook requires?
> 
> Is this what you had in mind? (not compile tested nor tested).

Actually I've drafted such a patch that had conflicts with the Xen/tboot hooks.
Then the patchset has to first delete the hooks to make test possible for 
testers.
It is here:
https://bugzilla.kernel.org/show_bug.cgi?id=54181

> 
> I am not even sure if outside the drivers/acpi you can call
> acpi_hw_get_bit_register_info ..

If we want this patch to be accepted without modification, then someone can 
help to do such cleanup in the future when ACPICA change happens.

> 
> And since the Xen bits would do the same exact bit manipulation it
> probably could use a library to do pm1* stuff so both tboot and Xen
> can use it.

This sounds better.
I think Xen and tboot will need such a library to atomically accessing PM 
register fields.

Thanks and best regards
-Lv

> 
> diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
> index f84fe00..59570b1 100644
> --- a/arch/x86/kernel/tboot.c
> +++ b/arch/x86/kernel/tboot.c
> @@ -273,20 +273,75 @@ static void tboot_copy_fadt(const struct
> acpi_table_fadt *fadt)
>               offsetof(struct acpi_table_facs, firmware_waking_vector);
>  }
> 
> -static int tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
> +static int tboot_get_pm_control(bool legacy)
> +{
> +     u32 pm1a_control;
> +     u32 pm1b_control;
> +     u32 in_value;
> +     acpi_status status;
> +     struct acpi_bit_register_info *sleep_type_reg_info;
> +     struct acpi_bit_register_info *sleep_enable_reg_info;
> +
> +     if (!legacy)
> +             return -ENOSPC;
> +
> +     status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
> +                                    &pm1a_control);
> +     if (ACPI_FAILURE(status)) {
> +             return -EXXX /* something */;
> +     }
> +     sleep_type_reg_info =
> acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
> +     sleep_enable_reg_info =
> acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
> +     /* Clear the SLP_EN and SLP_TYP fields */
> +
> +     pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
> +                       sleep_enable_reg_info->access_bit_mask);
> +     pm1b_control = pm1a_control;
> +
> +     /* Insert the SLP_TYP bits */
> +
> +     pm1a_control |=
> +         (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
> +     pm1b_control |=
> +         (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
> +
> +     /*
> +      * We split the writes of SLP_TYP and SLP_EN to workaround
> +      * poorly implemented hardware.
> +      */
> +
> +     /* Write #1: write the SLP_TYP data to the PM1 Control registers */
> +
> +     status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
> +     if (ACPI_FAILURE(status)) {
> +             return -EXXX /* something */;
> +     }
> +
> +     /* Insert the sleep enable (SLP_EN) bit */
> +
> +     pm1a_control |= sleep_enable_reg_info->access_bit_mask;
> +     pm1b_control |= sleep_enable_reg_info->access_bit_mask;
> +     tboot->acpi_sinfo.pm1a_cnt_val = pm1a_control;
> +     tboot->acpi_sinfo.pm1b_cnt_val = pm1b_control;
> +     return 0;
> +}
> +static int tboot_sleep(u8 sleep_state);
>  {
>       static u32 acpi_shutdown_map[ACPI_S_STATE_COUNT] = {
>               /* S0,1,2: */ -1, -1, -1,
>               /* S3: */ TB_SHUTDOWN_S3,
>               /* S4: */ TB_SHUTDOWN_S4,
>               /* S5: */ TB_SHUTDOWN_S5 };
> +     int rc;
> 
>       if (!tboot_enabled())
>               return 0;
> 
>       tboot_copy_fadt(&acpi_gbl_FADT);
> -     tboot->acpi_sinfo.pm1a_cnt_val = pm1a_control;
> -     tboot->acpi_sinfo.pm1b_cnt_val = pm1b_control;
> +
> +     rc = tboot_get_pm_control();
> +     if (rc < 0)
> +             return -1;
>       /* we always use the 32b wakeup vector */
>       tboot->acpi_sinfo.vector_width = 32;
> 
> diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c
> index 5e5f762..a8e98f9 100644
> --- a/drivers/acpi/acpica/hwesleep.c
> +++ b/drivers/acpi/acpica/hwesleep.c
> @@ -113,6 +113,15 @@ acpi_status acpi_hw_extended_sleep(u8
> sleep_state)
>           !acpi_gbl_FADT.sleep_status.address) {
>               return_ACPI_STATUS(AE_NOT_EXIST);
>       }
> +       /*
> +        * If using tboot or other platforms that need tweaks then
> +        * do them here, and also bail out if neccessary.
> +        */
> +       status = acpi_os_prepare_sleep(sleep_state);
> +       if (ACPI_SKIP(status))
> +               return_ACPI_STATUS(AE_OK);
> +       if (ACPI_FAILURE(status))
> +               return_ACPI_STATUS(status);
> 
>       /* Clear wake status (WAK_STS) */
> 
> diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
> index e3828cc..909b23b 100644
> --- a/drivers/acpi/acpica/hwsleep.c
> +++ b/drivers/acpi/acpica/hwsleep.c
> @@ -108,6 +108,16 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
>               return_ACPI_STATUS(status);
>       }
> 
> +     /*
> +      * If using tboot or other platforms that need tweaks then
> +      * do them here, and also bail out if neccessary.
> +      */
> +     status = acpi_os_prepare_sleep(sleep_state);
> +     if (ACPI_SKIP(status))
> +             return_ACPI_STATUS(AE_OK);
> +     if (ACPI_FAILURE(status))
> +             return_ACPI_STATUS(status);
> +
>       /* Get current value of PM1A control */
> 
>       status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
> @@ -152,12 +162,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
> 
>       ACPI_FLUSH_CPU_CACHE();
> 
> -     status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
> -                                    pm1b_control);
> -     if (ACPI_SKIP(status))
> -             return_ACPI_STATUS(AE_OK);
> -     if (ACPI_FAILURE(status))
> -             return_ACPI_STATUS(status);
>       /* Write #2: Write both SLP_TYP + SLP_EN */
> 
>       status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
> diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
> index e721863..ffcc364 100644
> --- a/drivers/acpi/osl.c
> +++ b/drivers/acpi/osl.c
> @@ -77,8 +77,7 @@ EXPORT_SYMBOL(acpi_in_debugger);
>  extern char line_buf[80];
>  #endif                               /*ENABLE_DEBUGGER */
> 
> -static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl,
> -                                   u32 pm1b_ctrl);
> +static int (*__acpi_os_prepare_sleep)(u8 sleep_state);
> 
>  static acpi_osd_handler acpi_irq_handler;
>  static void *acpi_irq_context;
> @@ -1757,13 +1756,11 @@ acpi_status acpi_os_terminate(void)
>       return AE_OK;
>  }
> 
> -acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
> -                               u32 pm1b_control)
> +acpi_status acpi_os_prepare_sleep(u8 sleep_state)
>  {
>       int rc = 0;
>       if (__acpi_os_prepare_sleep)
> -             rc = __acpi_os_prepare_sleep(sleep_state,
> -                                          pm1a_control, pm1b_control);
> +             rc = __acpi_os_prepare_sleep(sleep_state);
>       if (rc < 0)
>               return AE_ERROR;
>       else if (rc > 0)
> @@ -1772,8 +1769,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
> u32 pm1a_control,
>       return AE_OK;
>  }
> 
> -void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
> -                            u32 pm1a_ctrl, u32 pm1b_ctrl))
> +void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state))
>  {
>       __acpi_os_prepare_sleep = func;
>  }
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 17b5b59..8de1043 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -480,8 +480,7 @@ static inline bool acpi_driver_match_device(struct
> device *dev,
>  void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
>                              u32 pm1a_ctrl,  u32 pm1b_ctrl));
> 
> -acpi_status acpi_os_prepare_sleep(u8 sleep_state,
> -                               u32 pm1a_control, u32 pm1b_control);
> +acpi_status acpi_os_prepare_sleep(u8 sleep_state);
>  #ifdef CONFIG_X86
>  void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
>  #else
> 
> .. massive snip..
> > > > On 07/24/2013 10:38 AM, Moore, Robert wrote:
> > > > > I haven't found a high-level description of "acpi_os_prepare_sleep",
> > > perhaps I missed it.
> > > > >
> > > > > Can someone point me to the overall description of this change and why
> it is
> > > being considered?
> > > >
> > > > Hi Bob,
> > > >
> > > > For this series, the v6 of this series does a decent job of what it is
> > > > trying to accomplish:
> > > > https://lkml.org/lkml/2013/7/1/205
> > > >
> > > > However, I recognize that this does not really describe *why*
> > > > acpi_os_prepare_sleep is necessary to begin with. For that, we need to
> > > > go back a little more.
> > > >
> > > > The summary for the series that introduced it is a good description,
> > > > of the reasons it is necessary:
> > > > http://lkml.indiana.edu/hypermail/linux/kernel/1112.2/00450.html
> > > >
> > > > In summary though - in the case of Xen (and I believe this is also
> > > > true in tboot) a value inappropriate for a VM (which dom0 is a special
> > > > case
> > > > of) was being written to cr3, and the physical machine would never
> > > > come out of S3.
> > > >
> > > > This mechanism gives an os specific hook to do something else down at
> > > > the lower levels, while still being able to take advantage of the
> > > > large amount of OS independent code in ACPICA.
> > >
> > > It might be also prudent to look at original 'hook' that was added by 
> > > Intel in
> the
> > > Linux code to support TXT:
> > >
> > >
> > > commit 86886e55b273f565935491816c7c96b82469d4f8
> > > Author: Joseph Cihula <joseph.cihula@xxxxxxxxx>
> > > Date:   Tue Jun 30 19:31:07 2009 -0700
> > >
> > >     x86, intel_txt: Intel TXT Sx shutdown support
> > >
> > >     Support for graceful handling of sleep states (S3/S4/S5) after an
> Intel(R)
> > > TXT launch.
> > >
> > >     Without this patch, attempting to place the system in one of the ACPI
> > > sleep
> > >     states (S3/S4/S5) will cause the TXT hardware to treat this as an
> attack
> > > and
> > >     will cause a system reset, with memory locked.  Not only may the
> > > subsequent
> > >     memory scrub take some time, but the platform will be unable to
> enter
> > > the
> > >     requested power state.
> > >
> > >     This patch calls back into the tboot so that it may properly and
> securely
> > > clean
> > >     up system state and clear the secrets-in-memory flag, after which it
> will
> > > place
> > >     the system into the requested sleep state using ACPI information
> passed
> > > by the kernel.
> > >
> > >      arch/x86/kernel/smpboot.c     |    2 ++
> > >      drivers/acpi/acpica/hwsleep.c |    3 +++
> > >      kernel/cpu.c                  |    7 ++++++-
> > >      3 files changed, 11 insertions(+), 1 deletion(-)
> > >
> > >     Signed-off-by: Joseph Cihula <joseph.cihula@xxxxxxxxx>
> > >     Signed-off-by: Shane Wang <shane.wang@xxxxxxxxx>
> > >     Signed-off-by: H. Peter Anvin <hpa@xxxxxxxxx>
> > >
> > > I suspect that if tboot was used with a different OS (Solaris?) it would 
> > > hit the
> > > same case and a similar hook would be needed.
> > >
> > > Said 'hook' (which was a call to tboot_sleep) was converted to be a more
> > > neutral 'acpi_os_prepare_sleep' which tboot can use (and incidently Xen
> too).
> > >
> > > I think what Bob is saying that if said hook is neccessary (and I believe 
> > > it is -
> and
> > > Intel TXT maintainer thinks so too since he added it in the first place), 
> > > then
> the
> > > right way of adding it is via the ACPICA tree.
> > >
> > > Should the discussion for this be moved there ?
> (https://acpica.org/community)
> > > and an generic 'os_prepare_sleep' patch added in
> > > git://github.com/acpica/acpica.git?
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in 
> > > the
> body
> > > of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at
> > > http://vger.kernel.org/majordomo-info.html
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> >

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.