mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'x86_sev_for_v6.14_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 SEV updates from Borislav Petkov: - A segmented Reverse Map table (RMP) is a across-nodes distributed table of sorts which contains per-node descriptors of each node-local 4K page, denoting its ownership (hypervisor, guest, etc) in the realm of confidential computing. Add support for such a table in order to improve referential locality when accessing or modifying RMP table entries - Add support for reading the TSC in SNP guests by removing any interference or influence the hypervisor might have, with the goal of making a confidential guest even more independent from the hypervisor * tag 'x86_sev_for_v6.14_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/sev: Add the Secure TSC feature for SNP guests x86/tsc: Init the TSC for Secure TSC guests x86/sev: Mark the TSC in a secure TSC guest as reliable x86/sev: Prevent RDTSC/RDTSCP interception for Secure TSC enabled guests x86/sev: Prevent GUEST_TSC_FREQ MSR interception for Secure TSC enabled guests x86/sev: Change TSC MSR behavior for Secure TSC enabled guests x86/sev: Add Secure TSC support for SNP guests x86/sev: Relocate SNP guest messaging routines to common code x86/sev: Carve out and export SNP guest messaging init routines virt: sev-guest: Replace GFP_KERNEL_ACCOUNT with GFP_KERNEL virt: sev-guest: Remove is_vmpck_empty() helper x86/sev/docs: Document the SNP Reverse Map Table (RMP) x86/sev: Add full support for a segmented RMP table x86/sev: Treat the contiguous RMP table as a single RMP segment x86/sev: Map only the RMP table entries instead of the full RMP range x86/sev: Move the SNP probe routine out of the way x86/sev: Require the RMPREAD instruction after Zen4 x86/sev: Add support for the RMPREAD instruction x86/sev: Prepare for using the RMPREAD instruction to access the RMP
This commit is contained in:
@@ -130,8 +130,126 @@ SNP feature support.
|
||||
|
||||
More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR
|
||||
|
||||
Reverse Map Table (RMP)
|
||||
=======================
|
||||
|
||||
The RMP is a structure in system memory that is used to ensure a one-to-one
|
||||
mapping between system physical addresses and guest physical addresses. Each
|
||||
page of memory that is potentially assignable to guests has one entry within
|
||||
the RMP.
|
||||
|
||||
The RMP table can be either contiguous in memory or a collection of segments
|
||||
in memory.
|
||||
|
||||
Contiguous RMP
|
||||
--------------
|
||||
|
||||
Support for this form of the RMP is present when support for SEV-SNP is
|
||||
present, which can be determined using the CPUID instruction::
|
||||
|
||||
0x8000001f[eax]:
|
||||
Bit[4] indicates support for SEV-SNP
|
||||
|
||||
The location of the RMP is identified to the hardware through two MSRs::
|
||||
|
||||
0xc0010132 (RMP_BASE):
|
||||
System physical address of the first byte of the RMP
|
||||
|
||||
0xc0010133 (RMP_END):
|
||||
System physical address of the last byte of the RMP
|
||||
|
||||
Hardware requires that RMP_BASE and (RPM_END + 1) be 8KB aligned, but SEV
|
||||
firmware increases the alignment requirement to require a 1MB alignment.
|
||||
|
||||
The RMP consists of a 16KB region used for processor bookkeeping followed
|
||||
by the RMP entries, which are 16 bytes in size. The size of the RMP
|
||||
determines the range of physical memory that the hypervisor can assign to
|
||||
SEV-SNP guests. The RMP covers the system physical address from::
|
||||
|
||||
0 to ((RMP_END + 1 - RMP_BASE - 16KB) / 16B) x 4KB.
|
||||
|
||||
The current Linux support relies on BIOS to allocate/reserve the memory for
|
||||
the RMP and to set RMP_BASE and RMP_END appropriately. Linux uses the MSR
|
||||
values to locate the RMP and determine the size of the RMP. The RMP must
|
||||
cover all of system memory in order for Linux to enable SEV-SNP.
|
||||
|
||||
Segmented RMP
|
||||
-------------
|
||||
|
||||
Segmented RMP support is a new way of representing the layout of an RMP.
|
||||
Initial RMP support required the RMP table to be contiguous in memory.
|
||||
RMP accesses from a NUMA node on which the RMP doesn't reside
|
||||
can take longer than accesses from a NUMA node on which the RMP resides.
|
||||
Segmented RMP support allows the RMP entries to be located on the same
|
||||
node as the memory the RMP is covering, potentially reducing latency
|
||||
associated with accessing an RMP entry associated with the memory. Each
|
||||
RMP segment covers a specific range of system physical addresses.
|
||||
|
||||
Support for this form of the RMP can be determined using the CPUID
|
||||
instruction::
|
||||
|
||||
0x8000001f[eax]:
|
||||
Bit[23] indicates support for segmented RMP
|
||||
|
||||
If supported, segmented RMP attributes can be found using the CPUID
|
||||
instruction::
|
||||
|
||||
0x80000025[eax]:
|
||||
Bits[5:0] minimum supported RMP segment size
|
||||
Bits[11:6] maximum supported RMP segment size
|
||||
|
||||
0x80000025[ebx]:
|
||||
Bits[9:0] number of cacheable RMP segment definitions
|
||||
Bit[10] indicates if the number of cacheable RMP segments
|
||||
is a hard limit
|
||||
|
||||
To enable a segmented RMP, a new MSR is available::
|
||||
|
||||
0xc0010136 (RMP_CFG):
|
||||
Bit[0] indicates if segmented RMP is enabled
|
||||
Bits[13:8] contains the size of memory covered by an RMP
|
||||
segment (expressed as a power of 2)
|
||||
|
||||
The RMP segment size defined in the RMP_CFG MSR applies to all segments
|
||||
of the RMP. Therefore each RMP segment covers a specific range of system
|
||||
physical addresses. For example, if the RMP_CFG MSR value is 0x2401, then
|
||||
the RMP segment coverage value is 0x24 => 36, meaning the size of memory
|
||||
covered by an RMP segment is 64GB (1 << 36). So the first RMP segment
|
||||
covers physical addresses from 0 to 0xF_FFFF_FFFF, the second RMP segment
|
||||
covers physical addresses from 0x10_0000_0000 to 0x1F_FFFF_FFFF, etc.
|
||||
|
||||
When a segmented RMP is enabled, RMP_BASE points to the RMP bookkeeping
|
||||
area as it does today (16K in size). However, instead of RMP entries
|
||||
beginning immediately after the bookkeeping area, there is a 4K RMP
|
||||
segment table (RST). Each entry in the RST is 8-bytes in size and represents
|
||||
an RMP segment::
|
||||
|
||||
Bits[19:0] mapped size (in GB)
|
||||
The mapped size can be less than the defined segment size.
|
||||
A value of zero, indicates that no RMP exists for the range
|
||||
of system physical addresses associated with this segment.
|
||||
Bits[51:20] segment physical address
|
||||
This address is left shift 20-bits (or just masked when
|
||||
read) to form the physical address of the segment (1MB
|
||||
alignment).
|
||||
|
||||
The RST can hold 512 segment entries but can be limited in size to the number
|
||||
of cacheable RMP segments (CPUID 0x80000025_EBX[9:0]) if the number of cacheable
|
||||
RMP segments is a hard limit (CPUID 0x80000025_EBX[10]).
|
||||
|
||||
The current Linux support relies on BIOS to allocate/reserve the memory for
|
||||
the segmented RMP (the bookkeeping area, RST, and all segments), build the RST
|
||||
and to set RMP_BASE, RMP_END, and RMP_CFG appropriately. Linux uses the MSR
|
||||
values to locate the RMP and determine the size and location of the RMP
|
||||
segments. The RMP must cover all of system memory in order for Linux to enable
|
||||
SEV-SNP.
|
||||
|
||||
More details in the AMD64 APM Vol 2, section "15.36.3 Reverse Map Table",
|
||||
docID: 24593.
|
||||
|
||||
Secure VM Service Module (SVSM)
|
||||
===============================
|
||||
|
||||
SNP provides a feature called Virtual Machine Privilege Levels (VMPL) which
|
||||
defines four privilege levels at which guest software can run. The most
|
||||
privileged level is 0 and numerically higher numbers have lesser privileges.
|
||||
|
||||
Reference in New Issue
Block a user