libglvnd: Add support for ARMv7
This commit adds static and dynamic TSD stubs generation support for ARMv7. Testing coverage includes all ARM / Thumb mode combinations between libglvnd and a vendor implementation.
This commit is contained in:
parent
59aef8dacc
commit
66f478867c
|
@ -103,6 +103,9 @@ if test "x$enable_asm" = xyes; then
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
armv7l)
|
||||
asm_arch=armv7l
|
||||
;;
|
||||
sparc*)
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
|
@ -121,6 +124,10 @@ if test "x$enable_asm" = xyes; then
|
|||
DEFINES="$DEFINES -DUSE_X86_64_ASM"
|
||||
AC_MSG_RESULT([yes, x86_64])
|
||||
;;
|
||||
armv7l)
|
||||
DEFINES="$DEFINES -DUSE_ARMV7_ASM"
|
||||
AC_MSG_RESULT([yes, armv7l])
|
||||
;;
|
||||
sparc)
|
||||
DEFINES="$DEFINES -DUSE_SPARC_ASM"
|
||||
AC_MSG_RESULT([yes, sparc])
|
||||
|
@ -183,7 +190,7 @@ AC_ARG_ENABLE([tls],
|
|||
)
|
||||
|
||||
AC_MSG_CHECKING([for initial-exec TLS])
|
||||
if test "x$asm_arch" != xx86 && test "x$enable_tls" = "xyes"; then
|
||||
if test "x$asm_arch" != xx86 && test "x$asm_arch" != xarmv7l && test "x$enable_tls" = "xyes"; then
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
__thread int foo __attribute__((tls_model("initial-exec")));
|
||||
])],
|
||||
|
|
|
@ -39,7 +39,8 @@ libGL_la_SOURCES = \
|
|||
libgl.c \
|
||||
$(MAPI)/entry.c \
|
||||
$(MAPI)/stub.c \
|
||||
g_libglglxwrapper.c
|
||||
g_libglglxwrapper.c \
|
||||
$(top_srcdir)/src/util/utils_misc.c
|
||||
|
||||
BUILT_SOURCES = glapi_mapi_tmp.h g_libglglxwrapper.c
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
|
|
@ -63,6 +63,7 @@ enum {
|
|||
__GLDISPATCH_STUB_X86_TSD,
|
||||
__GLDISPATCH_STUB_PURE_C,
|
||||
__GLDISPATCH_STUB_X86_64_TSD,
|
||||
__GLDISPATCH_STUB_ARMV7_THUMB_TSD,
|
||||
__GLDISPATCH_STUB_NUM_TYPES
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ static inline void UNUSED __unused_tls_type_check(void)
|
|||
TLS_TYPE_CHECK(X86_64_TLS);
|
||||
TLS_TYPE_CHECK(X86_TSD);
|
||||
TLS_TYPE_CHECK(PURE_C);
|
||||
TLS_TYPE_CHECK(X86_64_TSD);
|
||||
TLS_TYPE_CHECK(ARMV7_THUMB_TSD);
|
||||
TLS_TYPE_CHECK(NUM_TYPES);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ MAPI_GLAPI_FILES = \
|
|||
$(TOP)/$(MAPI_PREFIX)/mapi_glapi.c \
|
||||
$(TOP)/$(MAPI_PREFIX)/stub.c \
|
||||
$(TOP)/$(MAPI_PREFIX)/table.c \
|
||||
$(MAPI_UTIL_FILES)
|
||||
$(MAPI_UTIL_FILES) \
|
||||
$(TOP)/src/util/utils_misc.c
|
||||
|
||||
libglapi_la_SOURCES = \
|
||||
$(MAPI_GLAPI_FILES) \
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
# else
|
||||
# include "entry_x86-64_tsd.h"
|
||||
# endif
|
||||
#elif defined(USE_ARMV7_ASM) && defined(__GNUC__)
|
||||
# include "entry_armv7_tsd.h"
|
||||
#else
|
||||
# include "entry_pure_c.h"
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@ enum {
|
|||
ENTRY_X86_TSD,
|
||||
ENTRY_PURE_C,
|
||||
ENTRY_X86_64_TSD,
|
||||
ENTRY_ARMV7_THUMB_TSD,
|
||||
ENTRY_NUM_TYPES
|
||||
};
|
||||
|
||||
|
|
228
src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.h
Normal file
228
src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.h
Normal file
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the
|
||||
* work of the Khronos Group."
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "entry.h"
|
||||
#include "u_macros.h"
|
||||
#include "u_current.h"
|
||||
#include "u_execmem.h"
|
||||
#include "utils_misc.h"
|
||||
|
||||
/*
|
||||
* See: https://sourceware.org/binutils/docs/as/ARM-Directives.html
|
||||
*/
|
||||
__asm__(".syntax unified\n\t");
|
||||
|
||||
/*
|
||||
* u_execmem_alloc() allocates 64 bytes per stub.
|
||||
*/
|
||||
#define ARMV7_ENTRY_SIZE 64
|
||||
|
||||
/*
|
||||
* This runs in Thumb mode.
|
||||
*
|
||||
* libglvnd on armv7 is built with -march=armv7-a, which uses the AAPCS ABI
|
||||
* that has ARM/Thumb interworking enabled by default.
|
||||
*
|
||||
* See: https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
|
||||
*/
|
||||
#define STUB_ASM_ENTRY(func) \
|
||||
".balign " U_STRINGIFY(ARMV7_ENTRY_SIZE) "\n\t" \
|
||||
".thumb_func\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 u_current[GLAPI_CURRENT_DISPATCH],
|
||||
* if not found then it jumps to the 'lookup_dispatch' and calls
|
||||
* u_current_get_internal() 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.
|
||||
*
|
||||
* This routine preserves the r0-r3 volatile registers as they store the
|
||||
* parameters of the entry point that is being looked up.
|
||||
*/
|
||||
#define STUB_ASM_CODE(slot) \
|
||||
"push {r0-r3}\n\t" \
|
||||
"ldr r0, 1f\n\t" \
|
||||
"ldr r0, [r0]\n\t" \
|
||||
"cmp r0, #0\n\t" \
|
||||
"it eq\n\t" \
|
||||
"beq 10f\n\t" \
|
||||
"11:\n\t" /* found_dispatch */ \
|
||||
"ldr r1, 3f\n\t" \
|
||||
"mov r2, #4\n\t" /* sizeof(void *) */ \
|
||||
"mul r1, r1, r2\n\t" \
|
||||
"ldr ip, [r0, +r1]\n\t" \
|
||||
"pop {r0-r3}\n\t" \
|
||||
"bx ip\n\t" \
|
||||
"10:\n\t" /* lookup_dispatch */ \
|
||||
"push {lr}\n\t" \
|
||||
"ldr r0, 2f\n\t" \
|
||||
"blx r0\n\t" \
|
||||
"pop {lr}\n\t" \
|
||||
"b 11b\n\t" \
|
||||
"1:\n\t" \
|
||||
".word " ENTRY_CURRENT_TABLE "\n\t" \
|
||||
"2:\n\t" \
|
||||
".word " ENTRY_CURRENT_TABLE_GET "\n\t" \
|
||||
"3:\n\t" \
|
||||
".word " slot "\n\t"
|
||||
|
||||
/*
|
||||
* Bytecode for STUB_ASM_CODE()
|
||||
*/
|
||||
static unsigned char BYTECODE_TEMPLATE[] =
|
||||
{
|
||||
0xb4, 0x0f,
|
||||
0xf8, 0xdf, 0x00, 0x28,
|
||||
0x68, 0x00,
|
||||
0x28, 0x00,
|
||||
0xbf, 0x08,
|
||||
0xe0, 0x08,
|
||||
0x49, 0x09,
|
||||
0xf0, 0x4f, 0x02, 0x04,
|
||||
0xfb, 0x01, 0xf1, 0x02,
|
||||
0xf8, 0x50, 0xc0, 0x01,
|
||||
0xbc, 0x0f,
|
||||
0x47, 0x60,
|
||||
0xb5, 0x00,
|
||||
0x48, 0x03,
|
||||
0x47, 0x80,
|
||||
0xf8, 0x5d, 0xeb, 0x04,
|
||||
0xe7, 0xf0,
|
||||
|
||||
// Offsets that need to be patched
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#define ARMV7_BYTECODE_SIZE sizeof(BYTECODE_TEMPLATE)
|
||||
|
||||
__asm__(".balign " U_STRINGIFY(ARMV7_ENTRY_SIZE) "\n\t"
|
||||
".section wtext, \"awx\"\n\t"
|
||||
"armv7_entry_start:\n\t");
|
||||
|
||||
#define MAPI_TMP_STUB_ASM_GCC
|
||||
#include "mapi_tmp.h"
|
||||
|
||||
__asm__(".balign " U_STRINGIFY(ARMV7_ENTRY_SIZE) "\n\t"
|
||||
".armv7_entry_end:\n\t"
|
||||
".text\n\t");
|
||||
|
||||
static const char armv7_entry_start[];
|
||||
static const char armv7_entry_end[];
|
||||
|
||||
/*
|
||||
* If built with -marm, let the assembler know that we are done with Thumb
|
||||
*/
|
||||
#if !defined(__thumb__)
|
||||
__asm__(".arm\n\t");
|
||||
#endif
|
||||
|
||||
const int entry_type = ENTRY_ARMV7_THUMB_TSD;
|
||||
const int entry_stub_size = ARMV7_ENTRY_SIZE;
|
||||
|
||||
static const int TEMPLATE_OFFSET_CURRENT_TABLE = ARMV7_BYTECODE_SIZE - 3*4;
|
||||
static const int TEMPLATE_OFFSET_CURRENT_TABLE_GET = ARMV7_BYTECODE_SIZE - 2*4;
|
||||
static const int TEMPLATE_OFFSET_SLOT = ARMV7_BYTECODE_SIZE - 4;
|
||||
static const int TEMPLATE_OFFSETS_SIZE = 3*4;
|
||||
|
||||
void
|
||||
entry_init_public(void)
|
||||
{
|
||||
STATIC_ASSERT(ARMV7_BYTECODE_SIZE <= ARMV7_ENTRY_SIZE);
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
glvnd_byte_swap16((uint16_t *)BYTECODE_TEMPLATE,
|
||||
entry_stub_size - TEMPLATE_OFFSETS_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
entry_generate_default_code(char *entry, int slot)
|
||||
{
|
||||
// Make sure the base address has the Thumb mode bit
|
||||
assert((uintptr_t)entry & (uintptr_t)0x1);
|
||||
|
||||
// Get the actual beginning of the stub allocation
|
||||
entry -= 1;
|
||||
|
||||
memcpy(entry, BYTECODE_TEMPLATE, ARMV7_BYTECODE_SIZE);
|
||||
|
||||
*((uint32_t *)(entry + TEMPLATE_OFFSET_SLOT)) = slot;
|
||||
*((uint32_t *)(entry + TEMPLATE_OFFSET_CURRENT_TABLE)) =
|
||||
(uint32_t)u_current;
|
||||
*((uint32_t *)(entry + TEMPLATE_OFFSET_CURRENT_TABLE_GET)) =
|
||||
(uint32_t)u_current_get_internal;
|
||||
|
||||
// See http://community.arm.com/groups/processors/blog/2010/02/17/caches-and-self-modifying-code
|
||||
__builtin___clear_cache(entry, entry + ARMV7_BYTECODE_SIZE);
|
||||
}
|
||||
|
||||
mapi_func
|
||||
entry_get_public(int slot)
|
||||
{
|
||||
// Add 1 to the base address to force Thumb mode when jumping to the stub
|
||||
return (mapi_func)(armv7_entry_start + (slot * ARMV7_ENTRY_SIZE) + 1);
|
||||
}
|
||||
|
||||
#if !defined(STATIC_DISPATCH_ONLY)
|
||||
void
|
||||
entry_patch(mapi_func entry, int slot)
|
||||
{
|
||||
entry_generate_default_code((char *)entry, slot);
|
||||
}
|
||||
|
||||
mapi_func
|
||||
entry_generate(int slot)
|
||||
{
|
||||
void *code;
|
||||
|
||||
code = u_execmem_alloc(ARMV7_BYTECODE_SIZE);
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
// Add 1 to the base address to force Thumb mode when jumping to the stub
|
||||
code = (void *)((char *)code + 1);
|
||||
|
||||
entry_generate_default_code(code, slot);
|
||||
|
||||
return (mapi_func)code;
|
||||
}
|
||||
#endif // !defined(STATIC_DISPATCH_ONLY)
|
|
@ -36,7 +36,8 @@ noinst_HEADERS = \
|
|||
libOpenGL_la_SOURCES = \
|
||||
libopengl.c \
|
||||
$(MAPI)/entry.c \
|
||||
$(MAPI)/stub.c
|
||||
$(MAPI)/stub.c \
|
||||
$(top_srcdir)/src/util/utils_misc.c
|
||||
|
||||
BUILT_SOURCES = glapi_mapi_tmp.h
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
|
|
@ -1,4 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the
|
||||
* work of the Khronos Group."
|
||||
*
|
||||
* 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 "glvnd_genentry.h"
|
||||
#include "utils_misc.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
@ -7,9 +37,11 @@
|
|||
#include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "utils_misc.h"
|
||||
#define USE_ASM (defined(USE_X86_ASM) || \
|
||||
defined(USE_X86_64_ASM) || \
|
||||
defined(USE_ARMV7_ASM))
|
||||
|
||||
#if defined(__GNUC__) && (defined(USE_X86_ASM) || defined(USE_X86_64_ASM))
|
||||
#if defined(__GNUC__) && USE_ASM
|
||||
|
||||
/// The maximum number of entrypoints that we can generate.
|
||||
#define GENERATED_ENTRYPOINT_MAX 4096
|
||||
|
@ -28,7 +60,6 @@ static const int DISPATCH_FUNC_OFFSET = 1;
|
|||
static const int DISPATCH_FUNC_OFFSET_REL = 5;
|
||||
|
||||
#elif defined(USE_X86_64_ASM)
|
||||
|
||||
// For x86_64, the offset from the entrypoint to the dispatch function might be
|
||||
// more than 2^31, and there's no JMP instruction that takes a 64-bit offset.
|
||||
static unsigned char STUB_TEMPLATE[] =
|
||||
|
@ -39,6 +70,23 @@ static unsigned char STUB_TEMPLATE[] =
|
|||
|
||||
static const int DISPATCH_FUNC_OFFSET = 2;
|
||||
|
||||
#elif defined(USE_ARMV7_ASM)
|
||||
// Thumb bytecode
|
||||
static unsigned char STUB_TEMPLATE[] =
|
||||
{
|
||||
// ldr ip, 1f
|
||||
0xf8, 0xdf, 0xc0, 0x04,
|
||||
// bx ip
|
||||
0x47, 0x60,
|
||||
// nop
|
||||
0xbf, 0x00,
|
||||
// Offset that needs to be patched
|
||||
// 1:
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const int DISPATCH_FUNC_OFFSET = 8;
|
||||
|
||||
#else
|
||||
#error "Can't happen -- not implemented"
|
||||
#endif
|
||||
|
@ -166,6 +214,12 @@ int InitEntrypoints(void)
|
|||
}
|
||||
entrypointBufferWrite = (uint8_t *) writeBuf;
|
||||
entrypointBufferExec = (uint8_t *) execBuf;
|
||||
|
||||
#if defined(USE_ARMV7_ASM)
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
glvnd_byte_swap16((uint16_t *)STUB_TEMPLATE, sizeof(STUB_TEMPLATE) - 4);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -181,6 +235,11 @@ void GenerateEntrypointFunc(GLVNDGenEntrypoint *entry, int index)
|
|||
// Copy the template into our buffer.
|
||||
memcpy(entry->entrypointWrite, STUB_TEMPLATE, sizeof(STUB_TEMPLATE));
|
||||
|
||||
#if defined(USE_ARMV7_ASM)
|
||||
// Add 1 to the base address to force Thumb mode when jumping to the stub
|
||||
entry->entrypointExec = (GLVNDentrypointStub)((char *)entry->entrypointExec + 1);
|
||||
#endif
|
||||
|
||||
// Assign DefaultDispatchFunc as the dispatch function.
|
||||
SetDispatchFuncPointer(entry, (GLVNDentrypointStub) DefaultDispatchFunc);
|
||||
}
|
||||
|
@ -197,11 +256,19 @@ void SetDispatchFuncPointer(GLVNDGenEntrypoint *entry,
|
|||
*((intptr_t *) (code + DISPATCH_FUNC_OFFSET)) = offset;
|
||||
|
||||
#elif defined(USE_X86_64_ASM)
|
||||
|
||||
// For x86_64, we have to use a movabs instruction, which needs the
|
||||
// absolute address of the dispatch function.
|
||||
*((GLVNDentrypointStub *) (code + DISPATCH_FUNC_OFFSET)) = dispatch;
|
||||
|
||||
#elif defined(USE_ARMV7_ASM)
|
||||
*((uint32_t *)(code + DISPATCH_FUNC_OFFSET)) = (uint32_t)dispatch;
|
||||
|
||||
// Make sure the base address has the Thumb mode bit
|
||||
assert((uintptr_t)entry->entrypointExec & (uintptr_t)0x1);
|
||||
|
||||
// See http://community.arm.com/groups/processors/blog/2010/02/17/caches-and-self-modifying-code
|
||||
__builtin___clear_cache((char *)entry->entrypointExec - 1,
|
||||
(char *)entry->entrypointExec + sizeof(STUB_TEMPLATE));
|
||||
#else
|
||||
#error "Can't happen -- not implemented"
|
||||
#endif
|
||||
|
@ -213,7 +280,7 @@ void *DefaultDispatchFunc(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#else // defined(__GNUC__) && (defined(USE_X86_ASM) || defined(USE_X86_64_ASM))
|
||||
#else // defined(__GNUC__) && USE_ASM
|
||||
|
||||
GLVNDentrypointStub glvndGenerateEntrypoint(const char *procName)
|
||||
{
|
||||
|
@ -228,4 +295,4 @@ void glvndUpdateEntrypoints(GLVNDentrypointUpdateCallback callback, void *param)
|
|||
{
|
||||
}
|
||||
|
||||
#endif // defined(__GNUC__) && (defined(USE_X86_ASM) || defined(USE_X86_64_ASM))
|
||||
#endif // defined(__GNUC__) && USE_ASM
|
||||
|
|
|
@ -1,3 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the
|
||||
* work of the Khronos Group."
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef GLVND_GENENTRY_H
|
||||
#define GLVND_GENENTRY_H
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "utils_misc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/mman.h>
|
||||
|
@ -240,3 +239,14 @@ void GetTempDirs(const char **dirs)
|
|||
dirs[count] = NULL;
|
||||
}
|
||||
|
||||
void glvnd_byte_swap16(uint16_t* array, const size_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert((size % 2) == 0);
|
||||
|
||||
for (i = 0; i < size / 2; i++) {
|
||||
array[i] = (array[i] << 8) | (array[i] >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NVIDIA CORPORATION.
|
||||
* Copyright (c) 2013-2015, NVIDIA CORPORATION.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and/or associated documentation files (the
|
||||
|
@ -31,6 +31,8 @@
|
|||
#define __UTILS_MISC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Various macros which may prove useful in various places
|
||||
|
@ -81,4 +83,12 @@ int AllocExecPages(size_t size, void **writePtr, void **execPtr);
|
|||
*/
|
||||
void FreeExecPages(size_t size, void *writePtr, void *execPtr);
|
||||
|
||||
/*!
|
||||
* Swaps the bytes of an array.
|
||||
*
|
||||
* @param array The array.
|
||||
* @param size The size in bytes of the array, must be a multiple of 2.
|
||||
*/
|
||||
void glvnd_byte_swap16(uint16_t* array, const size_t size);
|
||||
|
||||
#endif // !defined(__UTILS_MISC_H)
|
||||
|
|
|
@ -540,12 +540,62 @@ static void patch_x86_tls(char *writeEntry,
|
|||
#endif
|
||||
}
|
||||
|
||||
static void patch_armv7_thumb_tsd(char *writeEntry,
|
||||
const char *execEntry,
|
||||
int stubSize)
|
||||
{
|
||||
#if defined(__arm__)
|
||||
char *pSawVertex3fv = (char *)&__glXSawVertex3fv;
|
||||
|
||||
// Thumb bytecode
|
||||
char tmpl[] = {
|
||||
// ldr r0, 1f
|
||||
0x48, 0x02,
|
||||
// ldr r1, [r0]
|
||||
0x68, 0x01,
|
||||
// add r1, r1, #1
|
||||
0xf1, 0x01, 0x01, 0x01,
|
||||
// str r1, [r0]
|
||||
0x60, 0x01,
|
||||
// bx lr
|
||||
0x47, 0x70,
|
||||
// 1:
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
int offsetAddr = sizeof(tmpl) - 4;
|
||||
|
||||
if (stubSize < sizeof(tmpl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
glvnd_byte_swap16((uint16_t *)tmpl, offsetAddr);
|
||||
#endif
|
||||
|
||||
*((uint32_t *)(tmpl + offsetAddr)) = (uint32_t)pSawVertex3fv;
|
||||
|
||||
// Make sure the base address has the Thumb mode bit
|
||||
assert((uintptr_t)writeEntry & (uintptr_t)0x1);
|
||||
|
||||
// Get the actual beginning of the stub allocation
|
||||
writeEntry -= 1;
|
||||
|
||||
memcpy(writeEntry, tmpl, sizeof(tmpl));
|
||||
|
||||
__builtin___clear_cache(writeEntry, writeEntry + sizeof(tmpl));
|
||||
#else
|
||||
assert(0); // Should not be calling this
|
||||
#endif
|
||||
}
|
||||
|
||||
static GLboolean dummyCheckPatchSupported(int type, int stubSize)
|
||||
{
|
||||
switch (type) {
|
||||
case __GLDISPATCH_STUB_X86_64_TLS:
|
||||
case __GLDISPATCH_STUB_X86_TLS:
|
||||
case __GLDISPATCH_STUB_X86_64_TSD:
|
||||
case __GLDISPATCH_STUB_ARMV7_THUMB_TSD:
|
||||
return GL_TRUE;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
|
@ -573,6 +623,9 @@ static GLboolean dummyInitiatePatch(int type,
|
|||
case __GLDISPATCH_STUB_X86_TLS:
|
||||
patch_x86_tls(writeAddr, execAddr, stubSize);
|
||||
break;
|
||||
case __GLDISPATCH_STUB_ARMV7_THUMB_TSD:
|
||||
patch_armv7_thumb_tsd(writeAddr, execAddr, stubSize);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,14 @@ COMMON_CFLAGS = \
|
|||
-I$(top_srcdir)/include \
|
||||
-Wno-error=unused-function
|
||||
|
||||
COMMON_SOURCES = \
|
||||
GLX_dummy.c \
|
||||
$(top_srcdir)/src/util/utils_misc.c
|
||||
|
||||
libGLX_dummy_la_CFLAGS = $(COMMON_CFLAGS)
|
||||
libGLX_dummy_la_SOURCES = GLX_dummy.c
|
||||
libGLX_dummy_la_SOURCES = $(COMMON_SOURCES)
|
||||
libGLX_dummy_la_LIBADD = $(top_builddir)/src/util/trace/libtrace.la
|
||||
|
||||
libGLX_patchentry_la_CFLAGS = $(COMMON_CFLAGS) -DPATCH_ENTRYPOINTS
|
||||
libGLX_patchentry_la_SOURCES = GLX_dummy.c
|
||||
libGLX_patchentry_la_SOURCES = $(COMMON_SOURCES)
|
||||
libGLX_patchentry_la_LIBADD = $(top_builddir)/src/util/trace/libtrace.la
|
||||
|
|
Loading…
Reference in a new issue