From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@amdcloud.onmicrosoft.com header.s=selector2-amdcloud-onmicrosoft-com header.b=yv2OJB+q; spf=none, err=SPF record not found (domain: amd.com, ip: 40.107.74.49, mailfrom: thomas.lendacky@amd.com) Received: from NAM01-BN3-obe.outbound.protection.outlook.com (NAM01-BN3-obe.outbound.protection.outlook.com [40.107.74.49]) by groups.io with SMTP; Mon, 19 Aug 2019 14:36:09 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bEezeA4F1B7mPbaqmiUhHWH9Bz4xs5u8TOSYA0kqJPqWPMyL8ycp+ZvVP5GbXAcQG5GXZImc0Ep52PG65hm4nwo3bf03/ZBqUA7+uzX/S0vMhS1zrn+bigjC9KApqLRWEQ05LL+JcmpEg3hRQ548tqX+H4JeVF9V9yWMHO47LQLDdy+jc3x9iF5VSRcz/Wcmzqd/c0Eo5zF8RKwJTRF0lMvB0s+z24tgL4ptxyDbanfX0/Z/uLSDAAttSkYAb/mka7GJ3aaDn/8WgTOzKJH/ITSIqEt2FvMAbKp7aa6E1nbDNI+TSeso9nj5HNAFyqk35NvAQ55EZQj5LIprUZFgiw== 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=SGBpsSXoiHQ9Idl21MXIQ2KE7PjstkwDUU5cQvmerc8=; b=CTaaBmKM1HjtwxEKXtNpbBA2u//pHCnulVitOowjRp1kySMak7XEZ8AlwrYOg6Bj0eHZ7aiqk33LNDlBDQpGLGvciS06WjxlnrHLWlf8nHc21fsvWITPDa4OpWLzyTWYazIKDbKvQG+42yUv4yMKcBapTN7eNfe/NoJ+YHYKuzvyVmwNQagGyeseOQvUxRE7Qe81seNM7s7k2bqOw6HTcoGk0QRNg+8j3SVmi2cRXmmw7RaBdpmLIJHmzCjqpU9fPl8HeKYWTWgImAQlYitaS5bAoTX/1CtsRwN/F4er1N50xYqCKdGxTnAPphwee9uZv/+bAVFhyBY1tLWY0NXQlA== 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=SGBpsSXoiHQ9Idl21MXIQ2KE7PjstkwDUU5cQvmerc8=; b=yv2OJB+qZDzP+5XJBkYL3pZhIetKkBOS19xpNd5zAq/sfpCEP+7qSvUDkuol/0n5Xbk1fH9orYxfHd0FZI3FBF3vZYdsW7ibIiDqcQrEzpO/nIHehXpRMjw9nPojQ8krVRDJW9T06dWd7mPoOTy8CI9E0eogzWievGwpVWs2G30= Received: from BYAPR12MB3158.namprd12.prod.outlook.com (20.179.92.19) by BYAPR12MB2965.namprd12.prod.outlook.com (20.178.52.214) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2178.18; Mon, 19 Aug 2019 21:36:07 +0000 Received: from BYAPR12MB3158.namprd12.prod.outlook.com ([fe80::39b9:76bd:a491:1f27]) by BYAPR12MB3158.namprd12.prod.outlook.com ([fe80::39b9:76bd:a491:1f27%6]) with mapi id 15.20.2157.022; Mon, 19 Aug 2019 21:36:07 +0000 From: "Lendacky, Thomas" To: "devel@edk2.groups.io" CC: Jordan Justen , Laszlo Ersek , Ard Biesheuvel , Michael D Kinney , Liming Gao , Eric Dong , Ray Ni , "Singh, Brijesh" Subject: [RFC PATCH 15/28] UefiCpuPkg/CpuExceptionHandler: Add support for NPF NAE events (MMIO) Thread-Topic: [RFC PATCH 15/28] UefiCpuPkg/CpuExceptionHandler: Add support for NPF NAE events (MMIO) Thread-Index: AQHVVtYceB/Y6j0Ky0GF1inHI5osEg== Date: Mon, 19 Aug 2019 21:36:07 +0000 Message-ID: <2ac16b8d2ad147034a564dc7ccc86e38e09c7443.1566250534.git.thomas.lendacky@amd.com> References: In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.17.1 x-clientproxiedby: SN2PR01CA0031.prod.exchangelabs.com (2603:10b6:804:2::41) To BYAPR12MB3158.namprd12.prod.outlook.com (2603:10b6:a03:132::19) authentication-results: spf=none (sender IP is ) smtp.mailfrom=Thomas.Lendacky@amd.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [165.204.77.1] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 497551d1-3744-4f8f-74c8-08d724ed3e6a x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0;PCL:0;RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600148)(711020)(4605104)(1401327)(4618075)(2017052603328)(7193020);SRVR:BYAPR12MB2965; x-ms-traffictypediagnostic: BYAPR12MB2965: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:7219; x-forefront-prvs: 0134AD334F x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(4636009)(346002)(366004)(376002)(396003)(136003)(39860400002)(189003)(199004)(50226002)(53936002)(316002)(5660300002)(2351001)(52116002)(76176011)(36756003)(6436002)(71200400001)(19627235002)(6512007)(7736002)(256004)(14444005)(86362001)(14454004)(478600001)(305945005)(2906002)(71190400001)(2501003)(64756008)(186003)(118296001)(4326008)(26005)(6486002)(99286004)(1730700003)(386003)(6506007)(66066001)(66476007)(66556008)(8676002)(102836004)(81166006)(25786009)(66446008)(6916009)(54906003)(3846002)(6116002)(486006)(5640700003)(476003)(2616005)(11346002)(446003)(81156014)(66946007)(8936002);DIR:OUT;SFP:1101;SCL:1;SRVR:BYAPR12MB2965;H:BYAPR12MB3158.namprd12.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;MX:1;A:1; received-spf: None (protection.outlook.com: amd.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: vDo+DuDb/qbBQ06bSSHq65rF6zbvnnTbmpjsE6IxAIyQFAxbhgLwclESSXyh37B5McU/cqzigfSfZtsSMMElvpak+RynWTK96TSXdrjuKzs9Crf3DQ3wA8bJ0srbw7KEXL2utZ96WgIhW65d7/qdtpXNzK1LONO2badZqK9mozfVL8nOEaHUTpDqZQSzpBKtYYa9lp0oKfAsJEaVZUl7X2yzHWvRYqc30TOp1LQhSjnW9h3HIrEWIGWFucGSdWtubSx8qy36I+/vxYuaL98xW3M/kM4V45HkPNEUQ9um4vUgCqNmmIaLzjub+zWouanZuGDCUyRoyXEnvXS54vJx6xrKgIfreJJdbtt+zVazK6Z9OtDpbIdLCW+8DiUtMilnSR0PmEbs/+SGYr3Gkhwbi2V01nAQCozHQV2qtJDKG3Y= MIME-Version: 1.0 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 497551d1-3744-4f8f-74c8-08d724ed3e6a X-MS-Exchange-CrossTenant-originalarrivaltime: 19 Aug 2019 21:36:07.1616 (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: P7xC76GFBRWhwN8rQGRjb1l+UD1zaWQbhayRmshChFOQ1avQH/F2wUaslgIkY7WuIoRg84rqtmX/vgs+7hJOlQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BYAPR12MB2965 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-ID: <4F8DCFBF16C6FD40AE6BDCEB008D6541@namprd12.prod.outlook.com> Content-Transfer-Encoding: quoted-printable From: Tom Lendacky Under SEV-ES, a NPF intercept for an NPT entry with a reserved bit set generates a #VC exception. This condition is assumed to be an MMIO access. VMGEXIT must be used to allow the hypervisor to handle this intercept. Add support to construct the required GHCB values to support a NPF NAE event for MMIO. Parse the instruction that generated the #VC exception, setting the required register values in the GHCB and creating the proper SW_EXIT_INFO1, SW_EXITINFO2 and SW_SCRATCH values in the GHCB. Signed-off-by: Tom Lendacky --- .../X64/AMDSevVcCommon.c | 285 +++++++++++++++++- 1 file changed, 283 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c index 2b25919ea496..5b2df92acf72 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c @@ -78,8 +78,8 @@ typedef struct { UINT8 Scale; } Sib; =20 - UINTN RegData; - UINTN RmData; + INTN RegData; + INTN RmData; } SEV_ES_INSTRUCTION_OPCODE_EXT; =20 typedef struct { @@ -124,6 +124,198 @@ UINTN SEV_ES_INSTRUCTION_DATA *InstructionData ); =20 +STATIC +INT64 * +GetRegisterPointer ( + EFI_SYSTEM_CONTEXT_X64 *Regs, + UINT8 Register + ) +{ + UINT64 *Reg; + + switch (Register) { + case 0: + Reg =3D &Regs->Rax; + break; + case 1: + Reg =3D &Regs->Rcx; + break; + case 2: + Reg =3D &Regs->Rdx; + break; + case 3: + Reg =3D &Regs->Rbx; + break; + case 4: + Reg =3D &Regs->Rsp; + break; + case 5: + Reg =3D &Regs->Rbp; + break; + case 6: + Reg =3D &Regs->Rsi; + break; + case 7: + Reg =3D &Regs->Rdi; + break; + case 8: + Reg =3D &Regs->R8; + break; + case 9: + Reg =3D &Regs->R9; + break; + case 10: + Reg =3D &Regs->R10; + break; + case 11: + Reg =3D &Regs->R11; + break; + case 12: + Reg =3D &Regs->R12; + break; + case 13: + Reg =3D &Regs->R13; + break; + case 14: + Reg =3D &Regs->R14; + break; + case 15: + Reg =3D &Regs->R15; + break; + default: + Reg =3D NULL; + } + ASSERT (Reg); + + return (INT64 *) Reg; +} + +STATIC +VOID +UpdateForDisplacement ( + SEV_ES_INSTRUCTION_DATA *InstructionData, + UINTN Size + ) +{ + InstructionData->DisplacementSize =3D Size; + InstructionData->Immediate +=3D Size; + InstructionData->End +=3D Size; +} + +STATIC +BOOLEAN +IsRipRelative ( + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext =3D &InstructionData->Ext; + + return ((InstructionData =3D=3D LongMode64Bit) && + (Ext->ModRm.Mod =3D=3D 0) && + (Ext->ModRm.Rm =3D=3D 5) && + (InstructionData->SibPresent =3D=3D FALSE)); +} + +STATIC +UINTN +GetEffectiveMemoryAddress ( + EFI_SYSTEM_CONTEXT_X64 *Regs, + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext =3D &InstructionData->Ext; + INTN EffectiveAddress =3D 0; + + if (IsRipRelative (InstructionData)) { + /* RIP-relative displacement is a 32-bit signed value */ + INT32 RipRelative =3D *(INT32 *) InstructionData->Displacement; + + UpdateForDisplacement (InstructionData, 4); + return (UINTN) ((INTN) Regs->Rip + RipRelative); + } + + switch (Ext->ModRm.Mod) { + case 1: + UpdateForDisplacement (InstructionData, 1); + EffectiveAddress +=3D (INT8) (*(INT8 *) (InstructionData->Displacement= )); + break; + case 2: + switch (InstructionData->AddrSize) { + case Size16Bits: + UpdateForDisplacement (InstructionData, 2); + EffectiveAddress +=3D (INT16) (*(INT16 *) (InstructionData->Displace= ment)); + break; + default: + UpdateForDisplacement (InstructionData, 4); + EffectiveAddress +=3D (INT32) (*(INT32 *) (InstructionData->Displace= ment)); + break; + } + break; + } + + if (InstructionData->SibPresent) { + if (Ext->Sib.Index !=3D 4) { + EffectiveAddress +=3D (*GetRegisterPointer (Regs, Ext->Sib.Index) <<= Ext->Sib.Scale); + } + + if ((Ext->Sib.Base !=3D 5) || Ext->ModRm.Mod) { + EffectiveAddress +=3D *GetRegisterPointer (Regs, Ext->Sib.Base); + } else { + UpdateForDisplacement (InstructionData, 4); + EffectiveAddress +=3D (INT32) (*(INT32 *) (InstructionData->Displace= ment)); + } + } else { + EffectiveAddress +=3D *GetRegisterPointer (Regs, Ext->ModRm.Rm); + } + + return (UINTN) EffectiveAddress; +} + +STATIC +VOID +DecodeModRm ( + EFI_SYSTEM_CONTEXT_X64 *Regs, + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + SEV_ES_INSTRUCTION_REX_PREFIX *RexPrefix =3D &InstructionData->RexPrefi= x; + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext =3D &InstructionData->Ext; + SEV_ES_INSTRUCTION_MODRM *ModRm =3D &InstructionData->ModRm; + SEV_ES_INSTRUCTION_SIB *Sib =3D &InstructionData->Sib; + + InstructionData->ModRmPresent =3D TRUE; + ModRm->Uint8 =3D *(InstructionData->End); + + InstructionData->Displacement++; + InstructionData->Immediate++; + InstructionData->End++; + + Ext->ModRm.Mod =3D ModRm->Bits.Mod; + Ext->ModRm.Reg =3D (RexPrefix->Bits.R << 3) | ModRm->Bits.Reg; + Ext->ModRm.Rm =3D (RexPrefix->Bits.B << 3) | ModRm->Bits.Rm; + + Ext->RegData =3D *GetRegisterPointer (Regs, Ext->ModRm.Reg); + + if (Ext->ModRm.Mod =3D=3D 3) { + Ext->RmData =3D *GetRegisterPointer (Regs, Ext->ModRm.Rm); + } else { + if (ModRm->Bits.Rm =3D=3D 4) { + InstructionData->SibPresent =3D TRUE; + Sib->Uint8 =3D *(InstructionData->End); + + InstructionData->Displacement++; + InstructionData->Immediate++; + InstructionData->End++; + + Ext->Sib.Scale =3D Sib->Bits.Scale; + Ext->Sib.Index =3D (RexPrefix->Bits.X << 3) | Sib->Bits.Index; + Ext->Sib.Base =3D (RexPrefix->Bits.B << 3) | Sib->Bits.Base; + } + + Ext->RmData =3D GetEffectiveMemoryAddress (Regs, InstructionData); + } +} + STATIC VOID DecodePrefixes ( @@ -235,6 +427,91 @@ InitInstructionData ( DecodePrefixes (Regs, InstructionData); } =20 +STATIC +UINT64 +MmioExit ( + GHCB *Ghcb, + EFI_SYSTEM_CONTEXT_X64 *Regs, + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + UINT64 ExitInfo1, ExitInfo2; + UINTN Status; + UINTN Bytes; + INTN *Register; + + Bytes =3D 0; + + switch (*(InstructionData->OpCodes)) { + /* MMIO write */ + case 0x88: + Bytes =3D 1; + case 0x89: + DecodeModRm (Regs, InstructionData); + Bytes =3D (Bytes) ? Bytes + : (InstructionData->DataSize =3D=3D Size16Bits) ? 2 + : (InstructionData->DataSize =3D=3D Size32Bits) ? 4 + : (InstructionData->DataSize =3D=3D Size64Bits) ? 8 + : 0; + + if (InstructionData->Ext.ModRm.Mod =3D=3D 3) { + /* NPF on two register operands??? */ + VmgExit (Ghcb, SvmExitUnsupported, SvmExitNpf, 0); + ASSERT (0); + } + + ExitInfo1 =3D InstructionData->Ext.RmData; + ExitInfo2 =3D Bytes; + CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes); + + Ghcb->SaveArea.SwScratch =3D (UINT64) Ghcb->SharedBuffer; + Status =3D VmgExit (Ghcb, SvmExitMmioWrite, ExitInfo1, ExitInfo2); + if (Status) { + return Status; + } + break; + + /* MMIO read */ + case 0x8A: + Bytes =3D 1; + case 0x8B: + DecodeModRm (Regs, InstructionData); + Bytes =3D (Bytes) ? Bytes + : (InstructionData->DataSize =3D=3D Size16Bits) ? 2 + : (InstructionData->DataSize =3D=3D Size32Bits) ? 4 + : (InstructionData->DataSize =3D=3D Size64Bits) ? 8 + : 0; + if (InstructionData->Ext.ModRm.Mod =3D=3D 3) { + /* NPF on two register operands??? */ + VmgExit (Ghcb, SvmExitUnsupported, SvmExitNpf, 0); + ASSERT (0); + } + + ExitInfo1 =3D InstructionData->Ext.RmData; + ExitInfo2 =3D Bytes; + + Ghcb->SaveArea.SwScratch =3D (UINT64) Ghcb->SharedBuffer; + Status =3D VmgExit (Ghcb, SvmExitMmioRead, ExitInfo1, ExitInfo2); + if (Status) { + return Status; + } + + Register =3D GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg)= ; + if (Bytes =3D=3D 4) { + /* Zero-extend for 32-bit operation */ + *Register =3D 0; + } + CopyMem (Register, Ghcb->SharedBuffer, Bytes); + break; + + default: + Status =3D GP_EXCEPTION; + ASSERT (0); + } + + return Status; +} + STATIC UINTN UnsupportedExit ( @@ -590,6 +867,10 @@ DoVcCommon ( NaeExit =3D MsrExit; break; =20 + case SvmExitNpf: + NaeExit =3D MmioExit; + break; + default: NaeExit =3D UnsupportedExit; } --=20 2.17.1