diff mbox series

[v4,2/2] arm64: rust: Enable Rust support for AArch64

Message ID 20231020155056.3495121-3-Jamie.Cunliffe@arm.com (mailing list archive)
State New, archived
Headers show
Series Rust enablement for AArch64 | expand

Commit Message

Jamie Cunliffe Oct. 20, 2023, 3:50 p.m. UTC
This commit provides the build flags for Rust for AArch64. The core Rust
support already in the kernel does the rest. This enables the PAC ret
and BTI options in the Rust build flags to match the options that are
used when building C.

The Rust samples have been tested with this commit.

Signed-off-by: Jamie Cunliffe <Jamie.Cunliffe@arm.com>
Acked-by: Will Deacon <will@kernel.org>
---
 Documentation/rust/arch-support.rst | 1 +
 arch/arm64/Kconfig                  | 1 +
 arch/arm64/Makefile                 | 4 ++++
 rust/Makefile                       | 1 +
 scripts/generate_rust_target.rs     | 4 +++-
 5 files changed, 10 insertions(+), 1 deletion(-)

Comments

Catalin Marinas Oct. 20, 2023, 4:45 p.m. UTC | #1
On Fri, Oct 20, 2023 at 04:50:56PM +0100, Jamie Cunliffe wrote:
> This commit provides the build flags for Rust for AArch64. The core Rust
> support already in the kernel does the rest. This enables the PAC ret
> and BTI options in the Rust build flags to match the options that are
> used when building C.
> 
> The Rust samples have been tested with this commit.
> 
> Signed-off-by: Jamie Cunliffe <Jamie.Cunliffe@arm.com>
> Acked-by: Will Deacon <will@kernel.org>

Miguel, Will acked this already so I think it's good to go. Do you plan
to pick both patches via the Rust tree?

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

Thanks.
Andrew Lunn Oct. 20, 2023, 5:21 p.m. UTC | #2
> +``arm64``     Maintained        Little Endian only.

This question is just out of curiosity, not the patchset itself.

What is missing to make big endian work?

Network developers have expressed an interesting in testing Rust code
on big endian systems, since the code should work on both endians. It
might be easier to get an ARM board running big endian than get access
to an S390x machine.

      Andrew
Boqun Feng Oct. 20, 2023, 6:33 p.m. UTC | #3
On Fri, Oct 20, 2023 at 07:21:08PM +0200, Andrew Lunn wrote:
> > +``arm64``     Maintained        Little Endian only.
> 
> This question is just out of curiosity, not the patchset itself.
> 
> What is missing to make big endian work?
> 

FWIW, I tried the following:

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 8784284988e5..b697c2d7da68 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -227,7 +227,7 @@ config ARM64
        select HAVE_FUNCTION_ARG_ACCESS_API
        select MMU_GATHER_RCU_TABLE_FREE
        select HAVE_RSEQ
-       select HAVE_RUST if CPU_LITTLE_ENDIAN
+       select HAVE_RUST
        select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_KPROBES
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 4562a8173e90..4621f1e00e06 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -41,7 +41,11 @@ KBUILD_CFLAGS        += -mgeneral-regs-only  \
 KBUILD_CFLAGS  += $(call cc-disable-warning, psabi)
 KBUILD_AFLAGS  += $(compat_vdso)

+ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
+KBUILD_RUSTFLAGS += --target aarch64_be-unknown-linux-gnu -C target-feature="-neon"
+else
 KBUILD_RUSTFLAGS += --target aarch64-unknown-none -C target-feature="-neon"
+endif

 KBUILD_CFLAGS  += $(call cc-option,-mabi=lp64)
 KBUILD_AFLAGS  += $(call cc-option,-mabi=lp64)

and ran the following kunit command (it will run a few tests in a qemu
emulated VM):

	./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch arm64 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_CPU_BIG_ENDIAN=y

The kernel was built successfully, and all Rust related tests passed.

Of course this doesn't mean a lot, we still need people with deep
Rust compiler knowledge to confirm whether the support is completed or
not. But I think if people want to do experiments, the tool is there.

P.S. An unrelated topic: I found a few clk related tests (in
drivers/clk/clk-gate_test.c IIUC) don't pass (mostly due to that the
expected values don't handle big endian), a sample failure output:

[11:13:26]     # clk_gate_test_enable: EXPECTATION FAILED at drivers/clk/clk-gate_test.c:169
[11:13:26]     Expected enable_val == ctx->fake_reg, but
[11:13:26]         enable_val == 32 (0x20)
[11:13:26]         ctx->fake_reg == 536870912 (0x20000000)
[11:13:26] clk_unregister: unregistering prepared clock: test_gate
[11:13:26] clk_unregister: unregistering prepared clock: test_parent
[11:13:26] [FAILED] clk_gate_test_enable

(Cc clk folks)

Regards,
Boqun

> Network developers have expressed an interesting in testing Rust code
> on big endian systems, since the code should work on both endians. It
> might be easier to get an ARM board running big endian than get access
> to an S390x machine.
> 
>       Andrew
Andrew Lunn Oct. 20, 2023, 6:47 p.m. UTC | #4
> Of course this doesn't mean a lot, we still need people with deep
> Rust compiler knowledge to confirm whether the support is completed or
> not. But I think if people want to do experiments, the tool is there.

Thanks for testing this, its good to know.

       Andrew
Alice Ryhl Oct. 21, 2023, 12:50 p.m. UTC | #5
On 10/20/23 20:33, Boqun Feng wrote:
> On Fri, Oct 20, 2023 at 07:21:08PM +0200, Andrew Lunn wrote:
>>> +``arm64``     Maintained        Little Endian only.
>>
>> This question is just out of curiosity, not the patchset itself.
>>
>> What is missing to make big endian work?
>>
> 
> FWIW, I tried the following:
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 8784284988e5..b697c2d7da68 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -227,7 +227,7 @@ config ARM64
>          select HAVE_FUNCTION_ARG_ACCESS_API
>          select MMU_GATHER_RCU_TABLE_FREE
>          select HAVE_RSEQ
> -       select HAVE_RUST if CPU_LITTLE_ENDIAN
> +       select HAVE_RUST
>          select HAVE_STACKPROTECTOR
>          select HAVE_SYSCALL_TRACEPOINTS
>          select HAVE_KPROBES
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 4562a8173e90..4621f1e00e06 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -41,7 +41,11 @@ KBUILD_CFLAGS        += -mgeneral-regs-only  \
>   KBUILD_CFLAGS  += $(call cc-disable-warning, psabi)
>   KBUILD_AFLAGS  += $(compat_vdso)
> 
> +ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
> +KBUILD_RUSTFLAGS += --target aarch64_be-unknown-linux-gnu -C target-feature="-neon"
> +else
>   KBUILD_RUSTFLAGS += --target aarch64-unknown-none -C target-feature="-neon"
> +endif
> 
>   KBUILD_CFLAGS  += $(call cc-option,-mabi=lp64)
>   KBUILD_AFLAGS  += $(call cc-option,-mabi=lp64)
> 
> and ran the following kunit command (it will run a few tests in a qemu
> emulated VM):
> 
> 	./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch arm64 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_CPU_BIG_ENDIAN=y
> 
> The kernel was built successfully, and all Rust related tests passed.
> 
> Of course this doesn't mean a lot, we still need people with deep
> Rust compiler knowledge to confirm whether the support is completed or
> not. But I think if people want to do experiments, the tool is there.

For what it's worth, I have some experience with big endian Rust in 
userspace, and it generally works without issues. I would expect that it 
doesn't need any special support beyond setting the target architecture 
properly.

Alice
Miguel Ojeda Oct. 21, 2023, 1:40 p.m. UTC | #6
On Fri, Oct 20, 2023 at 6:46 PM Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> Miguel, Will acked this already so I think it's good to go. Do you plan
> to pick both patches via the Rust tree?

Thanks for taking a look!

As you prefer -- ideally the changes for each architecture would go
through their own trees (we are trying to get maintainers of the
different parts of the kernel involved with Rust for their own bits
and pieces), but if you think there is a reason to avoid that, I can
also take them as fallback for the time being.

> Acked-by: Catalin Marinas <catalin.marinas@arm.com>

If you decide to take them:

Acked-by: Miguel Ojeda <ojeda@kernel.org>

I have boot tested it in aarch64 QEMU and saw the KUnit Rust tests
passing and checked that the x86 side still works fine.

Cheers,
Miguel
Miguel Ojeda Oct. 21, 2023, 1:41 p.m. UTC | #7
On Fri, Oct 20, 2023 at 8:33 PM Boqun Feng <boqun.feng@gmail.com> wrote:
>
> But I think if people want to do experiments, the tool is there.

Yeah. If the Arm maintainers are OK adding it, I think we should also
put it in (next cycle perhaps) -- the sooner we have it in-tree, the
more testing it will hopefully get over time, and we can eventually
ask the CIs to add a run with it if they have the resources.

Cheers,
Miguel
Andrew Lunn Oct. 21, 2023, 4:03 p.m. UTC | #8
On Sat, Oct 21, 2023 at 03:41:54PM +0200, Miguel Ojeda wrote:
> On Fri, Oct 20, 2023 at 8:33 PM Boqun Feng <boqun.feng@gmail.com> wrote:
> >
> > But I think if people want to do experiments, the tool is there.
> 
> Yeah. If the Arm maintainers are OK adding it, I think we should also
> put it in (next cycle perhaps) -- the sooner we have it in-tree, the
> more testing it will hopefully get over time, and we can eventually
> ask the CIs to add a run with it if they have the resources.

As i said elsewhere, endiannes is interesting for networking.

Maybe at the netdev conference next month, how to handle endiannes can
be part of the presentation? I'm guessing, but is it part of the type
system? So long as a type is marked as 'cpu endian', little endian, or
big endian, the compiler will take care of adding the needed swaps?

    Andrew
Catalin Marinas Oct. 22, 2023, 10:48 a.m. UTC | #9
On Sat, Oct 21, 2023 at 03:40:21PM +0200, Miguel Ojeda wrote:
> On Fri, Oct 20, 2023 at 6:46 PM Catalin Marinas <catalin.marinas@arm.com> wrote:
> > Miguel, Will acked this already so I think it's good to go. Do you plan
> > to pick both patches via the Rust tree?
> 
> Thanks for taking a look!
> 
> As you prefer -- ideally the changes for each architecture would go
> through their own trees (we are trying to get maintainers of the
> different parts of the kernel involved with Rust for their own bits
> and pieces), but if you think there is a reason to avoid that, I can
> also take them as fallback for the time being.

The main reason I asked was that the first patch touches x86 and none of
the x86 maintainers have been cc'ed or acked the patch. I thought
there's some deal that Rust-related changes go via you tree.

> > Acked-by: Catalin Marinas <catalin.marinas@arm.com>
> 
> If you decide to take them:
> 
> Acked-by: Miguel Ojeda <ojeda@kernel.org>
> 
> I have boot tested it in aarch64 QEMU and saw the KUnit Rust tests
> passing and checked that the x86 side still works fine.

Thanks. I'll reply to the first patch and cc some x86 maintainers. I
assume your ack applies to the first patch as well.
Miguel Ojeda Oct. 22, 2023, 12:14 p.m. UTC | #10
On Sun, Oct 22, 2023 at 12:49 PM Catalin Marinas
<catalin.marinas@arm.com> wrote:
>
> The main reason I asked was that the first patch touches x86 and none of
> the x86 maintainers have been cc'ed or acked the patch.

Ah, yeah, they should have been Cc'd.

> I thought
> there's some deal that Rust-related changes go via you tree.

I see. The initial pieces went through our tree, yeah, and we are
happy to take things if needed (without the intention to bypass
maintainers), but if maintainers can take things already, that is way
better; e.g. some subsystems have already started to do that (Kbuild,
KUnit, wq...). So thanks a lot!

The only thing we ask for, for the time being, is that patches
relevant to Rust or that contain Rust code are Cc'd into the
rust-for-linux ML if possible (i.e. in addition to their usual lists),
so that anybody that wants to follow things in the initial setup
period can do so in a single place (e.g. maintainers that want to see
the sort of thing to look out for in reviews).

> Thanks. I'll reply to the first patch and cc some x86 maintainers. I
> assume your ack applies to the first patch as well.

Yeah, it does.

Thanks again Catalin & Will!

Cheers,
Miguel
Miguel Ojeda Oct. 22, 2023, 12:57 p.m. UTC | #11
On Sat, Oct 21, 2023 at 6:03 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> Maybe at the netdev conference next month, how to handle endiannes can
> be part of the presentation? I'm guessing, but is it part of the type
> system? So long as a type is marked as 'cpu endian', little endian, or
> big endian, the compiler will take care of adding the needed swaps?

Yeah, the type system can take care of ensuring that one does not
forget which type of quantity one is handling.

For instance, in this out-of-tree commit [1] from Wedson a `LE`
generic is added, which allows you to use e.g. `LE<u32>` in your
structs:

    struct Example {
        a: LE<u32>,
        b: LE<u32>,
    }

    fn sum(e: &Example) -> u32 {
        // `value` extracts the value in cpu representation.
        e.a.value() + e.b.value()
    }

Relatedly, the primitive integer types also provide "raw"
functionality for endianness, e.g. the `to_{le,be}` and
`to_{le,be,ne}_bytes` methods [2][3], and there are third-party crates
on this, e.g. [4].

[1] https://github.com/wedsonaf/linux/commit/ca4a93caff8b96a54a68fb052959801468bce01a
[2] https://doc.rust-lang.org/std/primitive.u32.html#method.to_le
[3] https://doc.rust-lang.org/std/primitive.u32.html#method.to_be_bytes
[4] https://docs.rs/byteorder/latest/byteorder/

Cheers,
Miguel
Stephen Boyd Oct. 24, 2023, 12:57 a.m. UTC | #12
Quoting Boqun Feng (2023-10-20 11:33:10)
> On Fri, Oct 20, 2023 at 07:21:08PM +0200, Andrew Lunn wrote:
> > > +``arm64``     Maintained        Little Endian only.
> > 
> > This question is just out of curiosity, not the patchset itself.
> > 
> > What is missing to make big endian work?
> > 
> 
> FWIW, I tried the following:
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 8784284988e5..b697c2d7da68 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -227,7 +227,7 @@ config ARM64
>         select HAVE_FUNCTION_ARG_ACCESS_API
>         select MMU_GATHER_RCU_TABLE_FREE
>         select HAVE_RSEQ
> -       select HAVE_RUST if CPU_LITTLE_ENDIAN
> +       select HAVE_RUST
>         select HAVE_STACKPROTECTOR
>         select HAVE_SYSCALL_TRACEPOINTS
>         select HAVE_KPROBES
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 4562a8173e90..4621f1e00e06 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -41,7 +41,11 @@ KBUILD_CFLAGS        += -mgeneral-regs-only  \
>  KBUILD_CFLAGS  += $(call cc-disable-warning, psabi)
>  KBUILD_AFLAGS  += $(compat_vdso)
> 
> +ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
> +KBUILD_RUSTFLAGS += --target aarch64_be-unknown-linux-gnu -C target-feature="-neon"
> +else
>  KBUILD_RUSTFLAGS += --target aarch64-unknown-none -C target-feature="-neon"
> +endif
> 
>  KBUILD_CFLAGS  += $(call cc-option,-mabi=lp64)
>  KBUILD_AFLAGS  += $(call cc-option,-mabi=lp64)
> 
> and ran the following kunit command (it will run a few tests in a qemu
> emulated VM):
> 
>         ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch arm64 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_CPU_BIG_ENDIAN=y
> 
> The kernel was built successfully, and all Rust related tests passed.
> 
> Of course this doesn't mean a lot, we still need people with deep
> Rust compiler knowledge to confirm whether the support is completed or
> not. But I think if people want to do experiments, the tool is there.
> 
> P.S. An unrelated topic: I found a few clk related tests (in
> drivers/clk/clk-gate_test.c IIUC) don't pass (mostly due to that the
> expected values don't handle big endian), a sample failure output:
> 
> [11:13:26]     # clk_gate_test_enable: EXPECTATION FAILED at drivers/clk/clk-gate_test.c:169
> [11:13:26]     Expected enable_val == ctx->fake_reg, but
> [11:13:26]         enable_val == 32 (0x20)
> [11:13:26]         ctx->fake_reg == 536870912 (0x20000000)
> [11:13:26] clk_unregister: unregistering prepared clock: test_gate
> [11:13:26] clk_unregister: unregistering prepared clock: test_parent
> [11:13:26] [FAILED] clk_gate_test_enable
> 
> (Cc clk folks)
> 

