Skip to content

Commit

Permalink
Merge branch 'linux-6.6.y' into linux-6.6-y-rolling-lts-stable
Browse files Browse the repository at this point in the history
  • Loading branch information
opsiff authored Aug 6, 2024
2 parents bcb151f + 1e1ca42 commit 3a8f471
Show file tree
Hide file tree
Showing 19 changed files with 335 additions and 12 deletions.
100 changes: 100 additions & 0 deletions Documentation/arch/x86/hygon-secure-virtualization.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
.. SPDX-License-Identifier: GPL-2.0
===========================
HYGON Secure Virtualization
===========================

China Secure Virtualization (CSV) is a key virtualization feature on Hygon
processors.

The 1st generation of CSV (CSV for short) is a secure virtualization technology
to provide memory encryption for the virtual machine (VM), each VM's memory is
encrypted by its unique encryption key which is managed by secure processor.

The 2nd generation of CSV (CSV2 for short) provides security enhancement to CSV
by encrypting not only the VM's memory but also the vCPU's registers of the VM.

The 3rd generation of CSV (CSV3 for short) is a more advanced secure
virtualization technology, it integrates secure processor, memory encryption and
memory isolation to provide the ability to protect guest's private data. The CSV3
guest's context like CPU registers, control block and nested page table is accessed
only by the guest itself and the secure processor. Neither other guests nor the
host can tamper with the guest's context.

The secure processor is a separate processor inside Hygon hardware. The firmware
running inside the secure processor performs activities in a secure way, such as
OVMF encryption, VM launch, secure memory management and nested page table
management etc. For more information, please see CSV spec and CSV3 spec from Hygon.

A CSV guest is running in the memory that is encrypted with a dedicated encrypt
key which is set by the secure processor. And CSV guest's memory encrypt key is
unique from the others. A low latency crypto engine resides on Hygon hardware
to minimize the negative effect on memory bandwidth. In CSV guest, a guest private
page will be automatically decrypted when read from memory and encrypted when
written to memory.

CSV3 provides an enhancement technology named memory isolation to improve the
security. A dedicated memory isolation hardware is built in Hygon hardware. Only
the secure processor has privilege to configure the isolation hardware. The VMM
allocates CMA memory and transfers them to secure processor. The secure processor
maps the memory to secure nested page table and manages them as guest's private
memory. Any memory access (read or write) to CSV3 guest's private memory outside
the guest will be blocked by isolation hardware.

A CSV3 guest may declare some memory regions as shared to share data with the
host. When a page is set as shared, read/write on the page will bypass the
isolation hardware and the guest's shared memory can be accessed by the host. A
method named CSV3 secure call command is designed and CSV3 guest sends the secure
call command to the secure processor to change private memory to shared memory.
In the method, 2 dedicated pages are reserved at early stage of the guest. Any
read/write on the dedicated pages will trigger nested page fault. When NPF
happens, the host helps to issue an external command to the secure processor but
cannot tamper with the data in the guest's private memory. Then the secure
processor checks the fault address and handles the command if the address is
exactly the dedicated pages.

Support for CSV can be determined through the CPUID instruction. The CPUID
function 0x8000001f reports information to CSV::

0x8000001f[eax]:
Bit[1] indicates support for CSV
Bit[3] indicates support for CSV2
Bit[30] indicates support for CSV3

If CSV is support, MSR 0xc0010131 can be used to determine if CSV is active::

0xc0010131:
Bit[0] 0 = CSV is not active
1 = CSV is active
Bit[1] 0 = CSV2 is not active
1 = CSV2 is active
Bit[30] 0 = CSV3 is not active
1 = CSV3 is active

All CSV/CSV2's configurations must be enabled in CSV3. Linux can activate CSV3 by
default (CONFIG_HYGON_CSV=y, CONFIG_CMA=y). CSV3 guest's memory is managed by
CMA (Contiguous Memory Allocation). User must specify CSV3 total secure memory on
the linux kernel command line with csv_mem_size or csv_mem_percentage::

csv_mem_size=nn[MG]
[KNL,CSV]
Reserve specified CSV3 memory size in CMA. CSV3's memory will be
allocated from these CMAs.
For instance, csv_mem_size=40G, 40G memory is reserved for CSV3.

csv_mem_percentage=nn
[KNL,CSV]
Reserve specified memory size which is prorated according to the
whole system memory size. CSV3 guest's memory will be allocated
from these CMAs.
For instance, csv_mem_percentage=60, means 60% system memory is
reserved for CSV3.
The maximum percentage is 80. And the default percentage is 0.

Limitations
The reserved CSV3 memory within CMA cannot be used by kernel or any application that
may pin memory using long term gup during the application's life time.
For instance, if the whole system memory is 64G and 32G is reserved for CSV3 with
kernel command line csv_mem_percentage=50, only 32G memory is available for CSV/CSV2.
As a result, user will fail to run a CSV/CSV2 guest with memory size which exceeds
32G.
23 changes: 23 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,29 @@ config EFI_RUNTIME_MAP

See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.

config HYGON_CSV
bool "Hygon secure virtualization CSV support"
default y
depends on CPU_SUP_HYGON && AMD_MEM_ENCRYPT
help
Hygon CSV integrates secure processor, memory encryption and
memory isolation to provide the ability to protect guest's private
data. It has evolved from CSV, CSV2 to CSV3.

For CSV, the guest's memory is encrypted.

For CSV2, not only the guest's memory, but also the guest's vCPU
registers are encrypted, neither other guests nor the host can tamper
with the vCPU registers.

For CSV3, the guest's context like vCPU registers, control block and
nested page table is accessed only by the guest itself and the secure
processor. Neither other guests nor the host can tamper with the
guest's context.

Say Y here to enable support for the whole capbilities of Hygon secure
virtualization on hygon processor.

source "kernel/Kconfig.hz"

config ARCH_SUPPORTS_KEXEC
Expand Down
1 change: 1 addition & 0 deletions arch/x86/configs/deepin_x86_desktop_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_EFI_MIXED=y
CONFIG_EFI_FAKE_MEMMAP=y
CONFIG_HYGON_CSV=y
CONFIG_LIVEPATCH=y
CONFIG_HIBERNATION=y
CONFIG_PM_WAKELOCKS=y
Expand Down
7 changes: 5 additions & 2 deletions arch/x86/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum cpuid_leafs
CPUID_8000_0021_EAX,
CPUID_LNX_5,
CPUID_C000_0006_EAX,
CPUID_8C86_0000_EDX, /* 23 */
NR_CPUID_WORDS,
};

Expand Down Expand Up @@ -96,8 +97,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 20, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 21, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 22, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 23, feature_bit) || \
REQUIRED_MASK_CHECK || \
BUILD_BUG_ON_ZERO(NCAPINTS != 23))
BUILD_BUG_ON_ZERO(NCAPINTS != 24))

#define DISABLED_MASK_BIT_SET(feature_bit) \
( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 0, feature_bit) || \
Expand All @@ -123,8 +125,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 20, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 21, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 22, feature_bit) || \
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 23, feature_bit) || \
DISABLED_MASK_CHECK || \
BUILD_BUG_ON_ZERO(NCAPINTS != 23))
BUILD_BUG_ON_ZERO(NCAPINTS != 24))

