From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=34.238.86.106; helo=mail.paulo.ac; envelope-from=paulo@paulo.ac; receiver=edk2-devel@lists.01.org Received: from mail.paulo.ac (mail.paulo.ac [34.238.86.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3D75F222EDCCD for ; Wed, 3 Jan 2018 06:40:51 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by mail.paulo.ac (Postfix) with ESMTP id 630C7C790F7; Wed, 3 Jan 2018 14:45:54 +0000 (UTC) X-Virus-Scanned: amavisd-new at paulo.ac X-Spam-Flag: NO X-Spam-Score: -1.099 X-Spam-Level: X-Spam-Status: No, score=-1.099 tagged_above=-999 required=6.31 tests=[ALL_TRUSTED=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no Authentication-Results: mail.paulo.ac (amavisd-new); dkim=pass (1024-bit key) header.d=paulo.ac Received: from mail.paulo.ac ([127.0.0.1]) by localhost (mail.paulo.ac [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pAe6_gcmzLC6; Wed, 3 Jan 2018 14:45:50 +0000 (UTC) Received: from [10.10.25.209] (unknown [15.65.243.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.paulo.ac (Postfix) with ESMTPSA id 225ECC78F5B; Wed, 3 Jan 2018 14:45:48 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.paulo.ac 225ECC78F5B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=paulo.ac; s=default; t=1514990750; bh=vYzYOH4Zz3mPNqY/saRFxPsp0mqFW3voK+ZzrXDlvOY=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=ctcphvBtsDlWu+I4VqxVX8hpdl0ZbxS3AMB891TZfAQTHn4g9rcrNX/CuuWGC+xet cInnI+dEOFEWfY2YQp+FdSRdKxtBpIaU5mNplmJh9VNre6ofa13cxuDpTRy4KU4DXl EMSJWmv/Nn6rSP8OM1dZe5zUEViu2LMYB2CQKpiE= To: Fan Jeff , "edk2-devel@lists.01.org" Cc: Laszlo Ersek , Eric Dong References: <32f06077006939f71560970f6abcbbb2062ea5c3.1514517573.git.paulo@paulo.ac> From: Paulo Alcantara Message-ID: Date: Wed, 3 Jan 2018 12:45:46 -0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 In-Reply-To: Subject: =?UTF-8?B?UmU6IOetlOWkjTogW1JGQyB2NCA0LzZdIFVlZmlDcHVQa2cvQ3B1RXhjZXB0aW9uSGFuZGxlckxpYjogQWRkIGhlbHBlciB0byB2YWxpZCBtZW1vcnkgYWRkcmVzc2Vz?= X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jan 2018 14:40:52 -0000 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Hi Jeff, On 1/3/2018 6:42 AM, Fan Jeff wrote: > Paul, > > +  // > +  // Calculate physical address of PML4E > +  // > +  PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); > +  PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; > + > > Should not pass VS build, instead you could use LShiftU64/RShiftU64 to > do 64bit shift operation as below: > >   PhysicalAddress = (UINT64)Cr3 & LShiftU64 (LShiftU64 (1, > MaxPhyAddrBits) - 1, 12); > >   PhysicalAddress |= LShiftU64 (RShiftU64((UINT64)LinearAddress, 39) & > 0x1FF), 3); OK - I'll fix them up and then build-test it with IA32/X64 MSFT toolchain. Thanks Paulo > > Jeff > > *发件人: *Paulo Alcantara > *发送时间: *2017年12月29日12:41 > *收件人: *edk2-devel@lists.01.org > *抄送: *Laszlo Ersek ; Eric Dong > > *主题: *[edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add > helper to valid memory addresses > > Introduce IsLinearAddressValid() function that will be used for > validating memory addresses that would get dereferenced during stack > traces in IA32 and X64 CPU exceptions. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Cc: Eric Dong > Cc: Laszlo Ersek > Requested-by: Brian Johnson > Requested-by: Jiewen Yao > Signed-off-by: Paulo Alcantara > --- >  UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 382 > ++++++++++++++++++++ >  UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h |  16 + >  2 files changed, 398 insertions(+) > > diff --git > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c > index 867c5c01d6..52b3eb1463 100644 > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c > @@ -14,6 +14,9 @@ > >  #include "CpuExceptionCommon.h" > > +#include > +#include > + >  // >  // Error code flag indicating whether or not an error code will be >  // pushed on the stack if an exception occurs. > @@ -194,3 +197,382 @@ GetPdbFileName ( >      } >    } >  } > + > +/** > +  Check if a linear address is valid by walking the page tables in 4-level > +  paging mode. > + > +  @param[in]  Cr3             CR3 control register. > +  @param[in]  MaxPhyAddrBits  MAXPHYADDRBITS bits. > +  @param[in]  LinearAddress   Linear address to be checked. > +**/ > +STATIC > +BOOLEAN > +Do4LevelPagingModeCheck ( > +  IN UINTN            Cr3, > +  IN UINT8            MaxPhyAddrBits, > +  IN UINTN            LinearAddress > +  ) > +{ > +  UINT64 PhysicalAddress; > +  UINT64 *Pml4TableEntry; > +  UINT64 *PageDirPtrTableEntry; > +  UINT64 *PageDirEntry; > +  UINT64 *PageTableEntry; > + > +  // > +  // In 4-level paging mode, linear addresses are 48 bits wide > +  // > +  if ((UINT64)LinearAddress > (1ULL << 48) - 1) { > +    return FALSE; > +  } > + > +  // > +  // Calculate physical address of PML4E > +  // > +  PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); > +  PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; > + > +  ASSERT ((PhysicalAddress & (sizeof (*Pml4TableEntry) - 1)) == 0); > + > +  Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check if a PDPTE is present > +  // > +  if ((*Pml4TableEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  // > +  // Calculate physical address of PDPTE > +  // > +  PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) > << 12); > +  PhysicalAddress |= (((UINT64)LinearAddress >> 30) & 0x1FF) << 3; > + > +  ASSERT ((PhysicalAddress & (sizeof (*PageDirPtrTableEntry) - 1)) == 0); > + > +  PageDirPtrTableEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check whether a PDPTE or 1GiB page entry is present > +  // > +  if ((*PageDirPtrTableEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  // > +  // Check if PDPTE maps an 1GiB page > +  // > +  if ((*PageDirPtrTableEntry & BIT7) != 0) { > +    return TRUE; > +  } > + > +  // > +  // Calculate physical address of PDE > +  // > +  PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) > - 1) << > +                                             12); > +  PhysicalAddress |= (((UINT64)LinearAddress >> 21) & 0x1FF) << 3; > + > +  ASSERT ((PhysicalAddress & (sizeof (*PageDirEntry) - 1)) == 0); > + > +  PageDirEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check whether a PDE or a 2MiB page entry is present > +  // > +  if ((*PageDirEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  // > +  // Check if PDE maps a 2MiB page > +  // > +  if ((*PageDirEntry & BIT7) != 0) { > +    return TRUE; > +  } > + > +  // > +  // Calculate physical address of PTE > +  // > +  PhysicalAddress = *PageDirEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); > +  PhysicalAddress |= (((UINT64)LinearAddress >> 12) & 0x1FF) << 3; > + > +  ASSERT ((PhysicalAddress & (sizeof (*PageTableEntry) - 1)) == 0); > + > +  PageTableEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check if PTE maps a 4KiB page > +  // > +  if ((*PageTableEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  return TRUE; > +} > + > +/** > +  Check if a linear address is valid by walking the page tables in > 32-bit paging > +  mode. > + > +  @param[in]  Cr3             CR3 control register. > +  @param[in]  Cr4             CR4 control register. > +  @param[in]  LinearAddress   Linear address to be checked. > +**/ > +STATIC > +BOOLEAN > +Do32BitPagingModeCheck ( > +  IN UINTN            Cr3, > +  IN UINTN            Cr4, > +  IN UINTN            LinearAddress > +  ) > +{ > +  UINT64 PhysicalAddress; > +  UINT32 *PageDirEntry; > +  UINT32 *PageTableEntry; > + > +  if (LinearAddress > MAX_UINT32) { > +    return FALSE; > +  } > + > +  // > +  // Calculate physical address of PDE > +  // > +  PhysicalAddress = (UINT32)Cr3 & (((1ULL << 20) - 1) << 12); > +  PhysicalAddress |= (((UINT32)LinearAddress >> 22) & 0x3FF) << 2; > + > +  ASSERT ((PhysicalAddress & (sizeof (*PageDirEntry) - 1)) == 0); > + > +  PageDirEntry = (UINT32 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check whether a PTE or a 4MiB page is present > +  // > +  if ((*PageDirEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  // > +  // Check if PDE maps a 4MiB page > +  // > +  if ((Cr4 & BIT4) != 0 && (*PageDirEntry & BIT7) != 0) { > +    return TRUE; > +  } > + > +  // > +  // Calculate physical address of PTE > +  // > +  PhysicalAddress = *PageDirEntry & (((1ULL << 20) - 1) << 12); > +  PhysicalAddress |= (((UINT32)LinearAddress >> 12) & 0x3FF) << 2; > + > +  ASSERT ((PhysicalAddress & (sizeof (*PageTableEntry) - 1)) == 0); > + > +  PageTableEntry = (UINT32 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check if PTE maps a 4KiB page > +  // > +  if ((*PageTableEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  return TRUE; > +} > + > +/** > +  Check if a linear address is valid by walking the page tables in PAE > paging > +  mode. > + > +  @param[in]  Cr3             CR3 control register. > +  @param[in]  MaxPhyAddrBits  MAXPHYADDRBITS bits. > +  @param[in]  LinearAddress   Linear address to be checked. > +**/ > +STATIC > +BOOLEAN > +DoPAEPagingModeCheck ( > +  IN UINTN            Cr3, > +  IN UINT8            MaxPhyAddrBits, > +  IN UINTN            LinearAddress > +  ) > +{ > +  UINT64 PhysicalAddress; > +  UINT64 *PageDirPtrTableEntry; > +  UINT64 *PageDirEntry; > +  UINT64 *PageTableEntry; > + > +  if (LinearAddress > MAX_UINT32) { > +    return FALSE; > +  } > + > +  // > +  // Calculate physical address of PDPTE > +  // > +  PhysicalAddress = (UINT32)Cr3 >> 5; > + > +  // > +  // Select PDPTE register > +  // > +  PhysicalAddress += > +    ((UINT32)LinearAddress >> 30) * sizeof (*PageDirPtrTableEntry); > + > +  PageDirPtrTableEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check if PDE is present > +  // > +  if ((*PageDirPtrTableEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) > - 1) << > +                                             12); > +  PhysicalAddress |= ((LinearAddress >> 21) & 0x1FF) << 3; > +  ASSERT ((PhysicalAddress & (sizeof (*PageDirEntry) - 1)) == 0); > + > +  PageDirEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check whether a PTE or a 2MiB page is present > +  // > +  if ((*PageDirEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  // > +  // Check if PDE maps a 2MiB page > +  // > +  if ((*PageDirEntry & BIT7) != 0) { > +    return TRUE; > +  } > + > +  // > +  // Calculate physical address of PTE > +  // > +  PhysicalAddress = *PageDirEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); > +  PhysicalAddress |= ((LinearAddress >> 12) & 0x1FF) << 3; > +  ASSERT ((PhysicalAddress & (sizeof (*PageTableEntry) - 1)) == 0); > + > +  PageTableEntry = (UINT64 *)(UINTN)PhysicalAddress; > + > +  // > +  // Check if PTE maps a 4KiB page > +  // > +  if ((*PageTableEntry & BIT0) == 0) { > +    return FALSE; > +  } > + > +  return TRUE; > +} > + > +/** > +  Check if a linear address is valid. > + > +  @param[in]  Cr0            CR0 control register. > +  @param[in]  Cr3            CR3 control register. > +  @param[in]  Cr4            CR4 control register. > +  @param[in]  LinearAddress  Linear address to be checked. > +**/ > +BOOLEAN > +IsLinearAddressValid ( > +  IN  UINTN              Cr0, > +  IN  UINTN              Cr3, > +  IN  UINTN              Cr4, > +  IN  UINTN              LinearAddress > +  ) > +{ > +  UINT32                  Eax; > +  UINT32                  Edx; > +  UINT8                   MaxPhyAddrBits; > +  MSR_IA32_EFER_REGISTER  Msr; > +  BOOLEAN                 AddressValid; > + > +  // > +  // Check for valid input parameters > +  // > +  if (Cr0 == 0 || Cr4 == 0 || LinearAddress == 0) { > +    return FALSE; > +  } > + > +  // > +  // Check if paging is disabled > +  // > +  if ((Cr0 & BIT31) == 0) { > +    // > +    // If CR4.PAE bit is set, then the linear (or physical) address > supports > +    // only up to 36 bits. > +    // > +    if (((Cr4 & BIT5) != 0 && (UINT64)LinearAddress > 0xFFFFFFFFFULL) || > +        LinearAddress > 0xFFFFFFFF) { > +      return FALSE; > +    } > + > +    return TRUE; > +  } > + > +  // > +  // Paging can be enabled only if CR0.PE bit is set > +  // > +  if ((Cr0 & BIT0) == 0) { > +    return FALSE; > +  } > + > +  // > +  // CR3 register cannot be zero if paging is enabled > +  // > +  if (Cr3 == 0) { > +    return FALSE; > +  } > + > +  // > +  // Get MAXPHYADDR bits > +  // > +  AsmCpuid (0x80000000, &Eax, NULL, NULL, NULL); > +  if (Eax >= 0x80000008) { > +    AsmCpuid (0x80000008, &Eax, NULL, NULL, NULL); > +    MaxPhyAddrBits = (UINT8)Eax; > +  } else { > +    AsmCpuid (1, NULL, NULL, NULL, &Edx); > +    if ((Edx & BIT6) != 0) { > +      MaxPhyAddrBits = 36; > +    } else { > +      MaxPhyAddrBits = 32; > +    } > +  } > + > +  ASSERT (MaxPhyAddrBits > 0); > + > +  AddressValid = FALSE; > + > +  // > +  // check if CR4.PAE bit is not set > +  // > +  if ((Cr4 & BIT5) == 0) { > +    // > +    // Check if linear address is valid in 32-bit paging mode > +    // > +    AddressValid = Do32BitPagingModeCheck (Cr3, Cr4, LinearAddress); > +  } else { > +    if (MaxPhyAddrBits > 52) { > +      return FALSE; > +    } > + > +    Msr.Uint64 = AsmReadMsr64 (MSR_IA32_EFER); > + > +    if (Msr.Bits.LME == 0) { > +      // > +      // Check if linear address is valid in PAE paging mode > +      // > +      AddressValid = DoPAEPagingModeCheck (Cr3, MaxPhyAddrBits, > LinearAddress); > +    } else { > +      // > +      // Check if linear address is valid in 4-level paging mode > +      // > +      AddressValid = Do4LevelPagingModeCheck (Cr3, MaxPhyAddrBits, > +                                              LinearAddress); > +    } > +  } > + > +  return AddressValid; > +} > diff --git > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > index ec46c2d9d3..1b51034c25 100644 > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > @@ -330,5 +330,21 @@ GetPdbFileName ( >    OUT CHAR8    **PdbFileName >    ); > > +/** > +  Check if a linear address is valid. > + > +  @param[in]  Cr0            CR0 control register. > +  @param[in]  Cr3            CR3 control register. > +  @param[in]  Cr4            CR4 control register. > +  @param[in]  LinearAddress  Linear address to be checked. > +**/ > +BOOLEAN > +IsLinearAddressValid ( > +  IN  UINTN              Cr0, > +  IN  UINTN              Cr3, > +  IN  UINTN              Cr4, > +  IN  UINTN              LinearAddress > +  ); > + >  #endif > > -- > 2.14.3 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel >