diff mbox series

[v2] tpm: Fix suspend/shutdown on some boards by preserving chip Locality

Message ID 20240307224957.29432-1-adamoa@gmail.com (mailing list archive)
State New, archived
Headers show
Series [v2] tpm: Fix suspend/shutdown on some boards by preserving chip Locality | expand

Commit Message

Adam Alves March 7, 2024, 10:49 p.m. UTC
Some buggy firmware might require the TPM device to be in default
locality (Locality 0) before suspend or shutdown. Failing to do so
would leave the system in a hanged state before sleep or power off
(after “reboot: Power down” message). Such is the case for the ASUSTeK
COMPUTER INC. TUF GAMING B460M-PLUS board, I believe this might be the
case for several other boards based on some bugs over the internet
while trying to find out how to fix my specific issue. Most forums
suggest the user to disable the TPM device on firmware BIOS in order to
work around this specific issue, which disables several security
features provided by TPM.

The root cause might be that after the ACPI command to put the device
to S3 or S5, some firmware application/driver will try to use the TPM
chip expecting it to be in Locality 0 as expected by TCG PC Client
Platform Firmware Profile Version 1.06 Revision 52 (3.1.1 – Pre-OS
Environment) and then when it fails to do so it simply halts the
whole system.

Enable a user to configure the kernel through
“tpm.locality_on_suspend=1” boot parameter so that the locality is set
before suspend/shutdown in order to diagnose whether or not the board is
one of the buggy ones that require this workaround. Since this bug is
related to the board/platform instead of the specific TPM chip, call
dmi_check_system on the tpm_init function so that this setting is
automatically enabled for boards specified in code (ASUS TUF GAMING
B460M-PLUS already included) – automatic configuration only works in
case CONFIG_DMI is set though, since dmi_check_system is a non-op when
CONFIG_DMI is not set.

In case “tpm.locality_on_suspend=0” (the default) don't change any
behavior thus preserving current functionality of any other board
except ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS and possibly future
boards as we successfully diagnose other boards with the same issue
fixed by using “tpm.locality_on_suspend=1”.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=217890
Signed-off-by: Adam Alves <adamoa@gmail.com>
---
v1->v2: fix formatting issues and simplified tpm_chip_stop code.

 drivers/char/tpm/tpm-chip.c      | 12 +++++++++++
 drivers/char/tpm/tpm-interface.c | 37 ++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm.h           |  1 +
 include/linux/tpm.h              |  1 +
 4 files changed, 51 insertions(+)

Comments

Paul Menzel March 8, 2024, 9:33 a.m. UTC | #1
Dear Adam,


Thank you very much for analyzing the problem and finding a fix. I have 
some small nits and questions. The current state is alright. Should you 
send another version, that you could address the nits.


Am 07.03.24 um 23:49 schrieb Adam Alves:
> Some buggy firmware might require the TPM device to be in default
> locality (Locality 0) before suspend or shutdown. Failing to do so
> would leave the system in a hanged state before sleep or power off
> (after “reboot: Power down” message).

Out of curiosity, would reboot work?

> Such is the case for the ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS
> board, I believe this might be the case for several other boards
> based on some bugs over the internet while trying to find out how to
> fix my specific issue. Most forums suggest the user to disable the
> TPM device on firmware BIOS in order to work around this specific
> issue, which disables several security features provided by TPM. >
> The root cause might be that after the ACPI command to put the device
> to S3 or S5, some firmware application/driver will try to use the TPM
> chip expecting it to be in Locality 0 as expected by TCG PC Client
> Platform Firmware Profile Version 1.06 Revision 52 (3.1.1 – Pre-OS
> Environment) and then when it fails to do so it simply halts the
> whole system.
> 
> Enable a user to configure the kernel through
> “tpm.locality_on_suspend=1” boot parameter so that the locality is set

I’d use `` from Markdown.

> before suspend/shutdown in order to diagnose whether or not the board is
> one of the buggy ones that require this workaround. Since this bug is
> related to the board/platform instead of the specific TPM chip, call
> dmi_check_system on the tpm_init function so that this setting is
> automatically enabled for boards specified in code (ASUS TUF GAMING
> B460M-PLUS already included) – automatic configuration only works in
> case CONFIG_DMI is set though, since dmi_check_system is a non-op when
> CONFIG_DMI is not set.

Could you please document the TPM for completeness?

> In case “tpm.locality_on_suspend=0” (the default) don't change any
> behavior thus preserving current functionality of any other board
> except ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS and possibly future
> boards as we successfully diagnose other boards with the same issue
> fixed by using “tpm.locality_on_suspend=1”.

Is the exception useful, if a user explicitly requests to disable the 
behavior? I was thinking for a case, where a newer system firmware has a 
fix (and the DMI check would need to be extended).

For completeness, I’d mention/paste the new log message.

> Link: https://bugzilla.kernel.org/show_bug.cgi?id=217890
> Signed-off-by: Adam Alves <adamoa@gmail.com>

Should this be backported to the stable series?

