1 From 9c83c3d3f443eb92f87dc87c7dcfe95577b95621 Mon Sep 17 00:00:00 2001
2 From: Simon South <simon@simonsouth.net>
3 Date: Thu, 28 May 2020 14:29:55 -0400
4 Subject: [PATCH] Add support for aarch64 on GNU/Linux
8 src/arch/Makefile.am | 2 +-
9 src/arch/aarch64.h | 110 ++++++++++++++++
10 src/os/linux/Makefile.am | 2 +-
11 src/os/linux/aarch64/Makefile.am | 28 ++++
12 src/os/linux/aarch64/callNative.S | 212 ++++++++++++++++++++++++++++++
13 src/os/linux/aarch64/dll_md.c | 59 +++++++++
14 src/os/linux/aarch64/init.c | 51 +++++++
15 8 files changed, 469 insertions(+), 5 deletions(-)
16 create mode 100644 src/arch/aarch64.h
17 create mode 100644 src/os/linux/aarch64/Makefile.am
18 create mode 100644 src/os/linux/aarch64/callNative.S
19 create mode 100644 src/os/linux/aarch64/dll_md.c
20 create mode 100644 src/os/linux/aarch64/init.c
22 diff --git a/configure.ac b/configure.ac
23 index ccd530f..707f281 100644
26 @@ -43,6 +43,7 @@ amd64-*-freebsd*) host_os=bsd libdl_needed=no ;;
27 arm*-*-linux*) host_cpu=arm host_os=linux ;;
28 arm*-*-openbsd*) host_cpu=arm host_os=bsd libdl_needed=no ;;
29 arm*-*-freebsd*) host_cpu=arm host_os=bsd libdl_needed=no ;;
30 +aarch64*-*-linux*) host_cpu=aarch64 host_os=linux ;;
31 powerpc*-*-linux*) host_cpu=powerpc host_os=linux ;;
32 powerpc*-*-openbsd*) host_cpu=powerpc host_os=bsd libdl_needed=no ;;
33 powerpc*-*-freebsd*) host_cpu=powerpc host_os=bsd libdl_needed=no ;;
34 @@ -149,9 +150,11 @@ AC_ARG_ENABLE(runtime-reloc-checks,
36 AC_ARG_ENABLE(int-inlining,
37 [AS_HELP_STRING(--enable-int-inlining,enable inline threaded version of the interpreter
38 - (by default enabled on x86_64, i386 and powerpc, disabled otherwise))],,
39 - [if test "$host_cpu" = x86_64 -o "$host_cpu" = i386 -o "$host_cpu" = powerpc && \
40 - test "$cross_compiling" = no -o "$enable_runtime_reloc_checks" != no; then
41 + (by default enabled on x86_64, i386, powerpc and aarch64,
42 + disabled otherwise))],,
43 + [if test "$host_cpu" = x86_64 -o "$host_cpu" = i386 -o "$host_cpu" = powerpc -o \
44 + "$host_cpu" = aarch64 && test "$cross_compiling" = no -o \
45 + "$enable_runtime_reloc_checks" != no; then
46 enable_int_inlining=yes
48 enable_int_inlining=no
49 @@ -298,6 +301,7 @@ AC_CONFIG_FILES(
50 src/os/linux/x86_64/Makefile \
51 src/os/linux/parisc/Makefile \
52 src/os/linux/mips/Makefile \
53 + src/os/linux/aarch64/Makefile \
54 src/os/darwin/i386/Makefile \
55 src/os/darwin/arm/Makefile \
56 src/os/darwin/powerpc/Makefile \
57 diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
58 index 078c1de..afb26d1 100644
59 --- a/src/arch/Makefile.am
60 +++ b/src/arch/Makefile.am
62 ## Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
65 -EXTRA_DIST = powerpc.h arm.h i386.h x86_64.h parisc.h mips.h
66 +EXTRA_DIST = powerpc.h arm.h i386.h x86_64.h parisc.h mips.h aarch64.h
67 diff --git a/src/arch/aarch64.h b/src/arch/aarch64.h
69 index 0000000..c96aa9f
71 +++ b/src/arch/aarch64.h
74 + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
75 + * Robert Lougher <rob@lougher.org.uk>.
76 + * Copyright (C) 2020 Simon South <simon@simonsouth.net>.
78 + * This file is part of JamVM.
80 + * This program is free software; you can redistribute it and/or
81 + * modify it under the terms of the GNU General Public License
82 + * as published by the Free Software Foundation; either version 2,
83 + * or (at your option) any later version.
85 + * This program is distributed in the hope that it will be useful,
86 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
87 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88 + * GNU General Public License for more details.
90 + * You should have received a copy of the GNU General Public License
91 + * along with this program; if not, write to the Free Software
92 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
97 +#define OS_ARCH "aarch64"
99 +#define HANDLER_TABLE_T static const void
100 +#define DOUBLE_1_BITS 0x3ff0000000000000LL
102 +#define READ_DBL(v,p,l) v = ((u8)p[0]<<56)|((u8)p[1]<<48)|((u8)p[2]<<40) \
103 + |((u8)p[3]<<32)|((u8)p[4]<<24)|((u8)p[5]<<16) \
104 + |((u8)p[6]<<8)|(u8)p[7]; p+=8
106 +/* Needed for i386 -- empty here */
109 +#define COMPARE_AND_SWAP_64(addr, old_val, new_val) \
111 + int result, read_val; \
112 + __asm__ __volatile__ (" \
116 + stlxr %w0, %4, %1; \
119 + 2: cset %w0, eq;" \
120 + : "=&r" (result), "+Q" (*addr), "=&r" (read_val) \
121 + : "r" (old_val), "r" (new_val) \
126 +#define COMPARE_AND_SWAP(addr, old_val, new_val) \
127 + COMPARE_AND_SWAP_64(addr, old_val, new_val)
129 +#define LOCKWORD_READ(addr) \
131 + uintptr_t result; \
132 + __asm__ __volatile__ (" \
140 +#define LOCKWORD_WRITE(addr, value) \
142 + __asm__ __volatile__ (" \
149 +#define LOCKWORD_COMPARE_AND_SWAP(addr, old_val, new_val) \
150 + COMPARE_AND_SWAP_64(addr, old_val, new_val)
152 +#define FLUSH_CACHE(addr, length) \
154 + uintptr_t start = (uintptr_t) (addr); \
155 + uintptr_t end = start + length; \
158 + for(i = start & aarch64_data_cache_line_mask; \
160 + i += aarch64_data_cache_line_len) \
161 + __asm__ ("dc cvau, %0" :: "r" (i)); \
163 + __asm__ ("dsb ish"); \
165 + for(i = start & aarch64_instruction_cache_line_mask; \
167 + i += aarch64_instruction_cache_line_len) \
168 + __asm__ ("ic ivau, %0" :: "r" (i)); \
170 + __asm__ ("dsb ish; isb"); \
173 +#define MBARRIER() __asm__ ("dmb ish" ::: "memory")
174 +#define UNLOCK_MBARRIER() __asm__ ("dmb ish" ::: "memory")
175 +#define JMM_LOCK_MBARRIER() __asm__ ("dmb ish" ::: "memory")
176 +#define JMM_UNLOCK_MBARRIER() JMM_LOCK_MBARRIER()
178 +/* Defined in src/os/linux/aarch64/init.c */
179 +extern unsigned char aarch64_data_cache_line_len;
180 +extern uintptr_t aarch64_data_cache_line_mask;
181 +extern unsigned char aarch64_instruction_cache_line_len;
182 +extern uintptr_t aarch64_instruction_cache_line_mask;
183 diff --git a/src/os/linux/Makefile.am b/src/os/linux/Makefile.am
184 index aa29be1..d582b97 100644
185 --- a/src/os/linux/Makefile.am
186 +++ b/src/os/linux/Makefile.am
191 -DIST_SUBDIRS = powerpc arm i386 x86_64 parisc mips
192 +DIST_SUBDIRS = powerpc arm i386 x86_64 parisc mips aarch64
194 noinst_LTLIBRARIES = libos.la
195 libos_la_SOURCES = os.c
196 diff --git a/src/os/linux/aarch64/Makefile.am b/src/os/linux/aarch64/Makefile.am
198 index 0000000..1024c3a
200 +++ b/src/os/linux/aarch64/Makefile.am
203 +## Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012
204 +## Robert Lougher <rob@lougher.org.uk>.
206 +## File added by Simon South <simon@simonsouth.net>.
208 +## This file is part of JamVM.
210 +## This program is free software; you can redistribute it and/or
211 +## modify it under the terms of the GNU General Public License
212 +## as published by the Free Software Foundation; either version 2,
213 +## or (at your option) any later version.
215 +## This program is distributed in the hope that it will be useful,
216 +## but WITHOUT ANY WARRANTY; without even the implied warranty of
217 +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
218 +## GNU General Public License for more details.
220 +## You should have received a copy of the GNU General Public License
221 +## along with this program; if not, write to the Free Software
222 +## Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
225 +noinst_LTLIBRARIES = libnative.la
226 +libnative_la_SOURCES = init.c dll_md.c callNative.S
228 +AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src
229 +AM_CCASFLAGS = -I$(top_builddir)/src
230 diff --git a/src/os/linux/aarch64/callNative.S b/src/os/linux/aarch64/callNative.S
232 index 0000000..e067c4f
234 +++ b/src/os/linux/aarch64/callNative.S
237 + * Copyright (C) 2008, 2009, 2011, 2012 Robert Lougher <rob@jamvm.org.uk>.
238 + * Copyright (C) 2020 Simon South <simon@simonsouth.net>.
240 + * This file is part of JamVM.
242 + * This program is free software; you can redistribute it and/or
243 + * modify it under the terms of the GNU General Public License
244 + * as published by the Free Software Foundation; either version 2,
245 + * or (at your option) any later version.
247 + * This program is distributed in the hope that it will be useful,
248 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
249 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
250 + * GNU General Public License for more details.
252 + * You should have received a copy of the GNU General Public License
253 + * along with this program; if not, write to the Free Software
254 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
263 + .global callJNIMethod
264 + .type callJNIMethod,function
267 + * Arguments passed in:
282 + * x16 function pntr
285 + * x13 float/double handler
286 + * x12 int/long handler
287 + * w11 fp regs remaining
288 + * w10 int regs remaining
290 + * x2-x7 outgoing int args
291 + * x1 outgoing class or this pntr
292 + * x0 outgoing JNIEnv (as passed in)
294 + * d0 - d7 outgoing float args
298 + stp x29, x30, [sp, #-32]!
300 + stp x19, x20, [x29, #16]
302 + sub sp, sp, w3 /* allocate room for stacked args */
305 + mov x20, x4 /* preserve ostack */
306 + add x19, x2, #1 /* init sig pntr -- skipping '(' */
308 + mov x16, x5 /* save function pntr */
309 + mov x15, x20 /* init ostack pntr */
311 + adr x13, fp_reg_handlers-8
312 + adr x12, int_reg_handlers-8
314 + mov w11, #8 /* fp regs remaining */
315 + mov w10, #6 /* int regs remaining */
317 + cbnz x1, scan_sig /* is method non-static? */
318 + ldr x1, [x15], #8 /* yes, load x1 with "this" */
321 + ldrb w9, [x19], #1 /* get next sig char */
323 + cmp w9, #41 /* ')' */
326 + cmp w9, #74 /* 'J' */
329 + cmp w9, #70 /* 'F' */
332 + cmp w9, #68 /* 'D' */
336 + cmp w9, #91 /* '[' */
341 + cmp w9, #76 /* 'L' */
346 + cmp w9, #59 /* ';' */
351 + cbz w10, stack_push
374 + cbz w10, stack_push
379 + cbz w11, stack_push
384 + cbz w11, stack_push
414 + /* Call the function */
417 + mov sp, x29 /* Pop argument area */
419 + ldrb w9, [x19] /* Return type */
421 + cmp w9, #86 /* 'V' */
424 + cmp w9, #68 /* 'D' */
429 + cmp w9, #70 /* 'F' */
434 + cmp w9, #74 /* 'J' */
442 + mov x0, x20 /* return ostack */
444 + ldp x19, x20, [x29, #16]
445 + ldp x29, x30, [sp], #32
448 diff --git a/src/os/linux/aarch64/dll_md.c b/src/os/linux/aarch64/dll_md.c
450 index 0000000..189f8a8
452 +++ b/src/os/linux/aarch64/dll_md.c
455 + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
456 + * Robert Lougher <rob@jamvm.org.uk>.
457 + * Copyright (C) 2020 Simon South <simon@simonsouth.net>.
459 + * This file is part of JamVM.
461 + * This program is free software; you can redistribute it and/or
462 + * modify it under the terms of the GNU General Public License
463 + * as published by the Free Software Foundation; either version 2,
464 + * or (at your option) any later version.
466 + * This program is distributed in the hope that it will be useful,
467 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
468 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
469 + * GNU General Public License for more details.
471 + * You should have received a copy of the GNU General Public License
472 + * along with this program; if not, write to the Free Software
473 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
480 +int nativeExtraArg(MethodBlock *mb) {
481 + char *sig = mb->type;
482 + int stack_args = 0;
486 + while(*++sig != ')')
502 + while(*++sig == '[');
504 + while(*++sig != ';');
508 + /* Ensure the stack remains 16 byte aligned. */
509 + return (stack_args + 15) & ~15;
513 diff --git a/src/os/linux/aarch64/init.c b/src/os/linux/aarch64/init.c
515 index 0000000..e03b446
517 +++ b/src/os/linux/aarch64/init.c
520 + * Copyright (C) 2003, 2004, 2005, 2006, 2007
521 + * Robert Lougher <rob@lougher.org.uk>.
522 + * Copyright (C) 2020 Simon South <simon@simonsouth.net>.
524 + * This file is part of JamVM.
526 + * This program is free software; you can redistribute it and/or
527 + * modify it under the terms of the GNU General Public License
528 + * as published by the Free Software Foundation; either version 2,
529 + * or (at your option) any later version.
531 + * This program is distributed in the hope that it will be useful,
532 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
533 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
534 + * GNU General Public License for more details.
536 + * You should have received a copy of the GNU General Public License
537 + * along with this program; if not, write to the Free Software
538 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
541 +#include "arch/aarch64.h"
543 +/* Length in bytes of the smallest line in the host system's data cache */
544 +unsigned char aarch64_data_cache_line_len;
546 +/* Mask used to align a virtual address to a line in the data cache */
547 +uintptr_t aarch64_data_cache_line_mask;
549 +/* Length in bytes of the smallest line in the host system's instruction
551 +unsigned char aarch64_instruction_cache_line_len;
553 +/* Mask used to align a virtual address to a line in the instruction cache */
554 +uintptr_t aarch64_instruction_cache_line_mask;
556 +void initialisePlatform() {
557 + unsigned int cache_type;
559 + /* Extract information from the cache-type register, which describes aspects
560 + of the host's cache configuration */
561 + __asm__ ("mrs %0, ctr_el0" : "=r" (cache_type));
563 + aarch64_data_cache_line_len = 4 << ((cache_type >> 16) & 0x0f);
564 + aarch64_data_cache_line_mask = ~(aarch64_data_cache_line_len - 1);
566 + aarch64_instruction_cache_line_len = 4 << (cache_type & 0x0f);
567 + aarch64_instruction_cache_line_mask =
568 + ~(aarch64_instruction_cache_line_len - 1);