| From 4dcd49405b52438a7cc16f6acf4aab3b1e268f39 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 6 Apr 2022 02:29:38 +0300 |
| Subject: ACPICA: Avoid cache flush inside virtual machines |
| |
| From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> |
| |
| [ Upstream commit e2efb6359e620521d1e13f69b2257de8ceaa9475 ] |
| |
| While running inside virtual machine, the kernel can bypass cache |
| flushing. Changing sleep state in a virtual machine doesn't affect the |
| host system sleep state and cannot lead to data loss. |
| |
| Before entering sleep states, the ACPI code flushes caches to prevent |
| data loss using the WBINVD instruction. This mechanism is required on |
| bare metal. |
| |
| But, any use WBINVD inside of a guest is worthless. Changing sleep |
| state in a virtual machine doesn't affect the host system sleep state |
| and cannot lead to data loss, so most hypervisors simply ignore it. |
| Despite this, the ACPI code calls WBINVD unconditionally anyway. |
| It's useless, but also normally harmless. |
| |
| In TDX guests, though, WBINVD stops being harmless; it triggers a |
| virtualization exception (#VE). If the ACPI cache-flushing WBINVD |
| were left in place, TDX guests would need handling to recover from |
| the exception. |
| |
| Avoid using WBINVD whenever running under a hypervisor. This both |
| removes the useless WBINVDs and saves TDX from implementing WBINVD |
| handling. |
| |
| Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> |
| Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> |
| Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com> |
| Reviewed-by: Dan Williams <dan.j.williams@intel.com> |
| Reviewed-by: Thomas Gleixner <tglx@linutronix.de> |
| Link: https://lkml.kernel.org/r/20220405232939.73860-30-kirill.shutemov@linux.intel.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/include/asm/acenv.h | 14 +++++++++++++- |
| 1 file changed, 13 insertions(+), 1 deletion(-) |
| |
| diff --git a/arch/x86/include/asm/acenv.h b/arch/x86/include/asm/acenv.h |
| index 1b010a859b8b..6de59a4f723c 100644 |
| --- a/arch/x86/include/asm/acenv.h |
| +++ b/arch/x86/include/asm/acenv.h |
| @@ -16,7 +16,19 @@ |
| |
| /* Asm macros */ |
| |
| -#define ACPI_FLUSH_CPU_CACHE() wbinvd() |
| +/* |
| + * ACPI_FLUSH_CPU_CACHE() flushes caches on entering sleep states. |
| + * It is required to prevent data loss. |
| + * |
| + * While running inside virtual machine, the kernel can bypass cache flushing. |
| + * Changing sleep state in a virtual machine doesn't affect the host system |
| + * sleep state and cannot lead to data loss. |
| + */ |
| +#define ACPI_FLUSH_CPU_CACHE() \ |
| +do { \ |
| + if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) \ |
| + wbinvd(); \ |
| +} while (0) |
| |
| int __acpi_acquire_global_lock(unsigned int *lock); |
| int __acpi_release_global_lock(unsigned int *lock); |
| -- |
| 2.35.1 |
| |