From: "Marcin Juszkiewicz" <marcin.juszkiewicz@linaro.org>
To: devel@edk2.groups.io, quic_llindhol@quicinc.com
Cc: 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 14:37:08 +0200 [thread overview]
Message-ID: <547e2870-c3cd-45ec-8a9c-208e835353c3@linaro.org> (raw)
In-Reply-To: <a12e5d2d-1e98-4e21-998d-2b2971da90d2@quicinc.com>
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).
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]!
// Load the SMC arguments values into the appropriate registers
ldp x6, x7, [x0, #48]
@@ -19,14 +21,18 @@ ASM_FUNC(ArmCallSmc)
smc #0
- // Pop the ARM_SMC_ARGS structure address from the stack into x9
- ldr x9, [sp], #16
+ // Pop the ARM_SMC_ARGS structure address from the stack into x18
+ ldr x18, [sp], #32
// Store the SMC returned values into the ARM_SMC_ARGS structure.
- // A SMC call can return up to 4 values - we do not need to store back x4-x7.
- stp x2, x3, [x9, #16]
- stp x0, x1, [x9, #0]
+ // A SMC call can return up to 18 values, let handle 8 for now
+ stp x6, x7, [x18, #48]
+ stp x4, x5, [x18, #32]
+ stp x2, x3, [x18, #16]
+ stp x0, x1, [x18, #0]
- mov x0, x9
+ mov x0, x18
+ // restore x18
+ ldr x18, [sp], #16
ret
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119446): https://edk2.groups.io/g/devel/message/119446
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]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-06-04 12:37 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 [this message]
2024-06-04 13:33 ` Ard Biesheuvel
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=547e2870-c3cd-45ec-8a9c-208e835353c3@linaro.org \
--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