public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Ard Biesheuvel" <ardb@kernel.org>
To: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
Cc: devel@edk2.groups.io, quic_llindhol@quicinc.com,
	 Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Sami Mujawar <sami.mujawar@arm.com>
Subject: Re: [edk2-devel] ArmCallSmc() and SMCCC specification
Date: Tue, 4 Jun 2024 15:33:21 +0200	[thread overview]
Message-ID: <CAMj1kXHw3RebAyjeXCC3KbVhOq+SRVWt4WrKzx_RqWDhoUKYfw@mail.gmail.com> (raw)
In-Reply-To: <547e2870-c3cd-45ec-8a9c-208e835353c3@linaro.org>

On Tue, 4 Jun 2024 at 14:37, Marcin Juszkiewicz
<marcin.juszkiewicz@linaro.org> wrote:
>
> W dniu 3.06.2024 o 18:47, Leif Lindholm via groups.io pisze:
>
> >> In 2020 we got version C of spec (and then D, E, F) which allows to
> >> use more registers:
> >>
> >>  > Allow R4—R7 (SMC32/HVC32) to be used as result registers.
> >>  > Allow X8—X17 to be used as parameter registers in SMC64/HVC64.
> >>  > Allow X4—X17 to be used as result registers in SMC64/HVC64.
> >>
> >> And I started to wonder how to update EDK2 to newer version of SMCCC
> >> spec as one of in-progress QemuSbsa SMC calls may return more than 4
> >> values.
> >
> > Yes, definitely. This has been a wishlist item for some time, but in
> > reality we've only ever updated these when we needed new functionality.
>
>
>
> >> ARM_SMC_ARGS in ArmSmcLib.h can be expanded to handle up to Arg17 in
> >> an easy way and guarded by "#if defined(__aarch64__)" to not change it
> >> on Arm32.
>
> My example code for it (including comment update):
>
> diff --git a/ArmPkg/Include/Library/ArmSmcLib.h b/ArmPkg/Include/Library/ArmSmcLib.h
> index beef0175c35c..af27781b72f6 100644
> --- a/ArmPkg/Include/Library/ArmSmcLib.h
> +++ b/ArmPkg/Include/Library/ArmSmcLib.h
> @@ -23,14 +23,31 @@ typedef struct {
>     UINTN    Arg5;
>     UINTN    Arg6;
>     UINTN    Arg7;
> +#if defined(__aarch64__)
> +  UINTN    Arg8;
> +  UINTN    Arg9;
> +  UINTN    Arg10;
> +  UINTN    Arg11;
> +  UINTN    Arg12;
> +  UINTN    Arg13;
> +  UINTN    Arg14;
> +  UINTN    Arg15;
> +  UINTN    Arg16;
> +  UINTN    Arg17;
> +#endif
>   } ARM_SMC_ARGS;
>
>   /**
>     Trigger an SMC call
>
> -  SMC calls can take up to 7 arguments and return up to 4 return values.
> -  Therefore, the 4 first fields in the ARM_SMC_ARGS structure are used
> -  for both input and output values.
> +  on SMC32/HVC32
> +  - R0 is a function identifier, R1-R7 are arguments
> +  - R0-R7 are results, R4-R7 must be preserved unless they contain results
> +
> +
> +  on SMC64/HVC64
> +  - W0 is a function identifier, X1-X17 are arguments
> +  - X0-X17 are results, X4-X17 must be preserved unless they contain results
>
>   **/
>   VOID
>
>
> >> Then ArmCallSmc() in {AArch64,Arm}/ArmSmc.S needs changes. But here it
> >> gets tricky.
> >>
> >> On Arm we preserve r4-r8 and restore them after call like spec says.
> >> Which we do not do on AArch64 as version B of spec did not required
> >> that (and this changed in version C).
> >>
> >> If we start handling more than 4 results then we need to know how many
> >> results are expected and restore rest of r4-r7/x4-x17 registers:
> >
> > Yeah, it feels like we may want to add a version field or/and number of
> > registers to save/restore to a new struct. And we should definitely
> > align Arm/AArch64 behaviour.
>
>
>
>
> >>  From what I saw in both edk2/ and edk2-platforms/ most of code uses
> >> ArmCallSmc() function with ARM_SMC_ARGS structure populared with
> >> arguments. ArmCallSmc[0-3]() are used by Smbios, Psci and QemuSbsa
> >> code only.
> >
> > The ArmCallSmc[0-3] helpers were only added as shorthand for most common
> > cases. I don't think we should worry about how those work for making any
> > design decisions. Everything they do can be described by the main
> > ArmCallSmc functions and a few lines of struct stuffing.
>
> >> Now the question is: how to handle change?
> >
> > It could be that it would be easiest to add a new call function, and
> > maybe even ra new egister struct, than trying to adapt the existing ones
> > in ways that doesn't break existing users?
> >
> > That is if we care about existing users. We could always modify it to
> > guarantee breakage and expect users to update their code. Since this is
> > a library, and not a protocol, we *mostly* don't need to worry about
> > users mixing prebuilt binaries using old structs with new functions.
>
> >> We could add ArmCallSmc[4-17] but that name only tells how many
> >> arguments we pass to SMC call, not how many results we expect. Or
> >> should we add NumberOfResults argument to ArmCallSmc() to know which
> >> registers we should preserve and which are results? And how
> >> complicated this assembly function will become?
> >
> > I don't think the assembly function needs to be that complicated. It'd
> > be a bit tedious with a bunch of tests, but...
>
> Note: I do not know aarch64 assembly. Did some changes to ArmCallSmc().
> I moved to use x18 register (preserved on stack) instead of x9 one. And
> changed code to handle 8 results (without preserving x4-x7).
>

