public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: "Kinney, Michael D" <michael.d.kinney@intel.com>,
	edk2-devel-01 <edk2-devel@lists.01.org>
Cc: "Ni, Ruiyu" <ruiyu.ni@intel.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	"Yao, Jiewen" <jiewen.yao@intel.com>,
	"Dong, Eric" <eric.dong@intel.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	"Leif Lindholm (Linaro address)" <leif.lindholm@linaro.org>
Subject: Re: [PATCH 1/3] UefiCpuPkg/PiSmmCpuDxeSmm: update comments in IA32 SmmStartup()
Date: Wed, 31 Jan 2018 11:40:06 +0100	[thread overview]
Message-ID: <352efa04-a5c3-af45-2da7-8e9e0043aee9@redhat.com> (raw)
In-Reply-To: <E92EE9817A31E24EB0585FDF735412F5B895B864@ORSMSX113.amr.corp.intel.com>

On 01/30/18 23:25, Kinney, Michael D wrote:
> Laszlo,
> 
> I agree that the function is better than a macro.
> 
> I thought of the alignment issues as well.  CopyMem()
> is a good solution.  We could also consider
> WriteUnalignedxx() functions in BaseLib.

IMO, the WriteUnalignedxx functions are a bit pointless in the exact
form they are declared (this was discussed earlier esp. with regard to
aarch64). The functions take pointers to objects that already have the
target type, such as

UINT32
EFIAPI
WriteUnaligned32 (
  OUT UINT32                    *Buffer,
  IN  UINT32                    Value
  )

Here the type of Buffer should be (VOID *), not (UINT32 *). Otherwise,
the undefined behavior (due to mis-alignment) surfaces as soon as the
function is called with an unaligned pointer (i.e. before the target
area is actually written).

> I was originally thinking this functionality would go
> into BaseLib.  But with the use of CopyMem(), we can't
> do that.

Can we put it in BaseMemoryLib instead (which is where CopyMem() is
from)? That library class is still low-level enough. And, while I count
9 library instances, PatchAssembly() is not a large function, we could
tolerate adding it to all 9 instances, identically.

Let me also ask the opposite question: should we perhaps make the
PatchAssembly() API *less* abstract? (Also suggested by your naming of
the macro, PATCH_X86_ASM.) If the instruction encoding on e.g. AARCH64
doesn't lend itself to such patching (= expressed through the address
right after the instruction), then even BaseMemoryLib may be too generic
for the API.

> Maybe we should use WriteUnalignedxx() and
> add some ASSERT() checks.
> 
> VOID
> PatchAssembly (
>   VOID    *BufferEnd,
>   UINT64  PatchValue,
>   UINTN   ValueSize
>   )
> {
>   ASSERT ((UINTN)BufferEnd > ValueSize);
>   switch (ValueSize) {
>   case 1:
>     ASSERT (PatchValue <= MAX_UINT8);
>     *((UINT8 *)BufferEnd - 1) = (UINT8)PatchValue;
>   case 2:
>     ASSERT (PatchValue <= MAX_UINT16);
>     WriteUnaligned16 ((UINT16 *)(BufferEnd) - 1, (UINT16)PatchValue));
>     break;
>   case 4:
>     ASSERT (PatchValue <= MAX_UINT32);
>     WriteUnaligned32 ((UINT32 *)(BufferEnd) - 1, (UINT32)PatchValue));
>     break;
>   case 8:
>     WriteUnaligned64 ((UINT64 *)(BufferEnd) - 1, PatchValue));
>     break;
>   default:
>     ASSERT (FALSE);
>   }
> }

In my opinion:

- If Ard and Leif say that PatchAssembly() API makes sense for AARCH64,
  then I think we can go with the above generic implementation (for
  BaseLib).

- If Ard and Leif say the API is only useful on x86, then I suggest that
  we implement the API separately for all arches (still in BaseLib):

  - On x86, we should simply open-code the unaligned accesses (like you
    originall suggested). The pointer arithmetic will look a bit wild,
    but it's safely hidden behind a BaseLib API, so client code will
    look nice.

  - On all other arches, we should implement the function with
    ASSERT(FALSE).

Thanks!
Laszlo

