From 05f75de5868531fedc928f812f493d3ed9a84b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?yes=EF=BC=8Ci=20Do?= <294669443@qq.com> Date: Tue, 20 Sep 2022 14:05:14 +0000 Subject: [PATCH] Add support for loongarch64. --- configure.ac | 13 ++ include/glvnd/GLdispatchABI.h | 5 + src/GLX/glvnd_genentry.c | 10 ++ src/GLdispatch/vnd-glapi/entry_common.c | 5 + src/GLdispatch/vnd-glapi/entry_files.mk | 6 + .../vnd-glapi/entry_loongarch64_tsd.c | 121 ++++++++++++++++++ src/GLdispatch/vnd-glapi/meson.build | 2 + tests/dummy/patchentrypoints.c | 34 +++++ 8 files changed, 196 insertions(+) create mode 100644 src/GLdispatch/vnd-glapi/entry_loongarch64_tsd.c diff --git a/configure.ac b/configure.ac index 83ec00b..1df8edb 100644 --- a/configure.ac +++ b/configure.ac @@ -165,6 +165,10 @@ if test "x$enable_asm" = xyes; then #endif ])], [asm_arch=ppc64],[]) + ;; + loongarch64) + asm_arch=loongarch64 + ;; esac case "$asm_arch" in @@ -188,6 +192,10 @@ if test "x$enable_asm" = xyes; then DEFINES="$DEFINES -DUSE_PPC64_ASM" AC_MSG_RESULT([yes, ppc64]) ;; + loongarch64) + DEFINES="$DEFINES -DUSE_LOONGARCH64_ASM" + AC_MSG_RESULT([yes, loongarch64]) + ;; *) AC_MSG_RESULT([no, platform '$host_cpu' not supported]) ;; @@ -264,6 +272,10 @@ xaarch64) # For aarch64, only the TSD stubs have been implemented yet. gldispatch_entry_type=aarch64_tsd ;; +xloongarch64) + # For loongarch64, only the TSD stubs have been implemented yet. + gldispatch_entry_type=loongarch64_tsd + ;; *) # The C stubs will work with either TLS or TSD. gldispatch_entry_type=pure_c @@ -313,6 +325,7 @@ AM_CONDITIONAL([GLDISPATCH_TYPE_PPC64_TLS], [test "x$gldispatch_entry_type" = "x AM_CONDITIONAL([GLDISPATCH_TYPE_PPC64_TSD], [test "x$gldispatch_entry_type" = "xppc64_tsd"]) AM_CONDITIONAL([GLDISPATCH_TYPE_ARMV7_TSD], [test "x$gldispatch_entry_type" = "xarmv7_tsd"]) AM_CONDITIONAL([GLDISPATCH_TYPE_AARCH64_TSD], [test "x$gldispatch_entry_type" = "xaarch64_tsd"]) +AM_CONDITIONAL([GLDISPATCH_TYPE_LOONGARCH64_TSD], [test "x$gldispatch_entry_type" = "xloongarch64_tsd"]) AM_CONDITIONAL([GLDISPATCH_TYPE_PURE_C], [test "x$gldispatch_entry_type" = "xpure_c"]) AS_IF([test "x$gldispatch_entry_type" != "xpure_c"], diff --git a/include/glvnd/GLdispatchABI.h b/include/glvnd/GLdispatchABI.h index 06260d1..0dce4cb 100644 --- a/include/glvnd/GLdispatchABI.h +++ b/include/glvnd/GLdispatchABI.h @@ -99,6 +99,11 @@ enum { * Used for stubs on PPC64LE systems. Same as PPC64, for compatibility. */ __GLDISPATCH_STUB_PPC64LE = __GLDISPATCH_STUB_PPC64, + + /*! + * Used for stubs on LOONGARCH/loongarch64. + */ + __GLDISPATCH_STUB_LOONGARCH64, }; /*! diff --git a/src/GLX/glvnd_genentry.c b/src/GLX/glvnd_genentry.c index b82aa14..5a7acfd 100644 --- a/src/GLX/glvnd_genentry.c +++ b/src/GLX/glvnd_genentry.c @@ -108,6 +108,16 @@ extern char glx_entrypoint_end[]; "mtctr 12\n" \ "bctr\n" +#elif defined(USE_LOONGARCH64_ASM) + +#define STUB_SIZE 32 +#define STUB_ASM_ARCH(slot) \ + "la.global $t0,entrypointFunctions\n" \ + "li.d $t1," slot "*8\r\n" \ + "add.d $t0, $t0,$t1\r\n" \ + "ld.d $t0, $t0,0\n" \ + "jirl $r0, $t0,0\n" + #else #error "Can't happen -- not implemented" #endif diff --git a/src/GLdispatch/vnd-glapi/entry_common.c b/src/GLdispatch/vnd-glapi/entry_common.c index e8bfe09..d98ccef 100644 --- a/src/GLdispatch/vnd-glapi/entry_common.c +++ b/src/GLdispatch/vnd-glapi/entry_common.c @@ -124,6 +124,11 @@ static void InvalidateCache(void) } __asm__ __volatile__("isync"); } +#elif defined(USE_LOONGARCH64_ASM) +static void InvalidateCache(void) +{ + __builtin___clear_cache(public_entry_start, public_entry_end); +} #else static void InvalidateCache(void) { diff --git a/src/GLdispatch/vnd-glapi/entry_files.mk b/src/GLdispatch/vnd-glapi/entry_files.mk index 2865ae7..d9801ac 100644 --- a/src/GLdispatch/vnd-glapi/entry_files.mk +++ b/src/GLdispatch/vnd-glapi/entry_files.mk @@ -50,6 +50,12 @@ MAPI_GLDISPATCH_ENTRY_FILES += entry_simple_asm.c MAPI_GLDISPATCH_ENTRY_FILES += entry_common.c endif +if GLDISPATCH_TYPE_LOONGARCH64_TSD +MAPI_GLDISPATCH_ENTRY_FILES = entry_loongarch64_tsd.c +MAPI_GLDISPATCH_ENTRY_FILES += entry_simple_asm.c +MAPI_GLDISPATCH_ENTRY_FILES += entry_common.c +endif + if GLDISPATCH_TYPE_PURE_C MAPI_GLDISPATCH_ENTRY_FILES = entry_pure_c.c endif diff --git a/src/GLdispatch/vnd-glapi/entry_loongarch64_tsd.c b/src/GLdispatch/vnd-glapi/entry_loongarch64_tsd.c new file mode 100644 index 0000000..c164fe7 --- /dev/null +++ b/src/GLdispatch/vnd-glapi/entry_loongarch64_tsd.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * unaltered in all copies or substantial portions of the Materials. + * Any additions, deletions, or changes to the original source files + * must be clearly indicated in accompanying documentation. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +#include "entry.h" +#include "entry_common.h" + +#include +#include +#include +#include + +#include "glapi.h" +#include "u_macros.h" +#include "u_current.h" +#include "utils_misc.h" +#include "glvnd/GLdispatchABI.h" + +/* + * The size of each dispatch stub. + */ +#define ENTRY_STUB_ALIGN 256 +#if !defined(GLDISPATCH_PAGE_SIZE) +// Note that on loongarch64, the page size is 16K. +#define GLDISPATCH_PAGE_SIZE 16384 +#endif + +#define STUB_ASM_ENTRY(func) \ + ".balign " U_STRINGIFY(ENTRY_STUB_ALIGN) "\n\t" \ + ".global " func "\n\t" \ + ".type " func ", %function\n\t" \ + func ":\n\t" + +/* + * Looks up the current dispatch table, finds the stub address at the given slot + * then jumps to it. + * + * First tries to find a dispatch table in _glapi_Current[GLAPI_CURRENT_DISPATCH], + * if not found then it jumps to the 'lookup_dispatch' and calls + * _glapi_get_current() then jumps back to the 'found_dispatch' label. + * + * The 'found_dispatch' section computes the correct offset in the dispatch + * table then does a branch without link to the function address. + */ +#define STUB_ASM_CODE(slot) \ + "addi.d $sp, $sp, -16\n\t" \ + "st.d $a1, $sp, 0\n\t" \ + "st.d $a0, $sp, 8\n\t" \ + "la.global $a0,_glapi_Current\n\t" \ + "ld.d $a0, $a0,0\n\t" \ + "beqz $a0, 10f\n\t" \ + "11:\n\t" /* found dispatch */ \ + "la.local $a1, 3f\n\t" \ + "ld.d $a1, $a1,0\n\t" \ + "ldx.d $t1, $a0, $a1\n\t" \ + "ld.d $a1, $sp, 0\n\t" \ + "ld.d $a0, $sp, 8\n\t" \ + "addi.d $sp, $sp, 16\n\t" \ + "jirl $r0,$t1,0\n\t" \ + "10:\n\t" /* lookup dispatch */ \ + "addi.d $sp, $sp, -8*8\n\t" \ + "st.d $ra, $sp, 0\n\t" \ + "st.d $a7, $sp, 8\n\t" \ + "st.d $a6, $sp, 16\n\t" \ + "st.d $a5, $sp, 24\n\t" \ + "st.d $a4, $sp, 32\n\t" \ + "st.d $a3, $sp, 40\n\t" \ + "st.d $a2, $sp, 48\n\t" \ + "la.global $a0,_glapi_get_current\n\t" \ + "jirl $ra, $a0,0\n\t" \ + "ld.d $ra, $sp, 0\n\t" \ + "ld.d $a7, $sp, 8\n\t" \ + "ld.d $a6, $sp, 16\n\t" \ + "ld.d $a5, $sp, 24\n\t" \ + "ld.d $a4, $sp, 32\n\t" \ + "ld.d $a3, $sp, 40\n\t" \ + "ld.d $a2, $sp, 48\n\t" \ + "addi.d $sp, $sp, 8*8\n\t" \ + "b 11b\n\t" \ + "3:\n\t" \ + ".dword " slot " * 8\n\t" /* size of (void *) */ + +__asm__(".section wtext,\"ax\"\n" + ".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n" + ".globl public_entry_start\n" + ".hidden public_entry_start\n" + "public_entry_start:\n"); + +#define MAPI_TMP_STUB_ASM_GCC +#include "mapi_tmp.h" + +__asm__(".balign " U_STRINGIFY(GLDISPATCH_PAGE_SIZE) "\n" + ".globl public_entry_end\n" + ".hidden public_entry_end\n" + "public_entry_end:\n" + ".text\n\t"); + +const int entry_type = __GLDISPATCH_STUB_LOONGARCH64; +const int entry_stub_size = ENTRY_STUB_ALIGN; + diff --git a/src/GLdispatch/vnd-glapi/meson.build b/src/GLdispatch/vnd-glapi/meson.build index 213241f..7408ac0 100644 --- a/src/GLdispatch/vnd-glapi/meson.build +++ b/src/GLdispatch/vnd-glapi/meson.build @@ -54,6 +54,8 @@ else _entry_files += 'entry_ppc64_tls.c' elif gl_dispatch_type == 'ppc64_tsd' _entry_files += 'entry_ppc64_tsd.c' + elif gl_dispatch_type == 'loongarch64_tsd' + _entry_files += 'entry_loongarch64_tsd.c' else error('No matching ASM file for @0@'.format(gl_dispatch_type)) endif diff --git a/tests/dummy/patchentrypoints.c b/tests/dummy/patchentrypoints.c index f11a3ef..2e01b2a 100644 --- a/tests/dummy/patchentrypoints.c +++ b/tests/dummy/patchentrypoints.c @@ -238,6 +238,36 @@ static void patch_ppc64(char *writeEntry, const char *execEntry, #endif } +static void patch_loongarch64(char *writeEntry, const char *execEntry, + int stubSize, void *incrementPtr) +{ +#if defined(__loongarch64) + const uint32_t tmpl[] = { + 0x1c000004, // pcaddu12i $r4,0 + 0x02c07084, // addi.d $r4,$r4,28(0x1c) + 0x28c00084, // ld.d $r4,$r4,0 + 0x28c00085, // ld.d $r5,$r4,0 + 0x02c004a5, // addi.d $r5,$r5,1(0x1) + 0x29c00085, // st.d $r5,$r4,0 + 0x4c000020, // jirl $r0,$r1,0 + // 1: + 0x00000000,0x00000000, + }; + + static const int offsetAddr = sizeof(tmpl) - 8; + + if (stubSize < sizeof(tmpl)) { + return; + } + + memcpy(writeEntry, tmpl, sizeof(tmpl)); + *((uint64_t *)(writeEntry + offsetAddr)) = (uint64_t) incrementPtr; + + __builtin___clear_cache((char *) execEntry, (char *) (execEntry + sizeof(tmpl))); +#else + assert(0); // Should not be calling this +#endif +} GLboolean dummyCheckPatchSupported(int type, int stubSize) { @@ -249,6 +279,7 @@ GLboolean dummyCheckPatchSupported(int type, int stubSize) case __GLDISPATCH_STUB_AARCH64: case __GLDISPATCH_STUB_X32: case __GLDISPATCH_STUB_PPC64: + case __GLDISPATCH_STUB_LOONGARCH64: return GL_TRUE; default: return GL_FALSE; @@ -287,6 +318,9 @@ GLboolean dummyPatchFunction(int type, int stubSize, case __GLDISPATCH_STUB_PPC64: patch_ppc64(writeAddr, execAddr, stubSize, incrementPtr); break; + case __GLDISPATCH_STUB_LOONGARCH64: + patch_loongarch64(writeAddr, execAddr, stubSize, incrementPtr); + break; default: assert(0); }