#define cpu_has(c, bit) \
(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
Expand Down
8 changes: 7 additions & 1 deletion arch/x86/include/asm/cpufeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/*
* Defines x86 CPU feature bits
*/
#define NCAPINTS 23 /* N 32-bit words worth of info */
#define NCAPINTS 24 /* N 32-bit words worth of info */
#define NBUGINTS 2 /* N 32-bit bug flags */

/*
Expand Down Expand Up @@ -465,6 +465,8 @@
#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* "" Virtual TSC_AUX */
#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */
#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* AMD SEV-ES full debug state swap support */
/* HYGON 3rd CSV */
#define X86_FEATURE_CSV3 (19*32 + 30) /* HYGON 3rd CSV */

/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */
Expand Down Expand Up @@ -492,6 +494,10 @@
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000006, word 22 */
#define X86_FEATURE_ZXPAUSE (22*32+ 0) /* ZHAOXIN ZXPAUSE */

/* HYGON-defined CPU features, CPUID level 0x8c860000:0 (EDX), word 23 */
#define X86_FEATURE_SM3 (23*32 + 1) /* SM3 instructions */
#define X86_FEATURE_SM4 (23*32 + 2) /* SM4 instructions */

/*
* BUG word(s)
*/
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/include/asm/disabled-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
#define DISABLED_MASK20 0
#define DISABLED_MASK21 0
#define DISABLED_MASK22 0
#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 23)
#define DISABLED_MASK23 0
#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 24)

#endif /* _ASM_X86_DISABLED_FEATURES_H */
6 changes: 6 additions & 0 deletions arch/x86/include/asm/mem_encrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ void add_encrypt_protection_map(void);

extern char __start_bss_decrypted[], __end_bss_decrypted[], __start_bss_decrypted_unused[];

#ifdef CONFIG_HYGON_CSV
extern void print_hygon_cc_feature_info(void);
#else /* !CONFIG_HYGON_CSV */
static inline void print_hygon_cc_feature_info(void) { }
#endif /* CONFIG_HYGON_CSV */

#endif /* __ASSEMBLY__ */

#endif /* __X86_MEM_ENCRYPT_H__ */
23 changes: 23 additions & 0 deletions arch/x86/include/asm/processor-hygon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* The helpers to support Hygon CPU specific code path.
*
* Copyright (C) 2024 Hygon Info Technologies Ltd.
*
* Author: Liyang Han <hanliyang@hygon.cn>
*/

#ifndef _ASM_X86_PROCESSOR_HYGON_H
#define _ASM_X86_PROCESSOR_HYGON_H

#include <asm/processor.h>

/*
* helper to determine HYGON CPU
*/
static inline bool is_x86_vendor_hygon(void)
{
return boot_cpu_data.x86_vendor == X86_VENDOR_HYGON;
}

#endif /* _ASM_X86_PROCESSOR_HYGON_H */
3 changes: 2 additions & 1 deletion arch/x86/include/asm/required-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
#define REQUIRED_MASK20 0
#define REQUIRED_MASK21 0
#define REQUIRED_MASK22 0
#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 23)
#define REQUIRED_MASK23 0
#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 24)

#endif /* _ASM_X86_REQUIRED_FEATURES_H */
65 changes: 65 additions & 0 deletions arch/x86/kernel/cpu/hygon.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,67 @@ static void bsp_init_hygon(struct cpuinfo_x86 *c)
resctrl_cpu_detect(c);
}

static void init_hygon_cap(struct cpuinfo_x86 *c)
{
/* Test for Extended Feature Flags presence */
if (cpuid_eax(0x8C860000) >= 0x8C860000) {
/*
* Store Extended Feature Flags of the CPU capability
* bit array
*/
c->x86_capability[CPUID_8C86_0000_EDX] = cpuid_edx(0x8C860000);
}
}

static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
{
u64 msr;
u32 eax;

eax = cpuid_eax(0x8000001f);

/* Check whether SME or CSV is supported */
if (!(eax & (BIT(0) | BIT(1))))
return;

/* If BIOS has not enabled SME then don't advertise the SME feature. */
rdmsrl(MSR_AMD64_SYSCFG, msr);
if (!(msr & MSR_AMD64_SYSCFG_MEM_ENCRYPT))
goto clear_all;

/*
* Always adjust physical address bits. Even though this will be a
* value above 32-bits this is still done for CONFIG_X86_32 so that
* accurate values are reported.
*/
c->x86_phys_bits -= (cpuid_ebx(0x8000001f) >> 6) & 0x3f;

/* Don't advertise SME and CSV features under CONFIG_X86_32. */
if (IS_ENABLED(CONFIG_X86_32))
goto clear_all;

/* Clear the SME feature flag if the kernel is not using it. */
if (!sme_me_mask)
setup_clear_cpu_cap(X86_FEATURE_SME);

/*
* If BIOS has not enabled CSV then don't advertise the CSV and CSV2
* feature.
*/
rdmsrl(MSR_K7_HWCR, msr);
if (!(msr & MSR_K7_HWCR_SMMLOCK))
goto clear_csv;

return;

clear_all:
setup_clear_cpu_cap(X86_FEATURE_SME);
clear_csv:
setup_clear_cpu_cap(X86_FEATURE_SEV);
setup_clear_cpu_cap(X86_FEATURE_SEV_ES);
setup_clear_cpu_cap(X86_FEATURE_CSV3);
}

