Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-23914

SIGBUS due to access to unaligned memory in ppc VM_Version::determine_features

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Undefined Undefined
    • None
    • rhel-8.6.0, rhel-8.7.0, rhel-8.8.0, rhel-8.9.0
    • java-1.8.0-openjdk
    • None
    • None
    • Moderate
    • Patch
    • rhel-sst-java
    • None
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • None
    • None
    • None

      (gdb) bt
      #0 os::ThreadCrashProtection::check_crash_protection (sig=4, thread=0x7fffa8050000)
      at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/os/posix/vm/os_posix.cpp:913
      #1 0x00007fffae3f9ee4 in JVM_handle_linux_signal (sig=<optimized out>, info=0x7fffad8fbc68, ucVoid=0x7fffad8faef0, abort_if_unrecognized=<optimized out>)
      at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp:181
      #2 0x00007fffae3e59b4 in signalHandler (sig=<optimized out>, info=0x7fffae9ea050 <VM_Version::_features>, uc=0x7fffad8fbef0)
      at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/os/linux/vm/os_linux.cpp:4584
      #3 <signal handler called>
      #4 0x00007fff980002a4 in ?? ()
      #5 0x00007fffae6b0bbc in VM_Version::determine_features () at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp:554
      #6 0x00007fffae6b147c in VM_Version::initialize () at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp:59
      #7 0x00007fffae6aec40 in VM_Version_init () at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/share/vm/runtime/vm_version.cpp:328
      #8 0x00007fffadfd94e0 in init_globals () at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/share/vm/runtime/init.cpp:101
      #9 0x00007fffae627fa4 in Threads::create_vm (args=<optimized out>, canTryAgain=0x7fffad8fe627)

      (gdb) frame 5
      #5 0x00007fffae6b0bbc in VM_Version::determine_features () at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp:554
      554 (*test)((address)mid_of_test_area, (uint64_t)0);
      (gdb) p test
      $1 = (void (address, uint64_t)) 0x7fff98000280
      (gdb) ptype test
      type = void (address, uint64_t)(gdb) list VM_Version::determine_features
      ...
      504 // Emit code.
      505 void (*test)(address addr, uint64_t offset)=(void(address addr, uint64_t offset))(void *)a->function_entry();
      506 uint32_t *code = (uint32_t *)a->pc();
      507 // Don't use R0 in ldarx.
      508 // Keep R3_ARG1 unmodified, it contains &field (see below).
      509 // Keep R4_ARG2 unmodified, it contains offset = 0 (see below).
      510 a->fsqrt(F3, F4); // code[0] -> fsqrt_m
      511 a->fsqrts(F3, F4); // code[1] -> fsqrts_m
      512 a->isel(R7, R5, R6, 0); // code[2] -> isel_m
      513 a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m
      514 a->cmpb(R7, R5, R6); // code[4] -> bcmp
      515 //a->mftgpr(R7, F3); // code[5] -> mftgpr
      516 a->popcntb(R7, R5); // code[6] -> popcntb
      517 a->popcntw(R7, R5); // code[7] -> popcntw
      518 a->fcfids(F3, F4); // code[8] -> fcfids
      519 a->vand(VR0, VR0, VR0); // code[9] -> vand
      520 a->lqarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[10] -> lqarx_m
      521 a->vcipher(VR0, VR1, VR2); // code[11] -> vcipher
      522 a->vpmsumb(VR0, VR1, VR2); // code[12] -> vpmsumb
      523 a->mfdscr(R0); // code[13] -> mfdscr
      ...
      (gdb) x/20i $pc-32
      0x7fff98000284: fsqrts f3,f4
      0x7fff98000288: isellt r7,r5,r6
      0x7fff9800028c: ldarx r7,r3,r4,1
      0x7fff98000290: cmpb r7,r5,r6
      0x7fff98000294: popcntb r7,r5
      0x7fff98000298: popcntw r7,r5
      0x7fff9800029c: fcfids f3,f4
      0x7fff980002a0: vand v0,v0,v0
      => 0x7fff980002a4: .long 0x7ce32229
      0x7fff980002a8: vcipher v0,v1,v2
      0x7fff980002ac: vpmsumb v0,v1,v2
      0x7fff980002b0: mfspr r0,3
      0x7fff980002b4: lxvd2x vs0,0,r3
      0x7fff980002b8: vshasigmaw v0,v1,1,15
      0x7fff980002bc: blr
      0x7fff980002c0: dcbz 0,r3
      0x7fff980002c4: blr
      ...

      I do not have documentation for the actual instruction, but openjdk code that
      added it is:

      // Atomics.
      LWARX_OPCODE = (31u << OPCODE_SHIFT | 20u << 1),
      LDARX_OPCODE = (31u << OPCODE_SHIFT | 84u << 1),
      + LQARX_OPCODE = (31u << OPCODE_SHIFT | 276u << 1),

      this should be an atomic acquire for a 128 bit memory address.

      The cpu probably does not support it, the kernel does not properly emulate
      it, or the arguments is not aligned.

      It is indeed an unaligned memory access:

      (gdb) frame 5
      #5 0x00007fffae6b0bbc in VM_Version::determine_features () at /usr/src/debug/java-1.8.0-openjdk-1.8.0.402.b06-2.el8.ppc64le/shenandoah-jdk8u402-b06/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp:554
      554 (*test)((address)mid_of_test_area, (uint64_t)0);

      (gdb) list VM_Version::determine_features
      ...
      491 // create test area
      492 enum{{{}

      { BUFFER_SIZE = 2*4*K }

      {}}}; // Needs to be >=2* max cache line size (cache line size can't exceed min page size).
      493 char test_area[BUFFER_SIZE];
      494 char *mid_of_test_area = &test_area[BUFFER_SIZE>>1];
      ...
      (gdb) p/x $r3
      $1 = 0x7fffad8fd0d8
      (gdb) p/x $r4
      $2 = 0x0
      (gdb) p/x $r3 & 15
      $3 = 0x8
      (gdb) p mid_of_test_area
      $4 = 0x7fffad8fd0d8 ""

      This is a bug in the openjdk code. The variable test_area should be 16 byte
      aligned, or rely on a hardware or kernel trap to fix it. But for an atomic acquire
      this might not be possible (trap and emulate the instruction).

      The feature test code likely is only handling SIGILL, to check for features.

      The fix should be the pseudo patch:

      hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp:VM_Version::determine_features()()
      - char test_area[BUFFER_SIZE];
      + char test_area[BUFFER_SIZE] {}attribute{} ((aligned (16)));

              rhn-engineering-ahughes Andrew Hughes
              rhn-support-pandrade Paulo Andrade
              Andrew Hughes Andrew Hughes
              David Kutalek David Kutalek
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated: