-
Notifications
You must be signed in to change notification settings - Fork 914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MIPS on Linux support #1075
Comments
As far as I can tell, there are only a few things required to add support for such a target:
I can't think of anywhere else where changes would be necessary. After the appropriate changes are added, you should be able to build for MIPS by supplying an appropriate LLVM target to the |
Is there specific MIPS hardware you are looking to support? |
@deadprogram This issue seems to be regarding a Linux target, rather than baremetal. |
Yeah, It would be great to have bare metal support for mips24kc out of the box since that's basically used by most routers. UPDATE:It seems that after manually building LLVM as mentioned in Getting Started doesn't contain mips arch as a target
|
Are you interested in baremetal or Linux support?
Yes, you need to modify this line to add Mips to the enabled targets: Line 157 in a9ba6eb
It may be easier to instead use a prebuilt version of LLVM, which you can easily install on MacOS and most Linux distributions. It will have Mips already included as a target (no need to rebuild LLVM). |
Thank you for the tip, I was already digging inside, getting that little mipsy mips support in LLVM 😄
I am honestly interested in having it work in both Linux and bare metal but I do understand that bringing bare metal support is a bit out of my skill scope, but I am very eager to learn and contribute UPDATE:Well, after some tinkering around, I was successfully able to compile mipsel targeted binaries (statically linked) and as well as executing them Here are the file size differences between golang compiled binaries and tinygo:
package main
func main() {
print("HELLO\n")
} Note: the binaries were compiled with omitted DWARF debugging information as well as symbol table generation using a brief
What's interesting here is the produced (by default) dynamically linked binary that is small in size albeit depending on libc.so.6 (glibC) which is missing by default on OpenWRT (muslC), so in order to fix this, an openwrt musl toolchain should be used but this out of the scope of this issue but I will eventually document that as soon as I'm finished. |
I'm also interrested on compiling for MTK7628NN with Linux support. With Go I select GOARCH=mipsle GOMIPS=softfloat. |
@olarriga this is not yet implemented, see my first comment on this issue |
Yes, it's possible and beautiful, I'm currently working on it, will have a PR and a documentation published soon. UPDATE:Currently the compilation is spewing a warning concerning wrong floating point setting but the binary is functioning properly, yet to figure out where to put the -msoft-float flag in tinygo/llvm given that the musl toolchain already uses -msoft-float
UPDATE:Seems like -msoft-float flag is being ignored by llvm/clang, but considering that the binaries are working properly, it isn't critical atm. UPDATE:After having configured both the mips and mipsel toolchains, I went ahead and tried to compile a sample golang code using the fmt library, the compiler spewed the following:
I figured that UPDATE:After hours of thorough studying of mips specs and docs, I have found out that the /o32 ABI only has 4 argument registers which is less than syscall6 arg length 🤔... additionally, the syscall manpage mentions that the syscall convention passes arguments 5+ through 8 on the user stack but that requires a different implementation in gollvm(?).. UPDATE:I had no luck in assembling a working solution so far so it's a roadblock at the moment, basically everything works but syscalls |
You probably need to set a flag (
Ah really, they are passing syscall arguments on the stack? That complicates things a bit. |
Any update on this? |
Unfortunately not, I have decided that writing code for MIPS based embedded devices is much better done via C/C++. |
Is there no reference value for the system call of the golang source code Go\src\syscall. Although C/C++ is good, cross-compilation is troublesome, and development efficiency is not good. Rust solves the cross-compilation problem well. |
Any update on this? This will really be very beneficial for running go code on routers. |
We could do it, but I haven't seen a lot of demand (except for this issue). I'm somewhat worried about the maintenance burden this will cause, because it would add yet another architecture. We currently support arm, arm64, 386, amd64, avr, xtensa, and wasm. But if there is enough demand or a good use case, this would certainly be interesting to support. |
Writing networking and server code for routers with go should be a very interesting use case. The main reason why go isn't even considered is because of the huge binary size, but if tiny go can be made to work with these routers, it will be a very good alternative to C/C++ for many cases. Example: |
I think mips is much more important than 386 and amd64. Mips are only embedded devices such as routing. On the contrary, 386 amd64 devices have huge space and can use official compilers. |
You could target wasm and then run wasm on mips...
…On Wed, 21 Sept 2022, 6:05 am dosgo, ***@***.***> wrote:
We could do it, but I haven't seen a lot of demand (except for this
issue). I'm somewhat worried about the maintenance burden this will cause,
because it would add yet another architecture. We currently support arm,
arm64, 386, amd64, avr, xtensa, and wasm. But if there is enough demand or
a good use case, this would certainly be interesting to support.
I think mips is much more important than 386 and amd64. Mips are only
embedded devices such as routing. On the contrary, 386 amd64 devices have
huge space and can use official compilers.
—
Reply to this email directly, view it on GitHub
<#1075 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AALP3FCFUTUKY2C764GXDX3V7J3OJANCNFSM4MRREVEA>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
So if we would add support for MIPS, which would it be? Apparently there are 4 MIPS architecture variants that we could support:
I don't think 64-bit MIPS needs TinyGo, so that leaves it with |
The mips endian seems to be OS dependent! https://openwrt.org/docs/platforms/start is little endian more. |
Was any decision made regarding this issue? |
We (Jangala - a charity that makes internet access systems for schools and clinics for marginalised communities around the world) would love to see this added. We currently use Lua for our codebase but are thinking of using TinyGo on our MCUs and would love to use it on our Arm64 and MIPS based boards that are running OpenWrt/Linux. The Ath79 target (a hugely popular router and AP chipset family) is big endian. If this became available it could be hugely popular amongst the OpenWrt community (who currently don't see Go as a viable option). For example, the Mender IoT remote package that @mutexstream references generates a 2MB+ binary which is prohibitive on this kind of target. |
Wasm seems interesting but by necessity the code we write interacts with system libraries and the kernel directly, which I guess (not knowing a huge amount about it) might be more difficult with Wasm |
I can look into adding support for MIPS. But again: which variant would be preferred or would actually be used in practice? There are four to pick from for initial support. "MIPS" is really more like 4 different architectures under a single name. (Note: big endian is probably going to be more difficult than little endian). |
Just looking at the number of end user devices that would be hit, I'd probably suggest the following order of priority:
The rationale for this is that just the ath79 family alone represents probably hundreds of millions of target devices worldwide |
I did some experimenting with MIPS support and managed to get very limited support working:
I have no plans currently to continue working on this, but if there's anybody interested feel free to complete support for MIPS. The branch is here: dev...mips |
Not yet, I'm working on it. |
I can confirm that current dev branch of TinyGo successfully builds the binary that works on the above HW. Great job @aykevl ! The super basic test - create package main
func main() {
println("hello world")
} Build with Docker:
What's interesting is the file size difference - when I build the
But after running
|
@DJAGABATWORK this might fix the issue: #4371 |
@b0ch3nski I don't know why that is, my guess is that MIPS is an even less efficient instruction set than amd64 (or it hasn't gotten a lot of optimization work). To reduce binary size, you can also try |
@b0ch3nski 's Docker example got me on the right track. Thank you.
Running from the same directory were the main.go file is. contents of main.go package main
func main() {
println("Hello from here")
}
Execution results:
So it is working with simple Hello World example on big endian mips. too! Good job @aykevl |
How did you test it? It's not merged, so if you used Docker you weren't using that change. (Also I formatted your comment a little, I hope you don't mind). |
So I found that Go normally uses MIPS32r1 as the minimum requirement, while TinyGo uses MIPS32r2. That could be a reason why it crashes. |
@aykevl @DJAGABATWORK HW seems to be MIPS32_24Kc (mips32r2): https://openwrt.org/docs/techref/instructionset/mips_24kc While my HW is MIPS32_1004Kc: https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MIPS32_1004K_1211.pdf |
You probably just got lucky. A hello world example is unlikely to use FPU instructions, and appears to also have avoided the new instructions introduced in mips32r2. After the softfloat PR is merged, I intend to make a new PR that switches to mips32r1 (aka mips32). |
Wouldn't it make sense to also have this configurable somehow? I realize that this potentially can break a lot of stuff but "I want to shoot myself in the foot" kind of switches are already present in TinyGo 😄 |
@b0ch3nski there's an accepted proposal for that: golang/go#60072 |
@aykevl: I have attached the binary in question.
Sorry. Somehow I assumed it was already merged. |
@DJAGABATWORK I found a way to detect invalid instructions using It looks like the sdc1 is present when building examples/serial with the dev branch, but with the mips-softfloat branch (#4371) it is avoided when you use |
@aykevl I noticed that the #4371 got merged. Therefore I tried the docker version again with softfloat support: The following occurred:
|
Without the softfloat option the command succeeds. |
Oh great, that looks like a LLVM bug. Can you provide the source, so that I can reproduce this issue locally? |
Can you provide the source, so that I can reproduce this issue locally? @aykevl Sure:
|
This is great progress! Thank you for working on this long awaited feature. Does the garbage collection work properly in this setup? |
Yes, it appears it should support everything except 64-bit atomics. |
I was wondering, With the supplied contents of main.go as the source, were you able to reproduce it locally @aykevl? |
@DJAGABATWORK yes I can reproduce the issue! This definitely looks like a LLVM bug. |
This should fix the issue: #4425 |
@aykevl: I've just tried it again after noticing #4425 got pushed to the dev branch.
The result on the Teltonika trying to execute the binary is the following:
|
@DJAGABATWORK well that's awkward. See: #4428 |
And to avoid MIPS32r2 instructions: #4429 |
Hmm. Well at least it works now with a simple example built with softfloat enabled running on a TRB-255. Good job! |
That one has a MIPS32r2 chip according to the product page (24Kc). So #4429 should not be needed. However there is also #4430 (and other to-be-written PRs) to fully support big-endian systems. Right now there are a few bugs for these systems, as MIPS is the first chip for TinyGo that's big endian and the compiler/stdlib still assumes little endian in a few places. |
Fixed another MIPS big-endian issue (the reflect package) so now it's almost on par with MIPS little-endian: #4430 Oh and I've seen an issue with unaligned loads/stores in the reflect package that I haven't investigated yet, a workaround is |
Closing since some MIPS support is now in TinyGo. Let's open new specific issues as needed. Thank you! |
It seems that tinygo doesn't not support MIPS based embedded devices out of the box, although LLVM does support the following:
My intent is to execute the tinygo compiled binary within a mipsel linux box, no bare metal support, so I assume that's feasible considering llvm support.
This would be extremely useful for routers with a limited set of storage and ram.
The text was updated successfully, but these errors were encountered: