From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-DM6-obe.outbound.protection.outlook.com (NAM12-DM6-obe.outbound.protection.outlook.com [40.107.243.74]) by mx.groups.io with SMTP id smtpd.web10.10755.1591363684004337805 for ; Fri, 05 Jun 2020 06:28:04 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amdcloud.onmicrosoft.com header.s=selector2-amdcloud-onmicrosoft-com header.b=nAXLPxj0; spf=none, err=SPF record not found (domain: amd.com, ip: 40.107.243.74, mailfrom: thomas.lendacky@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=PydiE+TVViWGESnBvm1WcsC0TtpbAAk3nK+84YCNt0rgDYX5CGA+a97ipH2hfQGNEQ99VvY9DPv8a3wF9PiJVZRvGPYuGqGJ/5jGiv24Ve6/gISGCgYSbl27tRlCWyzo5zWqCBJwz2mC+/LyRihwcntSwOJFM4EwHDkUPOvZAfk9nyc505Ei2nBrT4fabFgMEv27mbva9pvmZZ/elWfXznHB0KhrXi30AauKAIWo373EU0/WHRYmz+AcM+K8Y0L8xV1r5a8scPQCK4VxZPArqYL/qirYB8UYsfwVian4dC2iD0alnYGxW9EpyU7QC1YQr3/sJ5AO3ZbYoa9j0reBlg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1HCrifxrUg2GTFgVpzX2YRhHTCtpinqGBlENeWCPo/U=; b=A+QYl4yaNwH10pRErYt9QHxLqnDSZQGr6Vit0bbdlyci/x5HkE7V8X1S/JoCGz8hE2zzwKMj45u+MJVY5qxA+5wPGSFrVO6LRCtNYQM8FuEJM/WRzz3/kHqFtdwLs3RzksNii+kFg/pGPd2Mo0EdY7R7IZQzp1i6tMHEgYWZFsohMqDbzuxR84Vp4WRHgc8yvmeSolEg2K0sJg4xFSeEe0ZwweDr5Tb9Ag1we69znSYPHDScyrSlH35w50yC4YRB/PJRTQctUyqdAX4LBd8opgRTTYCiZ6rYO4rc7rgSG88PLoe+XyINGj7SNC/3RoLBVIoNbCbvCpYP0ST/mwjscg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1HCrifxrUg2GTFgVpzX2YRhHTCtpinqGBlENeWCPo/U=; b=nAXLPxj0tklPjVtr/t+ASIXPBa81f7izUPb3+laV+5BIyOyzGeWiSeR86ZMltIr2x7I2YRbSix9QnRt8K7sUmF6uN6YMLnFPi4Hsbk2qfI9Z6AADRXDUoBONJU8KIliJv84wbTdQw5+n+aVW7QNIWUxPohANfld1lb2LbMSDB9s= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=amd.com; Received: from DM5PR12MB1355.namprd12.prod.outlook.com (2603:10b6:3:6e::7) by DM5PR12MB1354.namprd12.prod.outlook.com (2603:10b6:3:7a::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3066.20; Fri, 5 Jun 2020 13:28:02 +0000 Received: from DM5PR12MB1355.namprd12.prod.outlook.com ([fe80::4ce1:9947:9681:c8b1]) by DM5PR12MB1355.namprd12.prod.outlook.com ([fe80::4ce1:9947:9681:c8b1%10]) with mapi id 15.20.3066.019; Fri, 5 Jun 2020 13:28:02 +0000 From: "Lendacky, Thomas" To: devel@edk2.groups.io Cc: Brijesh Singh , Ard Biesheuvel , Eric Dong , Jordan Justen , Laszlo Ersek , Liming Gao , Michael D Kinney , Ray Ni Subject: [PATCH v9 13/46] OvmfPkg/VmgExitLib: Add support for IOIO_PROT NAE events Date: Fri, 5 Jun 2020 08:27:04 -0500 Message-Id: <7b771ecff3a75639add17bf8a7753519bff05143.1591363657.git.thomas.lendacky@amd.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: X-ClientProxiedBy: DM5PR19CA0060.namprd19.prod.outlook.com (2603:10b6:3:116::22) To DM5PR12MB1355.namprd12.prod.outlook.com (2603:10b6:3:6e::7) Return-Path: thomas.lendacky@amd.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from tlendack-t1.amd.com (165.204.77.1) by DM5PR19CA0060.namprd19.prod.outlook.com (2603:10b6:3:116::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3066.18 via Frontend Transport; Fri, 5 Jun 2020 13:28:01 +0000 X-Mailer: git-send-email 2.27.0 X-Originating-IP: [165.204.77.1] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 1fd325a5-e405-4c7d-d188-08d80954456d X-MS-TrafficTypeDiagnostic: DM5PR12MB1354: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:7219; X-Forefront-PRVS: 0425A67DEF X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ZdBGH9rZRr3xWkQ0Kizga+rLzri5vznDGUWNwiexcAjpx/aZXWqG3muq/6LzfB7LFSW34wD7qca0gY/rzQu6iH4z8Fj5ni/BBJD7pSQG7MK6C6urGXl1lUG0wlOY085/N3rhh36TfLSvoVlLlr0Dz5YON/7fdaXURfexD8rV6h/1gI/ha41y6iUJTrQibQIa5hYjUmm48JyzsspOoNWtD4N4+SQ1mt4Snceh9ZVt4QKZBVO0QBukRO+GnMw81+jrUb5k3GQr9XjU6kyFcaq8KR0eYoF+C3fZKbcBhBg+MNunf789UiJkqeTAhKio668PB//7KIkXnDICiLuKaPATczgB2ed3GccVwUUfxgb/7Cmmuskm3FrDq99vTwkf9z4pv+uHcW98m15E87moJ5cKkF/YM6f5zs8yk2bZoO56m0vZsfD65RKDs+zYHoXP6nKlH5qQAi3qRBRE6luxv8bBNw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM5PR12MB1355.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(346002)(39860400002)(376002)(366004)(396003)(136003)(30864003)(52116002)(83380400001)(26005)(316002)(7696005)(54906003)(6486002)(478600001)(956004)(16526019)(86362001)(4326008)(36756003)(2616005)(966005)(6916009)(2906002)(8936002)(5660300002)(8676002)(66476007)(66946007)(66556008)(186003)(136400200001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: l//apjKs8IR/v3xoT6P3L/ozaB5C9FXVPCpUiJ5/v/WBTyghCHKir/1hn9IQg4hFXzih7lKPD7aXhXePiMuVOfSLB9qKywzTRjyiwZUAyYbRUh7/m0IXKSEk7kDeXLm00sXVkcG4OHqWqzOUAUeee6KMpsJW2M0I1n3K0FpgxGgeiLQpd8en6c4UGr8Ueftd2WFsydh3XUgk2lV+KdVb9RyW4KmpxeWIqO1H3M/byza3VBgB201eZ07TiR06RZ4clnXo99Bv+DV/0jKC9slgKzhN/G7MrAChcsORDE4xFa/r5+KZkJu3QxY0XKDr2xLoZc0jrXQyP5InEvixIZkhvCAeOEn6YHdNKgEBvHo+HrtmAKxEwQJ4Xxya8YY4cZHnw93UizM6/F7G+PE9unTizAZf1Zc6u81LbXvURgk6JHHjkwl9wvqiIWjsjbnyyRZbvmv25safn5j0sZNkp/q7wJ6dW39HhFYv6y4gkBpa/mo= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1fd325a5-e405-4c7d-d188-08d80954456d X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Jun 2020 13:28:02.2751 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 7lXyCc2b8ptRdREWB5Phwq7Nj3ceqEZP3vuz8XfxIyNIlYyA1T78DaHW8ZAY1EODs//qZh7TjU0XR8KgFQe/vQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB1354 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2198 Under SEV-ES, a IOIO_PROT intercept generates a #VC exception. VMGEXIT must be used to allow the hypervisor to handle this intercept. Add support to construct the required GHCB values to support a IOIO_PROT NAE event. Parse the instruction that generated the #VC exception, setting the required register values in the GHCB and creating the proper SW_EXITINFO1 value in the GHCB. Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Tom Lendacky --- OvmfPkg/Include/IndustryStandard/InstructionParsing.h | 83 +++ OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 560 ++++++++++++++= +++++- 2 files changed, 629 insertions(+), 14 deletions(-) diff --git a/OvmfPkg/Include/IndustryStandard/InstructionParsing.h b/OvmfPk= g/Include/IndustryStandard/InstructionParsing.h new file mode 100644 index 000000000000..149ff328e06c --- /dev/null +++ b/OvmfPkg/Include/IndustryStandard/InstructionParsing.h @@ -0,0 +1,83 @@ +/** @file=0D + Instruction parsing support definitions.=0D +=0D + Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef __INSTRUCTION_PARSING_H__=0D +#define __INSTRUCTION_PARSING_H__=0D +=0D +#include =0D +#include =0D +=0D +//=0D +// Instruction REX prefix definition=0D +//=0D +typedef union {=0D + struct {=0D + UINT8 BitB:1;=0D + UINT8 BitX:1;=0D + UINT8 BitR:1;=0D + UINT8 BitW:1;=0D + UINT8 Rex:4;=0D + } Bits;=0D +=0D + UINT8 Uint8;=0D +} INSTRUCTION_REX_PREFIX;=0D +=0D +//=0D +// Instruction ModRM definition=0D +//=0D +typedef union {=0D + struct {=0D + UINT8 Rm:3;=0D + UINT8 Reg:3;=0D + UINT8 Mod:2;=0D + } Bits;=0D +=0D + UINT8 Uint8;=0D +} INSTRUCTION_MODRM;=0D +=0D +//=0D +// Instruction SIB definition=0D +//=0D +typedef union {=0D + struct {=0D + UINT8 Base:3;=0D + UINT8 Index:3;=0D + UINT8 Scale:2;=0D + } Bits;=0D +=0D + UINT8 Uint8;=0D +} INSTRUCTION_SIB;=0D +=0D +//=0D +// Legacy Instruction Prefixes=0D +//=0D +#define OVERRIDE_SEGMENT_CS 0x2E=0D +#define OVERRIDE_SEGMENT_DS 0x3E=0D +#define OVERRIDE_SEGMENT_ES 0x26=0D +#define OVERRIDE_SEGMENT_SS 0x36=0D +#define OVERRIDE_SEGMENT_FS 0x64=0D +#define OVERRIDE_SEGMENT_GS 0x65=0D +#define OVERRIDE_OPERAND_SIZE 0x66=0D +#define OVERRIDE_ADDRESS_SIZE 0x67=0D +#define LOCK_PREFIX 0xF0=0D +#define REPNZ_PREFIX 0xF2=0D +#define REPZ_PREFIX 0xF3=0D +=0D +//=0D +// REX Prefixes=0D +//=0D +#define REX_PREFIX_START 0x40=0D +#define REX_PREFIX_STOP 0x4F=0D +#define REX_64BIT_OPERAND_SIZE_MASK 0x08=0D +=0D +//=0D +// Two-byte Opcode Flag=0D +//=0D +#define TWO_BYTE_OPCODE_ESCAPE 0x0F=0D +=0D +#endif=0D diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Librar= y/VmgExitLib/VmgExitVcHandler.c index b6a955ed8088..7c2bb12df10a 100644 --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c @@ -11,6 +11,529 @@ #include =0D #include =0D #include =0D +#include =0D +=0D +//=0D +// Instruction execution mode definition=0D +//=0D +typedef enum {=0D + LongMode64Bit =3D 0,=0D + LongModeCompat32Bit,=0D + LongModeCompat16Bit,=0D +} SEV_ES_INSTRUCTION_MODE;=0D +=0D +//=0D +// Instruction size definition (for operand and address)=0D +//=0D +typedef enum {=0D + Size8Bits =3D 0,=0D + Size16Bits,=0D + Size32Bits,=0D + Size64Bits,=0D +} SEV_ES_INSTRUCTION_SIZE;=0D +=0D +//=0D +// Intruction segment definition=0D +//=0D +typedef enum {=0D + SegmentEs =3D 0,=0D + SegmentCs,=0D + SegmentSs,=0D + SegmentDs,=0D + SegmentFs,=0D + SegmentGs,=0D +} SEV_ES_INSTRUCTION_SEGMENT;=0D +=0D +//=0D +// Instruction rep function definition=0D +//=0D +typedef enum {=0D + RepNone =3D 0,=0D + RepZ,=0D + RepNZ,=0D +} SEV_ES_INSTRUCTION_REP;=0D +=0D +typedef struct {=0D + UINT8 Rm;=0D + UINT8 Reg;=0D + UINT8 Mod;=0D +} SEV_ES_INSTRUCTION_MODRM_EXT;=0D +=0D +typedef struct {=0D + UINT8 Base;=0D + UINT8 Index;=0D + UINT8 Scale;=0D +} SEV_ES_INSTRUCTION_SIB_EXT;=0D +=0D +//=0D +// Instruction opcode definition=0D +//=0D +typedef struct {=0D + SEV_ES_INSTRUCTION_MODRM_EXT ModRm;=0D +=0D + SEV_ES_INSTRUCTION_SIB_EXT Sib;=0D +=0D + UINTN RegData;=0D + UINTN RmData;=0D +} SEV_ES_INSTRUCTION_OPCODE_EXT;=0D +=0D +//=0D +// Instruction parsing context definition=0D +//=0D +typedef struct {=0D + GHCB *Ghcb;=0D +=0D + SEV_ES_INSTRUCTION_MODE Mode;=0D + SEV_ES_INSTRUCTION_SIZE DataSize;=0D + SEV_ES_INSTRUCTION_SIZE AddrSize;=0D + BOOLEAN SegmentSpecified;=0D + SEV_ES_INSTRUCTION_SEGMENT Segment;=0D + SEV_ES_INSTRUCTION_REP RepMode;=0D +=0D + UINT8 *Begin;=0D + UINT8 *End;=0D +=0D + UINT8 *Prefixes;=0D + UINT8 *OpCodes;=0D + UINT8 *Displacement;=0D + UINT8 *Immediate;=0D +=0D + INSTRUCTION_REX_PREFIX RexPrefix;=0D +=0D + BOOLEAN ModRmPresent;=0D + INSTRUCTION_MODRM ModRm;=0D +=0D + BOOLEAN SibPresent;=0D + INSTRUCTION_SIB Sib;=0D +=0D + UINTN PrefixSize;=0D + UINTN OpCodeSize;=0D + UINTN DisplacementSize;=0D + UINTN ImmediateSize;=0D +=0D + SEV_ES_INSTRUCTION_OPCODE_EXT Ext;=0D +} SEV_ES_INSTRUCTION_DATA;=0D +=0D +//=0D +// Non-automatic Exit function prototype=0D +//=0D +typedef=0D +UINT64=0D +(*NAE_EXIT) (=0D + GHCB *Ghcb,=0D + EFI_SYSTEM_CONTEXT_X64 *Regs,=0D + SEV_ES_INSTRUCTION_DATA *InstructionData=0D + );=0D +=0D +=0D +/**=0D + Checks the GHCB to determine if the specified register has been marked v= alid.=0D +=0D + The ValidBitmap area represents the areas of the GHCB that have been mar= ked=0D + valid. Return an indication of whether the area of the GHCB that holds t= he=0D + specified register has been marked valid.=0D +=0D + @param[in] Ghcb Pointer to the Guest-Hypervisor Communication Block=0D + @param[in] Reg Offset in the GHCB of the register to check=0D +=0D + @retval TRUE Register has been marked vald in the GHCB=0D + @retval FALSE Register has not been marked valid in the GHCB=0D +=0D +**/=0D +STATIC=0D +BOOLEAN=0D +GhcbIsRegValid (=0D + IN GHCB *Ghcb,=0D + IN GHCB_REGISTER Reg=0D + )=0D +{=0D + UINT32 RegIndex;=0D + UINT32 RegBit;=0D +=0D + RegIndex =3D Reg / 8;=0D + RegBit =3D Reg & 0x07;=0D +=0D + return ((Ghcb->SaveArea.ValidBitmap[RegIndex] & (1 << RegBit)) !=3D 0);= =0D +}=0D +=0D +/**=0D + Marks a register as valid in the GHCB.=0D +=0D + The ValidBitmap area represents the areas of the GHCB that have been mar= ked=0D + valid. Set the area of the GHCB that holds the specified register as val= id.=0D +=0D + @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication Bl= ock=0D + @param[in] Reg Offset in the GHCB of the register to mark valid= =0D +=0D +**/=0D +STATIC=0D +VOID=0D +GhcbSetRegValid (=0D + IN OUT GHCB *Ghcb,=0D + IN GHCB_REGISTER Reg=0D + )=0D +{=0D + UINT32 RegIndex;=0D + UINT32 RegBit;=0D +=0D + RegIndex =3D Reg / 8;=0D + RegBit =3D Reg & 0x07;=0D +=0D + Ghcb->SaveArea.ValidBitmap[RegIndex] |=3D (1 << RegBit);=0D +}=0D +=0D +/**=0D + Decode instruction prefixes.=0D +=0D + Parse the instruction data to track the instruction prefixes that have=0D + been used.=0D +=0D + @param[in] Regs x64 processor context=0D + @param[in, out] InstructionData Instruction parsing context=0D +=0D +**/=0D +STATIC=0D +VOID=0D +DecodePrefixes (=0D + IN EFI_SYSTEM_CONTEXT_X64 *Regs,=0D + IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData=0D + )=0D +{=0D + SEV_ES_INSTRUCTION_MODE Mode;=0D + SEV_ES_INSTRUCTION_SIZE ModeDataSize;=0D + SEV_ES_INSTRUCTION_SIZE ModeAddrSize;=0D + UINT8 *Byte;=0D +=0D + //=0D + // Always in 64-bit mode=0D + //=0D + Mode =3D LongMode64Bit;=0D + ModeDataSize =3D Size32Bits;=0D + ModeAddrSize =3D Size64Bits;=0D +=0D + InstructionData->Mode =3D Mode;=0D + InstructionData->DataSize =3D ModeDataSize;=0D + InstructionData->AddrSize =3D ModeAddrSize;=0D +=0D + InstructionData->Prefixes =3D InstructionData->Begin;=0D +=0D + Byte =3D InstructionData->Prefixes;=0D + for ( ; ; Byte++, InstructionData->PrefixSize++) {=0D + //=0D + // Check the 0x40 to 0x4F range using an if statement here since some= =0D + // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids= =0D + // 16 case statements below.=0D + //=0D + if ((*Byte >=3D REX_PREFIX_START) && (*Byte <=3D REX_PREFIX_STOP)) {=0D + InstructionData->RexPrefix.Uint8 =3D *Byte;=0D + if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) !=3D 0) {=0D + InstructionData->DataSize =3D Size64Bits;=0D + }=0D + continue;=0D + }=0D +=0D + switch (*Byte) {=0D + case OVERRIDE_SEGMENT_CS:=0D + case OVERRIDE_SEGMENT_DS:=0D + case OVERRIDE_SEGMENT_ES:=0D + case OVERRIDE_SEGMENT_SS:=0D + if (Mode !=3D LongMode64Bit) {=0D + InstructionData->SegmentSpecified =3D TRUE;=0D + InstructionData->Segment =3D (*Byte >> 3) & 3;=0D + }=0D + break;=0D +=0D + case OVERRIDE_SEGMENT_FS:=0D + case OVERRIDE_SEGMENT_GS:=0D + InstructionData->SegmentSpecified =3D TRUE;=0D + InstructionData->Segment =3D *Byte & 7;=0D + break;=0D +=0D + case OVERRIDE_OPERAND_SIZE:=0D + if (InstructionData->RexPrefix.Uint8 =3D=3D 0) {=0D + InstructionData->DataSize =3D=0D + (Mode =3D=3D LongMode64Bit) ? Size16Bits :=0D + (Mode =3D=3D LongModeCompat32Bit) ? Size16Bits :=0D + (Mode =3D=3D LongModeCompat16Bit) ? Size32Bits : 0;=0D + }=0D + break;=0D +=0D + case OVERRIDE_ADDRESS_SIZE:=0D + InstructionData->AddrSize =3D=0D + (Mode =3D=3D LongMode64Bit) ? Size32Bits :=0D + (Mode =3D=3D LongModeCompat32Bit) ? Size16Bits :=0D + (Mode =3D=3D LongModeCompat16Bit) ? Size32Bits : 0;=0D + break;=0D +=0D + case LOCK_PREFIX:=0D + break;=0D +=0D + case REPZ_PREFIX:=0D + InstructionData->RepMode =3D RepZ;=0D + break;=0D +=0D + case REPNZ_PREFIX:=0D + InstructionData->RepMode =3D RepNZ;=0D + break;=0D +=0D + default:=0D + InstructionData->OpCodes =3D Byte;=0D + InstructionData->OpCodeSize =3D (*Byte =3D=3D TWO_BYTE_OPCODE_ESCAPE= ) ? 2 : 1;=0D +=0D + InstructionData->End =3D Byte + InstructionData->OpCodeSize;=0D + InstructionData->Displacement =3D InstructionData->End;=0D + InstructionData->Immediate =3D InstructionData->End;=0D + return;=0D + }=0D + }=0D +}=0D +=0D +/**=0D + Determine instruction length=0D +=0D + Return the total length of the parsed instruction.=0D +=0D + @param[in] InstructionData Instruction parsing context=0D +=0D + @return Length of parsed instruction=0D +=0D +**/=0D +STATIC=0D +UINT64=0D +InstructionLength (=0D + IN SEV_ES_INSTRUCTION_DATA *InstructionData=0D + )=0D +{=0D + return (UINT64) (InstructionData->End - InstructionData->Begin);=0D +}=0D +=0D +/**=0D + Initialize the instruction parsing context.=0D +=0D + Initialize the instruction parsing context, which includes decoding the= =0D + instruction prefixes.=0D +=0D + @param[in, out] InstructionData Instruction parsing context=0D + @param[in] Ghcb Pointer to the Guest-Hypervisor Communi= cation=0D + Block=0D + @param[in] Regs x64 processor context=0D +=0D +**/=0D +STATIC=0D +VOID=0D +InitInstructionData (=0D + IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData,=0D + IN GHCB *Ghcb,=0D + IN EFI_SYSTEM_CONTEXT_X64 *Regs=0D + )=0D +{=0D + SetMem (InstructionData, sizeof (*InstructionData), 0);=0D + InstructionData->Ghcb =3D Ghcb;=0D + InstructionData->Begin =3D (UINT8 *) Regs->Rip;=0D + InstructionData->End =3D (UINT8 *) Regs->Rip;=0D +=0D + DecodePrefixes (Regs, InstructionData);=0D +}=0D +=0D +/**=0D + Report an unsupported event to the hypervisor=0D +=0D + Use the VMGEXIT support to report an unsupported event to the hypervisor= .=0D +=0D + @param[in] Ghcb Pointer to the Guest-Hypervisor Communicatio= n=0D + Block=0D + @param[in] Regs x64 processor context=0D + @param[in] InstructionData Instruction parsing context=0D +=0D + @return New exception value to propagate=0D +=0D +**/=0D +STATIC=0D +UINT64=0D +UnsupportedExit (=0D + IN GHCB *Ghcb,=0D + IN EFI_SYSTEM_CONTEXT_X64 *Regs,=0D + IN SEV_ES_INSTRUCTION_DATA *InstructionData=0D + )=0D +{=0D + UINT64 Status;=0D +=0D + Status =3D VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);= =0D + if (Status =3D=3D 0) {=0D + GHCB_EVENT_INJECTION Event;=0D +=0D + Event.Uint64 =3D 0;=0D + Event.Elements.Vector =3D GP_EXCEPTION;=0D + Event.Elements.Type =3D GHCB_EVENT_INJECTION_TYPE_EXCEPTION;=0D + Event.Elements.Valid =3D 1;=0D +=0D + Status =3D Event.Uint64;=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Build the IOIO event information.=0D +=0D + The IOIO event information identifies the type of IO operation to be per= formed=0D + by the hypervisor. Build this information based on the instruction data.= =0D +=0D + @param[in] Regs x64 processor context=0D + @param[in, out] InstructionData Instruction parsing context=0D +=0D + @return IOIO event information value=0D +=0D +**/=0D +STATIC=0D +UINT64=0D +IoioExitInfo (=0D + IN EFI_SYSTEM_CONTEXT_X64 *Regs,=0D + IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData=0D + )=0D +{=0D + UINT64 ExitInfo;=0D +=0D + ExitInfo =3D 0;=0D +=0D + switch (*(InstructionData->OpCodes)) {=0D + //=0D + // IN immediate opcodes=0D + //=0D + case 0xE4:=0D + case 0xE5:=0D + InstructionData->ImmediateSize =3D 1;=0D + InstructionData->End++;=0D + ExitInfo |=3D IOIO_TYPE_IN;=0D + ExitInfo |=3D ((*(InstructionData->OpCodes + 1)) << 16);=0D + break;=0D +=0D + //=0D + // OUT immediate opcodes=0D + //=0D + case 0xE6:=0D + case 0xE7:=0D + InstructionData->ImmediateSize =3D 1;=0D + InstructionData->End++;=0D + ExitInfo |=3D IOIO_TYPE_OUT;=0D + ExitInfo |=3D ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OU= T;=0D + break;=0D +=0D + //=0D + // IN register opcodes=0D + //=0D + case 0xEC:=0D + case 0xED:=0D + ExitInfo |=3D IOIO_TYPE_IN;=0D + ExitInfo |=3D ((Regs->Rdx & 0xffff) << 16);=0D + break;=0D +=0D + //=0D + // OUT register opcodes=0D + //=0D + case 0xEE:=0D + case 0xEF:=0D + ExitInfo |=3D IOIO_TYPE_OUT;=0D + ExitInfo |=3D ((Regs->Rdx & 0xffff) << 16);=0D + break;=0D +=0D + default:=0D + return 0;=0D + }=0D +=0D + switch (*(InstructionData->OpCodes)) {=0D + //=0D + // Single-byte opcodes=0D + //=0D + case 0xE4:=0D + case 0xE6:=0D + case 0xEC:=0D + case 0xEE:=0D + ExitInfo |=3D IOIO_DATA_8;=0D + break;=0D +=0D + //=0D + // Length determined by instruction parsing=0D + //=0D + default:=0D + ExitInfo |=3D (InstructionData->DataSize =3D=3D Size16Bits) ? IOIO_DAT= A_16=0D + : IOIO_DATA_32;= =0D + }=0D +=0D + switch (InstructionData->AddrSize) {=0D + case Size16Bits:=0D + ExitInfo |=3D IOIO_ADDR_16;=0D + break;=0D +=0D + case Size32Bits:=0D + ExitInfo |=3D IOIO_ADDR_32;=0D + break;=0D +=0D + case Size64Bits:=0D + ExitInfo |=3D IOIO_ADDR_64;=0D + break;=0D +=0D + default:=0D + break;=0D + }=0D +=0D + if (InstructionData->RepMode !=3D 0) {=0D + ExitInfo |=3D IOIO_REP;=0D + }=0D +=0D + return ExitInfo;=0D +}=0D +=0D +/**=0D + Handle an IOIO event.=0D +=0D + Use the VMGEXIT instruction to handle an IOIO event.=0D +=0D + @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation=0D + Block=0D + @param[in, out] Regs x64 processor context=0D + @param[in] InstructionData Instruction parsing context=0D +=0D + @return 0 Event handled successfully=0D + @return Others New exception value to propagate=0D +=0D +**/=0D +STATIC=0D +UINT64=0D +IoioExit (=0D + IN OUT GHCB *Ghcb,=0D + IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,=0D + IN SEV_ES_INSTRUCTION_DATA *InstructionData=0D + )=0D +{=0D + UINT64 ExitInfo1, Status;=0D +=0D + ExitInfo1 =3D IoioExitInfo (Regs, InstructionData);=0D + if (ExitInfo1 =3D=3D 0) {=0D + return UnsupportedExit (Ghcb, Regs, InstructionData);=0D + }=0D +=0D + if ((ExitInfo1 & IOIO_TYPE_IN) !=3D 0) {=0D + Ghcb->SaveArea.Rax =3D 0;=0D + } else {=0D + CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1))= ;=0D + }=0D + GhcbSetRegValid (Ghcb, GhcbRax);=0D +=0D + Status =3D VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);=0D + if (Status !=3D 0) {=0D + return Status;=0D + }=0D +=0D + if ((ExitInfo1 & IOIO_TYPE_IN) !=3D 0) {=0D + if (!GhcbIsRegValid (Ghcb, GhcbRax)) {=0D + return UnsupportedExit (Ghcb, Regs, InstructionData);=0D + }=0D + CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1))= ;=0D + }=0D +=0D + return 0;=0D +}=0D =0D /**=0D Handle a #VC exception.=0D @@ -38,6 +561,8 @@ VmgExitHandleVc ( MSR_SEV_ES_GHCB_REGISTER Msr;=0D EFI_SYSTEM_CONTEXT_X64 *Regs;=0D GHCB *Ghcb;=0D + NAE_EXIT NaeExit;=0D + SEV_ES_INSTRUCTION_DATA InstructionData;=0D UINT64 ExitCode, Status;=0D EFI_STATUS VcRet;=0D =0D @@ -54,24 +579,31 @@ VmgExitHandleVc ( =0D ExitCode =3D Regs->ExceptionData;=0D switch (ExitCode) {=0D + case SVM_EXIT_IOIO_PROT:=0D + NaeExit =3D IoioExit;=0D + break;=0D +=0D default:=0D - Status =3D VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, ExitCode, 0);=0D - if (Status =3D=3D 0) {=0D - Regs->ExceptionData =3D 0;=0D - *ExceptionType =3D GP_EXCEPTION;=0D + NaeExit =3D UnsupportedExit;=0D + }=0D +=0D + InitInstructionData (&InstructionData, Ghcb, Regs);=0D +=0D + Status =3D NaeExit (Ghcb, Regs, &InstructionData);=0D + if (Status =3D=3D 0) {=0D + Regs->Rip +=3D InstructionLength (&InstructionData);=0D + } else {=0D + GHCB_EVENT_INJECTION Event;=0D +=0D + Event.Uint64 =3D Status;=0D + if (Event.Elements.ErrorCodeValid !=3D 0) {=0D + Regs->ExceptionData =3D Event.Elements.ErrorCode;=0D } else {=0D - GHCB_EVENT_INJECTION Event;=0D -=0D - Event.Uint64 =3D Status;=0D - if (Event.Elements.ErrorCodeValid !=3D 0) {=0D - Regs->ExceptionData =3D Event.Elements.ErrorCode;=0D - } else {=0D - Regs->ExceptionData =3D 0;=0D - }=0D -=0D - *ExceptionType =3D Event.Elements.Vector;=0D + Regs->ExceptionData =3D 0;=0D }=0D =0D + *ExceptionType =3D Event.Elements.Vector;=0D +=0D VcRet =3D EFI_PROTOCOL_ERROR;=0D }=0D =0D --=20 2.27.0