public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Brijesh Singh <brijesh.ksingh@gmail.com>
To: Laszlo Ersek <lersek@redhat.com>
Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>,
	edk2-devel@ml01.01.org,  Leo Duran <leo.duran@amd.com>,
	brijesh.singh@amd.com,  Tom Lendacky <Thomas.Lendacky@amd.com>
Subject: Re: [RFC PATCH v1 2/5] OvmfPkg/MemcryptSevLib: Add SEV helper library
Date: Fri, 17 Mar 2017 09:08:27 -0500	[thread overview]
Message-ID: <CA+HCGMaNU6YhG+KDp_uzutqhXtsXD0kxtK_ZxBy_kw5VDA37tQ@mail.gmail.com> (raw)
In-Reply-To: <a07a25d1-0aec-4176-312f-198bf10e29d1@redhat.com>

On Fri, Mar 17, 2017 at 5:29 AM, Laszlo Ersek <lersek@redhat.com> wrote:

> On 03/17/17 03:02, Brijesh Singh wrote:
> >
> >
> > On Wed, Mar 8, 2017 at 2:40 AM, Laszlo Ersek <lersek@redhat.com
> > <mailto:lersek@redhat.com>> wrote:
> >
> >     On 03/07/17 23:36, Brijesh Singh wrote:
> >     >
> >     >
> >     > On Tue, Mar 7, 2017 at 4:08 PM, Laszlo Ersek <lersek@redhat.com
> <mailto:lersek@redhat.com>
> >     > <mailto:lersek@redhat.com <mailto:lersek@redhat.com>>> wrote:
> >     >
> >     >     On 03/07/17 20:14, Brijesh Singh wrote:
> >     >     > On Tue, Mar 7, 2017 at 11:06 AM, Laszlo Ersek <
> lersek@redhat.com <mailto:lersek@redhat.com>
> >     >     <mailto:lersek@redhat.com <mailto:lersek@redhat.com>>> wrote:
> >     >     I think SevActive() and SevInitialize() should become part of
> >     >     PlatformPei only (if that's possible).
> >     >
> >     >     The upcoming PTE massaging functions could become part of the
> DMA lib
> >     >     stuff that you mention (as functions with external linkage),
> and then
> >     >     you could pull the DMA lib into QemuVideoDxe just to make these
> >     >     functions available.
> >     >
> >     >     Presently the suggested functions don't seem to justify two
> (or even
> >     >     one) new libclass.
> >     >
> >     >
> >     >
> >     > I think I should be able to accomate SevInitialize() and
> SevActive()
> >     > function inside the PlatformPei. I will drop MemcryptSevLib
> library in
> >     > next rev.
> >     >
> >     > I will go with your idea for adding PTE massaging function directly
> >     > inside the DMA library and will link that into QemuVideoDxe.
> >     >
> >     > Only part which I have not yet figured out,  how to deal with Qemu
> >     > FW_CFG DMA support, I believe some of FW_CFG DMA read and write
> >     > happens fairly early (PEI stage).
> >
> >     That's right, off the top of my head, minimally PlatformPei uses
> fw_cfg
> >     heavily during PEI.
> >
> >     > The PTE massaging code may need to
> >     > allocate memory and not sure how to allocate dynamic memory in
> early stages.
> >     > Any pointers ?
> >
> >     You can use MemoryAllocationLib functions for that (such as
> >     AllocatePool() and AllocatePages()). The OVMF DSC files resolve the
> lib
> >     class for the PEI phase like this:
> >
> >
> >     MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/
> PeiMemoryAllocationLib.inf
> >
> >     and the PeiMemoryAllocationLib instance maps those functions to the
> PEI
> >     services.
> >
> >     A few important things about this:
> >
> >     - AllocatePool() works up to only ~64KB in size, and the allocation
> is
> >     backed by a new HOB. Generally speaking, the HOB may be moved to a
> >     different spot in memory before entering the DXE phase, so pointers
> >     returned by such AllocatePool() calls (in PEI) are not safe to
> >     dereference in the DXE phase.
> >
> >     - FreePool() does nothing, the allocated memory (the HOB, see above)
> is
> >     only released when the guest OS starts (and it drops all boot
> services
> >     data type memory).
> >
> >     - AllocatePages() works as it says on the tin, and the pointer
> returned
> >     by it is safe to dereference in DXE.
> >
> >
> >
> > I took a stab at implementing SEV specific DMA hooks into QemuFwCfgLib.
> > But I found that QemuFWCfgLib is used in both PEI and Dxe phases.
> > It makes things interesting, in SEV guest we can perform DMA operation
> only
> > when processor is either in 32-bit PAE or long mode (mainly because C-bit
> > is not accessiable in 32 or 16-bit mode). It limits us to using
> OvmfX64.dsc.
> >
> > Ideally, I would prefer to support both OvmfPkgIa32X64.dsc and
> > OvmfPkgX64.dsc.
> > In my code browsing so far I have found that only QemuFwCfgLib does DMA
> > operations in PEI phase and other packages perform the DMA operation in
> > DXE phase.
> > If we can somehow manage to not require the DMA support in PEI phase
> then we
> > should be able to support both OvmfPkIa32X64.dsc and OvmfPkgX64.dsc.
> > How about defaulting to I/O operations in PEI stage for SEV guest ?
>
> I suggest the following:
>
> (1) Introduce an internal API to "QemuFwCfgLibInternal.h", called
> InternalQemuFwCfgSevIsEnabled().
>
> (2) Implement InternalQemuFwCfgSevIsEnabled() in "QemuFwCfgSec.c"
> without using global variables (i.e., with a CPUID on each call, on AMD
> processors, and return constant FALSE on Intel processors).
>
> (3) Create two copies of "QemuFwCfgPeiDxe.c", using the following names:
> QemuFwCfgPei.c, QemuFwCfgDxe.c, and then delete the original.
>
> (4) Accordingly, create two copies of "QemuFwCfgLib.inf",
> QemuFwCfgPeiLib.inf and QemuFwCfgDxeLib.inf, then delete the original.
>
> Don't forget to update the FILE_GUID defines.
>
> Additionally, update the library client module type restrictions in each
> (near LIBRARY_CLASS).
>
> (5) In QemuFwCfgDxeLib.inf / QemuFwCfgDxe.c, the constructor function
> should detect SEV, and store the result in a global variable. (As far as
> I remember, this detection should only happen on AMD processors, on
> Intel processors, the CPUID should not even be attempted -- is that right?)
>
>

Yes that is right. The CPUID detection function will return TRUE only when
SEV is enabled on AMD processor. On Intel it will return FALSE.



> The InternalQemuFwCfgSevIsEnabled() function should be implemented to
> return the global variable.
>
> (6) In QemuFwCfgPeiLib.inf / QemuFwCfgPei.c,
> InternalQemuFwCfgSevIsEnabled() should be implemented the same way, but
> the constructor function should also avoid setting
> mQemuFwCfgDmaSupported to TRUE if SEV is detected.
>
> (7) In "QemuFwCfgLib.c", the InternalQemuFwCfgDmaBytes() function should
> use a bounce buffer if InternalQemuFwCfgSevIsEnabled() returns TRUE.
>
> (Unfortunately, InternalQemuFwCfgDmaBytes() is not capable of returning
> an error, so if the bounce buffer allocation fails, you'll have to call
> ASSERT_EFI_ERROR (Status), and then an explicit CpuDeadLoop() too.)
>
> Note that skip operations never need a bounce buffer.
>
>
> The end result is that PEIMs will fall back to "IO only" if SEV is
> enabled (*), while DXE clients will use bounce buffers with DMA if SEV
> is enabled.
>
> (*) It's OK to use less performant solutions in PEI.
>
> > I do
> > understand
> > that QEMU prefers us to use DMA interface for FwCfg write.
>
> ... It's also OK to use less functional solutions in PEI. Normally, no
> fw_cfg write occurs in the PEI phase.
>
> Unfortunately, during S3 resume, fw_cfg writes (with DMA) do occur in
> PEI, performed by the stashed BootScriptExecutorDxe driver. And, in the
> S3 boot script, you cannot allocate memory (for bounce buffering)
> *dynamically*.
>
> However, in the S3 boot script, you cannot allocate memory dynamically
> for any other purpose either!
>
> Which is why QemuFwCfgS3Lib already pre-allocates reserved scratch space
> anyway, for the boot script opcodes (and QEMU) to operate upon.
>
> Thus, it should be possible to customize that too -- find the
> AllocateReservedPool() call in "QemuFwCfgS3Dxe.c", and make it allocate
> non-encrypted full pages instead, if SEV is enabled (you can call CPUID
> right there, on AMD processors).
>
> This way, whenever a DXE driver saves fw_cfg DMA writes into the ACPI S3
> boot script, to be run on S3 resume, the scratch space that it allocates
> in advance (for both the DMA control struct and the data to transfer),
> via QemuFwCfgS3CallWhenBootScriptReady(), will be plain-text.
>
> >
> > Additionally, I found that some FwCfg DMA access happens before
> >  PublishPeiMemory()
> > hence AllocatePages() was failing to allocate the bounce buffer for SEV
> DMA.
> > I was thinking that for SEV guest if we get a request to perform smaller
> > reads or writes
> > (maybe < 64 bytes) then silently fallback to IO else perform DMA
> operations.
>
> This should not be necessary with the above approach.
>
> (In general, AllocatePages() should not be used for temporary purposes
> in PEI (for bounce buffering or anything else), because those pages will
> be leaked for the rest of the firmware (unless something in DXE
> explicitly frees them up).)
>
> Thanks!
> Laszlo
>
>
> >
> > Thoughts ?
>
>
> >
> > -Brijesh
> >
> >  - FreePages() however is again a no-op, it practically leaks the memory,
> >
> >     and only the guest OS will be able to release it (see FreePool()
> above).
> >     One workaround for this could be to stash the address of the
> PEI-phase
> >     allocation in a GUID HOB or a PCD, and then let some DXE driver in
> the
> >     DXE phase release the memory with gBS->FreePages(). I'm not sure
> though
> >     if this complexity is worth it.
> >
> >     - Note that it is PlatformPei itself that installs the permanent PEI
> >     RAM. Before that happens, PEIMs (including PlatformPei itself) can
> only
> >     allocate memory from the temporary SEC/PEI heap, which is very very
> >     small, and only AllocatePool() would work at that point
> (AllocatePages()
> >     wouldn't). However, if you place the AllocatePages() function call
> after
> >     PublishPeiMemory(), then things should work.
> >
> >     As far as I can see, you added MemcryptSevInitialize() to the end of
> >     InitializePlatform(); allocating pages at that point should be fine.
> >
> >     - During S3 resume, a different (pre-reserved) memory area is used as
> >     permanent PEI RAM, which is quite smaller than the one used during
> >     normal boot. It means that, if you need a lot of memory for setting
> up
> >     SEV during S3 resume, AllocatePages() might run out of memory, and we
> >     might have to resize the pre-reservation mentioned above.
> >
> >     - If you could reasonably bound the allocation size with a constant,
> it
> >     might be simplest to use static arrays / variables. Those would be
> >     dropped as soon as the PEI phase was exited. As one quirk however,
> you
> >     should not rely on such variables being zero-initialized during S3
> >     resume.
> >
> >     Thanks
> >     Laszlo
> >
> >
> >
> >
> > --
> > Confusion is always the most honest response.
>
>


-- 
Confusion is always the most honest response.


  reply	other threads:[~2017-03-17 14:08 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-06 23:27 [RFC PATCH v1 0/5] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-03-06 23:27 ` [RFC PATCH v1 1/5] OvmfPkg/ResetVector: Set memory encryption when SEV is active Brijesh Singh
     [not found]   ` <3ec1cf2d-952d-97fa-108d-a6c70e613277@amd.com>
2017-03-07 16:34     ` Brijesh Singh
2017-03-07 16:35     ` Laszlo Ersek
2017-03-08 18:38   ` Jordan Justen
2017-03-08 18:42     ` Brijesh Singh
2017-03-06 23:27 ` [RFC PATCH v1 2/5] OvmfPkg/MemcryptSevLib: Add SEV helper library Brijesh Singh
2017-03-07 17:06   ` Laszlo Ersek
2017-03-07 19:14     ` Brijesh Singh
2017-03-07 22:08       ` Laszlo Ersek
2017-03-07 22:36         ` Brijesh Singh
2017-03-08  8:40           ` Laszlo Ersek
2017-03-17  2:02             ` Brijesh Singh
2017-03-17 10:29               ` Laszlo Ersek
2017-03-17 14:08                 ` Brijesh Singh [this message]
2017-03-08 14:56         ` Duran, Leo
2017-03-08 15:19           ` Laszlo Ersek
2017-03-06 23:27 ` [RFC PATCH v1 3/5] OvmfPkg/PlatformPei: Initialize SEV support Brijesh Singh
2017-03-07 17:08   ` Laszlo Ersek
2017-03-07 19:17     ` Brijesh Singh
2017-03-06 23:27 ` [RFC PATCH v1 4/5] OvmfPkg/BaseIoLibIntrinsic: import BaseIoLibIntrinsic package Brijesh Singh
2017-03-07 17:20   ` Laszlo Ersek
2017-03-07 20:06     ` Jordan Justen
2017-03-07 22:18       ` Laszlo Ersek
2017-03-08 15:41       ` Gao, Liming
2017-03-08 16:26         ` Brijesh Singh
2017-03-09  1:43           ` Gao, Liming
2017-03-08 18:58         ` Jordan Justen
2017-03-09  1:48           ` Gao, Liming
2017-03-09 15:36             ` Duran, Leo
2017-03-09 16:36               ` Laszlo Ersek
2017-03-06 23:28 ` [RFC PATCH v1 5/5] OvmfPkg/BaseIoLibIntrinsic: Unroll String I/O when SEV is active Brijesh Singh
     [not found]   ` <5a66f334-27e1-3b49-150e-c01209ecb2f6@amd.com>
2017-03-07 18:43     ` Brijesh Singh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CA+HCGMaNU6YhG+KDp_uzutqhXtsXD0kxtK_ZxBy_kw5VDA37tQ@mail.gmail.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox