Message ID | 20240905-mips-rust-v2-3-409d66819418@flygoat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | rust: Initial MIPS support | expand |
On Thu, 5 Sep 2024, Jiaxun Yang wrote: > diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs > index 863720777313..bbdf8a4dd169 100644 > --- a/scripts/generate_rust_target.rs > +++ b/scripts/generate_rust_target.rs [...] > + } else { > + ts.push("arch", "mips"); > + cfg.get("TARGET_ISA_REV").map(|isa_rev| { > + let feature = match isa_rev.as_str() { > + "1" => ",+mips32", > + "2" => ",+mips32r2", > + "5" => ",+mips32r5", > + "6" => ",+mips32r6", > + _ => ",+mips2", What's the consequence of using `mips2' rather than `mips1' here? How about other ISA revisions, e.g. `mips4' (that also applies to the 64BIT leg)? Maciej
在2024年9月8日九月 下午9:43,Maciej W. Rozycki写道: > On Thu, 5 Sep 2024, Jiaxun Yang wrote: > >> diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs >> index 863720777313..bbdf8a4dd169 100644 >> --- a/scripts/generate_rust_target.rs >> +++ b/scripts/generate_rust_target.rs > [...] >> + } else { >> + ts.push("arch", "mips"); >> + cfg.get("TARGET_ISA_REV").map(|isa_rev| { >> + let feature = match isa_rev.as_str() { >> + "1" => ",+mips32", >> + "2" => ",+mips32r2", >> + "5" => ",+mips32r5", >> + "6" => ",+mips32r6", >> + _ => ",+mips2", > > What's the consequence of using `mips2' rather than `mips1' here? How > about other ISA revisions, e.g. `mips4' (that also applies to the 64BIT > leg)? LLVM's mips1 backend is a little bit broken beyond repair, so I tried to use mips2 as a baseline. I should probably let HAVE_RUST depend on !CPU_R3000 to get it covered. We have no good way to tell ISA reversion prior to R1 just from Kconfig TARGET_ISA_REV, valid numbers for TARGET_ISA_REV are only 1, 2, 5, 6 from Kconfig. Given that mips 2 and 3 binaries (Rust object files) can link run flawlessly on all pre-R6 (despite R3000) hardware with matching bitness, they were chosen as fallback here. Thanks > > Maciej
On Thu, 05 Sep 2024 14:33:07 +0100 Jiaxun Yang <jiaxun.yang@flygoat.com> wrote: > Enable rust for linux by implement generate_rust_target.rs > and select relevant Kconfig options. > > We don't use builtin target as there is no sutiable baremetal > target for us that can cover all ISA variants supported by kernel. > > Link: https://github.com/Rust-for-Linux/linux/issues/107 > Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> > --- > v2: > - Add micromips flags > - Sync issues with upstream > --- > Documentation/rust/arch-support.rst | 1 + > .../translations/zh_CN/rust/arch-support.rst | 1 + > arch/mips/Kconfig | 2 + > scripts/generate_rust_target.rs | 68 ++++++++++++++++++++++ > 4 files changed, 72 insertions(+) > > diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst > index 750ff371570a..ab6c0ae5a407 100644 > --- a/Documentation/rust/arch-support.rst > +++ b/Documentation/rust/arch-support.rst > @@ -17,6 +17,7 @@ Architecture Level of support Constraints > ============= ================ ============================================== > ``arm64`` Maintained Little Endian only. > ``loongarch`` Maintained \- > +``mips`` Maintained \- > ``riscv`` Maintained ``riscv64`` only. > ``um`` Maintained \- > ``x86`` Maintained ``x86_64`` only. > diff --git a/Documentation/translations/zh_CN/rust/arch-support.rst b/Documentation/translations/zh_CN/rust/arch-support.rst > index abd708d48f82..1eaa6c3297ac 100644 > --- a/Documentation/translations/zh_CN/rust/arch-support.rst > +++ b/Documentation/translations/zh_CN/rust/arch-support.rst > @@ -21,6 +21,7 @@ > ============= ================ ============================================== > ``arm64`` Maintained 只有小端序 > ``loongarch`` Maintained \- > +``mips`` Maintained \- > ``riscv`` Maintained 只有 ``riscv64`` > ``um`` Maintained 只有 ``x86_64`` > ``x86`` Maintained 只有 ``x86_64`` > diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig > index 43da6d596e2b..a91f0a4fd8e9 100644 > --- a/arch/mips/Kconfig > +++ b/arch/mips/Kconfig > @@ -90,6 +90,8 @@ config MIPS > select HAVE_PERF_USER_STACK_DUMP > select HAVE_REGS_AND_STACK_ACCESS_API > select HAVE_RSEQ > + select HAVE_RUST > + select HAVE_GENERATE_RUST_TARGET > select HAVE_SPARSE_SYSCALL_NR > select HAVE_STACKPROTECTOR > select HAVE_SYSCALL_TRACEPOINTS > diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs > index 863720777313..bbdf8a4dd169 100644 > --- a/scripts/generate_rust_target.rs > +++ b/scripts/generate_rust_target.rs > @@ -141,6 +141,13 @@ fn has(&self, option: &str) -> bool { > let option = "CONFIG_".to_owned() + option; > self.0.contains_key(&option) > } > + > + /// Returns the value of the option in the configuration. > + /// The argument must be passed without the `CONFIG_` prefix. > + fn get(&self, option: &str) -> Option<&String> { > + let option = "CONFIG_".to_owned() + option; > + self.0.get(&option) I know you follow the code style above, but this should be let option = format!("CONFIG_{option}"); > + } > } > > fn main() { > @@ -203,6 +210,67 @@ fn main() { > ts.push("target-pointer-width", "32"); > } else if cfg.has("LOONGARCH") { > panic!("loongarch uses the builtin rustc loongarch64-unknown-none-softfloat target"); > + } else if cfg.has("MIPS") { > + let mut features = "+soft-float,+noabicalls".to_string(); > + > + if cfg.has("CPU_MICROMIPS") { > + features += ",+micromips"; > + } > + > + if cfg.has("64BIT") { > + ts.push("arch", "mips64"); > + ts.push("abi", "abi64"); > + cfg.get("TARGET_ISA_REV").map(|isa_rev| { if let Some(isa_rev) = cfg.get("TARGET_ISA_REV") { ... } > + let feature = match isa_rev.as_str() { > + "1" => ",+mips64", > + "2" => ",+mips64r2", > + "5" => ",+mips64r5", > + "6" => ",+mips64r6", > + _ => ",+mips3", > + }; > + features += feature; > + }); > + > + ts.push("features", features); > + if cfg.has("CPU_BIG_ENDIAN") { > + ts.push( > + "data-layout", > + "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128", > + ); > + ts.push("llvm-target", "mips64-unknown-linux-gnuabi64"); > + } else { > + ts.push( > + "data-layout", > + "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128", > + ); > + ts.push("llvm-target", "mips64el-unknown-linux-gnuabi64"); > + } > + ts.push("target-pointer-width", "64"); > + } else { > + ts.push("arch", "mips"); > + cfg.get("TARGET_ISA_REV").map(|isa_rev| { ditto > + let feature = match isa_rev.as_str() { > + "1" => ",+mips32", > + "2" => ",+mips32r2", > + "5" => ",+mips32r5", > + "6" => ",+mips32r6", > + _ => ",+mips2", > + }; > + features += feature; > + }); > + > + ts.push("features", features); > + if cfg.has("CPU_BIG_ENDIAN") { > + ts.push("data-layout", > + "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"); > + ts.push("llvm-target", "mips-unknown-linux-gnu"); > + } else { > + ts.push("data-layout", > + "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"); > + ts.push("llvm-target", "mipsel-unknown-linux-gnu"); > + } > + ts.push("target-pointer-width", "32"); > + } > } else { > panic!("Unsupported architecture"); > } > Best, Gary
On Mon, 9 Sep 2024, Jiaxun Yang wrote: > >> diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs > >> index 863720777313..bbdf8a4dd169 100644 > >> --- a/scripts/generate_rust_target.rs > >> +++ b/scripts/generate_rust_target.rs > > [...] > >> + } else { > >> + ts.push("arch", "mips"); > >> + cfg.get("TARGET_ISA_REV").map(|isa_rev| { > >> + let feature = match isa_rev.as_str() { > >> + "1" => ",+mips32", > >> + "2" => ",+mips32r2", > >> + "5" => ",+mips32r5", > >> + "6" => ",+mips32r6", > >> + _ => ",+mips2", > > > > What's the consequence of using `mips2' rather than `mips1' here? How > > about other ISA revisions, e.g. `mips4' (that also applies to the 64BIT > > leg)? > > LLVM's mips1 backend is a little bit broken beyond repair, so I tried to use mips2 > as a baseline. I should probably let HAVE_RUST depend on !CPU_R3000 to get it covered. GCC works just fine I suppose, just as with the other language frontends, doesn't it? > We have no good way to tell ISA reversion prior to R1 just from Kconfig TARGET_ISA_REV, > valid numbers for TARGET_ISA_REV are only 1, 2, 5, 6 from Kconfig. This approach doesn't work for some MIPS architecture processor configs anyway, e.g. what ISA revision will CPU_P5600 imply here? However if there's a need (and previously there wasn't), then I think it can be sorted in a straightforward way. We have just a bunch of CPU_* settings and we can define corresponding ISA_* settings to select, e.g. ISA_MIPS1, ISA_MIPS3, ISA_MIPS32_R1, ISA_MIPS64_R6, and so on, based on information extracted from per-CPU_* `-march=' compilation flags from arch/mips/Makefile (possibly combined with ISA data obtained from GCC/binutils for said flags). It could be a bit tedious to write, but not a big challenge really, just mechanical work. > Given that mips 2 and 3 binaries (Rust object files) can link run flawlessly on all pre-R6 > (despite R3000) hardware with matching bitness, they were chosen as fallback here. I'm fine with having a MIPS1/R3000 exception for broken LLVM, but I see no reason to disable it for GCC. Maciej
在2024年9月10日九月 下午5:03,Maciej W. Rozycki写道: > On Mon, 9 Sep 2024, Jiaxun Yang wrote: > >> > What's the consequence of using `mips2' rather than `mips1' here? How >> > about other ISA revisions, e.g. `mips4' (that also applies to the 64BIT >> > leg)? >> >> LLVM's mips1 backend is a little bit broken beyond repair, so I tried to use mips2 >> as a baseline. I should probably let HAVE_RUST depend on !CPU_R3000 to get it covered. > > GCC works just fine I suppose, just as with the other language frontends, > doesn't it? Nah, currently we can only use rustc with LLVM backend. target.json file we are generating here is also LLVM backend only for rustc. gccrs is not usable for kernel yet. > >> We have no good way to tell ISA reversion prior to R1 just from Kconfig TARGET_ISA_REV, >> valid numbers for TARGET_ISA_REV are only 1, 2, 5, 6 from Kconfig. > > This approach doesn't work for some MIPS architecture processor configs > anyway, e.g. what ISA revision will CPU_P5600 imply here? TARGET_ISA_REV will be set to 5 for CPU_P5600 (CPU_MIPSR5 will default to y on CPU_P5600, and CPU_MIPSR5 sets TARGET_ISA_REV to 5). > > However if there's a need (and previously there wasn't), then I think it > can be sorted in a straightforward way. We have just a bunch of CPU_* > settings and we can define corresponding ISA_* settings to select, e.g. > ISA_MIPS1, ISA_MIPS3, ISA_MIPS32_R1, ISA_MIPS64_R6, and so on, based on > information extracted from per-CPU_* `-march=' compilation flags from > arch/mips/Makefile (possibly combined with ISA data obtained from > GCC/binutils for said flags). > > It could be a bit tedious to write, but not a big challenge really, just > mechanical work. TARGET_ISA_REV is guaranteed to be aligned with CPU's supported ISA for now, so I see no reason to invent another set of symbols.... > >> Given that mips 2 and 3 binaries (Rust object files) can link run flawlessly on all pre-R6 >> (despite R3000) hardware with matching bitness, they were chosen as fallback here. > > I'm fine with having a MIPS1/R3000 exception for broken LLVM, but I see > no reason to disable it for GCC. It actually reminds me that LLVM lacks R4000 and some other workarounds as well. I shall fix those in Kconfig as well. Thanks > > Maciej
On Tue, 10 Sep 2024, Jiaxun Yang wrote: > >> We have no good way to tell ISA reversion prior to R1 just from Kconfig TARGET_ISA_REV, > >> valid numbers for TARGET_ISA_REV are only 1, 2, 5, 6 from Kconfig. > > > > This approach doesn't work for some MIPS architecture processor configs > > anyway, e.g. what ISA revision will CPU_P5600 imply here? > > TARGET_ISA_REV will be set to 5 for CPU_P5600 (CPU_MIPSR5 will default to y > on CPU_P5600, and CPU_MIPSR5 sets TARGET_ISA_REV to 5). > > > > However if there's a need (and previously there wasn't), then I think it > > can be sorted in a straightforward way. We have just a bunch of CPU_* > > settings and we can define corresponding ISA_* settings to select, e.g. > > ISA_MIPS1, ISA_MIPS3, ISA_MIPS32_R1, ISA_MIPS64_R6, and so on, based on > > information extracted from per-CPU_* `-march=' compilation flags from > > arch/mips/Makefile (possibly combined with ISA data obtained from > > GCC/binutils for said flags). > > > > It could be a bit tedious to write, but not a big challenge really, just > > mechanical work. > > TARGET_ISA_REV is guaranteed to be aligned with CPU's supported ISA for now, > so I see no reason to invent another set of symbols.... Ah, OK then, I missed these bits, thanks for pointing them out. So we only need to define CPU_MIPS1, CPU_MIPS3, and CPU_MIPS4 settings (we have no support for any MIPS II CPU; there was the R6000 only at that ISA level, exeedingly rare and unreliable) analogously to and along with the existing CPU_MIPSR1, CPU_MIPSR2, etc., which is even simpler. They can then be used accordingly for TARGET_ISA_REV == 0, either directly or perhaps via an additional TARGET_LEGACY_ISA_REV setting. Maciej
diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst index 750ff371570a..ab6c0ae5a407 100644 --- a/Documentation/rust/arch-support.rst +++ b/Documentation/rust/arch-support.rst @@ -17,6 +17,7 @@ Architecture Level of support Constraints ============= ================ ============================================== ``arm64`` Maintained Little Endian only. ``loongarch`` Maintained \- +``mips`` Maintained \- ``riscv`` Maintained ``riscv64`` only. ``um`` Maintained \- ``x86`` Maintained ``x86_64`` only. diff --git a/Documentation/translations/zh_CN/rust/arch-support.rst b/Documentation/translations/zh_CN/rust/arch-support.rst index abd708d48f82..1eaa6c3297ac 100644 --- a/Documentation/translations/zh_CN/rust/arch-support.rst +++ b/Documentation/translations/zh_CN/rust/arch-support.rst @@ -21,6 +21,7 @@ ============= ================ ============================================== ``arm64`` Maintained 只有小端序 ``loongarch`` Maintained \- +``mips`` Maintained \- ``riscv`` Maintained 只有 ``riscv64`` ``um`` Maintained 只有 ``x86_64`` ``x86`` Maintained 只有 ``x86_64`` diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 43da6d596e2b..a91f0a4fd8e9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -90,6 +90,8 @@ config MIPS select HAVE_PERF_USER_STACK_DUMP select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RSEQ + select HAVE_RUST + select HAVE_GENERATE_RUST_TARGET select HAVE_SPARSE_SYSCALL_NR select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs index 863720777313..bbdf8a4dd169 100644 --- a/scripts/generate_rust_target.rs +++ b/scripts/generate_rust_target.rs @@ -141,6 +141,13 @@ fn has(&self, option: &str) -> bool { let option = "CONFIG_".to_owned() + option; self.0.contains_key(&option) } + + /// Returns the value of the option in the configuration. + /// The argument must be passed without the `CONFIG_` prefix. + fn get(&self, option: &str) -> Option<&String> { + let option = "CONFIG_".to_owned() + option; + self.0.get(&option) + } } fn main() { @@ -203,6 +210,67 @@ fn main() { ts.push("target-pointer-width", "32"); } else if cfg.has("LOONGARCH") { panic!("loongarch uses the builtin rustc loongarch64-unknown-none-softfloat target"); + } else if cfg.has("MIPS") { + let mut features = "+soft-float,+noabicalls".to_string(); + + if cfg.has("CPU_MICROMIPS") { + features += ",+micromips"; + } + + if cfg.has("64BIT") { + ts.push("arch", "mips64"); + ts.push("abi", "abi64"); + cfg.get("TARGET_ISA_REV").map(|isa_rev| { + let feature = match isa_rev.as_str() { + "1" => ",+mips64", + "2" => ",+mips64r2", + "5" => ",+mips64r5", + "6" => ",+mips64r6", + _ => ",+mips3", + }; + features += feature; + }); + + ts.push("features", features); + if cfg.has("CPU_BIG_ENDIAN") { + ts.push( + "data-layout", + "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128", + ); + ts.push("llvm-target", "mips64-unknown-linux-gnuabi64"); + } else { + ts.push( + "data-layout", + "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128", + ); + ts.push("llvm-target", "mips64el-unknown-linux-gnuabi64"); + } + ts.push("target-pointer-width", "64"); + } else { + ts.push("arch", "mips"); + cfg.get("TARGET_ISA_REV").map(|isa_rev| { + let feature = match isa_rev.as_str() { + "1" => ",+mips32", + "2" => ",+mips32r2", + "5" => ",+mips32r5", + "6" => ",+mips32r6", + _ => ",+mips2", + }; + features += feature; + }); + + ts.push("features", features); + if cfg.has("CPU_BIG_ENDIAN") { + ts.push("data-layout", + "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"); + ts.push("llvm-target", "mips-unknown-linux-gnu"); + } else { + ts.push("data-layout", + "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"); + ts.push("llvm-target", "mipsel-unknown-linux-gnu"); + } + ts.push("target-pointer-width", "32"); + } } else { panic!("Unsupported architecture"); }
Enable rust for linux by implement generate_rust_target.rs and select relevant Kconfig options. We don't use builtin target as there is no sutiable baremetal target for us that can cover all ISA variants supported by kernel. Link: https://github.com/Rust-for-Linux/linux/issues/107 Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> --- v2: - Add micromips flags - Sync issues with upstream --- Documentation/rust/arch-support.rst | 1 + .../translations/zh_CN/rust/arch-support.rst | 1 + arch/mips/Kconfig | 2 + scripts/generate_rust_target.rs | 68 ++++++++++++++++++++++ 4 files changed, 72 insertions(+)