[upstream] - Notes on Node.JS and MIPS and OpenWRT

There’s been a couple of questions on the forums, and bugs reported in the tracker…

Just a hint… you’re probably not going to run this, as NodeJS is focused more on ARM and AMD64 these days.

There’s been some chat on the bugtracker, but supporting NodeJS requires changes that are deep into unsupported OpenWRT territory…

Changes that would impact both Atheros and MediaTek based devices…

If one has a need to run NodeJS - there are ARM based platforms like Rpi and ARM distro’s like Armbian, where one has full and direct support.

3 Likes

Comments on the bug after deeper investigation - there was an ask to enable MIPS_FPU_EMULATION, and FWIW, as far as I can tell, it already is based on digging into the upstream 18.06 and master on OpenWRT…

Ultimately - if one is cross-compiling code outside of OpenWRT on MIPS - step carefully and understand the behaviors there across different MIPS targets.

Had a chance to do some additional investigation on the ask here…

OpenWRT 18.06, and current master has the MIPS_FPU_EMULATOR enabled for both ar71xx and ath79 targets

The proposed 304-mips_disable_fpu.patch is something different - and that patch is in the the git and explains itself - something tells me it is still in discussion and not fully committed.

MIPS and FPU is a bit complicated - general guidance is to keep the emulator on, whether on a target that does have an FPU or not, as the MIPS floating point unit has crashing bugs, and the logic with soft float is smart enough to pass on to the coprocessor the instructions that would benefit at a slight cost.

GCC is strict - so one has to include -msoft-float in the compile directives, otherwise GCC assumes that an actual FPU is present, and it starts emitting assembler code to that effect. The challenge here is that when cross compiling, unless one sets the msoft-float ether in the make file, or in the environment parameters, one is going to get hard float code out of the cross compile toolchain, hence the crashing behavior outside of the OpenWRT environment.

The blame for NodeJS (and NodeRED) is really on the NodeJS team, the upstream V8 engine, and GCC in general - MIPS could take some of the blame here as well, by having a broken hard FPU… OpenWRT and the team that manages the MIPS based platforms could do a better job of explaining the how’s and why’s, as there is much confusion around this issue.

There’s nothing to do here for GL-iNet or the OpenWRT team - it’s really up to the external application devs outside to ensure that their code properly builds.

Most of the above conjecture is incorrect.

If you want to run NodeJS - the 2.x (upto 2.264) GL-iNET firmware will run it fine. If you want the 3.x firmware you will have to compile the firmware image from the GL-iNET repo and enable the MIPS_FPU option (as it was in the 2.x release) that it suggests should be enabled by default and it will work.

In firmware v2.263 for AR300M, there is special workaround for nodejs, including patching the toolchain and enabling MIPS_FPU.

In later version we didn’t have this. I didn’t observe a lot of such requirements. It should be a little slow.

What do you think.

Which? Others and myself have only had to change the N to a Y for MIPS_FPU.

You need to compile nodejs v6.9.1 in openwrt and that is not just FPU problem.

A guy who did numerous effort on this and shared with me.

Exactly… it can be done, but this is a nodejs issue at it’s core, not openwrt

nodejs (along with v8) defaults to hard-float, which looks directly for an FPU on the MIPS

1 Like

Again, this is incorrect.

I just enabled FPU and ticked the box for NodeJS on the gl-inet/openwrt tree:

root@GL-AR300M:~# cat /etc/os-release
NAME=“OpenWrt”
VERSION=“18.06.1”
ID=“openwrt”
ID_LIKE=“lede openwrt”
PRETTY_NAME=“OpenWrt 18.06.1”
VERSION_ID=“18.06.1”
HOME_URL=“http://openwrt.org/
BUG_URL=“http://bugs.openwrt.org/
SUPPORT_URL=“http://forum.lede-project.org/
BUILD_ID=“r7258-5eb055306f”
LEDE_BOARD=“ar71xx/nand”
LEDE_ARCH=“mips_24kc”
LEDE_TAINTS=“no-all busybox override”
LEDE_DEVICE_MANUFACTURER=“OpenWrt”
LEDE_DEVICE_MANUFACTURER_URL=“http://openwrt.org/
LEDE_DEVICE_PRODUCT=“Generic”
LEDE_DEVICE_REVISION=“v0”
LEDE_RELEASE=“OpenWrt 18.06.1 r7258-5eb055306f”
root@GL-AR300M:~# node
console.log(‘Hello from NodeJS’);
Hello from NodeJS
undefined
root@GL-AR300M:~# node --version
v8.10.0

As long as your solution works - that’s ok by me…

Going off a fork (v8mips), that’s cool - but Node evolves so fast, along with the rest of the NPM development, one will eventually get stuck in time, and sooner or later, things will break again.

I went down another path, fixing NodeJS and dependencies based on the mainline from Node directly - where, again, the default for MIPS is hard for Node and V8 - which perhaps is not the right choice, considering that most folks that work on MIPS acknowledge that hard calls to a real FPU can lead to crashes.

That being said - I actually do support enabling the MIPS Floating Point Emulator, as it is canonically correct to do so - it’s solves problems, and gets ahead of others.

ar300m_fpuenable

For cross compiling and the toolchain, I just use the OpenWRT SDK, which has the toolchain, along with the rest of the ancillaries, and one can be confident externals like Node (once fixed) will be consistent.

CONFIG_TARGET_ath79=y
CONFIG_TARGET_ath79_nand=y
CONFIG_TARGET_ath79_nand_DEVICE_glinet_gl-ar300m-nand=y
CONFIG_DEVEL=y
CONFIG_KERNEL_MIPS_FPU_EMULATOR=y
CONFIG_SDK=y
CONFIG_TARGET_OPTIONS=y

Anyways - I think @jeffsf is also working on master with his efforts sorting DTS for the AR-300MLite

But 18.06 - one can build on the current 18.06 ar71xx…

BTW - an ounce of politeness is worth more than a pint of attitude - take a chill, you’re smart, and you’ll get more collaboration if you recognize that yes, some folks know more than you do.

I share this with you as a lesson learned the hard way.

Maybe that was confusing. Here it is in the NodeJS mainline code:

I configured OpenWRT to build NodeJS in menuconfig which grabs the source from nodejs.org and it works.

This is incorrect as it defaults to soft-float unless hard-float is specifically set. See above.

Incorrect. This is not a bug or a crash.

MIPS floating points do no support all operations in hardware. A MIPS implementation is free to not implement certain cases in software. For example denormalized numbers - that’s numbers very close to zero - are not handled in hardware. In such a case MIPS FPU will throw an unimplemented exception and expects the exception handler to do deal with the issue. The software in the Linux kernel handles all this and more, it’s capable of fully emulating a hardware floating point unit. That is code built for hardware floating point will always run correctly, even on systems without an FPU.

https://www.linux-mips.org/wiki/Floating_point#The_Linux_kernel_and_floating_point

@nopro404 - I don’t think I can help you any further - have a nice hugging day, mate…

You can copy/paste from the top of the stack to fix a single thing, or work up from the bottom to fix many things.

As long as your situation works - all good…