static void early_init_hygon(struct cpuinfo_x86 *c)
{
u32 dummy;
Expand Down Expand Up @@ -294,6 +355,8 @@ static void early_init_hygon(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_VMMCALL);

hygon_get_topology_early(c);

early_detect_mem_encrypt(c);
}

static void init_hygon(struct cpuinfo_x86 *c)
Expand Down Expand Up @@ -355,6 +418,8 @@ static void init_hygon(struct cpuinfo_x86 *c)

/* Hygon CPUs don't need fencing after x2APIC/TSC_DEADLINE MSR writes. */
clear_cpu_cap(c, X86_FEATURE_APIC_MSRS_FENCE);

init_hygon_cap(c);
}

static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)
Expand Down
10 changes: 8 additions & 2 deletions arch/x86/kernel/cpu/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)

seq_puts(m, "flags\t\t:");
for (i = 0; i < 32*NCAPINTS; i++)
if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
seq_printf(m, " %s", x86_cap_flags[i]);
if (cpu_has(c, i) && x86_cap_flags[i] != NULL) {
if (c->x86_vendor == X86_VENDOR_HYGON)
seq_printf(m, " %s", i == X86_FEATURE_SEV ? "csv" :
(i == X86_FEATURE_SEV_ES ? "csv2" :
x86_cap_flags[i]));
else
seq_printf(m, " %s", x86_cap_flags[i]);
}

#ifdef CONFIG_X86_VMX_FEATURE_NAMES
if (cpu_has(c, X86_FEATURE_VMX) && c->vmx_capability[0]) {
Expand Down
7 changes: 5 additions & 2 deletions arch/x86/kvm/svm/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <asm/trapnr.h>
#include <asm/fpu/xcr.h>
#include <asm/debugreg.h>
#include <asm/processor-hygon.h>

#include "mmu.h"
#include "x86.h"
Expand Down Expand Up @@ -2288,13 +2289,15 @@ void __init sev_hardware_setup(void)

out:
if (boot_cpu_has(X86_FEATURE_SEV))
pr_info("SEV %s (ASIDs %u - %u)\n",
pr_info("%s %s (ASIDs %u - %u)\n",
is_x86_vendor_hygon() ? "CSV" : "SEV",
sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" :
"unusable" :
"disabled",
min_sev_asid, max_sev_asid);
if (boot_cpu_has(X86_FEATURE_SEV_ES))
pr_info("SEV-ES %s (ASIDs %u - %u)\n",
pr_info("%s %s (ASIDs %u - %u)\n",
is_x86_vendor_hygon() ? "CSV2" : "SEV-ES",
sev_es_supported ? "enabled" : "disabled",
min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);

Expand Down
4 changes: 3 additions & 1 deletion arch/x86/kvm/svm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <asm/traps.h>
#include <asm/reboot.h>
#include <asm/fpu/api.h>
#include <asm/processor-hygon.h>

#include <trace/events/ipi.h>

Expand Down Expand Up @@ -547,7 +548,8 @@ static bool __kvm_is_svm_supported(void)
}

if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
pr_info("KVM is unsupported when running as an SEV guest\n");
pr_info("KVM is unsupported when running as an %s guest\n",
is_x86_vendor_hygon() ? "CSV" : "SEV");
return false;
}

Expand Down
Loading

0 comments on commit 3a8f471

Please sign in to comment.