From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-BN7-obe.outbound.protection.outlook.com (NAM10-BN7-obe.outbound.protection.outlook.com [40.107.92.52]) by mx.groups.io with SMTP id smtpd.web09.1692.1580857338005546073 for ; Tue, 04 Feb 2020 15:02:18 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@amdcloud.onmicrosoft.com header.s=selector2-amdcloud-onmicrosoft-com header.b=c8hoyLIM; spf=none, err=SPF record not found (domain: amd.com, ip: 40.107.92.52, mailfrom: thomas.lendacky@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=dcgpiCROFiJSE1cfjAck2HsuXoA/9SUi3sCocb6JwId+gcRx3anZB+jEg339MGAqsD0BwVyCPX0CixVEVvSi6enx78empfJ05PPjuyD7PwS8vzSXo2ekpnlFocoyGW3pKsqZ4PDBjektdWsKChrpeBt+5Z/safwsJJ/AN+XcGwaw/dfu3SYXhazwXqpV7X6nL+QDIPQUqlbvQj3+1XjW3oK0RLutrahRldXpvnu6RY9nnRPPaNLeI/kbGOASOdZhIwOqTz/9xX8gL29jdie+rWqh67SinJNRywqm31v/RvoPdUi9SDJzDMLIaAWOOeDGg7Lb/7S5UeN/fZiz/AHBkg== 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=bRwJ+VzOYLoqshdx7mV97MZOmkwc78Mv6FHJ5LAs7do=; b=M+i5eNkYy+aVx9L9DphmhhhusGObuU8mvzE+1H/jT93Yc7LfNwQJFNgw467xmHQJiYYSjVZU5oD4j4Kyy6HMcXn0kfyk0JWSlkjiXQFBC07FRHuYvsVovS2wUs3pYQ/TyhF8EszgGlT62amhYXRkgAT7xCRjMhlj7DEWKFbmpXQBppXx2mO9dq8gvKn+NsIhY1pAW+zrcEvyjW3dr8yrxiMhysId6qjLG+EPG9buxbAMzxBs6FutK+SKyWo+hjz3uo3VSPkj6+ZCjoyHcag7yWyDflCqz6Q3qTsaNutV4/KaU4loKkC1raLAu3kEUKdgSAHJKijqCaEz2smJ3h2FZw== 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=bRwJ+VzOYLoqshdx7mV97MZOmkwc78Mv6FHJ5LAs7do=; b=c8hoyLIMqCoeWEXapt0yijv2HOqxVRMqMzNPXuVOe1tBbMLA9C1cM6ZXonWeXqWLRyaxEwmDy+OXOSc0xqLizIzY4489flz318LVB4GB/dH6v1NSk7Jd+PL+Pkqc+cqed8JNSJ9pxNASG713FFMDlZcNY2ieOvWrISWSCS9U9wM= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Thomas.Lendacky@amd.com; Received: from DM6PR12MB3163.namprd12.prod.outlook.com (20.179.71.154) by DM6PR12MB3930.namprd12.prod.outlook.com (10.255.174.19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2686.29; Tue, 4 Feb 2020 23:02:15 +0000 Received: from DM6PR12MB3163.namprd12.prod.outlook.com ([fe80::a0cd:463:f444:c270]) by DM6PR12MB3163.namprd12.prod.outlook.com ([fe80::a0cd:463:f444:c270%7]) with mapi id 15.20.2707.020; Tue, 4 Feb 2020 23:02:15 +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 , Brijesh Singh Subject: [PATCH v4 13/40] UefiCpuPkg/CpuExceptionHandler: Add support for NPF NAE events (MMIO) Date: Tue, 4 Feb 2020 17:01:17 -0600 Message-Id: <76cf9430278f4be37048eae0ad2bc7f1011f156f.1580857303.git.thomas.lendacky@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: X-ClientProxiedBy: SN6PR16CA0062.namprd16.prod.outlook.com (2603:10b6:805:ca::39) To DM6PR12MB3163.namprd12.prod.outlook.com (2603:10b6:5:15e::26) Return-Path: thomas.lendacky@amd.com MIME-Version: 1.0 Received: from tlendack-t1.amd.com (165.204.77.1) by SN6PR16CA0062.namprd16.prod.outlook.com (2603:10b6:805:ca::39) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2686.32 via Frontend Transport; Tue, 4 Feb 2020 23:02:13 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [165.204.77.1] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: c100c819-039a-497f-8267-08d7a9c64645 X-MS-TrafficTypeDiagnostic: DM6PR12MB3930:|DM6PR12MB3930: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:7219; X-Forefront-PRVS: 03030B9493 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4636009)(39860400002)(366004)(376002)(136003)(396003)(346002)(199004)(189003)(4326008)(478600001)(6916009)(81156014)(2616005)(956004)(81166006)(8676002)(966005)(316002)(54906003)(19627235002)(2906002)(6486002)(66476007)(66556008)(52116002)(7696005)(186003)(26005)(16526019)(5660300002)(86362001)(36756003)(66946007)(8936002);DIR:OUT;SFP:1101;SCL:1;SRVR:DM6PR12MB3930;H:DM6PR12MB3163.namprd12.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;A:1;MX:1; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: lZSdh+ZUrjUPjc4ENnSqEbguffb5bTH4Lc69tI2ULFrdJf9mUHs1LhMebdvZZ2EfMRvi7MSN7vgLjwJWkl+sO9saJmkuuQzNIQ/Sm6afrKZM2LWHJ+8jDUVSzbrdvmhCTFI3gF0GOCDwJg7EuEZK4Lgad6z99hgIo7Go+slI/u8+nV7jl02Ja7fKIEf/R2p5fQgP9JOnzKYb8NOTM351UxVhHCJkfzXZ/47ZbxypoX1N0gn+38NLH6gjsHD39JQJihjOR+OL2GFZ564PBUkSy6+BfA+RuSFp0y2umF+T2judVXeA7veujoiN6X76303h/IxXNBtFh9pdKbSpKOEPFGM3dH60CKU4EGS3BDFVf28J+eOXdzJc2Dk8qN76HH5QhpECQntsY2yei1w+3QqcDLQIAzdQQkhC72BXCucVoiB2+WAhfmFvBLY/v0VehBsSAhtYc/Xi3OuvmAflNyEuuuR/Pp5tA4XKXkRpHfmZMwZxm9zRHdPDvhcZFnFqd7z2yzAyErE5wlJqy/W1beX+DQ== X-MS-Exchange-AntiSpam-MessageData: TG06Uvg5Sgcb0KlNAeNmjsp2Y4VDYLhywZt7xUlF3Mit5lMqOfdYGSpamtT1PfcEDGS0IWXEPxYrUTRBWNOrjLq4UuE0rNpmSf0McBb/wL9vcKOrTJPJSeYhFXvM+w3leHvUrXLVLMb7uTMsswNQjA== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: c100c819-039a-497f-8267-08d7a9c64645 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Feb 2020 23:02:14.7011 (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: dzxyQbEeGoPaHkkNXXmnluICnPtx9IOLcxPWGmZgviMeTCElpr8IyebMBq2U+fnRDtVoAPcWjUZKYR29mUkpFA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB3930 Content-Type: text/plain BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 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. Cc: Eric Dong Cc: Ray Ni Cc: Laszlo Ersek Signed-off-by: Tom Lendacky --- .../X64/AMDSevVcCommon.c | 305 +++++++++++++++++- 1 file changed, 303 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c index 25bcc34218d7..c68aeb5d2c10 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c @@ -86,8 +86,8 @@ typedef struct { UINT8 Scale; } Sib; - UINTN RegData; - UINTN RmData; + INTN RegData; + INTN RmData; } SEV_ES_INSTRUCTION_OPCODE_EXT; typedef struct { @@ -159,6 +159,198 @@ GhcbSetRegValid ( Ghcb->SaveArea.ValidBitmap[RegIndex] |= (1 << RegBit); } +STATIC +INT64 * +GetRegisterPointer ( + EFI_SYSTEM_CONTEXT_X64 *Regs, + UINT8 Register + ) +{ + UINT64 *Reg; + + switch (Register) { + case 0: + Reg = &Regs->Rax; + break; + case 1: + Reg = &Regs->Rcx; + break; + case 2: + Reg = &Regs->Rdx; + break; + case 3: + Reg = &Regs->Rbx; + break; + case 4: + Reg = &Regs->Rsp; + break; + case 5: + Reg = &Regs->Rbp; + break; + case 6: + Reg = &Regs->Rsi; + break; + case 7: + Reg = &Regs->Rdi; + break; + case 8: + Reg = &Regs->R8; + break; + case 9: + Reg = &Regs->R9; + break; + case 10: + Reg = &Regs->R10; + break; + case 11: + Reg = &Regs->R11; + break; + case 12: + Reg = &Regs->R12; + break; + case 13: + Reg = &Regs->R13; + break; + case 14: + Reg = &Regs->R14; + break; + case 15: + Reg = &Regs->R15; + break; + default: + Reg = NULL; + } + ASSERT (Reg != NULL); + + return (INT64 *) Reg; +} + +STATIC +VOID +UpdateForDisplacement ( + SEV_ES_INSTRUCTION_DATA *InstructionData, + UINTN Size + ) +{ + InstructionData->DisplacementSize = Size; + InstructionData->Immediate += Size; + InstructionData->End += Size; +} + +STATIC +BOOLEAN +IsRipRelative ( + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext = &InstructionData->Ext; + + return ((InstructionData == LongMode64Bit) && + (Ext->ModRm.Mod == 0) && + (Ext->ModRm.Rm == 5) && + (InstructionData->SibPresent == FALSE)); +} + +STATIC +UINTN +GetEffectiveMemoryAddress ( + EFI_SYSTEM_CONTEXT_X64 *Regs, + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext = &InstructionData->Ext; + INTN EffectiveAddress = 0; + + if (IsRipRelative (InstructionData)) { + /* RIP-relative displacement is a 32-bit signed value */ + INT32 RipRelative = *(INT32 *) InstructionData->Displacement; + + UpdateForDisplacement (InstructionData, 4); + return (UINTN) ((INTN) Regs->Rip + RipRelative); + } + + switch (Ext->ModRm.Mod) { + case 1: + UpdateForDisplacement (InstructionData, 1); + EffectiveAddress += (INT8) (*(INT8 *) (InstructionData->Displacement)); + break; + case 2: + switch (InstructionData->AddrSize) { + case Size16Bits: + UpdateForDisplacement (InstructionData, 2); + EffectiveAddress += (INT16) (*(INT16 *) (InstructionData->Displacement)); + break; + default: + UpdateForDisplacement (InstructionData, 4); + EffectiveAddress += (INT32) (*(INT32 *) (InstructionData->Displacement)); + break; + } + break; + } + + if (InstructionData->SibPresent) { + if (Ext->Sib.Index != 4) { + EffectiveAddress += (*GetRegisterPointer (Regs, Ext->Sib.Index) << Ext->Sib.Scale); + } + + if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) { + EffectiveAddress += *GetRegisterPointer (Regs, Ext->Sib.Base); + } else { + UpdateForDisplacement (InstructionData, 4); + EffectiveAddress += (INT32) (*(INT32 *) (InstructionData->Displacement)); + } + } else { + EffectiveAddress += *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 = &InstructionData->RexPrefix; + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext = &InstructionData->Ext; + SEV_ES_INSTRUCTION_MODRM *ModRm = &InstructionData->ModRm; + SEV_ES_INSTRUCTION_SIB *Sib = &InstructionData->Sib; + + InstructionData->ModRmPresent = TRUE; + ModRm->Uint8 = *(InstructionData->End); + + InstructionData->Displacement++; + InstructionData->Immediate++; + InstructionData->End++; + + Ext->ModRm.Mod = ModRm->Bits.Mod; + Ext->ModRm.Reg = (RexPrefix->Bits.R << 3) | ModRm->Bits.Reg; + Ext->ModRm.Rm = (RexPrefix->Bits.B << 3) | ModRm->Bits.Rm; + + Ext->RegData = *GetRegisterPointer (Regs, Ext->ModRm.Reg); + + if (Ext->ModRm.Mod == 3) { + Ext->RmData = *GetRegisterPointer (Regs, Ext->ModRm.Rm); + } else { + if (ModRm->Bits.Rm == 4) { + InstructionData->SibPresent = TRUE; + Sib->Uint8 = *(InstructionData->End); + + InstructionData->Displacement++; + InstructionData->Immediate++; + InstructionData->End++; + + Ext->Sib.Scale = Sib->Bits.Scale; + Ext->Sib.Index = (RexPrefix->Bits.X << 3) | Sib->Bits.Index; + Ext->Sib.Base = (RexPrefix->Bits.B << 3) | Sib->Bits.Base; + } + + Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData); + } +} + STATIC VOID DecodePrefixes ( @@ -294,6 +486,111 @@ UnsupportedExit ( return Status; } +STATIC +UINT64 +MmioExit ( + GHCB *Ghcb, + EFI_SYSTEM_CONTEXT_X64 *Regs, + SEV_ES_INSTRUCTION_DATA *InstructionData + ) +{ + UINT64 ExitInfo1, ExitInfo2, Status; + UINTN Bytes; + INTN *Register; + + Bytes = 0; + + switch (*(InstructionData->OpCodes)) { + /* MMIO write */ + case 0x88: + Bytes = 1; + case 0x89: + DecodeModRm (Regs, InstructionData); + Bytes = (Bytes) ? Bytes + : (InstructionData->DataSize == Size16Bits) ? 2 + : (InstructionData->DataSize == Size32Bits) ? 4 + : (InstructionData->DataSize == Size64Bits) ? 8 + : 0; + + if (InstructionData->Ext.ModRm.Mod == 3) { + /* NPF on two register operands??? */ + return UnsupportedExit (Ghcb, Regs, InstructionData); + } + + ExitInfo1 = InstructionData->Ext.RmData; + ExitInfo2 = Bytes; + CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes); + + Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer; + Status = VmgExit (Ghcb, SvmExitMmioWrite, ExitInfo1, ExitInfo2); + if (Status) { + return Status; + } + break; + + case 0xC6: + Bytes = 1; + case 0xC7: + DecodeModRm (Regs, InstructionData); + Bytes = (Bytes) ? Bytes + : (InstructionData->DataSize == Size16Bits) ? 2 + : (InstructionData->DataSize == Size32Bits) ? 4 + : 0; + + InstructionData->ImmediateSize = Bytes; + InstructionData->End += Bytes; + + ExitInfo1 = InstructionData->Ext.RmData; + ExitInfo2 = Bytes; + CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes); + + Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer; + Status = VmgExit (Ghcb, SvmExitMmioWrite, ExitInfo1, ExitInfo2); + if (Status) { + return Status; + } + break; + + /* MMIO read */ + case 0x8A: + Bytes = 1; + case 0x8B: + DecodeModRm (Regs, InstructionData); + Bytes = (Bytes) ? Bytes + : (InstructionData->DataSize == Size16Bits) ? 2 + : (InstructionData->DataSize == Size32Bits) ? 4 + : (InstructionData->DataSize == Size64Bits) ? 8 + : 0; + if (InstructionData->Ext.ModRm.Mod == 3) { + /* NPF on two register operands??? */ + return UnsupportedExit (Ghcb, Regs, InstructionData); + } + + ExitInfo1 = InstructionData->Ext.RmData; + ExitInfo2 = Bytes; + + Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer; + Status = VmgExit (Ghcb, SvmExitMmioRead, ExitInfo1, ExitInfo2); + if (Status) { + return Status; + } + + Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg); + if (Bytes == 4) { + /* Zero-extend for 32-bit operation */ + *Register = 0; + } + CopyMem (Register, Ghcb->SharedBuffer, Bytes); + break; + + default: + Status = GP_EXCEPTION; + ASSERT (0); + } + + return Status; +} + STATIC UINT64 MsrExit ( @@ -607,6 +904,10 @@ DoVcCommon ( NaeExit = MsrExit; break; + case SvmExitNpf: + NaeExit = MmioExit; + break; + default: NaeExit = UnsupportedExit; } -- 2.17.1