You shouldn't use X18 - it is the so-called 'platform register' and
has a special meaning.

For example, this code could be called inside a runtime service
invoked by the OS with interrupts enabled, and the OS's interrupt
handler might misbehave if X18 was modified.


> diff --git a/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S b/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S
> index 4a8c2a8f59ea..0525a0a7887f 100644
> --- a/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S
> +++ b/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S
> @@ -8,8 +8,10 @@
>   #include <AsmMacroIoLibV8.h>
>
>   ASM_FUNC(ArmCallSmc)
> +  // preserve x18
> +  str   x18, [sp, #-16]!
>     // Push x0 on the stack - The stack must always be quad-word aligned
> -  str   x0, [sp, #-16]!
> +  str   x0, [sp, #-32]!
>

This code does not honour the ordinary calling convention - better to
stack and unstack the frame pointer and return address. That also
gives you X30 (the link register) as a scratch register.

// Create a stack frame
stp  x29, x30, [sp, #-16]!
mov  x29, sp

// Preserve X0 for later use
mov  x30, x0

// Load the SMC arguments values into the appropriate registers
ldp   x0, x1, [x30, #0]
ldp   x2, x3, [x30, #16]
ldp   x4, x5, [x30, #32]
ldp   x6, x7, [x30, #48]
ldp   x8, x9, [x30, #64]
ldp   x10, x11, [x30, #80]
ldp   x12, x13, [x30, #96]
ldp   x14, x15, [x30, #112]
ldp   x16, x17, [x30, #128]

smc   #0

// A SMC call can return up to 18 values.
stp   x0, x1, [x30, #0]
stp   x2, x3, [x30, #16]
stp   x4, x5, [x30, #32]
stp   x6, x7, [x30, #48]
stp   x8, x9, [x30, #64]
stp   x10, x11, [x30, #80]
stp   x12, x13, [x30, #96]
stp   x14, x15, [x30, #112]
stp   x16, x17, [x30, #128]

mov   x0, x30
ldp   x29, x30, [sp], #16
ret


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119448): https://edk2.groups.io/g/devel/message/119448
Mute This Topic: https://groups.io/mt/106403741/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



      reply	other threads:[~2024-06-04 13:33 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-31  7:14 [edk2-devel] ArmCallSmc() and SMCCC specification Marcin Juszkiewicz
2024-06-03 16:47 ` Leif Lindholm
2024-06-04 12:37   ` Marcin Juszkiewicz
2024-06-04 13:33     ` Ard Biesheuvel [this message]

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=CAMj1kXHw3RebAyjeXCC3KbVhOq+SRVWt4WrKzx_RqWDhoUKYfw@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