eclipse-openj9 / openj9

Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combines with the Extensions for OpenJDK for OpenJ9 repo.
Other
3.27k stars 721 forks source link

PowerPC 32-bit (G4) build fails with "unsupported OpenJ9 cpu powerpc" #2399

Closed wyatt8740 closed 6 years ago

wyatt8740 commented 6 years ago

I tried to build OpenJ9 for a PowerBook G4 running Debian today, and was met with the following failure while running the configure script in openj9-openjdk-jdk8:

checking build system type... powerpc-unknown-linux-gnu
checking host system type... powerpc-unknown-linux-gnu
checking target system type... powerpc-unknown-linux-gnu
checking openjdk-build os-cpu... linux-ppc
checking openjdk-target os-cpu... linux-ppc
checking compilation type... native
checking for presence of closed sources... no
checking if closed source is suppressed (openjdk-only)... no
checking which variant of the JDK to build... normal
checking which interpreter of the JVM to build... template
checking which variants of the JVM to build... server
checking which debug level to use... release
configure: error: unsupported OpenJ9 cpu powerpc
configure exiting with result code 1

I was under the impression that J9 supported 32-bit PowerPC CPU's, at least the 604. I do definitely remember IBM's Java 6 package ran on my Powerbook, when I told the JIT to generate PPC 604 instructions.

Was 32-bit PPC support dropped at some point between 2010 (last update to IBM's Java 1.6 J9 VM) and the initial open source release?

Or is there just something wrong with the configure script? A quick grep of the J9 sources indicates that there are still definitions present for the old CPU's (like the 601, 604, and 7xx chips).

A reasonable question would be, "Why are you trying to use a PowerBook G4 running Linux in 2018?" - my answer would simply be that:

  1. Keeping software concious of other architectures' existance is always a good thing and can result in more robust programs,
  2. As a college student, I simply can't afford a Talos II or the energy consumption of a Powermac G5, and
  3. I want J9 in particular on this powerbook because the 'regular' OpenJDK with zero JVM is ridiculously slow, and I'd like to keep this computer as useful as I can.

I do have an older amd64 machine with 8GB of RAM that I can cross compile it from, and another with 16, so RAM usage during compilation isn't a large concern for me.

Is there still any support in J9 for 32-bit PowerPC systems that could be enabled?

fjeremic commented 6 years ago

@gita-omr @ymanton @zl-wang FYI. IIRC @wyatt8740 I do think we dropped support but the people subscribed can confirm.

ymanton commented 6 years ago

OpenJ9 on Linux has only ever supported ppc64le, not ppc64 nor ppc32. It's the IBM JDK that still supports the latter two. The bulk of the code base is the same between OpenJ9 and the IBM JDK so there's no reason that OpenJ9 couldn't support them, it's just that it currently doesn't (and probably wont unless there is significant interest and volunteers to do the work). As you suspected, it's mostly the build environment that doesn't support it, the JVM itself should still run on ppc32 if you can get it to build.

pdbain-ibm commented 6 years ago

@dnakamura @gacholio do we still support 32-bit PowerPC?

pshipton commented 6 years ago

@ymaton OpenJ9 doesn't support 32-bit POWER processors, just a 32-bit VM running on 64-bit processors. According to https://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.80.doc/user/supported_env_80.html the minimums are POWER 4 for AIX and POWER 6 for Linux.

Also note OpenJDK also needs to support the platform, not just OpenJ9.

dragontamer8740 commented 6 years ago

@pshipton so the actual code for 32 bit POWER was already gone from IBM's code base when OpenJ9 got released? Or it just doesn't officially provide support for such builds?

At one point, IBM's J9 did run on G4's. I have 1.6 installed on my powerbook now.

That's disappointing (but hardly surprising considering the hardware's age). Thanks for letting me know. And OpenJDK does still function (very slowly) on 32-bit powerpc, when using the "zero" VM. So I don't know if the OpenJDK side would be an issue. Debian ports makes powerpc builds for OpenJDK with the zero VM up to and including OpenJDK 11.

Also, were I by some miracle able to re-introduce 32-bit PPC support into OpenJ9, would there be a chance of it being accepted if I made a pull request?

ymanton commented 6 years ago

OpenJ9 doesn't support 32-bit POWER processors, just a 32-bit VM running on 64-bit processors.

There is one place that I'm personally aware of where we expect (out of necessity) the processor is 64-bit capable despite the fact that it's a 32-bit build, but it's guarded by checks for specific processors and written to cope with the hazards. Are there others and are they unguarded?

If not, I'm struggling to think of any other reason why a 32-bit VM wouldn't run on an actual 32-bit processor, particularly if it was built from source on a relatively recent distro like Debian 8.

pshipton commented 6 years ago

I believe the code is gone/modified before OpenJ9 was released. @gacholio might remember more details. Somebody mentioned OpenJ9 using a compare and swap instruction that doesn't exist on the older processor, not sure if that is accurate.

pshipton commented 6 years ago

were I by some miracle able to re-introduce 32-bit PPC support into OpenJ9, would there be a chance of it being accepted if I made a pull request?

It depends on the extent of the changes. It won't be possible to maintain or ensure the changes keep working when other changes are made.

pshipton commented 6 years ago

Also note https://github.com/eclipse/openj9/blob/c351e884e20354ad9b612a876a65a4c507b9a1f6/runtime/vm/jvminit.c#L920

gacholio commented 6 years ago

Java requires the ability to use 64-bit atomics (Unsafe.compareAndSwapLong, etc). I don't believe that would be possible to implement on PPC32.

pdbain-ibm commented 6 years ago

A quick grep of the J9 sources indicates that there are still definitions present for the old CPU's (like the 601, 604, and 7xx chips).

I found references to legacy PPC CPUs in runtime/compiler/env/ProcessorDetection.cpp, j9sysinfo.c, j9port.h. We should remove those.

ymanton commented 6 years ago

Just to satisfy my own curiousity I gave this a try on Qemu, running Debian 8 as a G4, and after sidestepping that check in jvminit.c it eventually crashed on a ldarx coming from J9CAS8Helper called from the interpreter, which is the 64-bit atomics issue @gacholio mentioned. Executed a decent amount of code and compiled a handful of methods prior to that though, so there is hope for anyone really keen on this.

gacholio commented 6 years ago

The amount of time required to fix this could probably be better spent at a paying job so a new laptop could be purchased :)

The main issue here is that we would need runtime checks around the atomic operations (and possibly more) in the VM to see if we could use the hand-coded CAS, or fall back to something like a mutex. This would be a pervasive change that I believe would not be accepted into the codebase as it would penalize the supported hardware configurations.

ymanton commented 6 years ago

I agree a runtime check would be distasteful, but a build time config switch on the other hand...

Besides, anyone who has the time/skill/motivation to keep these old PPC machines going might also have time to contribute some good patches. :smirk:

gacholio commented 6 years ago

True, I'm still thinking in the past where wanted one VM to run everywhere we support. @pshipton comments still stand, that we would be unable to maintain it.

wyatt8740 commented 6 years ago

Thanks for the tips and interest on this issue. I might give it a shot when I'm back from vacation, because I really like the idea of a faster JVM for my powerbook. I'm just not sure I have the required level of skill or the want it badly enough to make it happen, when I can just run my same Java code on an x86 compatible running a JVM. That said, since there's still 32 bit JVM offerings for intel cpu's, I'd assume it's possible to implement things like Unsafe.compareAndSwapLong on 32 bit PPC as well, if not very efficiently. It's a turing complete computer, after all.

gacholio commented 6 years ago

x86 has cmpxchg8b to perform 64-bit CAS. The issue on PPC is "tearing" on 64-bit accesses (performing two 32-bit reads may be interrupted by another thread performs writes).

On supported 32-bit platforms, we play some tricks to perform atomic 64-bit read/write for volatile variables (ARM uses a compiler built-in CAS, x86 and PPC use 64-bit floating point instructions, s390 uses load/store multiple which guarantees atomicity).

On Linux PPC-32, you may be able to use the ARM trick if the compiler allows it - see https://github.com/eclipse/openj9/blob/master/runtime/util/arm32/volatile.c for details.

Essentially, a read uses CAS of two identical values to ensure the underlying memory is not modified, and the builtin returns the old, atomically-read value. The write reads the memory (possibly with tearing), and swaps in the desired value, under the assumption that if there are concurrent updates to the memory, it doesn't matter who wins.

To try this, you can copy the above file into the xp32 directory (deleting volatile.s first) and set the compiler CPU target appropriately.

wyatt8740 commented 6 years ago

Thanks for the tips, you've been extremely helpful and it's greatly appreciated. I'm new to low-level stuff on hardware more recent than the 6502 or Z80 CPU's, so this was all news to me and I had honestly never considered thread safety concerns. Once I have access to a laptop or desktop I will see what I can do.

gacholio commented 6 years ago

6502 and Z80 are my roots as well.

I went off on a tangent about volatile and confused the issue - volatile should be fine, it's CAS that needs to change:

https://github.com/eclipse/omr/blob/master/include_core/AtomicSupport.hpp

Try changing:

return J9CAS8Helper(address, ((uint32_t)&oldValue)[1], ((uint32_t)&oldValue)[0], ((uint32_t)&newValue)[1], ((uint32_t)&newValue)[0]);

to:

return __sync_val_compare_and_swap(address, oldValue, newValue);

Assuming you're using gcc.

JamesKingdon commented 6 years ago

Just a note that this is not just a legacy hardware issue. 32bit Power is quite popular in the embedded space, with significant families of processors currently in production.