Thanks for the report! We should treat it as an __le32 for now. I'll
have to add tests for the big endian flag as well. Does this fix it?

---8<----
diff --git a/drivers/clk/clk-gate_test.c b/drivers/clk/clk-gate_test.c
index e136aaad48bf..c96d93b19ddf 100644
--- a/drivers/clk/clk-gate_test.c
+++ b/drivers/clk/clk-gate_test.c
@@ -131,7 +131,7 @@ struct clk_gate_test_context {
 	void __iomem *fake_mem;
 	struct clk_hw *hw;
 	struct clk_hw *parent;
-	u32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
+	__le32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
 };
 
 static struct clk_gate_test_context *clk_gate_test_alloc_ctx(struct kunit *test)
@@ -166,7 +166,7 @@ static void clk_gate_test_enable(struct kunit *test)
 
 	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
 
-	KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
+	KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
@@ -183,10 +183,10 @@ static void clk_gate_test_disable(struct kunit *test)
 	u32 disable_val = 0;
 
 	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
-	KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
+	KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
 
 	clk_disable_unprepare(clk);
-	KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
+	KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
@@ -246,7 +246,7 @@ static void clk_gate_test_invert_enable(struct kunit *test)
 
 	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
 
-	KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
+	KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
@@ -263,10 +263,10 @@ static void clk_gate_test_invert_disable(struct kunit *test)
 	u32 disable_val = BIT(15);
 
 	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
-	KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
+	KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
 
 	clk_disable_unprepare(clk);
-	KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
+	KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
@@ -290,7 +290,7 @@ static int clk_gate_test_invert_init(struct kunit *test)
 					    2000000);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
 
-	ctx->fake_reg = BIT(15); /* Default to off */
+	ctx->fake_reg = cpu_to_le32(BIT(15)); /* Default to off */
 	hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0,
 					    ctx->fake_mem, 15,
 					    CLK_GATE_SET_TO_DISABLE, NULL);
@@ -319,7 +319,7 @@ static void clk_gate_test_hiword_enable(struct kunit *test)
 
 	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
 
-	KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
+	KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
 	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
@@ -336,10 +336,10 @@ static void clk_gate_test_hiword_disable(struct kunit *test)
 	u32 disable_val = BIT(9 + 16);
 
 	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
-	KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
+	KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
 
 	clk_disable_unprepare(clk);
-	KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
+	KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
 	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
@@ -387,7 +387,7 @@ static void clk_gate_test_is_enabled(struct kunit *test)
 	struct clk_gate_test_context *ctx;
 
 	ctx = clk_gate_test_alloc_ctx(test);
-	ctx->fake_reg = BIT(7);
+	ctx->fake_reg = cpu_to_le32(BIT(7));
 	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
 				  0, NULL);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
@@ -402,7 +402,7 @@ static void clk_gate_test_is_disabled(struct kunit *test)
 	struct clk_gate_test_context *ctx;
 
 	ctx = clk_gate_test_alloc_ctx(test);
-	ctx->fake_reg = BIT(4);
+	ctx->fake_reg = cpu_to_le32(BIT(4));
 	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
 				  0, NULL);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
@@ -417,7 +417,7 @@ static void clk_gate_test_is_enabled_inverted(struct kunit *test)
 	struct clk_gate_test_context *ctx;
 
 	ctx = clk_gate_test_alloc_ctx(test);
-	ctx->fake_reg = BIT(31);
+	ctx->fake_reg = cpu_to_le32(BIT(31));
 	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 2,
 				  CLK_GATE_SET_TO_DISABLE, NULL);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
@@ -432,7 +432,7 @@ static void clk_gate_test_is_disabled_inverted(struct kunit *test)
 	struct clk_gate_test_context *ctx;
 
 	ctx = clk_gate_test_alloc_ctx(test);