> ---
> v1->v2: fix formatting issues and simplified tpm_chip_stop code.
> 
>   drivers/char/tpm/tpm-chip.c      | 12 +++++++++++
>   drivers/char/tpm/tpm-interface.c | 37 ++++++++++++++++++++++++++++++++
>   drivers/char/tpm/tpm.h           |  1 +
>   include/linux/tpm.h              |  1 +
>   4 files changed, 51 insertions(+)
> 
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 42b1062e33cd..a183e1355289 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -137,6 +137,12 @@ EXPORT_SYMBOL_GPL(tpm_chip_start);
>    */
>   void tpm_chip_stop(struct tpm_chip *chip)
>   {
> +	if (chip->flags & TPM_CHIP_FLAG_PRESERVE_LOCALITY) {
> +		if (chip->locality != 0)
> +			tpm_request_locality(chip);
> +		return;
> +	}
> +
>   	tpm_go_idle(chip);
>   	tpm_relinquish_locality(chip);
>   	tpm_clk_disable(chip);
> @@ -291,6 +297,9 @@ int tpm_class_shutdown(struct device *dev)
>   {
>   	struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
>   
> +	if (tpm_locality_on_suspend)
> +		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> +
>   	down_write(&chip->ops_sem);
>   	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
>   		if (!tpm_chip_start(chip)) {
> @@ -668,6 +677,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
>    */
>   void tpm_chip_unregister(struct tpm_chip *chip)
>   {
> +	if (tpm_locality_on_suspend)
> +		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> +
>   	tpm_del_legacy_sysfs(chip);
>   	if (tpm_is_hwrng_enabled(chip))
>   		hwrng_unregister(&chip->hwrng);
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index 66b16d26eecc..7f770ea98402 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -26,6 +26,7 @@
>   #include <linux/suspend.h>
>   #include <linux/freezer.h>
>   #include <linux/tpm_eventlog.h>
> +#include <linux/dmi.h>
>   
>   #include "tpm.h"
>   
> @@ -382,6 +383,36 @@ int tpm_auto_startup(struct tpm_chip *chip)
>   	return rc;
>   }
>   
> +/*
> + * Bug workaround - some boards expect the TPM to be on Locality 0
> + * before suspend/shutdown, halting the system otherwise before
> + * suspend and shutdown. Change suspend behavior for these cases.
> + */
> +bool tpm_locality_on_suspend;
> +module_param_named(locality_on_suspend, tpm_locality_on_suspend, bool, 0644);
> +MODULE_PARM_DESC(locality_on_suspend,
> +		 "Put TPM at locality 0 before suspend/shutdown.");

I was wondering, if there is a name, that would make clear, that it is 
not only during suspend. But I couldn’t come up with one.

> +
> +static int __init tpm_set_locality_on_suspend(const struct dmi_system_id *system_id)
> +{
> +	pr_info("Board %s: TPM locality preserved before suspend/shutdown.\n",
> +		system_id->ident);
> +	tpm_locality_on_suspend = true;
> +
> +	return 0;
> +}
> +
> +static const struct dmi_system_id tpm_board_quirks[] __initconst = {
> +	{
> +		.ident = "TUF GAMING B460M-PLUS",
> +		.matches = {
> +			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
> +			DMI_MATCH(DMI_BOARD_NAME, "TUF GAMING B460M-PLUS"),
> +		},
> +		.callback = tpm_set_locality_on_suspend,
> +	},
> +};
> +
>   /*
>    * We are about to suspend. Save the TPM state
>    * so that it can be restored.
> @@ -394,6 +425,9 @@ int tpm_pm_suspend(struct device *dev)
>   	if (!chip)
>   		return -ENODEV;
>   
> +	if (tpm_locality_on_suspend)
> +		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> +
>   	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
>   		goto suspended;
>   
> @@ -431,6 +465,7 @@ int tpm_pm_resume(struct device *dev)
>   	if (chip == NULL)
>   		return -ENODEV;
>   
> +	chip->flags &= ~TPM_CHIP_FLAG_PRESERVE_LOCALITY;
>   	chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
>   
>   	/*
> @@ -476,6 +511,8 @@ static int __init tpm_init(void)
>   {
>   	int rc;
>   
> +	dmi_check_system(tpm_board_quirks);
> +
>   	rc = class_register(&tpm_class);
>   	if (rc) {
>   		pr_err("couldn't create tpm class\n");
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 61445f1dc46d..f2657b611b81 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -236,6 +236,7 @@ extern dev_t tpm_devt;
>   extern const struct file_operations tpm_fops;
>   extern const struct file_operations tpmrm_fops;
>   extern struct idr dev_nums_idr;
> +extern bool tpm_locality_on_suspend;
>   
>   ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
>   int tpm_get_timeouts(struct tpm_chip *);
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index 4ee9d13749ad..1fbb33f386d1 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -284,6 +284,7 @@ enum tpm_chip_flags {
>   	TPM_CHIP_FLAG_FIRMWARE_UPGRADE		= BIT(7),
>   	TPM_CHIP_FLAG_SUSPENDED			= BIT(8),
>   	TPM_CHIP_FLAG_HWRNG_DISABLED		= BIT(9),
> +	TPM_CHIP_FLAG_PRESERVE_LOCALITY		= BIT(10),
>   };
>   
>   #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)

Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>


Kind regards,

Paul
Adam Alves March 8, 2024, 2:22 p.m. UTC | #2
Dear Paul,

Thank you very much for your review, I will provide a new version with
some of your suggestions.

> Out of curiosity, would reboot work?

Reboot works, but clearly in an error handling path by the firmware
(the whole system is powered off for some seconds and then turned
backed on automatically), this doesn't happen when I am rebooting from
another OS. With this fix, reboot goes softly in Linux as well.

> I’d use `` from Markdown.
> Could you please document the TPM for completeness?

Done. Will be submitted with a new version.

> Is the exception useful, if a user explicitly requests to disable the
> behavior? I was thinking for a case, where a newer system firmware has a
> fix (and the DMI check would need to be extended).

Thanks! Will submit a new version with possibility to set module param
to force enable, force disable and auto. Will also include cmdline
documentation on parameter.

> For completeness, I’d mention/paste the new log message.

Will be submitted with a new version.

> Should this be backported to the stable series?

That would be great, please advise me if I need to do anything to allow that.

> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>

Thank you, will include this on the next version, submitting shortly -
I am currently testing.

Best,
Adam Alves
Jarkko Sakkinen March 11, 2024, 8:04 p.m. UTC | #3
On Fri Mar 8, 2024 at 12:49 AM EET, Adam Alves wrote:
> Some buggy firmware might require the TPM device to be in default
> locality (Locality 0) before suspend or shutdown. Failing to do so
> would leave the system in a hanged state before sleep or power off
> (after “reboot: Power down” message). Such is the case for the ASUSTeK
> COMPUTER INC. TUF GAMING B460M-PLUS board, I believe this might be the
> case for several other boards based on some bugs over the internet
> while trying to find out how to fix my specific issue. Most forums
> suggest the user to disable the TPM device on firmware BIOS in order to
> work around this specific issue, which disables several security
> features provided by TPM.

Re-write the paragraph as

  ASUSTeK TUF GAMING B460M-PLUS hangs on power down, after "reboot:
  Power down" message

Please do not add discussion to the commit message it should only
contain symptom and solution and rationale why the patch fixes the
issue.

And please done add any open-ended arguments ("some ..."). We care
only about identified bugs.

The lacking information here is the CPU model (/proc/cpuinfo), on
which kernel version the bug was produced and what kind of TPM the
system has (discrete chip or firmware TPM should be easy to check
from BIOS).

Also, which firmwre version you have and have you tested with the
most up to date firmware (BIOS)?

Before drawing any conclusions we need to know the environment
better.

>
> The root cause might be that after the ACPI command to put the device

What is "the ACPI command"? Refer to concrete items instead of
asking to guess what you is the ACPI command for you.

> chip expecting it to be in Locality 0 as expected by TCG PC Client
> Platform Firmware Profile Version 1.06 Revision 52 (3.1.1 – Pre-OS
> Environment) and then when it fails to do so it simply halts the
> whole system.

We don't speculate about the root cause here, only document it.
Please move this paragraph before diffstat (see below)>

> Enable a user to configure the kernel through
> “tpm.locality_on_suspend=1” boot parameter so that the locality is set
> before suspend/shutdown in order to diagnose whether or not the board is
> one of the buggy ones that require this workaround. Since this bug is
> related to the board/platform instead of the specific TPM chip, call
> dmi_check_system on the tpm_init function so that this setting is
> automatically enabled for boards specified in code (ASUS TUF GAMING
> B460M-PLUS already included) – automatic configuration only works in
> case CONFIG_DMI is set though, since dmi_check_system is a non-op when
> CONFIG_DMI is not set.

Please describe what the *kernel command-line" (for clarity
sake) semantically means.

Also please remove anything about diangnosing. We care only
about fixes.

>
> In case “tpm.locality_on_suspend=0” (the default) don't change any
> behavior thus preserving current functionality of any other board
> except ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS and possibly future
> boards as we successfully diagnose other boards with the same issue
> fixed by using “tpm.locality_on_suspend=1”.

This neither documents the default value. I'm also lost did setting
this "1" or "0" fix the issue in your case?

So: firmware version and being up-to-date is important and also this
needs to be reproduciable with the mainline Linux tree, not distro
kernel or custom kernel.

>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=217890
> Signed-off-by: Adam Alves <adamoa@gmail.com>
> ---

<cover letter>

OK, I'll try to check what is done here but please re-read
"describing your changes" before sending next version:

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes

> v1->v2: fix formatting issues and simplified tpm_chip_stop code.
>
>  drivers/char/tpm/tpm-chip.c      | 12 +++++++++++
>  drivers/char/tpm/tpm-interface.c | 37 ++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm.h           |  1 +
>  include/linux/tpm.h              |  1 +
>  4 files changed, 51 insertions(+)
>
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 42b1062e33cd..a183e1355289 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -137,6 +137,12 @@ EXPORT_SYMBOL_GPL(tpm_chip_start);
>   */
>  void tpm_chip_stop(struct tpm_chip *chip)
>  {
> +	if (chip->flags & TPM_CHIP_FLAG_PRESERVE_LOCALITY) {

The commit message did not explain what this flag is and what is its
purpose.

Also why you need to populate global flag inside chip, or the value
of it?

Why this is not just:
	
	if (tpm_locality_on_suspend) {
?


> +		if (chip->locality != 0)
> +			tpm_request_locality(chip);

This will unconditionally skip calling tpm_request_locality() because
Linux only uses locality 0. Not sure what good does this make.

> +		return;
> +	}
> +
>  	tpm_go_idle(chip);
>  	tpm_relinquish_locality(chip);
>  	tpm_clk_disable(chip);
> @@ -291,6 +297,9 @@ int tpm_class_shutdown(struct device *dev)
>  {
>  	struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
>  
> +	if (tpm_locality_on_suspend)
> +		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> +
>  	down_write(&chip->ops_sem);
>  	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
>  		if (!tpm_chip_start(chip)) {
> @@ -668,6 +677,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
>   */
>  void tpm_chip_unregister(struct tpm_chip *chip)
>  {
> +	if (tpm_locality_on_suspend)
> +		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> +
>  	tpm_del_legacy_sysfs(chip);
>  	if (tpm_is_hwrng_enabled(chip))
>  		hwrng_unregister(&chip->hwrng);
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index 66b16d26eecc..7f770ea98402 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -26,6 +26,7 @@
>  #include <linux/suspend.h>
>  #include <linux/freezer.h>
>  #include <linux/tpm_eventlog.h>
> +#include <linux/dmi.h>
>  
>  #include "tpm.h"
>  
> @@ -382,6 +383,36 @@ int tpm_auto_startup(struct tpm_chip *chip)
>  	return rc;
>  }
>  
> +/*
> + * Bug workaround - some boards expect the TPM to be on Locality 0
> + * before suspend/shutdown, halting the system otherwise before
> + * suspend and shutdown. Change suspend behavior for these cases.
> + */
> +bool tpm_locality_on_suspend;
> +module_param_named(locality_on_suspend, tpm_locality_on_suspend, bool, 0644);
> +MODULE_PARM_DESC(locality_on_suspend,
> +		 "Put TPM at locality 0 before suspend/shutdown.");
> +
> +static int __init tpm_set_locality_on_suspend(const struct dmi_system_id *system_id)
> +{
> +	pr_info("Board %s: TPM locality preserved before suspend/shutdown.\n",
> +		system_id->ident);

Please remove pr_info(), we do not want to bloat klog.

> +	tpm_locality_on_suspend = true;
> +
> +	return 0;
> +}
> +
> +static const struct dmi_system_id tpm_board_quirks[] __initconst = {

The commit message did not introduce this. Also should have inline
documentation.

/*
 * What the heck this.
 */

> +	{
> +		.ident = "TUF GAMING B460M-PLUS",
> +		.matches = {
> +			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
> +			DMI_MATCH(DMI_BOARD_NAME, "TUF GAMING B460M-PLUS"),
> +		},
> +		.callback = tpm_set_locality_on_suspend,
> +	},
> +};
> +
>  /*
>   * We are about to suspend. Save the TPM state
>   * so that it can be restored.
> @@ -394,6 +425,9 @@ int tpm_pm_suspend(struct device *dev)
>  	if (!chip)
>  		return -ENODEV;
>  
> +	if (tpm_locality_on_suspend)
> +		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> +
>  	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
>  		goto suspended;
>  
> @@ -431,6 +465,7 @@ int tpm_pm_resume(struct device *dev)
>  	if (chip == NULL)
>  		return -ENODEV;
>  
> +	chip->flags &= ~TPM_CHIP_FLAG_PRESERVE_LOCALITY;
>  	chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
>  
>  	/*
> @@ -476,6 +511,8 @@ static int __init tpm_init(void)
>  {
>  	int rc;
>  
> +	dmi_check_system(tpm_board_quirks);
> +
>  	rc = class_register(&tpm_class);
>  	if (rc) {
>  		pr_err("couldn't create tpm class\n");
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 61445f1dc46d..f2657b611b81 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -236,6 +236,7 @@ extern dev_t tpm_devt;
>  extern const struct file_operations tpm_fops;
>  extern const struct file_operations tpmrm_fops;
>  extern struct idr dev_nums_idr;
> +extern bool tpm_locality_on_suspend;
>  
>  ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
>  int tpm_get_timeouts(struct tpm_chip *);
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index 4ee9d13749ad..1fbb33f386d1 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -284,6 +284,7 @@ enum tpm_chip_flags {
>  	TPM_CHIP_FLAG_FIRMWARE_UPGRADE		= BIT(7),
>  	TPM_CHIP_FLAG_SUSPENDED			= BIT(8),
>  	TPM_CHIP_FLAG_HWRNG_DISABLED		= BIT(9),
> +	TPM_CHIP_FLAG_PRESERVE_LOCALITY		= BIT(10),
>  };
>  
>  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)


BR, Jarkko
Adam Alves March 13, 2024, 5:02 p.m. UTC | #4
Hi Jarkko,

Thank you very much for kindly reviewing this proposal.

After one week without any issues with my PC hanging, it happened
again. It seems that the fix I am proposing is not final (it only
reduced the frequency since it always happened when I shutdown after
couple hours of power up time and now it only happened after two weeks
with a similar usage rate).

I will share with you the data you requested below.

> The lacking information here is the CPU model (/proc/cpuinfo), on
> which kernel version the bug was produced and what kind of TPM the
> system has (discrete chip or firmware TPM should be easy to check
> from BIOS).

CPU model: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
I am attaching data from /proc/cpuinfo

TPM: No info on mainboard documentation regarding TPM. BIOS is not
clear whether or not it is discrete or firmware. Based on dmidecode
(attached) I get the following:
TPM Device
        Vendor ID: INTC
        Specification Version: 2.0
        Firmware Revision: 500.16
        Description: INTEL
        Characteristics:
                Family configurable via platform software support
        OEM-specific Information: 0x00000000
I also extracted TPM_CRB_INTF_ID_0 from the TPM: `a13a808600084311`
(Vendor ID 8086, Device ID a13a, Revision ID 00). The only match I
found while browsing for this device ID is 100 Series/C230 Series
Chipset Family MEI Controller #1, which is a PCI device, so it might
not be related to the TPM.

The driver bound to the tpm0 device is tpm_crb. The disassembled TPM2
ACPI table is also attached in case it helps.

The bug was reproduced from upstream kernel version 6.8.0 (attached
build .config that I used).

> Also, which firmwre version you have and have you tested with the
> most up to date firmware (BIOS)?

I have the most updated firmware provided by ASUS: TUF GAMING
B460M-PLUS BIOS 1601

> What is "the ACPI command"? Refer to concrete items instead of
> asking to guess what you is the ACPI command for you.

I enabled ACPI_DEBUG on my kernel to know where the it was actually
hanging. The last function is actually the last function that should
be called by the kernel for a successful shutdown:
hwsleep-0078 hw_legacy_sleep       : Entering sleep state [S5]^M
hwregs-0460 hw_write_pm1_control  : ----Entry^M
hwvalid-0097 hw_validate_io_request: ----Entry^M
hwvalid-0111 hw_validate_io_request: Address 0000000000001804
LastAddress 0000000000001805 Length 2  hwvalid-0128
hw_validate_io_request: ----Exit- AE_OK^M
hwregs-0360 hw_write              : Wrote: 0000000000001C01 width 16
to 0000000000001804 (SystemIO)^M
hwregs-0473 hw_write_pm1_control  : ----Exit- AE_OK^M
hwregs-0460 hw_write_pm1_control  : ----Entry^M
hwvalid-0097 hw_validate_io_request: ----Entry^M
hwvalid-0111 hw_validate_io_request: Address 0000000000001804
LastAddress 0000000000001805 Length 2  hwvalid-0128
hw_validate_io_request: ----Exit- AE_OK^M

It is writing both SLP_TYP + SLP_EN to ACPI PM1b_CNT registers (as
expected by specification). I checked the flags and it is in line with
the flags required by the system ACPI tables.

I understand from that that the system is hanging after ACPI firmware
takes over. The same issue happens if I force a EFI shutdown.

Since the the BUG has appeared again even with the fix implemented, I
am holding this patch for now until I find a solution that permanently
fixes the issue. The next time I try to submit a patch that will
comply with all your suggestions, thank you very much.

I would appreciate if you had any hint on how I could keep digging to
find the issue that might be causing this bug. This is an issue that
only happens when I shutdown from Linux and my TPM is activated in
BIOS. That's why my guess is that this is what should be causing it.
From Windows, shutdown is always flawless.

Best regards,
Adam

>
> > chip expecting it to be in Locality 0 as expected by TCG PC Client
> > Platform Firmware Profile Version 1.06 Revision 52 (3.1.1 – Pre-OS
> > Environment) and then when it fails to do so it simply halts the
> > whole system.
>
> We don't speculate about the root cause here, only document it.
> Please move this paragraph before diffstat (see below)>
>
> > Enable a user to configure the kernel through
> > “tpm.locality_on_suspend=1” boot parameter so that the locality is set
> > before suspend/shutdown in order to diagnose whether or not the board is
> > one of the buggy ones that require this workaround. Since this bug is
> > related to the board/platform instead of the specific TPM chip, call
> > dmi_check_system on the tpm_init function so that this setting is
> > automatically enabled for boards specified in code (ASUS TUF GAMING
> > B460M-PLUS already included) – automatic configuration only works in
> > case CONFIG_DMI is set though, since dmi_check_system is a non-op when
> > CONFIG_DMI is not set.
>
> Please describe what the *kernel command-line" (for clarity
> sake) semantically means.
>
> Also please remove anything about diangnosing. We care only
> about fixes.
>
> >
> > In case “tpm.locality_on_suspend=0” (the default) don't change any
> > behavior thus preserving current functionality of any other board
> > except ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS and possibly future
> > boards as we successfully diagnose other boards with the same issue
> > fixed by using “tpm.locality_on_suspend=1”.
>
> This neither documents the default value. I'm also lost did setting
> this "1" or "0" fix the issue in your case?
>
> So: firmware version and being up-to-date is important and also this
> needs to be reproduciable with the mainline Linux tree, not distro
> kernel or custom kernel.
>
> >
> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217890
> > Signed-off-by: Adam Alves <adamoa@gmail.com>
> > ---
>
> <cover letter>
>
> OK, I'll try to check what is done here but please re-read
> "describing your changes" before sending next version:
>
> https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
>
> > v1->v2: fix formatting issues and simplified tpm_chip_stop code.
> >
> >  drivers/char/tpm/tpm-chip.c      | 12 +++++++++++
> >  drivers/char/tpm/tpm-interface.c | 37 ++++++++++++++++++++++++++++++++
> >  drivers/char/tpm/tpm.h           |  1 +
> >  include/linux/tpm.h              |  1 +
> >  4 files changed, 51 insertions(+)
> >
> > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> > index 42b1062e33cd..a183e1355289 100644
> > --- a/drivers/char/tpm/tpm-chip.c
> > +++ b/drivers/char/tpm/tpm-chip.c
> > @@ -137,6 +137,12 @@ EXPORT_SYMBOL_GPL(tpm_chip_start);
> >   */
> >  void tpm_chip_stop(struct tpm_chip *chip)
> >  {
> > +     if (chip->flags & TPM_CHIP_FLAG_PRESERVE_LOCALITY) {
>
> The commit message did not explain what this flag is and what is its
> purpose.
>
> Also why you need to populate global flag inside chip, or the value
> of it?
>
> Why this is not just:
>
>         if (tpm_locality_on_suspend) {
> ?
>
>
> > +             if (chip->locality != 0)
> > +                     tpm_request_locality(chip);
>
> This will unconditionally skip calling tpm_request_locality() because
> Linux only uses locality 0. Not sure what good does this make.
>
> > +             return;
> > +     }
> > +
> >       tpm_go_idle(chip);
> >       tpm_relinquish_locality(chip);
> >       tpm_clk_disable(chip);
> > @@ -291,6 +297,9 @@ int tpm_class_shutdown(struct device *dev)
> >  {
> >       struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
> >
> > +     if (tpm_locality_on_suspend)
> > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > +
> >       down_write(&chip->ops_sem);
> >       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> >               if (!tpm_chip_start(chip)) {
> > @@ -668,6 +677,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
> >   */
> >  void tpm_chip_unregister(struct tpm_chip *chip)
> >  {
> > +     if (tpm_locality_on_suspend)
> > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > +
> >       tpm_del_legacy_sysfs(chip);
> >       if (tpm_is_hwrng_enabled(chip))
> >               hwrng_unregister(&chip->hwrng);
> > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> > index 66b16d26eecc..7f770ea98402 100644
> > --- a/drivers/char/tpm/tpm-interface.c
> > +++ b/drivers/char/tpm/tpm-interface.c
> > @@ -26,6 +26,7 @@
> >  #include <linux/suspend.h>
> >  #include <linux/freezer.h>
> >  #include <linux/tpm_eventlog.h>
> > +#include <linux/dmi.h>
> >
> >  #include "tpm.h"
> >
> > @@ -382,6 +383,36 @@ int tpm_auto_startup(struct tpm_chip *chip)
> >       return rc;
> >  }
> >
> > +/*
> > + * Bug workaround - some boards expect the TPM to be on Locality 0
> > + * before suspend/shutdown, halting the system otherwise before
> > + * suspend and shutdown. Change suspend behavior for these cases.
> > + */
> > +bool tpm_locality_on_suspend;
> > +module_param_named(locality_on_suspend, tpm_locality_on_suspend, bool, 0644);
> > +MODULE_PARM_DESC(locality_on_suspend,
> > +              "Put TPM at locality 0 before suspend/shutdown.");
> > +
> > +static int __init tpm_set_locality_on_suspend(const struct dmi_system_id *system_id)
> > +{
> > +     pr_info("Board %s: TPM locality preserved before suspend/shutdown.\n",
> > +             system_id->ident);
>
> Please remove pr_info(), we do not want to bloat klog.
>
> > +     tpm_locality_on_suspend = true;
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct dmi_system_id tpm_board_quirks[] __initconst = {
>
> The commit message did not introduce this. Also should have inline
> documentation.
>
> /*
>  * What the heck this.
>  */
>
> > +     {
> > +             .ident = "TUF GAMING B460M-PLUS",
> > +             .matches = {
> > +                     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
> > +                     DMI_MATCH(DMI_BOARD_NAME, "TUF GAMING B460M-PLUS"),
> > +             },
> > +             .callback = tpm_set_locality_on_suspend,
> > +     },
> > +};
> > +
> >  /*
> >   * We are about to suspend. Save the TPM state
> >   * so that it can be restored.
> > @@ -394,6 +425,9 @@ int tpm_pm_suspend(struct device *dev)
> >       if (!chip)
> >               return -ENODEV;
> >
> > +     if (tpm_locality_on_suspend)
> > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > +
> >       if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
> >               goto suspended;
> >
> > @@ -431,6 +465,7 @@ int tpm_pm_resume(struct device *dev)
> >       if (chip == NULL)
> >               return -ENODEV;
> >
> > +     chip->flags &= ~TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> >       chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
> >
> >       /*
> > @@ -476,6 +511,8 @@ static int __init tpm_init(void)
> >  {
> >       int rc;
> >
> > +     dmi_check_system(tpm_board_quirks);
> > +
> >       rc = class_register(&tpm_class);
> >       if (rc) {
> >               pr_err("couldn't create tpm class\n");
> > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> > index 61445f1dc46d..f2657b611b81 100644
> > --- a/drivers/char/tpm/tpm.h
> > +++ b/drivers/char/tpm/tpm.h
> > @@ -236,6 +236,7 @@ extern dev_t tpm_devt;
> >  extern const struct file_operations tpm_fops;
> >  extern const struct file_operations tpmrm_fops;
> >  extern struct idr dev_nums_idr;
> > +extern bool tpm_locality_on_suspend;
> >
> >  ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
> >  int tpm_get_timeouts(struct tpm_chip *);
> > diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> > index 4ee9d13749ad..1fbb33f386d1 100644
> > --- a/include/linux/tpm.h
> > +++ b/include/linux/tpm.h
> > @@ -284,6 +284,7 @@ enum tpm_chip_flags {
> >       TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
> >       TPM_CHIP_FLAG_SUSPENDED                 = BIT(8),
> >       TPM_CHIP_FLAG_HWRNG_DISABLED            = BIT(9),
> > +     TPM_CHIP_FLAG_PRESERVE_LOCALITY         = BIT(10),
> >  };
> >
> >  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
>
>
> BR, Jarkko



--
Adam Oliveira Alves
# dmidecode 3.5
Getting SMBIOS data from sysfs.
SMBIOS 3.2.0 present.
Table at 0x7FBB4000.

Handle 0x0000, DMI type 0, 26 bytes
BIOS Information
	Vendor: American Megatrends Inc.
	Version: 1601
	Release Date: 02/11/2022
	Address: 0xF0000
	Runtime Size: 64 kB
	ROM Size: 16 MB
	Characteristics:
		PCI is supported
		BIOS is upgradeable
		BIOS shadowing is allowed
		Boot from CD is supported
		Selectable boot is supported
		BIOS ROM is socketed
		EDD is supported
		5.25"/1.2 MB floppy services are supported (int 13h)
		3.5"/720 kB floppy services are supported (int 13h)
		3.5"/2.88 MB floppy services are supported (int 13h)
		Print screen service is supported (int 5h)
		Serial services are supported (int 14h)
		Printer services are supported (int 17h)
		ACPI is supported
		USB legacy is supported
		BIOS boot specification is supported
		Targeted content distribution is supported
		UEFI is supported
	BIOS Revision: 16.1

Handle 0x0001, DMI type 1, 27 bytes
System Information
	Manufacturer: ASUS
	Product Name: System Product Name
	Version: System Version
	Serial Number: System Serial Number
	UUID: 18e15754-7198-4cd0-b46a-3c7c3f3befe2
	Wake-up Type: Power Switch
	SKU Number: SKU
	Family: To be filled by O.E.M.

Handle 0x0002, DMI type 2, 15 bytes
Base Board Information
	Manufacturer: ASUSTeK COMPUTER INC.
	Product Name: TUF GAMING B460M-PLUS
	Version: Rev 1.xx
	Serial Number: 210378408203637
	Asset Tag: Default string
	Features:
		Board is a hosting board
		Board is replaceable
	Location In Chassis: Default string
	Chassis Handle: 0x0003
	Type: Motherboard
	Contained Object Handles: 0

Handle 0x0003, DMI type 3, 22 bytes
Chassis Information
	Manufacturer: Default string
	Type: Desktop
	Lock: Not Present
	Version: Default string
	Serial Number: Default string
	Asset Tag: Default string
	Boot-up State: Safe
	Power Supply State: Safe
	Thermal State: Safe
	Security Status: None
	OEM Information: 0x00000000
	Height: Unspecified
	Number Of Power Cords: 1
	Contained Elements: 0
	SKU Number: Default string

Handle 0x0004, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: KBMS_USB910
	Internal Connector Type: None
	External Reference Designator: PS/2 Mouse/Keyboard
	External Connector Type: PS/2
	Port Type: Mouse Port

Handle 0x0005, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: HDMI_DP
	Internal Connector Type: None
	External Reference Designator: HDMI_DP
	External Connector Type: Other
	Port Type: Other

Handle 0x0006, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: DVI
	Internal Connector Type: None
	External Reference Designator: DVI
	External Connector Type: Other
	Port Type: Other

Handle 0x0007, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: U32G1_34
	Internal Connector Type: None
	External Reference Designator: U32G1_34
	External Connector Type: Access Bus (USB)
	Port Type: USB

Handle 0x0008, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: LAN_U32G1_12
	Internal Connector Type: None
	External Reference Designator: LAN_U32G1_12
	External Connector Type: RJ-45
	Port Type: Network Port

Handle 0x0009, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: AUDIO
	Internal Connector Type: None
	External Reference Designator: AUDIO
	External Connector Type: Other
	Port Type: Audio Port

Handle 0x000A, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: CPU_FAN
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x000B, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: CPU_OPT
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x000C, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: CHA_FAN1
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x000D, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: CHA_FAN2
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x000E, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: RGB_HEADER1
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x000F, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: RGB_HEADER2
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x0010, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: ADD_GEN2
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x0011, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: COM
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x0012, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: AAFP
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x0013, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: PANEL
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x0014, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: COM_DEBUG
	Internal Connector Type: Other
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: Other

Handle 0x0015, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: USB78
	Internal Connector Type: Access Bus (USB)
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: USB

Handle 0x0016, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: USB_E12
	Internal Connector Type: Access Bus (USB)
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: USB

Handle 0x0017, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: U32G1_56
	Internal Connector Type: Access Bus (USB)
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: USB

Handle 0x0018, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: SATA6G_1
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x0019, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: SATA6G_2
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x001A, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: SATA6G_3
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x001B, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: SATA6G_4
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x001C, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: SATA6G_5
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x001D, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: SATA6G_6
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x001E, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: M.2_1(SOCKET3)
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x001F, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: M.2_2(SOCKET3)
	Internal Connector Type: SAS/SATA Plug Receptacle
	External Reference Designator: Not Specified
	External Connector Type: None
	Port Type: SATA

Handle 0x0020, DMI type 9, 17 bytes
System Slot Information
	Designation: PCIEX16_1
	Type: x16 PCI Express
	Current Usage: In Use
	Length: Long
	ID: 0
	Characteristics:
		3.3 V is provided
		Opening is shared
		PME signal is supported
	Bus Address: 0000:01:01.0

Handle 0x0021, DMI type 9, 17 bytes
System Slot Information
	Designation: PCIEX1
	Type: x1 PCI Express
	Current Usage: In Use
	Length: Short
	ID: 1
	Characteristics:
		3.3 V is provided
		Opening is shared
		PME signal is supported
	Bus Address: 0000:02:0d.4

Handle 0x0022, DMI type 9, 17 bytes
System Slot Information
	Designation: PCIEX16_2
	Type: x16 PCI Express
	Current Usage: Available
	Length: Long
	ID: 2
	Characteristics:
		3.3 V is provided
		Opening is shared
		PME signal is supported
	Bus Address: 0000:ff:0e.0

Handle 0x0023, DMI type 10, 6 bytes
On Board Device Information
	Type: Video
	Status: Enabled
	Description:    To Be Filled By O.E.M.

Handle 0x0024, DMI type 11, 5 bytes
OEM Strings
	String 1: Default string
	String 2: Default string
	String 3: MARYLAND
	String 4: Default string
	String 5: Default string
	String 6: Default string
	String 7: Default string
	String 8: Default string

Handle 0x0025, DMI type 12, 5 bytes
System Configuration Options
	Option 1: Default string

Handle 0x0026, DMI type 32, 20 bytes
System Boot Information
	Status: No errors detected

Handle 0x0027, DMI type 34, 11 bytes
Management Device
	Description: Nuvoton NCT6798D
	Type: LM78
	Address: 0x00000000
	Address Type: I/O Port

Handle 0x0028, DMI type 26, 22 bytes
Voltage Probe
	Description: LM78A
	Location: Motherboard
	Status: OK
	Maximum Value: Unknown
	Minimum Value: Unknown
	Resolution: Unknown
	Tolerance: Unknown
	Accuracy: Unknown
	OEM-specific Information: 0x00000000
	Nominal Value: Unknown

Handle 0x0029, DMI type 36, 16 bytes
Management Device Threshold Data
	Lower Non-critical Threshold: 1
	Upper Non-critical Threshold: 2
	Lower Critical Threshold: 3
	Upper Critical Threshold: 4
	Lower Non-recoverable Threshold: 5
	Upper Non-recoverable Threshold: 6

Handle 0x002A, DMI type 35, 11 bytes
Management Device Component
	Description: Default string
	Management Device Handle: 0x0027
	Component Handle: 0x0028
	Threshold Handle: 0x0029

Handle 0x002B, DMI type 28, 22 bytes
Temperature Probe
	Description: LM78A
	Location: Motherboard
	Status: OK
	Maximum Value: Unknown
	Minimum Value: Unknown
	Resolution: Unknown
	Tolerance: Unknown
	Accuracy: Unknown
	OEM-specific Information: 0x00000000
	Nominal Value: Unknown

Handle 0x002C, DMI type 36, 16 bytes
Management Device Threshold Data
	Lower Non-critical Threshold: 1
	Upper Non-critical Threshold: 2
	Lower Critical Threshold: 3
	Upper Critical Threshold: 4
	Lower Non-recoverable Threshold: 5
	Upper Non-recoverable Threshold: 6

Handle 0x002D, DMI type 35, 11 bytes
Management Device Component
	Description: Default string
	Management Device Handle: 0x0027
	Component Handle: 0x002B
	Threshold Handle: 0x002C

Handle 0x002E, DMI type 27, 15 bytes
Cooling Device
	Temperature Probe Handle: 0x002B
	Type: Power Supply Fan
	Status: OK
	Cooling Unit Group: 1
	OEM-specific Information: 0x00000000
	Nominal Speed: Unknown Or Non-rotating
	Description: Cooling Dev 1

Handle 0x002F, DMI type 36, 16 bytes
Management Device Threshold Data
	Lower Non-critical Threshold: 1
	Upper Non-critical Threshold: 2
	Lower Critical Threshold: 3
	Upper Critical Threshold: 4
	Lower Non-recoverable Threshold: 5
	Upper Non-recoverable Threshold: 6

Handle 0x0030, DMI type 35, 11 bytes
Management Device Component
	Description: Default string
	Management Device Handle: 0x0027
	Component Handle: 0x002E
	Threshold Handle: 0x002F

Handle 0x0031, DMI type 27, 15 bytes
Cooling Device
	Temperature Probe Handle: 0x002B
	Type: Power Supply Fan
	Status: OK
	Cooling Unit Group: 1
	OEM-specific Information: 0x00000000
	Nominal Speed: Unknown Or Non-rotating
	Description: Not Specified

Handle 0x0032, DMI type 36, 16 bytes
Management Device Threshold Data
	Lower Non-critical Threshold: 1
	Upper Non-critical Threshold: 2
	Lower Critical Threshold: 3
	Upper Critical Threshold: 4
	Lower Non-recoverable Threshold: 5
	Upper Non-recoverable Threshold: 6

Handle 0x0033, DMI type 35, 11 bytes
Management Device Component
	Description: Default string
	Management Device Handle: 0x0027
	Component Handle: 0x0031
	Threshold Handle: 0x0032

Handle 0x0034, DMI type 29, 22 bytes
Electrical Current Probe
	Description: ABC
	Location: Motherboard
	Status: OK
	Maximum Value: Unknown
	Minimum Value: Unknown
	Resolution: Unknown
	Tolerance: Unknown
	Accuracy: Unknown
	OEM-specific Information: 0x00000000
	Nominal Value: Unknown

Handle 0x0035, DMI type 36, 16 bytes
Management Device Threshold Data

Handle 0x0036, DMI type 35, 11 bytes
Management Device Component
	Description: Default string
	Management Device Handle: 0x0027
	Component Handle: 0x0034
	Threshold Handle: 0x0035

Handle 0x0037, DMI type 26, 22 bytes
Voltage Probe
	Description: LM78A
	Location: Power Unit
	Status: OK
	Maximum Value: Unknown
	Minimum Value: Unknown
	Resolution: Unknown
	Tolerance: Unknown
	Accuracy: Unknown
	OEM-specific Information: 0x00000000
	Nominal Value: Unknown

Handle 0x0038, DMI type 28, 22 bytes
Temperature Probe
	Description: LM78A
	Location: Power Unit
	Status: OK
	Maximum Value: Unknown
	Minimum Value: Unknown
	Resolution: Unknown
	Tolerance: Unknown
	Accuracy: Unknown
	OEM-specific Information: 0x00000000
	Nominal Value: Unknown

Handle 0x0039, DMI type 27, 15 bytes
Cooling Device
	Temperature Probe Handle: 0x0038
	Type: Power Supply Fan
	Status: OK
	Cooling Unit Group: 1
	OEM-specific Information: 0x00000000
	Nominal Speed: Unknown Or Non-rotating
	Description: Cooling Dev 1

Handle 0x003A, DMI type 29, 22 bytes
Electrical Current Probe
	Description: ABC
	Location: Power Unit
	Status: OK
	Maximum Value: Unknown
	Minimum Value: Unknown
	Resolution: Unknown
	Tolerance: Unknown
	Accuracy: Unknown
	OEM-specific Information: 0x00000000
	Nominal Value: Unknown

Handle 0x003B, DMI type 39, 22 bytes
System Power Supply
	Power Unit Group: 1
	Location: To Be Filled By O.E.M.
	Name: To Be Filled By O.E.M.
	Manufacturer: To Be Filled By O.E.M.
	Serial Number: To Be Filled By O.E.M.
	Asset Tag: To Be Filled By O.E.M.
	Model Part Number: To Be Filled By O.E.M.
	Revision: To Be Filled By O.E.M.
	Max Power Capacity: Unknown
	Status: Present, OK
	Type: Switching
	Input Voltage Range Switching: Auto-switch
	Plugged: Yes
	Hot Replaceable: No
	Input Voltage Probe Handle: 0x0037
	Cooling Device Handle: 0x0039
	Input Current Probe Handle: 0x003A

Handle 0x003C, DMI type 40, 50 bytes
Additional Information 1
	Referenced Handle: 0x0023
	Referenced Offset: 0x01
	String: To Be Filled By O.E.M. 1
	Value: 0x00000000
Additional Information 2
	Referenced Handle: 0x0001
	Referenced Offset: 0x0f
	String: Not Specified
	Value: 0x0000001e
Additional Information 3
	Referenced Handle: 0x004e
	Referenced Offset: 0x01
	String: Not Specified
	Value: 0x00000000
Additional Information 4
	Referenced Handle: 0x0001
	Referenced Offset: 0x1a
	String: PRODUCT_LINE
	Value: 0x00000000
Additional Information 5
	Referenced Handle: 0x0001
	Referenced Offset: 0x19
	String: PRODUCT_SKU
	Value: 0x00000003

Handle 0x003D, DMI type 43, 31 bytes
TPM Device
	Vendor ID: INTC
	Specification Version: 2.0
	Firmware Revision: 500.16
	Description: INTEL
	Characteristics:
		Family configurable via platform software support
	OEM-specific Information: 0x00000000

Handle 0x003E, DMI type 16, 23 bytes
Physical Memory Array
	Location: System Board Or Motherboard
	Use: System Memory
	Error Correction Type: None
	Maximum Capacity: 64 GB
	Error Information Handle: Not Provided
	Number Of Devices: 4

Handle 0x003F, DMI type 17, 84 bytes
Memory Device
	Array Handle: 0x003E
	Error Information Handle: Not Provided
	Total Width: 64 bits
	Data Width: 64 bits
	Size: 8 GB
	Form Factor: DIMM
	Set: None
	Locator: ChannelA-DIMM1
	Bank Locator: BANK 0
	Type: DDR4
	Type Detail: Synchronous
	Speed: 2666 MT/s
	Manufacturer: Kingston
	Serial Number: E4BC807B
	Asset Tag: 9876543210
	Part Number: KHX2666C16/8G       
	Rank: 1
	Configured Memory Speed: 2666 MT/s
	Minimum Voltage: 1.2 V
	Maximum Voltage: 1.2 V
	Configured Voltage: 1.2 V
	Memory Technology: DRAM
	Memory Operating Mode Capability: Volatile memory
	Firmware Version: Not Specified
	Module Manufacturer ID: Bank 2, Hex 0x98
	Module Product ID: Unknown
	Memory Subsystem Controller Manufacturer ID: Unknown
	Memory Subsystem Controller Product ID: Unknown
	Non-Volatile Size: None
	Volatile Size: 8 GB
	Cache Size: None
	Logical Size: None

Handle 0x0040, DMI type 17, 84 bytes
Memory Device
	Array Handle: 0x003E
	Error Information Handle: Not Provided
	Total Width: 64 bits
	Data Width: 64 bits
	Size: 8 GB
	Form Factor: DIMM
	Set: None
	Locator: ChannelA-DIMM2
	Bank Locator: BANK 1
	Type: DDR4
	Type Detail: Synchronous
	Speed: 2666 MT/s
	Manufacturer: Kingston
	Serial Number: B8BC7B2E
	Asset Tag: 9876543210
	Part Number: KHX2666C16/8G       
	Rank: 1
	Configured Memory Speed: 2666 MT/s
	Minimum Voltage: 1.2 V
	Maximum Voltage: 1.2 V
	Configured Voltage: 1.2 V
	Memory Technology: DRAM
	Memory Operating Mode Capability: Volatile memory
	Firmware Version: Not Specified
	Module Manufacturer ID: Bank 2, Hex 0x98
	Module Product ID: Unknown
	Memory Subsystem Controller Manufacturer ID: Unknown
	Memory Subsystem Controller Product ID: Unknown
	Non-Volatile Size: None
	Volatile Size: 8 GB
	Cache Size: None
	Logical Size: None

Handle 0x0041, DMI type 17, 84 bytes
Memory Device
	Array Handle: 0x003E
	Error Information Handle: Not Provided
	Total Width: 64 bits
	Data Width: 64 bits
	Size: 8 GB
	Form Factor: DIMM
	Set: None
	Locator: ChannelB-DIMM1
	Bank Locator: BANK 2
	Type: DDR4
	Type Detail: Synchronous
	Speed: 2666 MT/s
	Manufacturer: Kingston
	Serial Number: BABC7B1E
	Asset Tag: 9876543210
	Part Number: KHX2666C16/8G       
	Rank: 1
	Configured Memory Speed: 2666 MT/s
	Minimum Voltage: 1.2 V
	Maximum Voltage: 1.2 V
	Configured Voltage: 1.2 V
	Memory Technology: DRAM
	Memory Operating Mode Capability: Volatile memory
	Firmware Version: Not Specified
	Module Manufacturer ID: Bank 2, Hex 0x98
	Module Product ID: Unknown
	Memory Subsystem Controller Manufacturer ID: Unknown
	Memory Subsystem Controller Product ID: Unknown
	Non-Volatile Size: None
	Volatile Size: 8 GB
	Cache Size: None
	Logical Size: None

Handle 0x0042, DMI type 17, 84 bytes
Memory Device
	Array Handle: 0x003E
	Error Information Handle: Not Provided
	Total Width: 64 bits
	Data Width: 64 bits
	Size: 8 GB
	Form Factor: DIMM
	Set: None
	Locator: ChannelB-DIMM2
	Bank Locator: BANK 3
	Type: DDR4
	Type Detail: Synchronous
	Speed: 2666 MT/s
	Manufacturer: Kingston
	Serial Number: E1BC7BE3
	Asset Tag: 9876543210
	Part Number: KHX2666C16/8G       
	Rank: 1
	Configured Memory Speed: 2666 MT/s
	Minimum Voltage: 1.2 V
	Maximum Voltage: 1.2 V
	Configured Voltage: 1.2 V
	Memory Technology: DRAM
	Memory Operating Mode Capability: Volatile memory
	Firmware Version: Not Specified
	Module Manufacturer ID: Bank 2, Hex 0x98
	Module Product ID: Unknown
	Memory Subsystem Controller Manufacturer ID: Unknown
	Memory Subsystem Controller Product ID: Unknown
	Non-Volatile Size: None
	Volatile Size: 8 GB
	Cache Size: None
	Logical Size: None

Handle 0x0043, DMI type 19, 31 bytes
Memory Array Mapped Address
	Starting Address: 0x00000000000
	Ending Address: 0x007FFFFFFFF
	Range Size: 32 GB
	Physical Array Handle: 0x003E
	Partition Width: 4

Handle 0x0044, DMI type 20, 35 bytes
Memory Device Mapped Address
	Starting Address: 0x00000000000
	Ending Address: 0x001FFFFFFFF
	Range Size: 8 GB
	Physical Device Handle: 0x003F
	Memory Array Mapped Address Handle: 0x0043
	Partition Row Position: Unknown
	Interleave Position: 1
	Interleaved Data Depth: 2

Handle 0x0045, DMI type 20, 35 bytes
Memory Device Mapped Address
	Starting Address: 0x00400000000
	Ending Address: 0x005FFFFFFFF
	Range Size: 8 GB
	Physical Device Handle: 0x0040
	Memory Array Mapped Address Handle: 0x0043
	Partition Row Position: Unknown
	Interleave Position: 1
	Interleaved Data Depth: 2

Handle 0x0046, DMI type 20, 35 bytes
Memory Device Mapped Address
	Starting Address: 0x00200000000
	Ending Address: 0x003FFFFFFFF
	Range Size: 8 GB
	Physical Device Handle: 0x0041
	Memory Array Mapped Address Handle: 0x0043
	Partition Row Position: Unknown
	Interleave Position: 2
	Interleaved Data Depth: 2

Handle 0x0047, DMI type 20, 35 bytes
Memory Device Mapped Address
	Starting Address: 0x00600000000
	Ending Address: 0x007FFFFFFFF
	Range Size: 8 GB
	Physical Device Handle: 0x0042
	Memory Array Mapped Address Handle: 0x0043
	Partition Row Position: Unknown
	Interleave Position: 2
	Interleaved Data Depth: 2

Handle 0x0048, DMI type 221, 26 bytes
OEM-specific Type
	Header and Data:
		DD 1A 48 00 03 01 00 09 00 30 50 00 02 00 00 00
		00 E2 00 03 00 FF FF FF FF FF
	Strings:
		Reference Code - CPU
		uCode Version
		TXT ACM version

Handle 0x0049, DMI type 221, 26 bytes
OEM-specific Type
	Header and Data:
		DD 1A 49 00 03 01 00 09 00 30 50 00 02 00 00 00
		00 00 00 03 04 0E 05 19 CD 04
	Strings:
		Reference Code - ME
		MEBx version
		ME Firmware Version
		Consumer SKU

Handle 0x004A, DMI type 221, 47 bytes
OEM-specific Type
	Header and Data:
		DD 2F 4A 00 06 01 00 09 00 30 50 00 02 03 FF FF
		FF FF FF 04 00 FF FF FF 00 00 05 00 FF FF FF 00
		00 06 00 FF FF FF FF FF 07 00 0B 00 00 00 00
	Strings:
		Re.erence Code - CML PCH
		PCH-CRID Status
		Disabled
		PCH-CRID Original Value
		PCH-CRID New Value
		OPROM - RST - RAID
		CMLV PCH H Ax Hsio Version

Handle 0x004B, DMI type 221, 54 bytes
OEM-specific Type
	Header and Data:
		DD 36 4B 00 07 01 00 09 00 30 50 00 02 00 00 00
		00 45 00 03 00 09 00 30 50 00 04 05 FF FF FF FF
		FF 06 00 00 00 00 05 00 07 00 00 00 00 05 00 08
		00 FF FF FF FF FF
	Strings:
		Reference Code - SA - System Agent
		Reference Code - MRC
		SA - PCIe Version
		SA-CRID Status
		Disabled
		SA-CRID Original Value
		SA-CRID New Value
		OPROM - VBIOS

Handle 0x004C, DMI type 221, 12 bytes
OEM-specific Type
	Header and Data:
		DD 0C 4C 00 01 01 00 04 00 00 00 00
	Strings:
		FSP Binary Version

Handle 0x004D, DMI type 7, 27 bytes
Cache Information
	Socket Designation: L1 Cache
	Configuration: Enabled, Not Socketed, Level 1
	Operational Mode: Write Back
	Location: Internal
	Installed Size: 512 kB
	Maximum Size: 512 kB
	Supported SRAM Types:
		Synchronous
	Installed SRAM Type: Synchronous
	Speed: Unknown
	Error Correction Type: Parity
	System Type: Unified
	Associativity: 8-way Set-associative

Handle 0x004E, DMI type 7, 27 bytes
Cache Information
	Socket Designation: L2 Cache
	Configuration: Enabled, Not Socketed, Level 2
	Operational Mode: Write Back
	Location: Internal
	Installed Size: 2 MB
	Maximum Size: 2 MB
	Supported SRAM Types:
		Synchronous
	Installed SRAM Type: Synchronous
	Speed: Unknown
	Error Correction Type: Single-bit ECC
	System Type: Unified
	Associativity: 4-way Set-associative

Handle 0x004F, DMI type 7, 27 bytes
Cache Information
	Socket Designation: L3 Cache
	Configuration: Enabled, Not Socketed, Level 3
	Operational Mode: Write Back
	Location: Internal
	Installed Size: 16 MB
	Maximum Size: 16 MB
	Supported SRAM Types:
		Synchronous
	Installed SRAM Type: Synchronous
	Speed: Unknown
	Error Correction Type: Multi-bit ECC
	System Type: Unified
	Associativity: 16-way Set-associative

Handle 0x0050, DMI type 4, 48 bytes
Processor Information
	Socket Designation: LGA1200
	Type: Central Processor
	Family: Core i7
	Manufacturer: Intel(R) Corporation
	ID: 55 06 0A 00 FF FB EB BF
	Signature: Type 0, Family 6, Model 165, Stepping 5
	Flags:
		FPU (Floating-point unit on-chip)
		VME (Virtual mode extension)
		DE (Debugging extension)
		PSE (Page size extension)
		TSC (Time stamp counter)
		MSR (Model specific registers)
		PAE (Physical address extension)
		MCE (Machine check exception)
		CX8 (CMPXCHG8 instruction supported)
		APIC (On-chip APIC hardware supported)
		SEP (Fast system call)
		MTRR (Memory type range registers)
		PGE (Page global enable)
		MCA (Machine check architecture)
		CMOV (Conditional move instruction supported)
		PAT (Page attribute table)
		PSE-36 (36-bit page size extension)
		CLFSH (CLFLUSH instruction supported)
		DS (Debug store)
		ACPI (ACPI supported)
		MMX (MMX technology supported)
		FXSR (FXSAVE and FXSTOR instructions supported)
		SSE (Streaming SIMD extensions)
		SSE2 (Streaming SIMD extensions 2)
		SS (Self-snoop)
		HTT (Multi-threading)
		TM (Thermal monitor supported)
		PBE (Pending break enabled)
	Version: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
	Voltage: 0.9 V
	External Clock: 100 MHz
	Max Speed: 8300 MHz
	Current Speed: 2871 MHz
	Status: Populated, Enabled
	Upgrade: Other
	L1 Cache Handle: 0x004D
	L2 Cache Handle: 0x004E
	L3 Cache Handle: 0x004F
	Serial Number: To Be Filled By O.E.M.
	Asset Tag: To Be Filled By O.E.M.
	Part Number: To Be Filled By O.E.M.
	Core Count: 8
	Core Enabled: 8
	Thread Count: 16
	Characteristics:
		64-bit capable
		Multi-Core
		Hardware Thread
		Execute Protection
		Enhanced Virtualization
		Power/Performance Control

Handle 0x0051, DMI type 131, 64 bytes
OEM-specific Type
	Header and Data:
		83 40 51 00 31 00 00 00 00 00 00 00 00 00 00 00
		F8 00 C8 A3 00 00 00 00 01 00 00 00 05 00 0E 00
		CD 04 19 00 00 00 00 00 FE 00 55 0D 00 00 00 00
		00 00 00 00 22 00 00 00 76 50 72 6F 00 00 00 00

Handle 0x0052, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Other
	Type: Other
	Status: Enabled
	Type Instance: 1
	Bus Address: 0000:00:00.0

Handle 0x0053, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Other
	Type: Other
	Status: Enabled
	Type Instance: 2
	Bus Address: 0000:00:14.0

Handle 0x0054, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Other
	Type: Other
	Status: Enabled
	Type Instance: 3
	Bus Address: 0000:00:16.0

Handle 0x0055, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - SATA
	Type: SATA Controller
	Status: Enabled
	Type Instance: 1
	Bus Address: 0000:00:17.0

Handle 0x0056, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Other
	Type: Other
	Status: Enabled
	Type Instance: 4
	Bus Address: 0000:00:1f.0

Handle 0x0057, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Other
	Type: Other
	Status: Enabled
	Type Instance: 5
	Bus Address: 0000:00:1f.2

Handle 0x0058, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Sound
	Type: Sound
	Status: Enabled
	Type Instance: 1
	Bus Address: 0000:00:1f.3

Handle 0x0059, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Other
	Type: Other
	Status: Enabled
	Type Instance: 6
	Bus Address: 0000:00:1f.4

Handle 0x005A, DMI type 41, 11 bytes
Onboard Device
	Reference Designation: Onboard - Ethernet
	Type: Ethernet
	Status: Enabled
	Type Instance: 1
	Bus Address: 0000:00:1f.6

Handle 0x005B, DMI type 221, 89 bytes
OEM-specific Type
	Header and Data:
		DD 59 5B 00 0C 01 00 00 00 00 A6 00 02 00 FF FF
		FF FF FF 03 04 FF FF FF FF FF 05 06 FF FF FF FF
		FF 07 08 FF FF FF FF FF 09 00 00 00 00 00 00 0A
		00 FF FF FF FF FF 0B 00 FF FF 00 00 00 0C 00 FF
		FF FF FF FF 0D 00 FF FF FF FF FF 0E 00 00 07 00
		00 00 0F 00 00 02 00 0F 00
	Strings:
		Lan Phy Version
		Sensor Firmware Version
		Debug Mode Status
		Disabled
		Performance Mode Status
		Disabled
		Debug Use USB(Disabled:Serial)
		Disabled
		ICC Overclocking Version
		UNDI Version
		EC FW Version
		GOP Version
		Royal Park Version
		Platform Version
		Client Silicon Version

Handle 0x005C, DMI type 14, 8 bytes
Group Associations
	Name: $MEI
	Items: 1
		0x0000 (OEM-specific)

Handle 0x005D, DMI type 219, 106 bytes
OEM-specific Type
	Header and Data:
		DB 6A 5D 00 01 04 01 45 02 00 90 06 01 10 82 20
		00 00 00 00 48 08 00 00 00 00 00 00 00 00 40 02
		FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
		FF FF FF FF FF FF FF FF 03 00 00 00 80 00 00 00
		00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
		00 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
		FF FF FF FF FF FF FF FF FF FF
	Strings:
		MEI1
		MEI2
		MEI3
		MEI4

Handle 0x005E, DMI type 136, 6 bytes
OEM-specific Type
	Header and Data:
		88 06 5E 00 00 00

Handle 0x005F, DMI type 14, 23 bytes
Group Associations
	Name: Firmware Version Info
	Items: 6
		0x0048 (OEM-specific)
		0x0049 (OEM-specific)
		0x004A (OEM-specific)
		0x004B (OEM-specific)
		0x004C (OEM-specific)
		0x005B (OEM-specific)

Handle 0x0060, DMI type 13, 22 bytes
BIOS Language Information
	Language Description Format: Long
	Installable Languages: 9
		en|US|iso8859-1
		fr|FR|iso8859-1
		zh|TW|unicode
		zh|CN|unicode
		ja|JP|unicode
		de|DE|iso8859-1
		es|ES|iso8859-1
		ru|RU|iso8859-5
		ko|KR|unicode
	Currently Installed Language: en|US|iso8859-1

Handle 0x0061, DMI type 127, 4 bytes
End Of Table
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.080
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 0
cpu cores	: 8
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 1
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.020
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 1
cpu cores	: 8
apicid		: 2
initial apicid	: 2
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 2
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.000
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 2
cpu cores	: 8
apicid		: 4
initial apicid	: 4
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 3
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.091
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 3
cpu cores	: 8
apicid		: 6
initial apicid	: 6
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 4
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.225
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 4
cpu cores	: 8
apicid		: 8
initial apicid	: 8
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 5
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.216
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 5
cpu cores	: 8
apicid		: 10
initial apicid	: 10
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 6
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.076
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 6
cpu cores	: 8
apicid		: 12
initial apicid	: 12
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 7
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.000
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 7
cpu cores	: 8
apicid		: 14
initial apicid	: 14
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 8
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.000
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 0
cpu cores	: 8
apicid		: 1
initial apicid	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 9
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.049
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 1
cpu cores	: 8
apicid		: 3
initial apicid	: 3
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 10
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.000
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 2
cpu cores	: 8
apicid		: 5
initial apicid	: 5
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 11
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.264
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 3
cpu cores	: 8
apicid		: 7
initial apicid	: 7
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 12
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.027
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 4
cpu cores	: 8
apicid		: 9
initial apicid	: 9
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 13
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 799.998
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 5
cpu cores	: 8
apicid		: 11
initial apicid	: 11
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 14
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 799.990
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 6
cpu cores	: 8
apicid		: 13
initial apicid	: 13
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 15
vendor_id	: GenuineIntel
cpu family	: 6
model		: 165
model name	: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
stepping	: 5
microcode	: 0xf8
cpu MHz		: 800.002
cache size	: 16384 KB
physical id	: 0
siblings	: 16
core id		: 7
cpu cores	: 8
apicid		: 15
initial apicid	: 15
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust sgx bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi pku ospke sgx_lc md_clear flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs pml ept_mode_based_exec
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs itlb_multihit srbds mmio_stale_data retbleed eibrs_pbrsb gds
bogomips	: 5799.77
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:
Adam Alves March 14, 2024, 4:31 p.m. UTC | #5
Hi Jarkko,

I have an update here. I would like you to check if it makes sense
before I submit a patch.

The problem might be related to the chip itself which leaves the idle
state whenever the locality is relinquished.

I probed the chip while operating and noted that the
TPM_CRB_CTRL_STS_0.tpmIdle bit (located at `regs_t->ctrl_sts` on
`crb_priv` structure in tpm_crb.c) is always cleared whenever the
locality is relinquished.

The result is that this chip never becomes idle since after going idle
the locality is relinquished (`tpm_chip_stop` function in tpm-chip.c).

I patched the 7.8.0 kernel for bypassing the `tpm_relinquish_locality`
call and so far the PC is suspending and power off normally,
TPM_CRB_CTRL_STS_0.tpmIdle remains set whenever the device is not used
now.

I believe this is related to this specific chip, if the fix remains
working for 2 weeks I will submit the patch. Please advise me if it
makes sense.

Best regards,
Adam

Em qua., 13 de mar. de 2024 às 14:02, Adam Alves <adamoa@gmail.com> escreveu:
>
> Hi Jarkko,
>
> Thank you very much for kindly reviewing this proposal.
>
> After one week without any issues with my PC hanging, it happened
> again. It seems that the fix I am proposing is not final (it only
> reduced the frequency since it always happened when I shutdown after
> couple hours of power up time and now it only happened after two weeks
> with a similar usage rate).
>
> I will share with you the data you requested below.
>
> > The lacking information here is the CPU model (/proc/cpuinfo), on
> > which kernel version the bug was produced and what kind of TPM the
> > system has (discrete chip or firmware TPM should be easy to check
> > from BIOS).
>
> CPU model: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
> I am attaching data from /proc/cpuinfo
>
> TPM: No info on mainboard documentation regarding TPM. BIOS is not
> clear whether or not it is discrete or firmware. Based on dmidecode
> (attached) I get the following:
> TPM Device
>         Vendor ID: INTC
>         Specification Version: 2.0
>         Firmware Revision: 500.16
>         Description: INTEL
>         Characteristics:
>                 Family configurable via platform software support
>         OEM-specific Information: 0x00000000
> I also extracted TPM_CRB_INTF_ID_0 from the TPM: `a13a808600084311`
> (Vendor ID 8086, Device ID a13a, Revision ID 00). The only match I
> found while browsing for this device ID is 100 Series/C230 Series
> Chipset Family MEI Controller #1, which is a PCI device, so it might
> not be related to the TPM.
>
> The driver bound to the tpm0 device is tpm_crb. The disassembled TPM2
> ACPI table is also attached in case it helps.
>
> The bug was reproduced from upstream kernel version 6.8.0 (attached
> build .config that I used).
>
> > Also, which firmwre version you have and have you tested with the
> > most up to date firmware (BIOS)?
>
> I have the most updated firmware provided by ASUS: TUF GAMING
> B460M-PLUS BIOS 1601
>
> > What is "the ACPI command"? Refer to concrete items instead of
> > asking to guess what you is the ACPI command for you.
>
> I enabled ACPI_DEBUG on my kernel to know where the it was actually
> hanging. The last function is actually the last function that should
> be called by the kernel for a successful shutdown:
> hwsleep-0078 hw_legacy_sleep       : Entering sleep state [S5]^M
> hwregs-0460 hw_write_pm1_control  : ----Entry^M
> hwvalid-0097 hw_validate_io_request: ----Entry^M
> hwvalid-0111 hw_validate_io_request: Address 0000000000001804
> LastAddress 0000000000001805 Length 2  hwvalid-0128
> hw_validate_io_request: ----Exit- AE_OK^M
> hwregs-0360 hw_write              : Wrote: 0000000000001C01 width 16
> to 0000000000001804 (SystemIO)^M
> hwregs-0473 hw_write_pm1_control  : ----Exit- AE_OK^M
> hwregs-0460 hw_write_pm1_control  : ----Entry^M
> hwvalid-0097 hw_validate_io_request: ----Entry^M
> hwvalid-0111 hw_validate_io_request: Address 0000000000001804
> LastAddress 0000000000001805 Length 2  hwvalid-0128
> hw_validate_io_request: ----Exit- AE_OK^M
>
> It is writing both SLP_TYP + SLP_EN to ACPI PM1b_CNT registers (as
> expected by specification). I checked the flags and it is in line with
> the flags required by the system ACPI tables.
>
> I understand from that that the system is hanging after ACPI firmware
> takes over. The same issue happens if I force a EFI shutdown.
>
> Since the the BUG has appeared again even with the fix implemented, I
> am holding this patch for now until I find a solution that permanently
> fixes the issue. The next time I try to submit a patch that will
> comply with all your suggestions, thank you very much.
>
> I would appreciate if you had any hint on how I could keep digging to
> find the issue that might be causing this bug. This is an issue that
> only happens when I shutdown from Linux and my TPM is activated in
> BIOS. That's why my guess is that this is what should be causing it.
> From Windows, shutdown is always flawless.
>
> Best regards,
> Adam
>
> >
> > > chip expecting it to be in Locality 0 as expected by TCG PC Client
> > > Platform Firmware Profile Version 1.06 Revision 52 (3.1.1 – Pre-OS
> > > Environment) and then when it fails to do so it simply halts the
> > > whole system.
> >
> > We don't speculate about the root cause here, only document it.
> > Please move this paragraph before diffstat (see below)>
> >
> > > Enable a user to configure the kernel through
> > > “tpm.locality_on_suspend=1” boot parameter so that the locality is set
> > > before suspend/shutdown in order to diagnose whether or not the board is
> > > one of the buggy ones that require this workaround. Since this bug is
> > > related to the board/platform instead of the specific TPM chip, call
> > > dmi_check_system on the tpm_init function so that this setting is
> > > automatically enabled for boards specified in code (ASUS TUF GAMING
> > > B460M-PLUS already included) – automatic configuration only works in
> > > case CONFIG_DMI is set though, since dmi_check_system is a non-op when
> > > CONFIG_DMI is not set.
> >
> > Please describe what the *kernel command-line" (for clarity
> > sake) semantically means.
> >
> > Also please remove anything about diangnosing. We care only
> > about fixes.
> >
> > >
> > > In case “tpm.locality_on_suspend=0” (the default) don't change any
> > > behavior thus preserving current functionality of any other board
> > > except ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS and possibly future
> > > boards as we successfully diagnose other boards with the same issue
> > > fixed by using “tpm.locality_on_suspend=1”.
> >
> > This neither documents the default value. I'm also lost did setting
> > this "1" or "0" fix the issue in your case?
> >
> > So: firmware version and being up-to-date is important and also this
> > needs to be reproduciable with the mainline Linux tree, not distro
> > kernel or custom kernel.
> >
> > >
> > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217890
> > > Signed-off-by: Adam Alves <adamoa@gmail.com>
> > > ---
> >
> > <cover letter>
> >
> > OK, I'll try to check what is done here but please re-read
> > "describing your changes" before sending next version:
> >
> > https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
> >
> > > v1->v2: fix formatting issues and simplified tpm_chip_stop code.
> > >
> > >  drivers/char/tpm/tpm-chip.c      | 12 +++++++++++
> > >  drivers/char/tpm/tpm-interface.c | 37 ++++++++++++++++++++++++++++++++
> > >  drivers/char/tpm/tpm.h           |  1 +
> > >  include/linux/tpm.h              |  1 +
> > >  4 files changed, 51 insertions(+)
> > >
> > > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> > > index 42b1062e33cd..a183e1355289 100644
> > > --- a/drivers/char/tpm/tpm-chip.c
> > > +++ b/drivers/char/tpm/tpm-chip.c
> > > @@ -137,6 +137,12 @@ EXPORT_SYMBOL_GPL(tpm_chip_start);
> > >   */
> > >  void tpm_chip_stop(struct tpm_chip *chip)
> > >  {
> > > +     if (chip->flags & TPM_CHIP_FLAG_PRESERVE_LOCALITY) {
> >
> > The commit message did not explain what this flag is and what is its
> > purpose.
> >
> > Also why you need to populate global flag inside chip, or the value
> > of it?
> >
> > Why this is not just:
> >
> >         if (tpm_locality_on_suspend) {
> > ?
> >
> >
> > > +             if (chip->locality != 0)
> > > +                     tpm_request_locality(chip);
> >
> > This will unconditionally skip calling tpm_request_locality() because
> > Linux only uses locality 0. Not sure what good does this make.
> >
> > > +             return;
> > > +     }
> > > +
> > >       tpm_go_idle(chip);
> > >       tpm_relinquish_locality(chip);
> > >       tpm_clk_disable(chip);
> > > @@ -291,6 +297,9 @@ int tpm_class_shutdown(struct device *dev)
> > >  {
> > >       struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
> > >
> > > +     if (tpm_locality_on_suspend)
> > > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > +
> > >       down_write(&chip->ops_sem);
> > >       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> > >               if (!tpm_chip_start(chip)) {
> > > @@ -668,6 +677,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
> > >   */
> > >  void tpm_chip_unregister(struct tpm_chip *chip)
> > >  {
> > > +     if (tpm_locality_on_suspend)
> > > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > +
> > >       tpm_del_legacy_sysfs(chip);
> > >       if (tpm_is_hwrng_enabled(chip))
> > >               hwrng_unregister(&chip->hwrng);
> > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> > > index 66b16d26eecc..7f770ea98402 100644
> > > --- a/drivers/char/tpm/tpm-interface.c
> > > +++ b/drivers/char/tpm/tpm-interface.c
> > > @@ -26,6 +26,7 @@
> > >  #include <linux/suspend.h>
> > >  #include <linux/freezer.h>
> > >  #include <linux/tpm_eventlog.h>
> > > +#include <linux/dmi.h>
> > >
> > >  #include "tpm.h"
> > >
> > > @@ -382,6 +383,36 @@ int tpm_auto_startup(struct tpm_chip *chip)
> > >       return rc;
> > >  }
> > >
> > > +/*
> > > + * Bug workaround - some boards expect the TPM to be on Locality 0
> > > + * before suspend/shutdown, halting the system otherwise before
> > > + * suspend and shutdown. Change suspend behavior for these cases.
> > > + */
> > > +bool tpm_locality_on_suspend;
> > > +module_param_named(locality_on_suspend, tpm_locality_on_suspend, bool, 0644);
> > > +MODULE_PARM_DESC(locality_on_suspend,
> > > +              "Put TPM at locality 0 before suspend/shutdown.");
> > > +
> > > +static int __init tpm_set_locality_on_suspend(const struct dmi_system_id *system_id)
> > > +{
> > > +     pr_info("Board %s: TPM locality preserved before suspend/shutdown.\n",
> > > +             system_id->ident);
> >
> > Please remove pr_info(), we do not want to bloat klog.
> >
> > > +     tpm_locality_on_suspend = true;
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static const struct dmi_system_id tpm_board_quirks[] __initconst = {
> >
> > The commit message did not introduce this. Also should have inline
> > documentation.
> >
> > /*
> >  * What the heck this.
> >  */
> >
> > > +     {
> > > +             .ident = "TUF GAMING B460M-PLUS",
> > > +             .matches = {
> > > +                     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
> > > +                     DMI_MATCH(DMI_BOARD_NAME, "TUF GAMING B460M-PLUS"),
> > > +             },
> > > +             .callback = tpm_set_locality_on_suspend,
> > > +     },
> > > +};
> > > +
> > >  /*
> > >   * We are about to suspend. Save the TPM state
> > >   * so that it can be restored.
> > > @@ -394,6 +425,9 @@ int tpm_pm_suspend(struct device *dev)
> > >       if (!chip)
> > >               return -ENODEV;
> > >
> > > +     if (tpm_locality_on_suspend)
> > > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > +
> > >       if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
> > >               goto suspended;
> > >
> > > @@ -431,6 +465,7 @@ int tpm_pm_resume(struct device *dev)
> > >       if (chip == NULL)
> > >               return -ENODEV;
> > >
> > > +     chip->flags &= ~TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > >       chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
> > >
> > >       /*
> > > @@ -476,6 +511,8 @@ static int __init tpm_init(void)
> > >  {
> > >       int rc;
> > >
> > > +     dmi_check_system(tpm_board_quirks);
> > > +
> > >       rc = class_register(&tpm_class);
> > >       if (rc) {
> > >               pr_err("couldn't create tpm class\n");
> > > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> > > index 61445f1dc46d..f2657b611b81 100644
> > > --- a/drivers/char/tpm/tpm.h
> > > +++ b/drivers/char/tpm/tpm.h
> > > @@ -236,6 +236,7 @@ extern dev_t tpm_devt;
> > >  extern const struct file_operations tpm_fops;
> > >  extern const struct file_operations tpmrm_fops;
> > >  extern struct idr dev_nums_idr;
> > > +extern bool tpm_locality_on_suspend;
> > >
> > >  ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
> > >  int tpm_get_timeouts(struct tpm_chip *);
> > > diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> > > index 4ee9d13749ad..1fbb33f386d1 100644
> > > --- a/include/linux/tpm.h
> > > +++ b/include/linux/tpm.h
> > > @@ -284,6 +284,7 @@ enum tpm_chip_flags {
> > >       TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
> > >       TPM_CHIP_FLAG_SUSPENDED                 = BIT(8),
> > >       TPM_CHIP_FLAG_HWRNG_DISABLED            = BIT(9),
> > > +     TPM_CHIP_FLAG_PRESERVE_LOCALITY         = BIT(10),
> > >  };
> > >
> > >  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
> >
> >
> > BR, Jarkko
>
>
>
> --
> Adam Oliveira Alves
Adam Alves March 14, 2024, 4:32 p.m. UTC | #6
Fixing a typo: I patched the 6.8.0 kernel.

Em qui., 14 de mar. de 2024 às 13:31, Adam Alves <adamoa@gmail.com> escreveu:
>
> Hi Jarkko,
>
> I have an update here. I would like you to check if it makes sense
> before I submit a patch.
>
> The problem might be related to the chip itself which leaves the idle
> state whenever the locality is relinquished.
>
> I probed the chip while operating and noted that the
> TPM_CRB_CTRL_STS_0.tpmIdle bit (located at `regs_t->ctrl_sts` on
> `crb_priv` structure in tpm_crb.c) is always cleared whenever the
> locality is relinquished.
>
> The result is that this chip never becomes idle since after going idle
> the locality is relinquished (`tpm_chip_stop` function in tpm-chip.c).
>
> I patched the 7.8.0 kernel for bypassing the `tpm_relinquish_locality`
> call and so far the PC is suspending and power off normally,
> TPM_CRB_CTRL_STS_0.tpmIdle remains set whenever the device is not used
> now.
>
> I believe this is related to this specific chip, if the fix remains
> working for 2 weeks I will submit the patch. Please advise me if it
> makes sense.
>
> Best regards,
> Adam
>
> Em qua., 13 de mar. de 2024 às 14:02, Adam Alves <adamoa@gmail.com> escreveu:
> >
> > Hi Jarkko,
> >
> > Thank you very much for kindly reviewing this proposal.
> >
> > After one week without any issues with my PC hanging, it happened
> > again. It seems that the fix I am proposing is not final (it only
> > reduced the frequency since it always happened when I shutdown after
> > couple hours of power up time and now it only happened after two weeks
> > with a similar usage rate).
> >
> > I will share with you the data you requested below.
> >
> > > The lacking information here is the CPU model (/proc/cpuinfo), on
> > > which kernel version the bug was produced and what kind of TPM the
> > > system has (discrete chip or firmware TPM should be easy to check
> > > from BIOS).
> >
> > CPU model: Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz
> > I am attaching data from /proc/cpuinfo
> >
> > TPM: No info on mainboard documentation regarding TPM. BIOS is not
> > clear whether or not it is discrete or firmware. Based on dmidecode
> > (attached) I get the following:
> > TPM Device
> >         Vendor ID: INTC
> >         Specification Version: 2.0
> >         Firmware Revision: 500.16
> >         Description: INTEL
> >         Characteristics:
> >                 Family configurable via platform software support
> >         OEM-specific Information: 0x00000000
> > I also extracted TPM_CRB_INTF_ID_0 from the TPM: `a13a808600084311`
> > (Vendor ID 8086, Device ID a13a, Revision ID 00). The only match I
> > found while browsing for this device ID is 100 Series/C230 Series
> > Chipset Family MEI Controller #1, which is a PCI device, so it might
> > not be related to the TPM.
> >
> > The driver bound to the tpm0 device is tpm_crb. The disassembled TPM2
> > ACPI table is also attached in case it helps.
> >
> > The bug was reproduced from upstream kernel version 6.8.0 (attached
> > build .config that I used).
> >
> > > Also, which firmwre version you have and have you tested with the
> > > most up to date firmware (BIOS)?
> >
> > I have the most updated firmware provided by ASUS: TUF GAMING
> > B460M-PLUS BIOS 1601
> >
> > > What is "the ACPI command"? Refer to concrete items instead of
> > > asking to guess what you is the ACPI command for you.
> >
> > I enabled ACPI_DEBUG on my kernel to know where the it was actually
> > hanging. The last function is actually the last function that should
> > be called by the kernel for a successful shutdown:
> > hwsleep-0078 hw_legacy_sleep       : Entering sleep state [S5]^M
> > hwregs-0460 hw_write_pm1_control  : ----Entry^M
> > hwvalid-0097 hw_validate_io_request: ----Entry^M
> > hwvalid-0111 hw_validate_io_request: Address 0000000000001804
> > LastAddress 0000000000001805 Length 2  hwvalid-0128
> > hw_validate_io_request: ----Exit- AE_OK^M
> > hwregs-0360 hw_write              : Wrote: 0000000000001C01 width 16
> > to 0000000000001804 (SystemIO)^M
> > hwregs-0473 hw_write_pm1_control  : ----Exit- AE_OK^M
> > hwregs-0460 hw_write_pm1_control  : ----Entry^M
> > hwvalid-0097 hw_validate_io_request: ----Entry^M
> > hwvalid-0111 hw_validate_io_request: Address 0000000000001804
> > LastAddress 0000000000001805 Length 2  hwvalid-0128
> > hw_validate_io_request: ----Exit- AE_OK^M
> >
> > It is writing both SLP_TYP + SLP_EN to ACPI PM1b_CNT registers (as
> > expected by specification). I checked the flags and it is in line with
> > the flags required by the system ACPI tables.
> >
> > I understand from that that the system is hanging after ACPI firmware
> > takes over. The same issue happens if I force a EFI shutdown.
> >
> > Since the the BUG has appeared again even with the fix implemented, I
> > am holding this patch for now until I find a solution that permanently
> > fixes the issue. The next time I try to submit a patch that will
> > comply with all your suggestions, thank you very much.
> >
> > I would appreciate if you had any hint on how I could keep digging to
> > find the issue that might be causing this bug. This is an issue that
> > only happens when I shutdown from Linux and my TPM is activated in
> > BIOS. That's why my guess is that this is what should be causing it.
> > From Windows, shutdown is always flawless.
> >
> > Best regards,
> > Adam
> >
> > >
> > > > chip expecting it to be in Locality 0 as expected by TCG PC Client
> > > > Platform Firmware Profile Version 1.06 Revision 52 (3.1.1 – Pre-OS
> > > > Environment) and then when it fails to do so it simply halts the
> > > > whole system.
> > >
> > > We don't speculate about the root cause here, only document it.
> > > Please move this paragraph before diffstat (see below)>
> > >
> > > > Enable a user to configure the kernel through
> > > > “tpm.locality_on_suspend=1” boot parameter so that the locality is set
> > > > before suspend/shutdown in order to diagnose whether or not the board is
> > > > one of the buggy ones that require this workaround. Since this bug is
> > > > related to the board/platform instead of the specific TPM chip, call
> > > > dmi_check_system on the tpm_init function so that this setting is
> > > > automatically enabled for boards specified in code (ASUS TUF GAMING
> > > > B460M-PLUS already included) – automatic configuration only works in
> > > > case CONFIG_DMI is set though, since dmi_check_system is a non-op when
> > > > CONFIG_DMI is not set.
> > >
> > > Please describe what the *kernel command-line" (for clarity
> > > sake) semantically means.
> > >
> > > Also please remove anything about diangnosing. We care only
> > > about fixes.
> > >
> > > >
> > > > In case “tpm.locality_on_suspend=0” (the default) don't change any
> > > > behavior thus preserving current functionality of any other board
> > > > except ASUSTeK COMPUTER INC. TUF GAMING B460M-PLUS and possibly future
> > > > boards as we successfully diagnose other boards with the same issue
> > > > fixed by using “tpm.locality_on_suspend=1”.
> > >
> > > This neither documents the default value. I'm also lost did setting
> > > this "1" or "0" fix the issue in your case?
> > >
> > > So: firmware version and being up-to-date is important and also this
> > > needs to be reproduciable with the mainline Linux tree, not distro
> > > kernel or custom kernel.
> > >
> > > >
> > > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217890
> > > > Signed-off-by: Adam Alves <adamoa@gmail.com>
> > > > ---
> > >
> > > <cover letter>
> > >
> > > OK, I'll try to check what is done here but please re-read
> > > "describing your changes" before sending next version:
> > >
> > > https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
> > >
> > > > v1->v2: fix formatting issues and simplified tpm_chip_stop code.
> > > >
> > > >  drivers/char/tpm/tpm-chip.c      | 12 +++++++++++
> > > >  drivers/char/tpm/tpm-interface.c | 37 ++++++++++++++++++++++++++++++++
> > > >  drivers/char/tpm/tpm.h           |  1 +
> > > >  include/linux/tpm.h              |  1 +
> > > >  4 files changed, 51 insertions(+)
> > > >
> > > > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> > > > index 42b1062e33cd..a183e1355289 100644
> > > > --- a/drivers/char/tpm/tpm-chip.c
> > > > +++ b/drivers/char/tpm/tpm-chip.c
> > > > @@ -137,6 +137,12 @@ EXPORT_SYMBOL_GPL(tpm_chip_start);
> > > >   */
> > > >  void tpm_chip_stop(struct tpm_chip *chip)
> > > >  {
> > > > +     if (chip->flags & TPM_CHIP_FLAG_PRESERVE_LOCALITY) {
> > >
> > > The commit message did not explain what this flag is and what is its
> > > purpose.
> > >
> > > Also why you need to populate global flag inside chip, or the value
> > > of it?
> > >
> > > Why this is not just:
> > >
> > >         if (tpm_locality_on_suspend) {
> > > ?
> > >
> > >
> > > > +             if (chip->locality != 0)
> > > > +                     tpm_request_locality(chip);
> > >
> > > This will unconditionally skip calling tpm_request_locality() because
> > > Linux only uses locality 0. Not sure what good does this make.
> > >
> > > > +             return;
> > > > +     }
> > > > +
> > > >       tpm_go_idle(chip);
> > > >       tpm_relinquish_locality(chip);
> > > >       tpm_clk_disable(chip);
> > > > @@ -291,6 +297,9 @@ int tpm_class_shutdown(struct device *dev)
> > > >  {
> > > >       struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
> > > >
> > > > +     if (tpm_locality_on_suspend)
> > > > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > > +
> > > >       down_write(&chip->ops_sem);
> > > >       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> > > >               if (!tpm_chip_start(chip)) {
> > > > @@ -668,6 +677,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
> > > >   */
> > > >  void tpm_chip_unregister(struct tpm_chip *chip)
> > > >  {
> > > > +     if (tpm_locality_on_suspend)
> > > > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > > +
> > > >       tpm_del_legacy_sysfs(chip);
> > > >       if (tpm_is_hwrng_enabled(chip))
> > > >               hwrng_unregister(&chip->hwrng);
> > > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> > > > index 66b16d26eecc..7f770ea98402 100644
> > > > --- a/drivers/char/tpm/tpm-interface.c
> > > > +++ b/drivers/char/tpm/tpm-interface.c
> > > > @@ -26,6 +26,7 @@
> > > >  #include <linux/suspend.h>
> > > >  #include <linux/freezer.h>
> > > >  #include <linux/tpm_eventlog.h>
> > > > +#include <linux/dmi.h>
> > > >
> > > >  #include "tpm.h"
> > > >
> > > > @@ -382,6 +383,36 @@ int tpm_auto_startup(struct tpm_chip *chip)
> > > >       return rc;
> > > >  }
> > > >
> > > > +/*
> > > > + * Bug workaround - some boards expect the TPM to be on Locality 0
> > > > + * before suspend/shutdown, halting the system otherwise before
> > > > + * suspend and shutdown. Change suspend behavior for these cases.
> > > > + */
> > > > +bool tpm_locality_on_suspend;
> > > > +module_param_named(locality_on_suspend, tpm_locality_on_suspend, bool, 0644);
> > > > +MODULE_PARM_DESC(locality_on_suspend,
> > > > +              "Put TPM at locality 0 before suspend/shutdown.");
> > > > +
> > > > +static int __init tpm_set_locality_on_suspend(const struct dmi_system_id *system_id)
> > > > +{
> > > > +     pr_info("Board %s: TPM locality preserved before suspend/shutdown.\n",
> > > > +             system_id->ident);
> > >
> > > Please remove pr_info(), we do not want to bloat klog.
> > >
> > > > +     tpm_locality_on_suspend = true;
> > > > +
> > > > +     return 0;
> > > > +}
> > > > +
> > > > +static const struct dmi_system_id tpm_board_quirks[] __initconst = {
> > >
> > > The commit message did not introduce this. Also should have inline
> > > documentation.
> > >
> > > /*
> > >  * What the heck this.
> > >  */
> > >
> > > > +     {
> > > > +             .ident = "TUF GAMING B460M-PLUS",
> > > > +             .matches = {
> > > > +                     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
> > > > +                     DMI_MATCH(DMI_BOARD_NAME, "TUF GAMING B460M-PLUS"),
> > > > +             },
> > > > +             .callback = tpm_set_locality_on_suspend,
> > > > +     },
> > > > +};
> > > > +
> > > >  /*
> > > >   * We are about to suspend. Save the TPM state
> > > >   * so that it can be restored.
> > > > @@ -394,6 +425,9 @@ int tpm_pm_suspend(struct device *dev)
> > > >       if (!chip)
> > > >               return -ENODEV;
> > > >
> > > > +     if (tpm_locality_on_suspend)
> > > > +             chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > > +
> > > >       if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
> > > >               goto suspended;
> > > >
> > > > @@ -431,6 +465,7 @@ int tpm_pm_resume(struct device *dev)
> > > >       if (chip == NULL)
> > > >               return -ENODEV;
> > > >
> > > > +     chip->flags &= ~TPM_CHIP_FLAG_PRESERVE_LOCALITY;
> > > >       chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
> > > >
> > > >       /*
> > > > @@ -476,6 +511,8 @@ static int __init tpm_init(void)
> > > >  {
> > > >       int rc;
> > > >
> > > > +     dmi_check_system(tpm_board_quirks);
> > > > +
> > > >       rc = class_register(&tpm_class);
> > > >       if (rc) {
> > > >               pr_err("couldn't create tpm class\n");
> > > > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> > > > index 61445f1dc46d..f2657b611b81 100644
> > > > --- a/drivers/char/tpm/tpm.h
> > > > +++ b/drivers/char/tpm/tpm.h
> > > > @@ -236,6 +236,7 @@ extern dev_t tpm_devt;
> > > >  extern const struct file_operations tpm_fops;
> > > >  extern const struct file_operations tpmrm_fops;
> > > >  extern struct idr dev_nums_idr;
> > > > +extern bool tpm_locality_on_suspend;
> > > >
> > > >  ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
> > > >  int tpm_get_timeouts(struct tpm_chip *);
> > > > diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> > > > index 4ee9d13749ad..1fbb33f386d1 100644
> > > > --- a/include/linux/tpm.h
> > > > +++ b/include/linux/tpm.h
> > > > @@ -284,6 +284,7 @@ enum tpm_chip_flags {
> > > >       TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
> > > >       TPM_CHIP_FLAG_SUSPENDED                 = BIT(8),
> > > >       TPM_CHIP_FLAG_HWRNG_DISABLED            = BIT(9),
> > > > +     TPM_CHIP_FLAG_PRESERVE_LOCALITY         = BIT(10),
> > > >  };
> > > >
> > > >  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
> > >
> > >
> > > BR, Jarkko
> >
> >
> >
> > --
> > Adam Oliveira Alves
>
>
>
> --
> Adam Oliveira Alves
Jarkko Sakkinen March 19, 2024, 7:57 p.m. UTC | #7
On Wed Mar 13, 2024 at 7:02 PM EET, Adam Alves wrote:
> Hi Jarkko,
>
> Thank you very much for kindly reviewing this proposal.
>
> After one week without any issues with my PC hanging, it happened
> again. It seems that the fix I am proposing is not final (it only
> reduced the frequency since it always happened when I shutdown after
> couple hours of power up time and now it only happened after two weeks
> with a similar usage rate).
>
> I will share with you the data you requested below.

Thanks I'll definitely check these in detail.

Any possible bug fix (if we decide to fix anything) is tpm_crb.c
including possible kernel command-line parameters or whatever. The
current proposal affects all the possible pieces of TPM hardware so
in all cases it is unacceptable.

Do you have dmesg/journactl transcript? Did you try to update the
firmware?

BR, Jarkko
Jarkko Sakkinen March 19, 2024, 8:07 p.m. UTC | #8
On Thu Mar 14, 2024 at 6:31 PM EET, Adam Alves wrote:
> Hi Jarkko,
>
> I have an update here. I would like you to check if it makes sense
> before I submit a patch.
>
> The problem might be related to the chip itself which leaves the idle
> state whenever the locality is relinquished.

There's no real discrete chip. It is a TPM living in the firmware,
namely management engine.

So first thing to check would be to update the BIOS entirely.

> I probed the chip while operating and noted that the
> TPM_CRB_CTRL_STS_0.tpmIdle bit (located at `regs_t->ctrl_sts` on
> `crb_priv` structure in tpm_crb.c) is always cleared whenever the
> locality is relinquished.
>
> The result is that this chip never becomes idle since after going idle
> the locality is relinquished (`tpm_chip_stop` function in tpm-chip.c).

This can be verified as tpm_crb does print "goIdle timed out" if it does
not go to idle. Should be visible in klog.

BR, Jarkko
Jarkko Sakkinen March 19, 2024, 9:38 p.m. UTC | #9
On Tue Mar 19, 2024 at 9:57 PM EET, Jarkko Sakkinen wrote:
> On Wed Mar 13, 2024 at 7:02 PM EET, Adam Alves wrote:
> > Hi Jarkko,
> >
> > Thank you very much for kindly reviewing this proposal.
> >
> > After one week without any issues with my PC hanging, it happened
> > again. It seems that the fix I am proposing is not final (it only
> > reduced the frequency since it always happened when I shutdown after
> > couple hours of power up time and now it only happened after two weeks
> > with a similar usage rate).
> >
> > I will share with you the data you requested below.
>
> Thanks I'll definitely check these in detail.
>
> Any possible bug fix (if we decide to fix anything) is tpm_crb.c
> including possible kernel command-line parameters or whatever. The
> current proposal affects all the possible pieces of TPM hardware so
> in all cases it is unacceptable.
>
> Do you have dmesg/journactl transcript? Did you try to update the
> firmware?

OK so I do have ASUS motherboard and my TPM2 ACPI table is almost the
same match but:

BIOS Information
        Vendor: American Megatrends Inc.
        Version: 2212
        Release Date: 12/13/2022
        Address: 0xF0000
        Runtime Size: 64 kB
        ROM Size: 24 MB

Where as in you dmidecode.txt:

Handle 0x0000, DMI type 0, 26 bytes
BIOS Information
	Vendor: American Megatrends Inc.
	Version: 1601
	Release Date: 02/11/2022
	Address: 0xF0000
	Runtime Size: 64 kB
	ROM Size: 16 MB

So at least the BIOS version is older. Can you update BIOS and see if
that could possibly fix the issue?

Make sure that it contains update for both BIOS and Management Engine.

BR, Jarkko
Jarkko Sakkinen March 19, 2024, 9:41 p.m. UTC | #10
On Tue Mar 19, 2024 at 11:38 PM EET, Jarkko Sakkinen wrote:
> On Tue Mar 19, 2024 at 9:57 PM EET, Jarkko Sakkinen wrote:
> > On Wed Mar 13, 2024 at 7:02 PM EET, Adam Alves wrote:
> > > Hi Jarkko,
> > >
> > > Thank you very much for kindly reviewing this proposal.
> > >
> > > After one week without any issues with my PC hanging, it happened
> > > again. It seems that the fix I am proposing is not final (it only
> > > reduced the frequency since it always happened when I shutdown after
> > > couple hours of power up time and now it only happened after two weeks
> > > with a similar usage rate).
> > >
> > > I will share with you the data you requested below.
> >
> > Thanks I'll definitely check these in detail.
> >
> > Any possible bug fix (if we decide to fix anything) is tpm_crb.c
> > including possible kernel command-line parameters or whatever. The
> > current proposal affects all the possible pieces of TPM hardware so
> > in all cases it is unacceptable.
> >
> > Do you have dmesg/journactl transcript? Did you try to update the
> > firmware?
>
> OK so I do have ASUS motherboard and my TPM2 ACPI table is almost the
> same match but:
>
> BIOS Information
>         Vendor: American Megatrends Inc.
>         Version: 2212
>         Release Date: 12/13/2022
>         Address: 0xF0000
>         Runtime Size: 64 kB
>         ROM Size: 24 MB
>
> Where as in you dmidecode.txt:
>
> Handle 0x0000, DMI type 0, 26 bytes
> BIOS Information
> 	Vendor: American Megatrends Inc.
> 	Version: 1601
> 	Release Date: 02/11/2022
> 	Address: 0xF0000
> 	Runtime Size: 64 kB
> 	ROM Size: 16 MB
>
> So at least the BIOS version is older. Can you update BIOS and see if
> that could possibly fix the issue?
>
> Make sure that it contains update for both BIOS and Management Engine.

AND if you end up still proposing any fix please make sure that it only
changes tpm_crb.c so that there is something to analyze. Sprinkled
arbitrary changes are not something we can really not say much.

If you don't know exactly what you are fixing and why please try to keep
the fix local to the issue. But yeah, BIOS update is really the first
trial here.

BR, Jarkko
diff mbox series

Patch

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 42b1062e33cd..a183e1355289 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -137,6 +137,12 @@  EXPORT_SYMBOL_GPL(tpm_chip_start);
  */
 void tpm_chip_stop(struct tpm_chip *chip)
 {
+	if (chip->flags & TPM_CHIP_FLAG_PRESERVE_LOCALITY) {
+		if (chip->locality != 0)
+			tpm_request_locality(chip);
+		return;
+	}
+
 	tpm_go_idle(chip);
 	tpm_relinquish_locality(chip);
 	tpm_clk_disable(chip);
@@ -291,6 +297,9 @@  int tpm_class_shutdown(struct device *dev)
 {
 	struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
 
+	if (tpm_locality_on_suspend)
+		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
+
 	down_write(&chip->ops_sem);
 	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
 		if (!tpm_chip_start(chip)) {
@@ -668,6 +677,9 @@  EXPORT_SYMBOL_GPL(tpm_chip_register);
  */
 void tpm_chip_unregister(struct tpm_chip *chip)
 {
+	if (tpm_locality_on_suspend)
+		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
+
 	tpm_del_legacy_sysfs(chip);
 	if (tpm_is_hwrng_enabled(chip))
 		hwrng_unregister(&chip->hwrng);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 66b16d26eecc..7f770ea98402 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -26,6 +26,7 @@ 
 #include <linux/suspend.h>
 #include <linux/freezer.h>
 #include <linux/tpm_eventlog.h>
+#include <linux/dmi.h>
 
 #include "tpm.h"
 
@@ -382,6 +383,36 @@  int tpm_auto_startup(struct tpm_chip *chip)
 	return rc;
 }
 
+/*
+ * Bug workaround - some boards expect the TPM to be on Locality 0
+ * before suspend/shutdown, halting the system otherwise before
+ * suspend and shutdown. Change suspend behavior for these cases.
+ */
+bool tpm_locality_on_suspend;
+module_param_named(locality_on_suspend, tpm_locality_on_suspend, bool, 0644);
+MODULE_PARM_DESC(locality_on_suspend,
+		 "Put TPM at locality 0 before suspend/shutdown.");
+
+static int __init tpm_set_locality_on_suspend(const struct dmi_system_id *system_id)
+{
+	pr_info("Board %s: TPM locality preserved before suspend/shutdown.\n",
+		system_id->ident);
+	tpm_locality_on_suspend = true;
+
+	return 0;
+}
+
+static const struct dmi_system_id tpm_board_quirks[] __initconst = {
+	{
+		.ident = "TUF GAMING B460M-PLUS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "TUF GAMING B460M-PLUS"),
+		},
+		.callback = tpm_set_locality_on_suspend,
+	},
+};
+
 /*
  * We are about to suspend. Save the TPM state
  * so that it can be restored.
@@ -394,6 +425,9 @@  int tpm_pm_suspend(struct device *dev)
 	if (!chip)
 		return -ENODEV;
 
+	if (tpm_locality_on_suspend)
+		chip->flags |= TPM_CHIP_FLAG_PRESERVE_LOCALITY;
+
 	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
 		goto suspended;
 
@@ -431,6 +465,7 @@  int tpm_pm_resume(struct device *dev)
 	if (chip == NULL)
 		return -ENODEV;
 
+	chip->flags &= ~TPM_CHIP_FLAG_PRESERVE_LOCALITY;
 	chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
 
 	/*
@@ -476,6 +511,8 @@  static int __init tpm_init(void)
 {
 	int rc;
 
+	dmi_check_system(tpm_board_quirks);
+
 	rc = class_register(&tpm_class);
 	if (rc) {
 		pr_err("couldn't create tpm class\n");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 61445f1dc46d..f2657b611b81 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -236,6 +236,7 @@  extern dev_t tpm_devt;
 extern const struct file_operations tpm_fops;
 extern const struct file_operations tpmrm_fops;
 extern struct idr dev_nums_idr;
+extern bool tpm_locality_on_suspend;
 
 ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz);
 int tpm_get_timeouts(struct tpm_chip *);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 4ee9d13749ad..1fbb33f386d1 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -284,6 +284,7 @@  enum tpm_chip_flags {
 	TPM_CHIP_FLAG_FIRMWARE_UPGRADE		= BIT(7),
 	TPM_CHIP_FLAG_SUSPENDED			= BIT(8),
 	TPM_CHIP_FLAG_HWRNG_DISABLED		= BIT(9),
+	TPM_CHIP_FLAG_PRESERVE_LOCALITY		= BIT(10),
 };
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)