Bionic
Author: Ludovic HENRY ludovic.henry@qti.qualcomm.com
Date: 2026-06-17
Scope: RISC-V (riscv64/linux) support status for Android Bionic
Audience: Technical leadership, resource allocation strategy
Verification policy: Every claim is cross-referenced to a primary upstream source. Items that could not be verified against a second source are marked [NEEDS VERIFICATION].
1. Project Overview
Android Bionic is the C library, math library, and dynamic linker shipped with Android. It replaces glibc and provides the ABI foundation for all native Android code. The project is hosted exclusively on Google infrastructure at android.googlesource.com/platform/bionic and is governed entirely by Google. All OWNERS-file entries are Google employees. There is no independent foundation, technical steering committee, or external maintainer with commit authority.
License: BSD 2-clause for core AOSP-authored files. BSD 3-clause for SiFive-authored RISC-V string assembly (memcpy.S and related). Upstream-ported BSD components (FreeBSD, OpenBSD, NetBSD) carry their original 2- or 3-clause BSD licenses. There is no Apache 2.0 umbrella for this library.
The dominant maintainer is Elliott Hughes (enh@google.com, Google). Additional OWNERS are Christopher Ferris, Dan Albert, Ryan Prichard, and three other Google employees. All external contributions require Code-Review+2 from a listed Google owner before submission.
2. Port History and Upstreaming Timeline
The riscv64 port originated with a monolithic RFC submitted by a team from Alibaba (Change #2142912, filed 2022-06-30, 85+ patch sets, abandoned 2022-11-30). Elliott Hughes declined to merge it as a single patch due to binary blob policy and code style, and instead broke it into individually reviewable changes starting October 2022.
The original RFC carries Signed-off-by credits from: Mao Han, Xia Lifang, Chen Guoyin, Wang Chen, and Lu Xufan (all Alibaba). The split changes preserve these SOB chains. The Alibaba team expressed concern in the RFC review thread that attribution be preserved; Elliott Hughes acknowledged this and kept SOB chains in all derived commits.
Foundation phase (Oct-Nov 2022):
| Change | Title | Merged |
|---|---|---|
| 2237209 | Add riscv64 to the list of uapi architectures | 2022-09-30 |
| 2239865 | Initial import of the risc-v uapi headers | 2022-10-01 |
| 2240295 | Add riscv64 to the map files | 2022-10-04 |
| 2245796 | riscv64 syscall stub and seccomp filter generation | 2022-10-14 |
| 2246833 | riscv64 TLS support | 2022-10-12 |
| 2254947 | riscv64: add bionic assembler and string functions | 2022-10-15 |
| 2256273 | riscv64: fenv implementation | 2022-10-15 |
| 2258484 | riscv64 setjmp | 2022-10-18 |
| 2264528 | riscv64: build the linker | 2022-10-22 |
| 2298684 | Add a hack for a RISC-V bug (frame pointer ABI) | 2022-11-11 |
Hardening and optimization phase (2023):
| Change | Title | Merged |
|---|---|---|
| 2427910 | riscv64 SCS (Shadow Call Stack) support | 2023-03-21 |
| 2526530 | setjmp.h: increase riscv64 jmp_buf size | 2023-04-07 |
| 2526531 | riscv64: switch from x18 to gp for shadow call stack | 2023-04-13 |
| 2562193 | Add SYS_riscv_flush_icache | 2023-04-25 |
| 2586065 | riscv64: fix return value when errno is 4095 | 2023-05-11 |
| 2606625 | Implement RVV version mem* and str* for riscv64 (SiFive) | 2023-06-08 |
| 2657071 | Add riscv_hwprobe to the seccomp allowlist | 2023-07-13 |
| 2679530 | riscv64: add sys/hwprobe.h | 2023-07-27 |
| 2681597 | riscv64: use vdso for __riscv_hwprobe() | 2023-07-29 |
| 2695693 | riscv64: fix ifuncs, align calling convention with glibc | 2023-08-22 |
| 2719577 | riscv64: increase jmp_buf size (second increase) | 2023-08-22 |
| 2752785 | Add the risc-v TLSDESC relocations | 2023-09-15 |
Cleanup and stabilization phase (2024-2025):
| Change | Title | Merged |
|---|---|---|
| 3047343 | [RISC-V] Add misaligned load store tests | 2024-04-20 |
| 3094537 | Add riscv64 implementation of __get_bionic_tcb_for_thread() | 2024-05-17 |
| 3199470 | libc.map.txt: remove the two riscv64 special cases | 2024-07-30 |
| 3279653 | Use new riscv unistd names for syscall definition | 2024-09-24 |
| 3408180 | libc: remove riscv64 mem/str ifuncs and fallbacks | 2024-12-11 |
| 3472473 | Clean up the riscv64 assembler slightly | 2025-01-31 |
| 3472474 | riscv64: remove unused file | 2025-01-31 |
The last meaningful merge is from January 2025. Activity since then has been quiet. No master tracking issue exists. The original RFC (#2142912) was the umbrella; it was abandoned once the atomic changes landed. No Google Issue Tracker bug is publicly accessible.
First release: Android 14 (API 34, released October 2023) was the first Android version with official riscv64 support. All foundation changes merged between September 2022 and August 2023 shipped in Android 14.
3. Upstream Support Tier
AOSP publishes no formal architecture tier policy analogous to Rust or LLVM tier definitions. Architectures present in the tree (arm, arm64, x86, x86_64, riscv64) are implicitly supported by Google product decisions. The riscv64 port was initiated and is maintained by an internal Google engineer.
The NDK riscv64 ABI is explicitly described as provisional. NDK r27 (2024) was the first release to include a riscv64 sysroot; the release notes state: “A RISC-V sysroot (AKA riscv64, or rv64) has been added. It is not supported.” Its stated purpose is OS vendor bringup only. meta/abis.json sets "default": false for riscv64.
In short: the architecture is in the tree as first-class source code, but the NDK ABI contract for riscv64 is not finalized and ABI breaks remain possible.
4. Technical Architecture and RISC-V-Specific Subsystems
4.1 libc core assembly (libc/arch-riscv64/bionic/, 5 files)
All 5 files are hand-written RISC-V assembly:
-
syscall.S: shuffles C args into RISC-V registers (a7 = syscall number, a0-a5 = arguments), issuesecall, routes errors via__set_errno_internal. riscv64 was the first primary-only architecture in Bionic (no 32-bit companion) and the first that post-dates the kernel’s 64-bit time syscall work, requiring special-casing in the seccomp filter and syscall stub generators. -
setjmp.S: saves 29 words – ra, sp, gp, s0-s11, fs0-fs11, and signal mask. Uses XOR cookie mangling and a checksum. Shadow Call Stack (SCS): only the low bits of gp are saved, deliberately avoiding storing a full SCS pointer gadget. The jmp_buf was enlarged twice: once to accommodate the x18-to-gp SCS register switch (#2526530), and once proactively in anticipation of future Zsslpcfi hardware SCS requirements (#2719577). The commit message for the second increase notes: “musl and glibc only have the minimum needed (which I think means they’ll need an ABI break to support SCS unless they just use a callee-saved general purpose register), but since we can’t do ABI breaks after we ship, let’s play it safe.” -
__bionic_clone.S: implementsclone(2), sets up child stack, pushes fn and arg, issuesecall, zeroes fp and ra in child then tail-calls__start_thread. -
vfork.S: temporarily setscached_pid_=0andvforked_=1in TLS, issuesclone(CLONE_VM|CLONE_VFORK|SIGCHLD)viaecall. -
_exit_with_stack_teardown.S: issuesmunmapthenexitsyscall; ignores munmap failure.
Frame pointer ABI note: Change #2298684 added a workaround for the RISC-V frame record layout, in which the frame pointer points past both saved values (return address at frame[-1], previous FP at frame[-2]), differing from most other architectures. The commit message states: “I can’t find this documented anywhere, other than people observing that RISC-V appears to behave in this way.” The reviewer (Lifang Xia, Alibaba) pointed to psABI issue #18 and noted that GCC 7.2 already implemented this convention. The LLVM workaround reference is D87579.
4.2 Shadow Call Stack register evolution
The SCS register was initially x18, chosen due to LLVM constraints at the time. It was switched to gp (x3) in April 2023 (#2526531) because gp is effectively unused in the Android RISC-V ABI (the kernel does not touch it, and Android does not use GP relaxation). This freed x18 for application code. The switch required a compiler change; the commit message notes: “untested, obviously, for lack of a suitable compiler.”
4.3 RVV-optimized string functions (libc/arch-riscv64/string/, 15 files)
All 15 files are hand-written RISC-V Vector (RVV) assembly, co-credited to SiFive, Inc. (2023). The contribution originates from sifive/sifive-libc under BSD 3-clause license. They were introduced in #2606625 by Yun Hsiang (SiFive).
These implementations are compiled unconditionally when the V extension is enabled. There is no IFUNC dispatch for riscv64 in bionic_ifuncs.h; RISC-V falls into the default empty-args case (no hwcap argument passed to resolvers, unlike aarch64). The ifunc resolver calling convention was corrected in #2695693 to match glibc: first argument is hwcap, second is null. That commit notes: “I actually went away and looked at a sample of top apps to see how many are using ifuncs currently. The result? Zero.”
Key RVV techniques used:
| Function | Technique |
|---|---|
memcpy, memset |
vsetvli + vle8.v/vse8.v, LMUL=8; includes __memcpy_chk, __memset_chk |
memchr |
vle8ff.v (fault-only-first load), vmseq.vx, vfirst.m |
strlen |
vle8ff.v, vmseq.vi, vfirst.m, csrr vl |
strcmp |
Progressive LMUL ramp-up (mf2 to m4); dual vfirst.m for null vs. mismatch |
strcpy |
Fault-first load + vmsif.m masked store |
memcmp |
vmsne.vv + vfirst.m to find first differing byte |
stpcpy, strcat, strchr, strncat, strncmp, strncpy, strnlen |
Dedicated .S files using same RVV pattern |
4.4 Dynamic linker (linker/arch/riscv64/, 2 files)
-
begin.S: linker entry point. Sets.cfi_undefined ra, passesspto__linker_init, jumps to the returned entry point. -
tlsdesc_resolver.S: implements the RISC-V TLSDESC (TLS Descriptor) protocol with four entry points (tlsdesc_resolver_static,tlsdesc_resolver_dynamic,tlsdesc_resolver_dynamic_slow_path,tlsdesc_resolver_unresolved_weak). The slow path spills 35 general-purpose registers plus all RVV vector registers (v0,v8,v16,v24viavlenb-scaled offsets) before calling__tls_get_addr.
TLSDESC relocation types were added in #2752785 after the RISC-V psABI standardized them (psABI issue #94). This resolved android-riscv64#3.
Full relocation coverage verified: R_RISCV_64, R_RISCV_JUMP_SLOT, R_RISCV_RELATIVE, R_RISCV_IRELATIVE, R_RISCV_COPY, all TLS variants (DTPMOD64, DTPREL64, TPREL64), and TLSDESC.
4.5 libm (libm/fenv-riscv64.c)
Implements all fenv.h functions via inline RISC-V CSR instructions (frcsr/fscsr, frflags/fsrm/frrm). feenableexcept correctly returns -1 (RISC-V hardware has no FP trap-on-exception support). fegetexcept returns 0. Higher-level math functions (fma, fmax, fmin, llrint, lround, round family) are handled via clang compiler builtins, the same policy used for arm64.
There is no equivalent of libarm-optimized-routines for RISC-V. The generic C math from FreeBSD/NetBSD is used for functions not covered by clang builtins.
4.6 Kernel UAPI headers (libc/kernel/uapi/asm-riscv/asm/, 39 files)
Auto-generated from the Linux kernel. Notable entries:
hwcap.h:COMPAT_HWCAP_ISA_*bits (I, M, A, F, D, C, V).hwprobe.h:struct riscv_hwprobewith 48+RISCV_HWPROBE_EXT_*constants (Zba, Zbb, Zbs, V, Zvbb, Zvkb, Zfh, ZTSO, ZACAS, etc.) and misaligned access performance keys.ptrace.h: RISC-V ptrace register layout.unistd_64.h: riscv64 syscall numbers.elf.h: riscv64 ELF machine and relocation types.sigcontext.h,ucontext.h: signal frame register save layout.
__riscv_hwprobe() was moved to the vDSO in #2681597 to avoid a full syscall round-trip for capability probes.
One unique syscall entry in SYSCALLS.TXT:
__riscv_flush_icache:riscv_flush_icache(void*, void*, unsigned long) riscv64
4.7 API additions (Android V / API 35)
__riscv_flush_icache(void* start, void* end, unsigned long flags)in<sys/cachectl.h>. The range is currently ignored per a Linux 6.12 note. Flag:SYS_RISCV_FLUSH_ICACHE_LOCAL = 1UL.__riscv_hwprobe(struct riscv_hwprobe* pairs, size_t pair_count, size_t cpu_count, unsigned long* cpus, unsigned int flags)in<sys/hwprobe.h>.__riscv_hwprobe_tfunction pointer typedef for use in riscv64 ifunc resolvers.
5. Build System, Cross-Compilation, and Toolchain
5.1 Build system
Android Bionic uses Soong (Android.bp files) exclusively. There are no CMakeLists.txt, no configure scripts, and no -DUSE_X=OFF flags anywhere in the repository. The build is driven via:
source build/envsetup.sh
lunch <target>
mm
The NDK’s android.toolchain.cmake contains one riscv64 line:
elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^riscv64-")
set(CMAKE_ANDROID_ARCH_ABI riscv64)
This is for NDK users building third-party code, not for building Bionic itself.
5.2 Toolchain
Android is Clang/LLVM-only. GCC was fully removed before riscv64 was added; NDK r23 removed libgcc entirely, replacing it with LLVM’s libunwind and libclang_rt. No GCC minimum version applies.
NDK versions and their clang tags:
- NDK r27 / r27c:
clang-r522817/clang-r522817c - NDK r28:
clang-r530567b
No explicit Clang minimum version is documented in the Bionic repository for riscv64. The Android LLVM toolchain follows LLVM main with approximately 3-4 updates per year.
Known LLVM bug for riscv64: frame pointer addresses were implemented incorrectly. Bionic applies a -16 byte offset workaround in android_unsafe_frame_pointer_chase.cpp. Reference: LLVM D87579.
Shadow Call Stack is enabled for riscv64 in tests via:
riscv64: {
cflags: ["-fsanitize=shadow-call-stack"],
}
5.3 riscv64 source layout in build files
libc/Android.bp references:
arch-riscv64/bionic/:__bionic_clone.S,_exit_with_stack_teardown.S,setjmp.S,syscall.S,vfork.Sarch-riscv64/string/: 15 RVV assembly files- Version script:
libc.riscv64.map
linker/Android.bp:
riscv64: {
srcs: [":linker_sources_riscv64"],
}
Files: arch/riscv64/begin.S, arch/riscv64/tlsdesc_resolver.S, arch/riscv64/linker_wrapper_begin.S. Uses linker.generic.map version script (same as arm64/x86/x86_64).
5.4 Page size
riscv64 does not support 16 KiB page sizes in the NDK (unlike arm64 and x86_64, which gained 16 KiB support in NDK r27/r28).
5.5 Host testing
The build/run-on-host.sh script gates its logic on TARGET_ARCH = x86 -o TARGET_ARCH = x86_64. For any other TARGET_ARCH, including riscv64, it prints "$0 not supported on TARGET_ARCH=$TARGET_ARCH" and exits. No QEMU invocation or riscv64 emulator setup script exists anywhere in the repository.
5.6 Infrastructure Dockerfile
The NDK provides one Dockerfile (infra/docker/Dockerfile) based on Ubuntu 14.04 (Trusty). It installs only bison, build-essential, curl, flex, git, make, pbzip2, python, python-pip, texinfo, uuid-runtime, and zip. It contains no riscv64 toolchain packages, no QEMU, and no cross-compiler. It predates riscv64 support and has not been updated.
6. Feature Coverage and Gap Analysis vs. arm64 and amd64
| Feature | arm64 | amd64 | riscv64 | Notes |
|---|---|---|---|---|
| Syscall stub | Hand-written asm | Hand-written asm | Hand-written asm | Full parity |
| setjmp/longjmp | Hand-written asm | Hand-written asm | Hand-written asm | Full parity; cookie mangling present on all three |
| Shadow Call Stack | x18 register | N/A | gp (x3) | riscv64 uses gp after April 2023 switch |
| Hardware SCS | Via Pointer Authentication (future) | N/A | Via Zsslpcfi (future) | Neither is deployed; both tracked as open issues |
| RVV/NEON/SSE string ops | NEON in libarm-optimized-routines | SSE/AVX via generic | RVV in arch-riscv64/string/ | SiFive-contributed; 15 functions covered |
| IFUNC dispatch | hwcap passed to resolvers | hwcap passed | hwcap passed (fixed Aug 2023) | Fixed in #2695693; zero top apps use ifuncs on any arch as of Aug 2023 |
| TLSDESC | Full | Full | Full (since Sep 2023) | Required psABI standardization before implementation |
| vDSO for hwprobe | N/A | N/A | Yes (since Jul 2023) | RISC-V-specific capability query mechanism |
| fenv (FP trap-on-exception) | Supported | Supported | Not supported (hardware limitation) | feenableexcept returns -1; correctly documented |
__memcmp16 (String.compareTo) |
Hand-written asm | Hand-written asm | Portable C fallback | Open bug android-riscv64#161 |
| libm optimized routines | libarm-optimized-routines | Arch-tuned | FreeBSD/NetBSD generic C | No RISC-V equivalent of libarm-optimized-routines |
| 16 KiB page size | Yes (NDK r27+) | Yes | No | Not supported |
| LTO ABI correctness | OK | OK | Bug (open, #61) | -mcpu/-march not correctly propagated during LTO |
7. CI/CD Infrastructure
No riscv64 CI is evidenced in any CI configuration file in the repository. The following files were examined and contain no riscv64 references:
/TEST_MAPPING: lists three test groups (presubmit,hwasan-presubmit,kernel-presubmit) with 16+ architecture-neutral test suite names. No riscv64 architecture tag, no riscv64-specific runner./PREUPLOAD.cfg: onlyclang_format, an AOSP SHA validation hook, and a notice updater./build/run-on-host.sh: explicitly handles only x86 and x86_64; riscv64 causes an immediate exit./build/directory: three files total (coverage.sh,NOTICE,run-on-host.sh). No CI pipeline files.- No
.github/directory exists (returns 404). ci.android.com: no riscv64 build targets visible.
The riscv64 architecture source code in libc/arch-riscv64/ is not CI. No dedicated riscv64 CI configuration, no riscv64-specific TEST_MAPPING entries, and no riscv64 presubmit build targets were found in any configuration file.
Testing known to occur: basic functionality verified on Cuttlefish (QEMU-based Android emulator). QEMU >= 8.1 is required; QEMU 9.0 fixes the V extension; QEMU 9.2 adds speedups for V. Boot to Android home screen takes approximately 10 minutes even on fast Xeon hardware. No physical hardware CI is documented.
8. Distribution and Release Status
In Android: riscv64 is a first-class source target in AOSP main since October 2022. Android 14 (API 34, October 2023) was the first release with official riscv64 support. NDK r27 (2024) was the first NDK release with a riscv64 sysroot; it is explicitly marked unsupported and not built by default.
As a standalone package in Linux distributions: Android Bionic does not exist as a standalone binary package in PyPI, Debian, Ubuntu, Arch Linux RISC-V, or Repology. The only packaged form is android-bionic-uapi in GNU Guix (version 7.1.2_r36), which is a headers-only package copying libc/kernel/uapi headers. It produces no compiled binary for any architecture, including riscv64. GNU Guix does not officially support riscv64 as a host system in its mainline distribution.
9. Dependencies
| Dependency | Role | riscv64 Build Status | Key Notes |
|---|---|---|---|
| libc (Bionic) | Core C library | Builds; dedicated arch-riscv64/ assembly | NDK ABI not finalized; ABI breaks still possible |
| libm (Bionic) | Math library | Builds; fenv-riscv64.c with CSR inline asm | No libarm-optimized-routines equivalent; generic C math |
| libdl (Bionic) | Dynamic linker interface | Builds; same ABI as other arches | No riscv64-specific issues |
| linker/linker64 | ELF dynamic linker | Builds; begin.S + tlsdesc_resolver.S | TLS descriptor ABI correctness depends on toolchain alignment |
| libstdc++ (Bionic) | Minimal C++ ABI | Builds (pure C++, no arch asm) | No riscv64-specific issues |
| llvm-libc | Selected libc function implementations | Builds; included as whole_static_libs | LLVM libc riscv64 support not listed in official platform docs; gaps possible [NEEDS VERIFICATION] |
| Scudo (LLVM compiler-rt) | Default hardened allocator | Builds via generic Linux platform layer | No riscv64-specific tuning; allocator parameters may not be optimal |
| jemalloc (libjemalloc5) | Alternate allocator | Builds via generic GCC atomic backends | quantum size and vaddr bits must be validated for riscv64 |
| GWP-ASan | Guard-page heap sampler | Builds (pure C++, platform-agnostic) | PerfectlyRightAlign option noted as potentially architecture-incompatible [NEEDS VERIFICATION] |
| libunwind (LLVM) | Stack unwinding | Builds; REGISTERS_RISCV defined | Official docs do not list riscv64 as supported; relies on DWARF metadata |
| zlib | Compression (APK/ZIP loading) | Builds (pure C, no arch exclusions) | No RVV optimizations; generic C only |
| libbase (Android platform) | Utility library; used by linker | Builds via generic rules | No riscv64-specific issues |
| liblog (Android) | Logging; used by linker internals | Builds (no arch exclusions in Android.bp) | No riscv64-specific issues |
| Linux kernel UAPI headers | Syscall interface | 39 files in libc/kernel/uapi/asm-riscv/ | Header set leaner than arm64; specialized subsystem headers may be missing |
| libarm-optimized-routines | High-performance ARM string/math | Not applicable (ARM-only) | riscv64 uses arch-riscv64/string/ instead |
| ICU / libicu4x_bionic | Unicode/timezone (Rust FFI) | Builds; riscv64 listed as Rust FFI target | ICU4C does not list riscv64 as officially tested; correctness not formally validated [NEEDS VERIFICATION] |
10. Ecosystem Status
RISE Project
Google is a Premier Member of the RISE Project (riseproject.dev) with a Governing Board seat. SiFive and DAMO Academy (Alibaba) are also Premier Members. Andes Technology, ByteDance, Canonical, ISCAS, and others are General Members.
Android Bionic does not appear in any RISE blog post (all 27 posts checked, May 2024 through June 2026). It does not appear in any of the 16 funded RFP projects (RP001-RP016). The System Libraries Working Group (elected lead: Ruinland Chuan-Tzu Tsai, Andes Technology) lists “Android, C runtimes, musl-libc, glibc, Linux/FreeBSD, and Linux distribution bootstrapping” as its scope, which covers Bionic. No dedicated Android Bionic funding or deliverable is publicly documented. This WG is being consolidated into an “Enablement/Optimization WG” effective June 25, 2026.
Contributor origins
| Organization | Contribution |
|---|---|
| Google (Elliott Hughes lead) | All OWNERS-file authority; majority of merged changes |
| Alibaba (Mao Han, Xia Lifang, et al.) | Original RFC and SOB chain attribution; errno=4095 fix |
| SiFive (Yun Hsiang) | RVV-optimized string functions (15 files, BSD 3-clause) |
| ISCAS | Listed in SOB chains of foundation commits |
| Paul Kirth | TLS Descriptor prototype (2024) |
| George Burgess IV (Google) | Removal of riscv64 ifunc fallback overhead (Dec 2024) |
11. Known Bugs and Active Issues
Open issues at github.com/google/android-riscv64
| Issue | Title | Category |
|---|---|---|
| #167 | Support vector regalloc for RISC-V backend in ART | Performance (ART) |
| #165 | ART: revisit intrinsics to use V and B | Performance (ART) |
| #161 | ART: implement custom __memcmp16? |
Performance gap – String.compareTo() uses portable C fallback on riscv64; all other architectures have hand-written asm |
| #153 | Implement MethodHandleInvokeExact intrinsic for riscv64 | Correctness/Performance (ART) |
| #148 | ART: Implement optimizations with Zbs extension | Performance (ART) |
| #147 | ART: implement BitstringTypeCheck for RISC-V | Correctness (ART) |
| #141 | ART: unimplemented intrinsics | Performance gap – full list in code_generator_riscv64.h under UNIMPLEMENTED_INTRINSIC_LIST_RISCV64; these fall back to slower non-optimized paths |
| #62 | Enable -msave-restore at -Oz | Code-size/performance (compiler) |
| #61 | Fix ABI and mcpu/march for LTO | Correctness bug (labeled bug) – references LLVM patches D132843, D71387, D72245, D102582, D106347 |
| #60 | Investigate the status of SLP vectorizer | Performance (compiler vectorization) |
| #59 | frameworks/av: optimization | Performance (media framework) |
| #58 | Fix platform:Android bugs in llvm-project | Correctness/Performance (labeled bug) |
| #53 | kernel: crypto optimization | Performance (kernel/security) |
| #39 | external/skia: optimization | Performance |
| #37 | external/libpng: optimization | Performance |
| #36 | external/boringssl: optimization | Performance |
| #35 | external/libjpeg-turbo: optimization | Performance |
| #34 | external/libmpeg2: optimization | Performance |
| #33 | external/libhevc/: optimization | Performance |
| #32 | external/libavc/: optimization | Performance |
| #29 | external/flac/: need V optimization | Performance (V extension) |
| #15 | security: hardware CFI (“landing pads”) support | Correctness/Security (ABI) |
| #14 | security: hardware shadow call stack | Correctness/Security |
| #13 | external/aac: inline assembler | Performance |
| #5 | bionic/tests/sys_ptrace_test.cpp: add instruction writing > 64 bits | Correctness (test gap) |
Recently closed issues relevant to Bionic
| Issue | Title | Notes |
|---|---|---|
| #162 | Structure accesses with NDK r27 produce more instructions than expected | Missed optimization: 3-byte struct read generates 3x lbu instead of 1x lhu + 1x lbu; LLVM backend not exploiting zbb |
| #160 | $x.* symbol in libc.so |
$x.0 at 6.37% cpu-cycles in profiling; compiler mapping symbols obscure real hotspot names |
| #111 | clang driver: enable fast unaligned access for android | Fast unaligned access was not enabled by default |
| #8 | what’s the ifunc story? hwcap.h | Linux kernel hwcap.h lacked V extension bit at filing; ifunc dispatch fragmented by Zb* sub-extension proliferation |
Only open Gerrit change for riscv64
Change #2320311 – “Disable Rust dep.” (topic: riscv). Created 2022-11-29. Status: New/WIP. Last activity: 2024-06-10. Owner: Ulya Trofimovich (Google). One unresolved comment from Elliott Hughes asking whether the change is still needed. The reviewer (Xin Li) removed themselves in June 2024 and activity ceased. This is a one-line change to apex/Android.bp disabling a Rust dependency; the motivation may no longer apply.
Benchmark data
No public benchmark numbers with exact figures exist for Android Bionic on riscv64. The only performance-adjacent quantitative data found:
- QEMU emulation: boot to Android home screen takes approximately 10 minutes on fast Xeon hardware. QEMU >= 8.1 required; QEMU 9.0 fixes the V extension; QEMU 9.2 adds V speedups.
- Profiling artifact (#160):
$x.0consumed 6.37% of cpu-cycles fromlibc.soduring cpu-cycles profiling. The symbol is a compiler-generated mapping symbol, not a real function name. This represents a profiling infrastructure gap, not a benchmark result. - No arm64 vs. riscv64 comparative benchmark data is publicly available from any accessible source.
Data not available: riscv64 vs. arm64 performance comparison for any libc function (memcpy, strlen, strcmp, or others). Data not available: riscv64 vs. arm64 application-level performance for any Android workload.
12. Objections and Upstream Blockers
1. NDK ABI not finalized. The Android NDK riscv64 ABI is explicitly described as provisional. ABI breaks are acknowledged as possible. Application binaries built today may be ABI-incompatible with future Android riscv64 releases. This is the single largest blocking item for production deployment. Tracked at github.com/google/android-riscv64.
2. No CI for riscv64. No CI configuration file in the repository targets riscv64. The only on-host build/test script (run-on-host.sh) explicitly exits for non-x86 targets. There are no riscv64 build targets on ci.android.com. Regressions can merge undetected.
3. LTO ABI correctness bug (open, labeled bug, #61). -mcpu/-march flags are not correctly propagated during LTO. This is a build-system/compiler interaction bug that can silently produce incorrect binaries when LTO is enabled.
4. __memcmp16 missing asm (#161, open). String.compareTo() uses a portable C fallback on riscv64. All other architectures have hand-written assembler. This is a measurable performance gap for Java string-heavy workloads.
5. Unimplemented ART intrinsics (#141, open). The full list lives in code_generator_riscv64.h under UNIMPLEMENTED_INTRINSIC_LIST_RISCV64. These fall back to slower non-optimized paths. The gap is larger than on arm64 or x86_64.
6. Hardware security features not deployed. Hardware CFI via Zisslpcfi landing pads (#15) and hardware Shadow Call Stack via Zsslpcfi (#14) are open with no target date. The current software SCS via gp register is a stop-gap.
7. QEMU-only testing. No physical hardware CI path exists. QEMU 9.0+ is required for correct V extension behavior. Emulator boot time is approximately 10 minutes. Results on real hardware may differ substantially.
8. No RISC-V libm optimization library. libarm-optimized-routines provides highly tuned math and string routines for arm64. There is no equivalent for riscv64. Math performance relies on FreeBSD/NetBSD generic C and clang builtins.
9. Profiling infrastructure gap. Compiler-generated $x.* mapping symbols in libc.so obscure real function names during cpu-cycles profiling (#160). This makes hotspot analysis unreliable.
10. Google-controlled governance. All OWNERS-file entries are Google employees. External contributors cannot merge without Google Code-Review+2. There is no path for non-Google parties to hold commit authority regardless of contribution volume or quality.
13. Investment Analysis
13.1 Functional Enablement
The core Bionic riscv64 port is complete. The five essential libc assembly files (syscall, setjmp, clone, vfork, exit), the dynamic linker entry and TLSDESC resolver, and all fenv functions are present and production-quality. Functional gaps relative to arm64 are confined to ART intrinsics and __memcmp16. No functional blocker exists for running Android on riscv64 hardware today – the NDK ABI being provisional is a stability/compatibility risk, not an execution blocker.
Investment required for functional parity: implement __memcmp16 in RVV assembly (closes #161); address unimplemented ART intrinsics (#141). Neither item is in Bionic directly – __memcmp16 lives in ART, and the intrinsics are in ART’s code generator.
13.2 Performance Optimization
Identified performance gaps with no current owner:
- No RISC-V equivalent of
libarm-optimized-routinesfor math functions. Generic C math is measurably slower than NEON-tuned routines for trigonometric, exponential, and rounding functions. __memcmp16portable C fallback vs. hand-written asm (quantitative gap: data not available).- Unimplemented ART intrinsics (quantitative gap: data not available).
- Profiling infrastructure gap (
$x.*symbols) prevents identifying and fixing additional hotspots inlibc.so. - SLP vectorizer effectiveness (#60) – not yet characterized.
- zlib has no RVV optimizations. Generic C only.
- Multiple media/codec libraries have open optimization issues: boringssl (#36), libjpeg-turbo (#35), libmpeg2 (#34), libhevc (#33), libavc (#32), flac (#29), libpng (#37).
13.3 CI/CD Infrastructure
No riscv64 CI exists. This is the highest-risk structural gap: the architecture has no automated regression detection. Any change to Bionic can silently break riscv64. Establishing even a build-only CI for riscv64 would provide a meaningful regression signal. A test-execution CI requires either physical hardware or a maintained QEMU integration (QEMU 9.0+ for V extension correctness).
This is unlikely to be addressed by Google for a non-product architecture. It is a direct investment opportunity for a company with riscv64 hardware.
13.4 Ecosystem Enablement
The RISE System Libraries WG covers Android/Bionic in its stated scope, but no funded project exists. SiFive has already demonstrated the pattern: contributing production-quality RVV string assembly (15 files) that was accepted and merged. This is the established contribution model.
The LTO ABI correctness bug (#61) is a compiler/build-system issue that benefits all Android riscv64 users. It has LLVM patch references (D132843 et al.) but is still open.
13.5 Summary Table
| Area | Work Item | Effort (person-weeks) | Owner | Priority |
|---|---|---|---|---|
| Functional | Fix LTO ABI / -mcpu/-march propagation (#61) | 4-8 | LLVM/Bionic | Critical |
| Functional | Implement __memcmp16 in RVV asm (#161) |
1-2 | ART/Bionic | High |
| Functional | Implement unimplemented ART intrinsics (#141) | 8-16 | ART | High |
| Functional | Hardware CFI / Zsslpcfi support (#15, #14) | 8-20 | Bionic/compiler/kernel | High (long-lead) |
| Performance | RVV-optimized libm routines (equivalent of libarm-optimized-routines) | 12-24 | Bionic/libm | High |
| Performance | Fix $x.* profiling symbol gap in libc.so (#160) |
1-2 | LLVM/Bionic | Medium |
| Performance | RVV-optimized zlib | 4-8 | External (zlib/upstream) | Medium |
| Performance | boringssl RVV optimization (#36) | 4-8 | External/Bionic | Medium |
| Performance | libjpeg-turbo RVV optimization (#35) | 4-8 | External/Bionic | Medium |
| Performance | Media codec library optimizations (#32, #33, #34, #37, #29) | 20-40 total | External libraries | Low-Medium |
| Performance | SLP vectorizer characterization (#60) | 2-4 | LLVM | Medium |
| CI/CD | Establish riscv64 build CI (compile-only) | 3-6 | Google/chip company | Critical |
| CI/CD | Establish riscv64 test CI on hardware or QEMU 9.2+ | 8-16 | chip company with hardware | High |
| CI/CD | Extend run-on-host.sh to support riscv64 |
1-2 | Bionic | Medium |
| Ecosystem | Close android-riscv64#61 upstream LLVM patches | 4-8 | LLVM toolchain team | Critical |
| Ecosystem | NDK riscv64 ABI finalization | Data not available: no public timeline or tracking issue found | Google internal | Blocking |
14. Updates
No updates yet – initial report dated 2026-06-17.
15. References
- Android Bionic repository
- Android Bionic Gerrit review
- google/android-riscv64 issue tracker
- RFC #2142912 – Add riscv64 support (abandoned)
- Change #2245796 – riscv64 syscall stub and seccomp filter generation
- Change #2254947 – riscv64: add bionic assembler and string functions (first commit)
- Change #2298684 – Add a hack for a RISC-V bug (frame pointer)
- Change #2427910 – riscv64 SCS support
- Change #2526531 – riscv64: switch from x18 to gp for shadow call stack
- Change #2606625 – Implement RVV version mem* and str* for riscv64 (SiFive)
- Change #2681597 – riscv64: use vdso for __riscv_hwprobe()
- Change #2695693 – riscv64: fix ifuncs, improve the ifunc tests
- Change #2752785 – Add the risc-v TLSDESC relocations
- Change #3408180 – libc: remove riscv64 mem/str ifuncs and fallbacks
- Change #2320311 – Disable Rust dep. (only open riscv64 WIP change)
- android-riscv64#61 – Fix ABI and mcpu/march for LTO
- android-riscv64#161 – ART: implement custom __memcmp16?
- android-riscv64#141 – ART: unimplemented intrinsics
- android-riscv64#160 – $x.* symbol in libc.so
- LLVM D87579 – RISC-V frame pointer workaround
- RISC-V psABI issue #18 – frame pointer convention
- RISC-V psABI issue #94 – TLSDESC relocations
- RISE Project working group election results (March 2025)
- sifive/sifive-libc (source of RVV string contributions)