Secure Encrypted Virtualization (SEV) does not support string I/O, so
unroll the string I/O operation into a loop operating on one element at
a time.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
.../BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf | 3
.../Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm | 19 +++
.../Library/BaseIoLibIntrinsic/Ia32/SevIoFifo.nasm | 141 ++++++++++++++++++++
OvmfPkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm | 19 +++
.../Library/BaseIoLibIntrinsic/X64/SevIoFifo.nasm | 143 ++++++++++++++++++++
5 files changed, 324 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/SevIoFifo.nasm
create mode 100644 OvmfPkg/Library/BaseIoLibIntrinsic/X64/SevIoFifo.nasm
diff --git a/OvmfPkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf b/OvmfPkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
index 8844b1c..e7eeb59 100644
--- a/OvmfPkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+++ b/OvmfPkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
@@ -28,7 +28,6 @@
VERSION_STRING = 1.0
LIBRARY_CLASS = IoLib
-
#
# VALID_ARCHITECTURES = IA32 X64 EBC IPF ARM AARCH64
#
@@ -45,6 +44,7 @@
IoLib.c
Ia32/IoFifo.nasm
Ia32/IoFifo.asm
+ Ia32/SevIoFifo.nasm
[Sources.X64]
IoLibGcc.c | GCC
@@ -53,6 +53,7 @@
IoLib.c
X64/IoFifo.nasm
X64/IoFifo.asm
+ X64/SevIoFifo.nasm
[Sources.EBC]
IoLibEbc.c
diff --git a/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm b/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm
index bcaa743..fb585e6 100644
--- a/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm
+++ b/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm
@@ -13,6 +13,10 @@
;
;------------------------------------------------------------------------------
+ EXTERN ASM_PFX(SevIoReadFifo8)
+ EXTERN ASM_PFX(SevIoReadFifo16)
+ EXTERN ASM_PFX(SevIoReadFifo32)
+
SECTION .text
;------------------------------------------------------------------------------
@@ -31,7 +35,12 @@ ASM_PFX(IoReadFifo8):
mov dx, [esp + 8]
mov ecx, [esp + 12]
mov edi, [esp + 16]
+ call SevIoReadFifo8
+ cmp ecx, 0
+ jz IoReadFifo8Exit
rep insb
+
+IoReadFifo8Exit:
pop edi
ret
@@ -51,7 +60,12 @@ ASM_PFX(IoReadFifo16):
mov dx, [esp + 8]
mov ecx, [esp + 12]
mov edi, [esp + 16]
+ call SevIoReadFifo16
+ cmp ecx, 0
+ jz IoReadFifo16Exit
rep insw
+
+IoReadFifo16Exit:
pop edi
ret
@@ -71,7 +85,12 @@ ASM_PFX(IoReadFifo32):
mov dx, [esp + 8]
mov ecx, [esp + 12]
mov edi, [esp + 16]
+ call SevIoReadFifo32
+ cmp ecx, 0
+ jz IoReadFifo32Exit
rep insd
+
+IoReadFifo32Exit:
pop edi
ret
diff --git a/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/SevIoFifo.nasm b/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/SevIoFifo.nasm
new file mode 100644
index 0000000..ac6bee3
--- /dev/null
+++ b/OvmfPkg/Library/BaseIoLibIntrinsic/Ia32/SevIoFifo.nasm
@@ -0,0 +1,141 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+;
+; This program and the accompanying materials are licensed and made available
+; under the terms and conditions of the BSD License which accompanies this
+; distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;------------------------------------------------------------------------------
+
+%define KVM_FEATURE_SEV 8
+
+ SECTION .data
+SevCheckedOnce db 0
+SevStatus db 0
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; Check if Secure Encrypted Virtualization (SEV) feature
+; is enabled in KVM
+;
+; Return // eax (1 - active, 0 - not active)
+;------------------------------------------------------------------------------
+global ASM_PFX(CheckSevFeature)
+ASM_PFX(CheckSevFeature):
+ ; Check CPUID once, if its already checked then return SevStatus
+ mov eax, 1
+ cmp [SevCheckedOnce], eax
+ jz SevFeatureCheckExit
+
+ ; Start the SEV feature check
+ mov [SevCheckedOnce], eax
+
+ ; CPUID clobbers ebx, ecx and edx
+ push ebx
+ push ecx
+ push edx
+
+ mov eax, 0x40000001
+ cpuid
+
+ bt eax, KVM_FEATURE_SEV
+ jnc SevCheckExit
+
+ ; Check for memory encryption feature:
+ ; CPUID Fn8000_001F[EAX] - Bit 0
+ ;
+ mov eax, 0x8000001f
+ cpuid
+ bt eax, 0
+ jnc SevCheckExit
+ mov eax, 1
+ mov [SevStatus], eax
+
+SevCheckExit:
+ pop edx
+ pop ecx
+ pop ebx
+
+SevFeatureCheckExit:
+ mov eax, [SevStatus]
+ ret
+
+;------------------------------------------------------------------------------
+; unroll 'rep ins' String I/O instructions when SEV is active
+; nothing
+;
+; Port // dx
+; Size // ecx
+; Buffer // rdi
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(SevIoReadFifo8)
+ASM_PFX(SevIoReadFifo8):
+ call CheckSevFeature
+ cmp eax, 1
+ jnz ReadFifo8Exit
+ReadFifo8Loop:
+ cmp ecx, 0
+ jz ReadFifo8Exit
+ in al, dx
+ mov [edi], al
+ dec ecx
+ inc edi
+ jmp ReadFifo8Loop
+ReadFifo8Exit:
+ ret
+
+;------------------------------------------------------------------------------
+; unroll 'rep insw' String I/O instructions when SEV is active
+;
+; Port // dx
+; Size // ecx
+; Buffer // rdi
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(SevIoReadFifo16)
+ASM_PFX(SevIoReadFifo16):
+ call CheckSevFeature
+ cmp eax, 1
+ jnz ReadFifo16Exit
+ReadFifo16Loop:
+ cmp ecx, 0
+ jz ReadFifo16Exit
+ in ax, dx
+ mov [edi], ax
+ dec ecx
+ add edi, 2
+ jmp ReadFifo16Loop
+ReadFifo16Exit:
+ ret
+
+;------------------------------------------------------------------------------
+; unroll 'rep insl' String I/O instructions when SEV is active
+;
+; Port // dx
+; Size // ecx
+; Buffer // rdi
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(SevIoReadFifo32)
+ASM_PFX(SevIoReadFifo32):
+ call CheckSevFeature
+ cmp eax, 1
+ jnz ReadFifo32Exit
+ReadFifo32Loop:
+ cmp ecx, 0
+ jz ReadFifo32Exit
+ in eax, dx
+ mov [edi], eax
+ dec ecx
+ add edi, 4
+ jmp ReadFifo32Loop
+ReadFifo32Exit:
+ ret
+
diff --git a/OvmfPkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm b/OvmfPkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm
index 7bd72d0..71fbe62 100644
--- a/OvmfPkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm
+++ b/OvmfPkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm
@@ -13,6 +13,10 @@
;
;------------------------------------------------------------------------------
+ EXTERN ASM_PFX(SevIoReadFifo8)
+ EXTERN ASM_PFX(SevIoReadFifo16)
+ EXTERN ASM_PFX(SevIoReadFifo32)
+
DEFAULT REL
SECTION .text
@@ -30,7 +34,12 @@ ASM_PFX(IoReadFifo8):
cld
xchg rcx, rdx
xchg rdi, r8 ; rdi: buffer address; r8: save rdi
+ call SevIoReadFifo8
+ cmp ecx, 0
+ jz IoReadFifo8Exit
rep insb
+
+IoReadFifo8Exit:
mov rdi, r8 ; restore rdi
ret
@@ -48,7 +57,12 @@ ASM_PFX(IoReadFifo16):
cld
xchg rcx, rdx
xchg rdi, r8 ; rdi: buffer address; r8: save rdi
+ call SevIoReadFifo16
+ cmp ecx, 0
+ jz IoReadFifo16Exit
rep insw
+
+IoReadFifo16Exit:
mov rdi, r8 ; restore rdi
ret
@@ -66,7 +80,12 @@ ASM_PFX(IoReadFifo32):
cld
xchg rcx, rdx
xchg rdi, r8 ; rdi: buffer address; r8: save rdi
+ call SevIoReadFifo32
+ cmp ecx, 0
+ jz IoReadFifo32Exit
rep insd
+
+IoReadFifo32Exit:
mov rdi, r8 ; restore rdi
ret
diff --git a/OvmfPkg/Library/BaseIoLibIntrinsic/X64/SevIoFifo.nasm b/OvmfPkg/Library/BaseIoLibIntrinsic/X64/SevIoFifo.nasm
new file mode 100644
index 0000000..5e70cb6
--- /dev/null
+++ b/OvmfPkg/Library/BaseIoLibIntrinsic/X64/SevIoFifo.nasm
@@ -0,0 +1,143 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+;
+; This program and the accompanying materials are licensed and made available
+; under the terms and conditions of the BSD License which accompanies this
+; distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;------------------------------------------------------------------------------
+
+%define KVM_FEATURE_SEV 8
+
+ EXTERN ASM_PFX(SevEnabled)
+
+ SECTION .data
+SevCheckedOnce db 0
+SevStatus db 0
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; Check if Secure Encrypted Virtualization (SEV) feature
+; is enabled in KVM
+;
+; Return // eax (1 - active, 0 - not active)
+;------------------------------------------------------------------------------
+global ASM_PFX(CheckSevFeature)
+ASM_PFX(CheckSevFeature):
+ ; Check CPUID once, if its already checked then return SevStatus
+ mov eax, 1
+ cmp [SevCheckedOnce], eax
+ jz SevFeatureCheckExit
+
+ ; Start the SEV feature check
+ mov [SevCheckedOnce], eax
+
+ ; CPUID clobbers ebx, ecx and edx
+ push rbx
+ push rcx
+ push rdx
+
+ mov eax, 0x40000001
+ cpuid
+
+ bt eax, KVM_FEATURE_SEV
+ jnc SevCheckExit
+
+ ; Check for memory encryption feature:
+ ; CPUID Fn8000_001F[EAX] - Bit 0
+ ;
+ mov eax, 0x8000001f
+ cpuid
+ bt eax, 0
+ jnc SevCheckExit
+ mov eax, 1
+ mov [SevStatus], eax
+
+SevCheckExit:
+ pop rdx
+ pop rcx
+ pop rbx
+
+SevFeatureCheckExit:
+ mov eax, [SevStatus]
+ ret
+
+;------------------------------------------------------------------------------
+; unroll 'rep ins' String I/O instructions when SEV is active
+; nothing
+;
+; Port // dx
+; Size // ecx
+; Buffer // rdi
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(SevIoReadFifo8)
+ASM_PFX(SevIoReadFifo8):
+ call CheckSevFeature
+ cmp eax, 1
+ jnz ReadFifo8Exit
+ReadFifo8Loop:
+ cmp ecx, 0
+ jz ReadFifo8Exit
+ in al, dx
+ mov [edi], al
+ dec ecx
+ inc edi
+ jmp ReadFifo8Loop
+ReadFifo8Exit:
+ ret
+
+;------------------------------------------------------------------------------
+; unroll 'rep insw' String I/O instructions when SEV is active
+;
+; Port // dx
+; Size // ecx
+; Buffer // rdi
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(SevIoReadFifo16)
+ASM_PFX(SevIoReadFifo16):
+ call CheckSevFeature
+ cmp eax, 1
+ jnz ReadFifo16Exit
+ReadFifo16Loop:
+ cmp ecx, 0
+ jz ReadFifo16Exit
+ in ax, dx
+ mov [edi], ax
+ dec ecx
+ add edi, 2
+ jmp ReadFifo16Loop
+ReadFifo16Exit:
+ ret
+
+;------------------------------------------------------------------------------
+; unroll 'rep insl' String I/O instructions when SEV is active
+;
+; Port // dx
+; Size // ecx
+; Buffer // rdi
+;
+;------------------------------------------------------------------------------
+global ASM_PFX(SevIoReadFifo32)
+ASM_PFX(SevIoReadFifo32):
+ call CheckSevFeature
+ cmp eax, 1
+ jnz ReadFifo32Exit
+ReadFifo32Loop:
+ cmp ecx, 0
+ jz ReadFifo32Exit
+ in eax, dx
+ mov [edi], eax
+ dec ecx
+ add edi, 4
+ jmp ReadFifo32Loop
+ReadFifo32Exit:
+ ret
+
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.