-	ctx->fake_reg = BIT(29);
+	ctx->fake_reg = cpu_to_le32(BIT(29));
 	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 29,
 				  CLK_GATE_SET_TO_DISABLE, NULL);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
Boqun Feng Oct. 25, 2023, 11:55 p.m. UTC | #13
On Mon, Oct 23, 2023 at 05:57:59PM -0700, Stephen Boyd wrote:
> Quoting Boqun Feng (2023-10-20 11:33:10)
> > On Fri, Oct 20, 2023 at 07:21:08PM +0200, Andrew Lunn wrote:
> > > > +``arm64``     Maintained        Little Endian only.
> > > 
> > > This question is just out of curiosity, not the patchset itself.
> > > 
> > > What is missing to make big endian work?
> > > 
> > 
> > FWIW, I tried the following:
> > 
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 8784284988e5..b697c2d7da68 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -227,7 +227,7 @@ config ARM64
> >         select HAVE_FUNCTION_ARG_ACCESS_API
> >         select MMU_GATHER_RCU_TABLE_FREE
> >         select HAVE_RSEQ
> > -       select HAVE_RUST if CPU_LITTLE_ENDIAN
> > +       select HAVE_RUST
> >         select HAVE_STACKPROTECTOR
> >         select HAVE_SYSCALL_TRACEPOINTS
> >         select HAVE_KPROBES
> > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> > index 4562a8173e90..4621f1e00e06 100644
> > --- a/arch/arm64/Makefile
> > +++ b/arch/arm64/Makefile
> > @@ -41,7 +41,11 @@ KBUILD_CFLAGS        += -mgeneral-regs-only  \
> >  KBUILD_CFLAGS  += $(call cc-disable-warning, psabi)
> >  KBUILD_AFLAGS  += $(compat_vdso)
> > 
> > +ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
> > +KBUILD_RUSTFLAGS += --target aarch64_be-unknown-linux-gnu -C target-feature="-neon"
> > +else
> >  KBUILD_RUSTFLAGS += --target aarch64-unknown-none -C target-feature="-neon"
> > +endif
> > 
> >  KBUILD_CFLAGS  += $(call cc-option,-mabi=lp64)
> >  KBUILD_AFLAGS  += $(call cc-option,-mabi=lp64)
> > 
> > and ran the following kunit command (it will run a few tests in a qemu
> > emulated VM):
> > 
> >         ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch arm64 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_CPU_BIG_ENDIAN=y
> > 
> > The kernel was built successfully, and all Rust related tests passed.
> > 
> > Of course this doesn't mean a lot, we still need people with deep
> > Rust compiler knowledge to confirm whether the support is completed or
> > not. But I think if people want to do experiments, the tool is there.
> > 
> > P.S. An unrelated topic: I found a few clk related tests (in
> > drivers/clk/clk-gate_test.c IIUC) don't pass (mostly due to that the
> > expected values don't handle big endian), a sample failure output:
> > 
> > [11:13:26]     # clk_gate_test_enable: EXPECTATION FAILED at drivers/clk/clk-gate_test.c:169
> > [11:13:26]     Expected enable_val == ctx->fake_reg, but
> > [11:13:26]         enable_val == 32 (0x20)
> > [11:13:26]         ctx->fake_reg == 536870912 (0x20000000)
> > [11:13:26] clk_unregister: unregistering prepared clock: test_gate
> > [11:13:26] clk_unregister: unregistering prepared clock: test_parent
> > [11:13:26] [FAILED] clk_gate_test_enable
> > 
> > (Cc clk folks)
> > 
> 
> Thanks for the report! We should treat it as an __le32 for now. I'll
> have to add tests for the big endian flag as well. Does this fix it?

Yep! I just tested with kunit, and all the tests pass.

Feel free to add:

Tested-by: Boqun Feng <boqun.feng@gmail.com>

Regards,
Boqun

