mbox series

[GIT,PULL] KVM: x86: LAM support for 6.8

Message ID 20240104193303.3175844-4-seanjc@google.com (mailing list archive)
State New, archived
Headers show
Series [GIT,PULL] KVM: x86: LAM support for 6.8 | expand

Pull-request

https://github.com/kvm-x86/linux.git tags/kvm-x86-lam-6.8

Message

Sean Christopherson Jan. 4, 2024, 7:32 p.m. UTC
LAM virtualization support.  FWIW, I intended to send this in early-ish
December as you've asked in the past, but December was basically a lost cause
for me in terms of doing upstream work.  :-/

The following changes since commit e9e60c82fe391d04db55a91c733df4a017c28b2f:

  selftests/kvm: fix compilation on non-x86_64 platforms (2023-11-21 11:58:25 -0500)

are available in the Git repository at:

  https://github.com/kvm-x86/linux.git tags/kvm-x86-lam-6.8

for you to fetch changes up to 183bdd161c2b773a62f01d1c030f5a3a5b7c33b5:

  KVM: x86: Use KVM-governed feature framework to track "LAM enabled" (2023-11-28 17:54:09 -0800)

----------------------------------------------------------------
KVM x86 support for virtualizing Linear Address Masking (LAM)

Add KVM support for Linear Address Masking (LAM).  LAM tweaks the canonicality
checks for most virtual address usage in 64-bit mode, such that only the most
significant bit of the untranslated address bits must match the polarity of the
last translated address bit.  This allows software to use ignored, untranslated
address bits for metadata, e.g. to efficiently tag pointers for address
sanitization.

LAM can be enabled separately for user pointers and supervisor pointers, and
for userspace LAM can be select between 48-bit and 57-bit masking

 - 48-bit LAM: metadata bits 62:48, i.e. LAM width of 15.
 - 57-bit LAM: metadata bits 62:57, i.e. LAM width of 6.

For user pointers, LAM enabling utilizes two previously-reserved high bits from
CR3 (similar to how PCID_NOFLUSH uses bit 63): LAM_U48 and LAM_U57, bits 62 and
61 respectively.  Note, if LAM_57 is set, LAM_U48 is ignored, i.e.:

 - CR3.LAM_U48=0 && CR3.LAM_U57=0 == LAM disabled for user pointers
 - CR3.LAM_U48=1 && CR3.LAM_U57=0 == LAM-48 enabled for user pointers
 - CR3.LAM_U48=x && CR3.LAM_U57=1 == LAM-57 enabled for user pointers

For supervisor pointers, LAM is controlled by a single bit, CR4.LAM_SUP, with
the 48-bit versus 57-bit LAM behavior following the current paging mode, i.e.:

 - CR4.LAM_SUP=0 && CR4.LA57=x == LAM disabled for supervisor pointers
 - CR4.LAM_SUP=1 && CR4.LA57=0 == LAM-48 enabled for supervisor pointers
 - CR4.LAM_SUP=1 && CR4.LA57=1 == LAM-57 enabled for supervisor pointers

The modified LAM canonicality checks:
 - LAM_S48                : [ 1 ][ metadata ][ 1 ]
                              63               47
 - LAM_U48                : [ 0 ][ metadata ][ 0 ]
                              63               47
 - LAM_S57                : [ 1 ][ metadata ][ 1 ]
                              63               56
 - LAM_U57 + 5-lvl paging : [ 0 ][ metadata ][ 0 ]
                              63               56
 - LAM_U57 + 4-lvl paging : [ 0 ][ metadata ][ 0...0 ]
                              63               56..47

The bulk of KVM support for LAM is to emulate LAM's modified canonicality
checks.  The approach taken by KVM is to "fill" the metadata bits using the
highest bit of the translated address, e.g. for LAM-48, bit 47 is sign-extended
to bits 62:48.  The most significant bit, 63, is *not* modified, i.e. its value
from the raw, untagged virtual address is kept for the canonicality check. This
untagging allows