> 
> Mike
> 
>> -----Original Message-----
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Tuesday, January 30, 2018 1:45 PM
>> To: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>> devel-01 <edk2-devel@lists.01.org>
>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Paolo Bonzini
>> <pbonzini@redhat.com>; Yao, Jiewen
>> <jiewen.yao@intel.com>; Dong, Eric <eric.dong@intel.com>
>> Subject: Re: [edk2] [PATCH 1/3]
>> UefiCpuPkg/PiSmmCpuDxeSmm: update comments in IA32
>> SmmStartup()
>>
>> On 01/30/18 21:31, Kinney, Michael D wrote:
>>> Laszlo,
>>>
>>> We have already used this technique in other NASM files
>>> to remove DBs.
>>
>> OK.
>>
>>> Let us know if you have suggestions on how to make the
>>> C code that performs the patches easier to read and
>>> maintain.
>>
>> How about this:
>>
>>   VOID
>>   PatchAssembly (
>>     VOID   *BufferEnd,
>>     UINT64 PatchValue,
>>     UINTN  ValueSize
>>     )
>>   {
>>     CopyMem (
>>       (VOID *)((UINTN)BufferEnd - ValueSize),
>>       &PatchValue,
>>       ValueSize
>>       );
>>   }
>>
>>   extern UINT8 gAsmSmmCr0;
>>   extern UINT8 gAsmSmmCr3;
>>   extern UINT8 gAsmSmmCr4;
>>
>>   ...
>>   {
>>     PatchAssembly (&gAsmSmmCr0, AsmReadCr0 (), 4);
>>     PatchAssembly (&gAsmSmmCr3, AsmReadCr3 (), 4);
>>     PatchAssembly (&gAsmSmmCr4, AsmReadCr4 (), 4);
>>     ...
>>   }
>>
>> (I think it's fine to open-code the last argument as "4",
>> rather than
>> "sizeof (UINT32)", because for patching, we must have
>> intimate knowledge
>> of the instruction anyway.)
>>
>> To me, this is easier to read, because:
>>
>> - there are no complex casts in the "business logic"
>> - the size is spelled out once per patching
>> - the function name and the variable names make it clear
>> we are patching
>>   separately compiled assembly code that was linked into
>> the same
>>   module.
>>
>> What do you think?
>>
>> Thanks!
>> Laszlo
>>
>>>> -----Original Message-----
>>>> From: edk2-devel [mailto:edk2-devel-
>> bounces@lists.01.org]
>>>> On Behalf Of Laszlo Ersek
>>>> Sent: Tuesday, January 30, 2018 10:17 AM
>>>> To: Kinney, Michael D <michael.d.kinney@intel.com>;
>> edk2-
>>>> devel-01 <edk2-devel@lists.01.org>
>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Paolo Bonzini
>>>> <pbonzini@redhat.com>; Yao, Jiewen
>>>> <jiewen.yao@intel.com>; Dong, Eric
>> <eric.dong@intel.com>
>>>> Subject: Re: [edk2] [PATCH 1/3]
>>>> UefiCpuPkg/PiSmmCpuDxeSmm: update comments in IA32
>>>> SmmStartup()
>>>>
>>>> On 01/30/18 18:22, Kinney, Michael D wrote:
>>>>> Laszlo,
>>>>>
>>>>> The DBs can be removed if the label is moved after
>>>>> the instruction and the patch is done to the label
>>>>> minus the size of the patch value.
>>>>
>>>> Indeed I haven't thought of this.
>>>>
>>>> If I understand correctly, it means
>>>>
>>>>   extern UINT8 gSmmCr0;
>>>>
>>>>   *(UINT32*)(&gSmmCr0 - sizeof (UINT32)) =
>>>> (UINT32)AsmReadCr0 ();
>>>>
>>>> TBH, the DB feels less ugly to me than this :)
>>>>
>>>> Still, if you think it would be an acceptable price to
>>>> pay for removing
>>>> the remaining DBs, I can respin.
>>>>
>>>> Thanks
>>>> Laszlo
>>>>
>>>>>> -----Original Message-----
>>>>>> From: edk2-devel [mailto:edk2-devel-
>>>> bounces@lists.01.org]
>>>>>> On Behalf Of Laszlo Ersek
>>>>>> Sent: Tuesday, January 30, 2018 7:34 AM
>>>>>> To: edk2-devel-01 <edk2-devel@lists.01.org>
>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Yao, Jiewen
>>>>>> <jiewen.yao@intel.com>; Dong, Eric
>>>> <eric.dong@intel.com>;
>>>>>> Paolo Bonzini <pbonzini@redhat.com>
>>>>>> Subject: [edk2] [PATCH 1/3]
>> UefiCpuPkg/PiSmmCpuDxeSmm:
>>>>>> update comments in IA32 SmmStartup()
>>>>>>
>>>>>> The gSmmCr3, gSmmCr4, gSmmCr0 and gSmmJmpAddr global
>>>>>> variables  are used
>>>>>> for patching assembly instructions, thus we can
>> never
>>>>>> remove the DB
>>>>>> encodings for those instructions. At least we should
>>>> add
>>>>>> the intended
>>>>>> meanings in comments.
>>>>>>
>>>>>> This patch only changes comments.
>>>>>>
>>>>>> Cc: Eric Dong <eric.dong@intel.com>
>>>>>> Cc: Jian J Wang <jian.j.wang@intel.com>
>>>>>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>>>>>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>>>>>> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
>>>>>> Contributed-under: TianoCore Contribution Agreement
>>>> 1.1
>>>>>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>>>>>> ---
>>>>>>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm | 8
>> ++++-
>>>> ---
>>>>>>  1 file changed, 4 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git
>>>> a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm
>>>>>> b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm
>>>>>> index e96dd8d2392a..08534dba64b7 100644
>>>>>> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm
>>>>>> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm
>>>>>> @@ -44,34 +44,34 @@ global ASM_PFX(SmmStartup)
>>>>>>  ASM_PFX(SmmStartup):
>>>>>>      DB      0x66
>>>>>>      mov     eax, 0x80000001             ; read
>>>>>> capability
>>>>>>      cpuid
>>>>>>      DB      0x66
>>>>>>      mov     ebx, edx                    ; rdmsr
>> will
>>>>>> change edx. keep it in ebx.
>>>>>> -    DB      0x66, 0xb8
>>>>>> +    DB      0x66, 0xb8                  ; mov eax,
>>>> imm32
>>>>>>  ASM_PFX(gSmmCr3): DD 0
>>>>>>      mov     cr3, eax
>>>>>>      DB      0x67, 0x66
>>>>>>      lgdt    [cs:ebp + (ASM_PFX(gcSmiInitGdtr) -
>>>>>> ASM_PFX(SmmStartup))]
>>>>>> -    DB      0x66, 0xb8
>>>>>> +    DB      0x66, 0xb8                  ; mov eax,
>>>> imm32
>>>>>>  ASM_PFX(gSmmCr4): DD 0
>>>>>>      mov     cr4, eax
>>>>>>      DB      0x66
>>>>>>      mov     ecx, 0xc0000080             ; IA32_EFER
>>>> MSR
>>>>>>      rdmsr
>>>>>>      DB      0x66
>>>>>>      test    ebx, BIT20                  ; check NXE
>>>>>> capability
>>>>>>      jz      .1
>>>>>>      or      ah, BIT3                    ; set NXE
>> bit
>>>>>>      wrmsr
>>>>>>  .1:
>>>>>> -    DB      0x66, 0xb8
>>>>>> +    DB      0x66, 0xb8                  ; mov eax,
>>>> imm32
>>>>>>  ASM_PFX(gSmmCr0): DD 0
>>>>>>      DB      0xbf, PROTECT_MODE_DS, 0    ; mov di,
>>>>>> PROTECT_MODE_DS
>>>>>>      mov     cr0, eax
>>>>>> -    DB      0x66, 0xea                   ; jmp far
>>>>>> [ptr48]
>>>>>> +    DB      0x66, 0xea                  ; jmp far
>>>>>> [ptr48]
>>>>>>  ASM_PFX(gSmmJmpAddr):
>>>>>>      DD      @32bit
>>>>>>      DW      PROTECT_MODE_CS
>>>>>>  @32bit:
>>>>>>      mov     ds, edi
>>>>>>      mov     es, edi
>>>>>> --
>>>>>> 2.14.1.3.gb7cf6e02401b
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> edk2-devel mailing list
>>>>>> edk2-devel@lists.01.org
>>>>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>>>
>>>> _______________________________________________
>>>> edk2-devel mailing list
>>>> edk2-devel@lists.01.org
>>>> https://lists.01.org/mailman/listinfo/edk2-devel
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
> 



  parent reply	other threads:[~2018-01-31 10:34 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-30 15:33 [PATCH 0/3] UefiCpuPkg/PiSmmCpuDxeSmm: fix IA32 SmmStartup() regression on KVM Laszlo Ersek
2018-01-30 15:33 ` [PATCH 1/3] UefiCpuPkg/PiSmmCpuDxeSmm: update comments in IA32 SmmStartup() Laszlo Ersek
2018-01-30 17:22   ` Kinney, Michael D
2018-01-30 18:17     ` Laszlo Ersek
2018-01-30 20:31       ` Kinney, Michael D
2018-01-30 21:26         ` Kinney, Michael D
2018-01-30 21:55           ` Laszlo Ersek
2018-01-30 21:45         ` Laszlo Ersek
2018-01-30 22:25           ` Kinney, Michael D
2018-01-31  5:44             ` Ni, Ruiyu
2018-01-31  5:54               ` Ni, Ruiyu
2018-01-31 10:56                 ` Laszlo Ersek
2018-01-31 10:42               ` Laszlo Ersek
2018-01-31 10:40             ` Laszlo Ersek [this message]
2018-01-31 22:11               ` Kinney, Michael D
2018-02-02  6:05                 ` Laszlo Ersek
2018-02-02 10:06               ` Ard Biesheuvel
2018-02-02 13:26                 ` Laszlo Ersek
2018-02-02 13:28                 ` Leif Lindholm
2018-02-02 13:36                   ` Laszlo Ersek
2018-01-30 15:33 ` [PATCH 2/3] UefiCpuPkg/PiSmmCpuDxeSmm: remove unneeded DBs from " Laszlo Ersek
2018-01-31  5:45   ` Ni, Ruiyu
2018-01-30 15:33 ` [PATCH 3/3] UefiCpuPkg/PiSmmCpuDxeSmm: eliminate conditional jump in " Laszlo Ersek
2018-01-31  5:12   ` Ni, Ruiyu
2018-01-30 16:37 ` [PATCH 0/3] UefiCpuPkg/PiSmmCpuDxeSmm: fix IA32 SmmStartup() regression on KVM Paolo Bonzini
2018-01-31 12:17 ` Laszlo Ersek
2018-02-01  1:20 ` Wang, Jian J

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=352efa04-a5c3-af45-2da7-8e9e0043aee9@redhat.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