> 
> ---8<----
> diff --git a/drivers/clk/clk-gate_test.c b/drivers/clk/clk-gate_test.c
> index e136aaad48bf..c96d93b19ddf 100644
> --- a/drivers/clk/clk-gate_test.c
> +++ b/drivers/clk/clk-gate_test.c
> @@ -131,7 +131,7 @@ struct clk_gate_test_context {
>  	void __iomem *fake_mem;
>  	struct clk_hw *hw;
>  	struct clk_hw *parent;
> -	u32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
> +	__le32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
>  };
>  
>  static struct clk_gate_test_context *clk_gate_test_alloc_ctx(struct kunit *test)
> @@ -166,7 +166,7 @@ static void clk_gate_test_enable(struct kunit *test)
>  
>  	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
>  
> -	KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
> +	KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
> @@ -183,10 +183,10 @@ static void clk_gate_test_disable(struct kunit *test)
>  	u32 disable_val = 0;
>  
>  	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
> -	KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
> +	KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
>  
>  	clk_disable_unprepare(clk);
> -	KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
> +	KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
> @@ -246,7 +246,7 @@ static void clk_gate_test_invert_enable(struct kunit *test)
>  
>  	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
>  
> -	KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
> +	KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
> @@ -263,10 +263,10 @@ static void clk_gate_test_invert_disable(struct kunit *test)
>  	u32 disable_val = BIT(15);
>  
>  	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
> -	KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
> +	KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
>  
>  	clk_disable_unprepare(clk);
> -	KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
> +	KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
> @@ -290,7 +290,7 @@ static int clk_gate_test_invert_init(struct kunit *test)
>  					    2000000);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
>  
> -	ctx->fake_reg = BIT(15); /* Default to off */
> +	ctx->fake_reg = cpu_to_le32(BIT(15)); /* Default to off */
>  	hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0,
>  					    ctx->fake_mem, 15,
>  					    CLK_GATE_SET_TO_DISABLE, NULL);
> @@ -319,7 +319,7 @@ static void clk_gate_test_hiword_enable(struct kunit *test)
>  
>  	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
>  
> -	KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg);
> +	KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
>  	KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
> @@ -336,10 +336,10 @@ static void clk_gate_test_hiword_disable(struct kunit *test)
>  	u32 disable_val = BIT(9 + 16);
>  
>  	KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
> -	KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg);
> +	KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
>  
>  	clk_disable_unprepare(clk);
> -	KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg);
> +	KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
>  	KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
> @@ -387,7 +387,7 @@ static void clk_gate_test_is_enabled(struct kunit *test)
>  	struct clk_gate_test_context *ctx;
>  
>  	ctx = clk_gate_test_alloc_ctx(test);
> -	ctx->fake_reg = BIT(7);
> +	ctx->fake_reg = cpu_to_le32(BIT(7));
>  	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
>  				  0, NULL);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
> @@ -402,7 +402,7 @@ static void clk_gate_test_is_disabled(struct kunit *test)
>  	struct clk_gate_test_context *ctx;
>  
>  	ctx = clk_gate_test_alloc_ctx(test);
> -	ctx->fake_reg = BIT(4);
> +	ctx->fake_reg = cpu_to_le32(BIT(4));
>  	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
>  				  0, NULL);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
> @@ -417,7 +417,7 @@ static void clk_gate_test_is_enabled_inverted(struct kunit *test)
>  	struct clk_gate_test_context *ctx;
>  
>  	ctx = clk_gate_test_alloc_ctx(test);
> -	ctx->fake_reg = BIT(31);
> +	ctx->fake_reg = cpu_to_le32(BIT(31));
>  	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 2,
>  				  CLK_GATE_SET_TO_DISABLE, NULL);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
> @@ -432,7 +432,7 @@ static void clk_gate_test_is_disabled_inverted(struct kunit *test)
>  	struct clk_gate_test_context *ctx;
>  
>  	ctx = clk_gate_test_alloc_ctx(test);
> -	ctx->fake_reg = BIT(29);
> +	ctx->fake_reg = cpu_to_le32(BIT(29));
>  	hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 29,
>  				  CLK_GATE_SET_TO_DISABLE, NULL);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
>
Matthew Maurer Oct. 31, 2023, 6:31 p.m. UTC | #14
On Fri, Oct 20, 2023 at 8:53 AM Jamie Cunliffe <Jamie.Cunliffe@arm.com> wrote:
> +KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon"
If I have aarch64-unknown-none target support already installed in my
local Rust compiler (either build a custom compiler and enable the
target, as is my real case, or as the common case, run `rustup target
add aarch64-unknown-none`), this produces a build error I didn't get
from the previous target.json approach:

error[E0464]: multiple candidates for `rmeta` dependency `core` found
  |
  = note: candidate #1:
/usr/local/google/home/mmaurer/android/linux/out/cache/65c6e8ea/common/rust/libcore.rmeta
  = note: candidate #2:
/usr/local/google/home/mmaurer/android/linux/prebuilts/rust/linux-x86/1.72.1/lib/rustlib/aarch64-unknown-none/lib/libcore-690113bb4de6f7fb.rlib

Are we sure that we want to try to use `--target=aarch64-unknown-none`
rather than a custom target.json? If our libcore and their libcore may
be compiled differently (and they can be, because we are controlling
additional compilation options), it seems to me that we ought to be
defining our own target.

If we really do want to go ahead with using targets directly form
rustc, this patch should add `--sysroot=/dev/null` or a similar
override to `rustc_library_cmd` and `rust_common_cmd` to prevent rustc
from picking up any already installed sysroot libraries.
Linus Walleij Nov. 1, 2023, 3:04 p.m. UTC | #15
[Andrew wrote]

> > Network developers have expressed an interesting in testing Rust code
> > on big endian systems, since the code should work on both endians. It
> > might be easier to get an ARM board running big endian than get access
> > to an S390x machine.