Aside from emulating LAM's canonical checks behavior, LAM has the usual KVM
touchpoints for selectable features: enumeration (CPUID.7.1:EAX.LAM[bit 26],
enabling via CR3 and CR4 bits, etc.

----------------------------------------------------------------
Binbin Wu (9):
      KVM: x86: Consolidate flags for __linearize()
      KVM: x86: Add an emulation flag for implicit system access
      KVM: x86: Add X86EMUL_F_INVLPG and pass it in em_invlpg()
      KVM: x86/mmu: Drop non-PA bits when getting GFN for guest's PGD
      KVM: x86: Add & use kvm_vcpu_is_legal_cr3() to check CR3's legality
      KVM: x86: Remove kvm_vcpu_is_illegal_gpa()
      KVM: x86: Introduce get_untagged_addr() in kvm_x86_ops and call it in emulator
      KVM: x86: Untag addresses for LAM emulation where applicable
      KVM: x86: Use KVM-governed feature framework to track "LAM enabled"

Robert Hoo (3):
      KVM: x86: Virtualize LAM for supervisor pointer
      KVM: x86: Virtualize LAM for user pointer
      KVM: x86: Advertise and enable LAM (user and supervisor)

 arch/x86/include/asm/kvm-x86-ops.h |  1 +
 arch/x86/include/asm/kvm_host.h    |  5 +++-
 arch/x86/kvm/cpuid.c               |  2 +-
 arch/x86/kvm/cpuid.h               | 13 +++++----
 arch/x86/kvm/emulate.c             | 27 ++++++++++---------
 arch/x86/kvm/governed_features.h   |  1 +
 arch/x86/kvm/kvm_emulate.h         |  9 +++++++
 arch/x86/kvm/mmu.h                 |  8 ++++++
 arch/x86/kvm/mmu/mmu.c             |  2 +-
 arch/x86/kvm/mmu/mmu_internal.h    |  1 +
 arch/x86/kvm/mmu/paging_tmpl.h     |  2 +-
 arch/x86/kvm/svm/nested.c          |  4 +--
 arch/x86/kvm/vmx/nested.c          | 11 +++++---
 arch/x86/kvm/vmx/sgx.c             |  1 +
 arch/x86/kvm/vmx/vmx.c             | 55 ++++++++++++++++++++++++++++++++++++--
 arch/x86/kvm/vmx/vmx.h             |  2 ++
 arch/x86/kvm/x86.c                 | 18 +++++++++++--
 arch/x86/kvm/x86.h                 |  2 ++
 18 files changed, 134 insertions(+), 30 deletions(-)

Comments

Paolo Bonzini Jan. 8, 2024, 1:04 p.m. UTC | #1
On Thu, Jan 4, 2024 at 8:33 PM Sean Christopherson <seanjc@google.com> wrote:
>
> LAM virtualization support.  FWIW, I intended to send this in early-ish
> December as you've asked in the past, but December was basically a lost cause
> for me in terms of doing upstream work.  :-/
>
> The following changes since commit e9e60c82fe391d04db55a91c733df4a017c28b2f:
>
>   selftests/kvm: fix compilation on non-x86_64 platforms (2023-11-21 11:58:25 -0500)
>
> are available in the Git repository at:
>
>   https://github.com/kvm-x86/linux.git tags/kvm-x86-lam-6.8
>
> for you to fetch changes up to 183bdd161c2b773a62f01d1c030f5a3a5b7c33b5:
>
>   KVM: x86: Use KVM-governed feature framework to track "LAM enabled" (2023-11-28 17:54:09 -0800)

Patches are surprisingly small for this. What's the state of tests
(https://www.spinics.net/lists/kvm/msg313712.html) though?

Thanks,

Paolo

> ----------------------------------------------------------------
> KVM x86 support for virtualizing Linear Address Masking (LAM)
>
> Add KVM support for Linear Address Masking (LAM).  LAM tweaks the canonicality
> checks for most virtual address usage in 64-bit mode, such that only the most
> significant bit of the untranslated address bits must match the polarity of the
> last translated address bit.  This allows software to use ignored, untranslated
> address bits for metadata, e.g. to efficiently tag pointers for address
> sanitization.
>
> LAM can be enabled separately for user pointers and supervisor pointers, and
> for userspace LAM can be select between 48-bit and 57-bit masking
>
>  - 48-bit LAM: metadata bits 62:48, i.e. LAM width of 15.
>  - 57-bit LAM: metadata bits 62:57, i.e. LAM width of 6.
>
> For user pointers, LAM enabling utilizes two previously-reserved high bits from
> CR3 (similar to how PCID_NOFLUSH uses bit 63): LAM_U48 and LAM_U57, bits 62 and
> 61 respectively.  Note, if LAM_57 is set, LAM_U48 is ignored, i.e.:
>
>  - CR3.LAM_U48=0 && CR3.LAM_U57=0 == LAM disabled for user pointers
>  - CR3.LAM_U48=1 && CR3.LAM_U57=0 == LAM-48 enabled for user pointers
>  - CR3.LAM_U48=x && CR3.LAM_U57=1 == LAM-57 enabled for user pointers
>
> For supervisor pointers, LAM is controlled by a single bit, CR4.LAM_SUP, with
> the 48-bit versus 57-bit LAM behavior following the current paging mode, i.e.:
>
>  - CR4.LAM_SUP=0 && CR4.LA57=x == LAM disabled for supervisor pointers
>  - CR4.LAM_SUP=1 && CR4.LA57=0 == LAM-48 enabled for supervisor pointers
>  - CR4.LAM_SUP=1 && CR4.LA57=1 == LAM-57 enabled for supervisor pointers
>
> The modified LAM canonicality checks:
>  - LAM_S48                : [ 1 ][ metadata ][ 1 ]
>                               63               47
>  - LAM_U48                : [ 0 ][ metadata ][ 0 ]
>                               63               47
>  - LAM_S57                : [ 1 ][ metadata ][ 1 ]
>                               63               56
>  - LAM_U57 + 5-lvl paging : [ 0 ][ metadata ][ 0 ]
>                               63               56
>  - LAM_U57 + 4-lvl paging : [ 0 ][ metadata ][ 0...0 ]
>                               63               56..47
>
> The bulk of KVM support for LAM is to emulate LAM's modified canonicality
> checks.  The approach taken by KVM is to "fill" the metadata bits using the
> highest bit of the translated address, e.g. for LAM-48, bit 47 is sign-extended
> to bits 62:48.  The most significant bit, 63, is *not* modified, i.e. its value
> from the raw, untagged virtual address is kept for the canonicality check. This
> untagging allows
>
> Aside from emulating LAM's canonical checks behavior, LAM has the usual KVM
> touchpoints for selectable features: enumeration (CPUID.7.1:EAX.LAM[bit 26],
> enabling via CR3 and CR4 bits, etc.
>
> ----------------------------------------------------------------
> Binbin Wu (9):
>       KVM: x86: Consolidate flags for __linearize()
>       KVM: x86: Add an emulation flag for implicit system access
>       KVM: x86: Add X86EMUL_F_INVLPG and pass it in em_invlpg()
>       KVM: x86/mmu: Drop non-PA bits when getting GFN for guest's PGD
>       KVM: x86: Add & use kvm_vcpu_is_legal_cr3() to check CR3's legality
>       KVM: x86: Remove kvm_vcpu_is_illegal_gpa()
>       KVM: x86: Introduce get_untagged_addr() in kvm_x86_ops and call it in emulator
>       KVM: x86: Untag addresses for LAM emulation where applicable
>       KVM: x86: Use KVM-governed feature framework to track "LAM enabled"
>
> Robert Hoo (3):
>       KVM: x86: Virtualize LAM for supervisor pointer
>       KVM: x86: Virtualize LAM for user pointer
>       KVM: x86: Advertise and enable LAM (user and supervisor)
>
>  arch/x86/include/asm/kvm-x86-ops.h |  1 +
>  arch/x86/include/asm/kvm_host.h    |  5 +++-
>  arch/x86/kvm/cpuid.c               |  2 +-
>  arch/x86/kvm/cpuid.h               | 13 +++++----
>  arch/x86/kvm/emulate.c             | 27 ++++++++++---------
>  arch/x86/kvm/governed_features.h   |  1 +
>  arch/x86/kvm/kvm_emulate.h         |  9 +++++++
>  arch/x86/kvm/mmu.h                 |  8 ++++++
>  arch/x86/kvm/mmu/mmu.c             |  2 +-
>  arch/x86/kvm/mmu/mmu_internal.h    |  1 +
>  arch/x86/kvm/mmu/paging_tmpl.h     |  2 +-
>  arch/x86/kvm/svm/nested.c          |  4 +--
>  arch/x86/kvm/vmx/nested.c          | 11 +++++---
>  arch/x86/kvm/vmx/sgx.c             |  1 +
>  arch/x86/kvm/vmx/vmx.c             | 55 ++++++++++++++++++++++++++++++++++++--
>  arch/x86/kvm/vmx/vmx.h             |  2 ++
>  arch/x86/kvm/x86.c                 | 18 +++++++++++--
>  arch/x86/kvm/x86.h                 |  2 ++
>  18 files changed, 134 insertions(+), 30 deletions(-)
>
Binbin Wu Jan. 22, 2024, 7:57 a.m. UTC | #2
On 1/8/2024 9:04 PM, Paolo Bonzini wrote:
> On Thu, Jan 4, 2024 at 8:33 PM Sean Christopherson <seanjc@google.com> wrote:
>> LAM virtualization support.  FWIW, I intended to send this in early-ish
>> December as you've asked in the past, but December was basically a lost cause
>> for me in terms of doing upstream work.  :-/
>>
>> The following changes since commit e9e60c82fe391d04db55a91c733df4a017c28b2f:
>>
>>    selftests/kvm: fix compilation on non-x86_64 platforms (2023-11-21 11:58:25 -0500)
>>
>> are available in the Git repository at:
>>
>>    https://github.com/kvm-x86/linux.git tags/kvm-x86-lam-6.8
>>
>> for you to fetch changes up to 183bdd161c2b773a62f01d1c030f5a3a5b7c33b5:
>>
>>    KVM: x86: Use KVM-governed feature framework to track "LAM enabled" (2023-11-28 17:54:09 -0800)
> Patches are surprisingly small for this. What's the state of tests
> (https://www.spinics.net/lists/kvm/msg313712.html) though?

The patch series is tested by the LAM kselftest cases as well as
a set of test cases[1] in kvm-unit-tests.

[1] 
https://lore.kernel.org/kvm/20230530024356.24870-1-binbin.wu@linux.intel.com/
Will send a new version with minor change to resolve a feedback soon.


>
> Thanks,
>
> Paolo
>
>> ----------------------------------------------------------------
>> KVM x86 support for virtualizing Linear Address Masking (LAM)
>>
>> Add KVM support for Linear Address Masking (LAM).  LAM tweaks the canonicality
>> checks for most virtual address usage in 64-bit mode, such that only the most
>> significant bit of the untranslated address bits must match the polarity of the
>> last translated address bit.  This allows software to use ignored, untranslated
>> address bits for metadata, e.g. to efficiently tag pointers for address
>> sanitization.
>>
>> LAM can be enabled separately for user pointers and supervisor pointers, and
>> for userspace LAM can be select between 48-bit and 57-bit masking
>>
>>   - 48-bit LAM: metadata bits 62:48, i.e. LAM width of 15.
>>   - 57-bit LAM: metadata bits 62:57, i.e. LAM width of 6.
>>
>> For user pointers, LAM enabling utilizes two previously-reserved high bits from
>> CR3 (similar to how PCID_NOFLUSH uses bit 63): LAM_U48 and LAM_U57, bits 62 and
>> 61 respectively.  Note, if LAM_57 is set, LAM_U48 is ignored, i.e.:
>>
>>   - CR3.LAM_U48=0 && CR3.LAM_U57=0 == LAM disabled for user pointers
>>   - CR3.LAM_U48=1 && CR3.LAM_U57=0 == LAM-48 enabled for user pointers
>>   - CR3.LAM_U48=x && CR3.LAM_U57=1 == LAM-57 enabled for user pointers
>>
>> For supervisor pointers, LAM is controlled by a single bit, CR4.LAM_SUP, with
>> the 48-bit versus 57-bit LAM behavior following the current paging mode, i.e.:
>>
>>   - CR4.LAM_SUP=0 && CR4.LA57=x == LAM disabled for supervisor pointers
>>   - CR4.LAM_SUP=1 && CR4.LA57=0 == LAM-48 enabled for supervisor pointers
>>   - CR4.LAM_SUP=1 && CR4.LA57=1 == LAM-57 enabled for supervisor pointers
>>
>> The modified LAM canonicality checks:
>>   - LAM_S48                : [ 1 ][ metadata ][ 1 ]
>>                                63               47
>>   - LAM_U48                : [ 0 ][ metadata ][ 0 ]
>>                                63               47
>>   - LAM_S57                : [ 1 ][ metadata ][ 1 ]
>>                                63               56
>>   - LAM_U57 + 5-lvl paging : [ 0 ][ metadata ][ 0 ]
>>                                63               56
>>   - LAM_U57 + 4-lvl paging : [ 0 ][ metadata ][ 0...0 ]
>>                                63               56..47
>>
>> The bulk of KVM support for LAM is to emulate LAM's modified canonicality
>> checks.  The approach taken by KVM is to "fill" the metadata bits using the
>> highest bit of the translated address, e.g. for LAM-48, bit 47 is sign-extended
>> to bits 62:48.  The most significant bit, 63, is *not* modified, i.e. its value
>> from the raw, untagged virtual address is kept for the canonicality check. This
>> untagging allows
>>
>> Aside from emulating LAM's canonical checks behavior, LAM has the usual KVM
>> touchpoints for selectable features: enumeration (CPUID.7.1:EAX.LAM[bit 26],
>> enabling via CR3 and CR4 bits, etc.
>>
>> ----------------------------------------------------------------
>> Binbin Wu (9):
>>        KVM: x86: Consolidate flags for __linearize()
>>        KVM: x86: Add an emulation flag for implicit system access
>>        KVM: x86: Add X86EMUL_F_INVLPG and pass it in em_invlpg()
>>        KVM: x86/mmu: Drop non-PA bits when getting GFN for guest's PGD
>>        KVM: x86: Add & use kvm_vcpu_is_legal_cr3() to check CR3's legality
>>        KVM: x86: Remove kvm_vcpu_is_illegal_gpa()
>>        KVM: x86: Introduce get_untagged_addr() in kvm_x86_ops and call it in emulator
>>        KVM: x86: Untag addresses for LAM emulation where applicable
>>        KVM: x86: Use KVM-governed feature framework to track "LAM enabled"
>>
>> Robert Hoo (3):
>>        KVM: x86: Virtualize LAM for supervisor pointer
>>        KVM: x86: Virtualize LAM for user pointer
>>        KVM: x86: Advertise and enable LAM (user and supervisor)
>>
>>   arch/x86/include/asm/kvm-x86-ops.h |  1 +
>>   arch/x86/include/asm/kvm_host.h    |  5 +++-
>>   arch/x86/kvm/cpuid.c               |  2 +-
>>   arch/x86/kvm/cpuid.h               | 13 +++++----
>>   arch/x86/kvm/emulate.c             | 27 ++++++++++---------
>>   arch/x86/kvm/governed_features.h   |  1 +
>>   arch/x86/kvm/kvm_emulate.h         |  9 +++++++
>>   arch/x86/kvm/mmu.h                 |  8 ++++++
>>   arch/x86/kvm/mmu/mmu.c             |  2 +-
>>   arch/x86/kvm/mmu/mmu_internal.h    |  1 +
>>   arch/x86/kvm/mmu/paging_tmpl.h     |  2 +-
>>   arch/x86/kvm/svm/nested.c          |  4 +--
>>   arch/x86/kvm/vmx/nested.c          | 11 +++++---
>>   arch/x86/kvm/vmx/sgx.c             |  1 +
>>   arch/x86/kvm/vmx/vmx.c             | 55 ++++++++++++++++++++++++++++++++++++--
>>   arch/x86/kvm/vmx/vmx.h             |  2 ++
>>   arch/x86/kvm/x86.c                 | 18 +++++++++++--
>>   arch/x86/kvm/x86.h                 |  2 ++
>>   18 files changed, 134 insertions(+), 30 deletions(-)
>>
>