From b36697e233ff1ef1cc3ad2e687581520656d4755 Mon Sep 17 00:00:00 2001 From: Brian Mastenbrook Date: Thu, 30 Dec 2004 13:44:26 +0000 Subject: [PATCH] 0.8.19.1: PowerPC linkage tables (darwin only for now) * Linkage tables are now implemented on PowerPC. Right now I've only enabled it on Darwin; to enable it on Linux, the addresses used for linkage table spaces would need to be tested. * Lazy foreign functions do not work correctly - the code expects the signal that occurs when jumping to a write-protected page to be the same as the signal that occurs when reading from one. On Darwin the former is SIGBUS and the latter is SIGSEGV; this means that the fault address testing does not work on Darwin. --- NEWS | 5 +++ make-config.sh | 2 +- src/code/save.lisp | 2 +- src/compiler/ppc/c-call.lisp | 15 +++++++ src/compiler/ppc/parms.lisp | 6 ++- src/runtime/Config.ppc-darwin | 3 +- src/runtime/ppc-arch.c | 92 +++++++++++++++++++++++++++++++++++++++++ version.lisp-expr | 2 +- 8 files changed, 121 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index d956277..601d7bd 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +changes in sbcl-0.8.19 relative to sbcl-0.8.18: + * enhancement: saving cores with foreign code loaded is now + supported on ppc/Darwin in addition to the previously supported + platforms. + changes in sbcl-0.8.18 relative to sbcl-0.8.17: * new feature: reloading changed shared object files with LOAD-SHARED-OBJECT now causes the new definitions to take effect. diff --git a/make-config.sh b/make-config.sh index e725cfe..0ba561e 100644 --- a/make-config.sh +++ b/make-config.sh @@ -206,7 +206,7 @@ elif [ "$sbcl_arch" = "ppc" -a "$sbcl_os" = "linux" ]; then tools-for-build/where-is-mcontext > src/runtime/ppc-linux-mcontext.h elif [ "$sbcl_arch" = "ppc" -a "$sbcl_os" = "darwin" ]; then # We provide a dlopen shim, so a little lie won't hurt - printf " :os-provides-dlopen" >> $ltf + printf " :os-provides-dlopen :linkage-table" >> $ltf # The default stack ulimit under darwin is too small to run PURIFY. # Best we can do is complain and exit at this stage if [ "`ulimit -s`" = "512" ]; then diff --git a/src/code/save.lisp b/src/code/save.lisp index 5351515..8cefec9 100644 --- a/src/code/save.lisp +++ b/src/code/save.lisp @@ -78,7 +78,7 @@ do not survive intact on all platforms: in this case a WARNING is signalled when saving the core. If no warning is signalled, then the foreign symbol references will remain intact. Platforms where this is currently the case are x86/FreeBSD, x86/Linux, x86/NetBSD, -sparc/Linux, and sparc/SunOS. +sparc/Linux, sparc/SunOS, and ppc/Darwin. This implementation is not as polished and painless as you might like: * It corrupts the current Lisp image enough that the current process diff --git a/src/compiler/ppc/c-call.lisp b/src/compiler/ppc/c-call.lisp index d14fe07..1942ef5 100644 --- a/src/compiler/ppc/c-call.lisp +++ b/src/compiler/ppc/c-call.lisp @@ -310,6 +310,21 @@ (:generator 2 (inst lr res (make-fixup (extern-alien-name foreign-symbol) :foreign)))) +#!+linkage-table +(define-vop (foreign-symbol-dataref-address) + (:translate foreign-symbol-dataref-address) + (:policy :fast-safe) + (:args) + (:arg-types (:constant simple-string)) + (:info foreign-symbol) + (:results (res :scs (sap-reg))) + (:result-types system-area-pointer) + (:temporary (:scs (non-descriptor-reg)) addr) + (:generator 2 + (inst lr addr (make-fixup (extern-alien-name foreign-symbol) + :foreign-dataref)) + (loadw res addr))) + (define-vop (call-out) (:args (function :scs (sap-reg) :target cfunc) (args :more t)) diff --git a/src/compiler/ppc/parms.lisp b/src/compiler/ppc/parms.lisp index 2b7db4f..aaebb53 100644 --- a/src/compiler/ppc/parms.lisp +++ b/src/compiler/ppc/parms.lisp @@ -102,7 +102,11 @@ (def!constant dynamic-1-space-start #x48000000) (def!constant dynamic-1-space-end #x4ffff000) - +#+darwin +(progn + (def!constant linkage-table-space-start #x50000000) + (def!constant linkage-table-space-end #x51000000) + (def!constant linkage-table-entry-size 16)) ;;;; Other random constants. diff --git a/src/runtime/Config.ppc-darwin b/src/runtime/Config.ppc-darwin index 0b136ab..01ec5f6 100644 --- a/src/runtime/Config.ppc-darwin +++ b/src/runtime/Config.ppc-darwin @@ -3,8 +3,7 @@ CFLAGS = -Dppc -g -Wall -O2 -no-cpp-precomp OS_SRC = bsd-os.c os-common.c ppc-darwin-os.c ppc-darwin-dlshim.c ppc-darwin-langinfo.c OS_LIBS = -lSystem -lc -lm -# Avoid the gcc 3.3 prerelease tarpit of death! -CC = gcc3 +CC = gcc ASSEM_SRC = ppc-assem.S ldso-stubs.S ARCH_SRC = ppc-arch.c diff --git a/src/runtime/ppc-arch.c b/src/runtime/ppc-arch.c index a8df962..7aa24ef 100644 --- a/src/runtime/ppc-arch.c +++ b/src/runtime/ppc-arch.c @@ -266,3 +266,95 @@ ppc_flush_icache(os_vm_address_t address, os_vm_size_t length) address += 32; } } + +#ifdef LISP_FEATURE_LINKAGE_TABLE + +/* Linkage tables for PowerPC + * + * Linkage entry size is 16, because we need at least 4 instructions to + * implement a jump. + */ + +/* + * Define the registers to use in the linkage jump table. Can be the + * same. Some care must be exercised when choosing these. It has to be + * a register that is not otherwise being used. reg_NFP is a good + * choice. call_into_c trashes reg_NFP without preserving it, so we can + * trash it in the linkage jump table. + */ +#define LINKAGE_TEMP_REG reg_NFP +#define LINKAGE_ADDR_REG reg_NFP + +/* + * Insert the necessary jump instructions at the given address. + */ +void +arch_write_linkage_table_jmp(void* reloc_addr, void *target_addr) +{ + /* + * Make JMP to function entry. + * + * The instruction sequence is: + * + * addis 13, 0, (hi part of addr) + * ori 13, 13, (low part of addr) + * mtctr 13 + * bctr + * + */ + int* inst_ptr; + unsigned long hi; /* Top 16 bits of address */ + unsigned long lo; /* Low 16 bits of address */ + unsigned int inst; + + inst_ptr = (int*) reloc_addr; + + /* + * Split the target address into hi and lo parts for the sethi + * instruction. hi is the top 22 bits. lo is the low 10 bits. + */ + hi = (unsigned long) target_addr; + lo = hi & 0xffff; + hi >>= 16; + + /* + * addis 13, 0, (hi part) + */ + + inst = (15 << 26) | (LINKAGE_TEMP_REG << 21) | (0 << 16) | hi; + *inst_ptr++ = inst; + + /* + * ori 13, 13, (lo part) + */ + + inst = (24 << 26) | (LINKAGE_TEMP_REG << 21) | (LINKAGE_TEMP_REG << 16) | lo; + *inst_ptr++ = inst; + + /* + * mtctr 13 + */ + + inst = (31 << 26) | (LINKAGE_TEMP_REG << 21) | (9 << 16) | (467 << 1); + *inst_ptr++ = inst; + + /* + * bctr + */ + + inst = (19 << 26) | (20 << 21) | (528 << 1); + *inst_ptr++ = inst; + + + *inst_ptr++ = inst; + + os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - (char*) reloc_addr); +} + +void +arch_write_linkage_table_ref(void * reloc_addr, void *target_addr) +{ + *(unsigned long *)reloc_addr = (unsigned long)target_addr; +} + +#endif diff --git a/version.lisp-expr b/version.lisp-expr index 0371295..eff2dce 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.8.18" +"0.8.19.1" -- 1.7.10.4