If you mean ARM32 BE I have that on the IXP4xx systems up and running
mainline kernels and mainline OpenWrt now, but I haven't
seen rust enablement for ARM32 yet (but it can't be that hard).

Yours,
Linus Walleij
Boqun Feng Nov. 28, 2023, 6:29 p.m. UTC | #16
On Tue, Oct 31, 2023 at 11:31:14AM -0700, Matthew Maurer wrote:
> On Fri, Oct 20, 2023 at 8:53 AM Jamie Cunliffe <Jamie.Cunliffe@arm.com> wrote:
> > +KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon"
> If I have aarch64-unknown-none target support already installed in my
> local Rust compiler (either build a custom compiler and enable the
> target, as is my real case, or as the common case, run `rustup target
> add aarch64-unknown-none`), this produces a build error I didn't get
> from the previous target.json approach:
> 
> error[E0464]: multiple candidates for `rmeta` dependency `core` found
>   |
>   = note: candidate #1:
> /usr/local/google/home/mmaurer/android/linux/out/cache/65c6e8ea/common/rust/libcore.rmeta
>   = note: candidate #2:
> /usr/local/google/home/mmaurer/android/linux/prebuilts/rust/linux-x86/1.72.1/lib/rustlib/aarch64-unknown-none/lib/libcore-690113bb4de6f7fb.rlib
> 
> Are we sure that we want to try to use `--target=aarch64-unknown-none`
> rather than a custom target.json? If our libcore and their libcore may
> be compiled differently (and they can be, because we are controlling
> additional compilation options), it seems to me that we ought to be
> defining our own target.
> 

FWIW, the discussion around this:

	https://lore.kernel.org/rust-for-linux/20230126163552.GD29438@willie-the-truck/	

> If we really do want to go ahead with using targets directly form
> rustc, this patch should add `--sysroot=/dev/null` or a similar
> override to `rustc_library_cmd` and `rust_common_cmd` to prevent rustc
> from picking up any already installed sysroot libraries.
> 

Agreed.

Regards,
Boqun
Miguel Ojeda Dec. 13, 2023, 7 p.m. UTC | #17
On Tue, Oct 31, 2023 at 7:31 PM Matthew Maurer <mmaurer@google.com> wrote:
>
> If we really do want to go ahead with using targets directly form
> rustc, this patch should add `--sysroot=/dev/null` or a similar
> override to `rustc_library_cmd` and `rust_common_cmd` to prevent rustc
> from picking up any already installed sysroot libraries.

For reference, Matthew sent the patch to do this at
https://lore.kernel.org/rust-for-linux/20231031201752.1189213-1-mmaurer@google.com/
and I have picked it up in `rust-next` (with a couple extra changes
noted in that thread), so this should be OK.

When this series also arrives in `-next` I will be testing the
combination further just in case.

Cheers,
Miguel
Fabien Parent Jan. 22, 2024, 2:01 a.m. UTC | #18
I've been using this patch for quite some time, so:

Tested-by: Fabien Parent <fabien.parent@linaro.org>
Dirk Behme Jan. 22, 2024, 5:27 a.m. UTC | #19
On 20.10.2023 17:50, Jamie Cunliffe wrote:
> This commit provides the build flags for Rust for AArch64. The core Rust
> support already in the kernel does the rest. This enables the PAC ret
> and BTI options in the Rust build flags to match the options that are
> used when building C.
> 
> The Rust samples have been tested with this commit.
> 
> Signed-off-by: Jamie Cunliffe <Jamie.Cunliffe@arm.com>
> Acked-by: Will Deacon <will@kernel.org>


I'm using it since some weeks cross compiling from x86. Boots executing 
the sample code and the KUnit doctests. So:

Tested-by: Dirk Behme <dirk.behme@de.bosch.com>

Would be nice if we could get this merged :)

Dirk


> ---
>   Documentation/rust/arch-support.rst | 1 +
>   arch/arm64/Kconfig                  | 1 +
>   arch/arm64/Makefile                 | 4 ++++
>   rust/Makefile                       | 1 +
>   scripts/generate_rust_target.rs     | 4 +++-
>   5 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst
> index b91e9ef4d0c2..6bcb3b97c5b6 100644
> --- a/Documentation/rust/arch-support.rst
> +++ b/Documentation/rust/arch-support.rst
> @@ -15,6 +15,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
>   ============  ================  ==============================================
>   Architecture  Level of support  Constraints
>   ============  ================  ==============================================
> +``arm64``     Maintained        Little Endian only.
>   ``um``        Maintained        ``x86_64`` only.
>   ``x86``       Maintained        ``x86_64`` only.
>   ============  ================  ==============================================
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 78f20e632712..d72618433521 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -227,6 +227,7 @@ config ARM64
>   	select HAVE_FUNCTION_ARG_ACCESS_API
>   	select MMU_GATHER_RCU_TABLE_FREE
>   	select HAVE_RSEQ
> +	select HAVE_RUST if CPU_LITTLE_ENDIAN
>   	select HAVE_STACKPROTECTOR
>   	select HAVE_SYSCALL_TRACEPOINTS
>   	select HAVE_KPROBES
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 2d49aea0ff67..52d75c9483a9 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -41,6 +41,8 @@ KBUILD_CFLAGS	+= -mgeneral-regs-only	\
>   KBUILD_CFLAGS	+= $(call cc-disable-warning, psabi)
>   KBUILD_AFLAGS	+= $(compat_vdso)
>   
> +KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon"
> +
>   KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
>   KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
>   
> @@ -65,7 +67,9 @@ endif
>   
>   ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
>     KBUILD_CFLAGS += -mbranch-protection=pac-ret+bti
> +  KBUILD_RUSTFLAGS += -Zbranch-protection=bti,pac-ret
>   else ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
> +  KBUILD_RUSTFLAGS += -Zbranch-protection=pac-ret
>     ifeq ($(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET),y)
>       KBUILD_CFLAGS += -mbranch-protection=pac-ret
>     else
> diff --git a/rust/Makefile b/rust/Makefile
> index 8d75a6ffe951..8ced65c9b905 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -294,6 +294,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
>   
>   # Derived from `scripts/Makefile.clang`.
>   BINDGEN_TARGET_x86	:= x86_64-linux-gnu
> +BINDGEN_TARGET_arm64	:= aarch64-linux-gnu
>   BINDGEN_TARGET		:= $(BINDGEN_TARGET_$(SRCARCH))
>   
>   # All warnings are inhibited since GCC builds are very experimental,
> diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs
> index 3c6cbe2b278d..ec5ef35dbe52 100644
> --- a/scripts/generate_rust_target.rs
> +++ b/scripts/generate_rust_target.rs
> @@ -148,7 +148,9 @@ fn main() {
>       let mut ts = TargetSpec::new();
>   
>       // `llvm-target`s are taken from `scripts/Makefile.clang`.
> -    if cfg.has("X86_64") {
> +    if cfg.has("ARM64") {
> +        panic!("arm64 uses the builtin rustc aarch64-unknown-none target");
> +    } else if cfg.has("X86_64") {
>           ts.push("arch", "x86_64");
>           ts.push(
>               "data-layout",
Alice Ryhl Jan. 22, 2024, 9:30 a.m. UTC | #20
Jamie Cunliffe <Jamie.Cunliffe@arm.com> writes:
> This commit provides the build flags for Rust for AArch64. The core Rust
> support already in the kernel does the rest. This enables the PAC ret
> and BTI options in the Rust build flags to match the options that are
> used when building C.
> 
> The Rust samples have been tested with this commit.
> 
> Signed-off-by: Jamie Cunliffe <Jamie.Cunliffe@arm.com>
> Acked-by: Will Deacon <will@kernel.org>

Tested with Rust Binder.

Tested-by: Alice Ryhl <aliceryhl@google.com>
diff mbox series

Patch

diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst
index b91e9ef4d0c2..6bcb3b97c5b6 100644
--- a/Documentation/rust/arch-support.rst
+++ b/Documentation/rust/arch-support.rst
@@ -15,6 +15,7 @@  support corresponds to ``S`` values in the ``MAINTAINERS`` file.
 ============  ================  ==============================================
 Architecture  Level of support  Constraints
 ============  ================  ==============================================
+``arm64``     Maintained        Little Endian only.
 ``um``        Maintained        ``x86_64`` only.
 ``x86``       Maintained        ``x86_64`` only.
 ============  ================  ==============================================
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 78f20e632712..d72618433521 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -227,6 +227,7 @@  config ARM64
 	select HAVE_FUNCTION_ARG_ACCESS_API
 	select MMU_GATHER_RCU_TABLE_FREE
 	select HAVE_RSEQ
+	select HAVE_RUST if CPU_LITTLE_ENDIAN
 	select HAVE_STACKPROTECTOR
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_KPROBES
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2d49aea0ff67..52d75c9483a9 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -41,6 +41,8 @@  KBUILD_CFLAGS	+= -mgeneral-regs-only	\
 KBUILD_CFLAGS	+= $(call cc-disable-warning, psabi)
 KBUILD_AFLAGS	+= $(compat_vdso)
 
+KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon"
+
 KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
 KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
 
@@ -65,7 +67,9 @@  endif
 
 ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
   KBUILD_CFLAGS += -mbranch-protection=pac-ret+bti
+  KBUILD_RUSTFLAGS += -Zbranch-protection=bti,pac-ret
 else ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
+  KBUILD_RUSTFLAGS += -Zbranch-protection=pac-ret
   ifeq ($(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET),y)
     KBUILD_CFLAGS += -mbranch-protection=pac-ret
   else
diff --git a/rust/Makefile b/rust/Makefile
index 8d75a6ffe951..8ced65c9b905 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -294,6 +294,7 @@  bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
 
 # Derived from `scripts/Makefile.clang`.
 BINDGEN_TARGET_x86	:= x86_64-linux-gnu
+BINDGEN_TARGET_arm64	:= aarch64-linux-gnu
 BINDGEN_TARGET		:= $(BINDGEN_TARGET_$(SRCARCH))
 
 # All warnings are inhibited since GCC builds are very experimental,
diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs
index 3c6cbe2b278d..ec5ef35dbe52 100644
--- a/scripts/generate_rust_target.rs
+++ b/scripts/generate_rust_target.rs
@@ -148,7 +148,9 @@  fn main() {
     let mut ts = TargetSpec::new();
 
     // `llvm-target`s are taken from `scripts/Makefile.clang`.
-    if cfg.has("X86_64") {
+    if cfg.has("ARM64") {
+        panic!("arm64 uses the builtin rustc aarch64-unknown-none target");
+    } else if cfg.has("X86_64") {
         ts.push("arch", "x86_64");
         ts.push(
             "data-layout",