From 37c3d2ead6d690fc5269d5de0072ae2e51461d15 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sat, 30 Dec 2006 17:45:08 +0000 Subject: [PATCH] Merge (from 3_2_BRANCH) r6457/8 (Support 64k pages on ppc32/64-linux (Jakub Jelink, Dave Nomura) ) git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6459 --- coregrind/m_aspacemgr/aspacemgr-common.c | 4 ++- coregrind/m_main.c | 36 +++++++++++++++++++ coregrind/m_replacemalloc/vg_replace_malloc.c | 9 +++-- coregrind/m_syswrap/syswrap-ppc32-linux.c | 4 +-- coregrind/m_syswrap/syswrap-ppc64-linux.c | 4 +-- coregrind/m_syswrap/syswrap-x86-linux.c | 5 ++- coregrind/m_ume.c | 4 +-- coregrind/m_vki.c | 11 +++++- coregrind/pub_core_aspacemgr.h | 9 +++-- include/vki/vki-amd64-linux.h | 2 ++ include/vki/vki-ppc32-linux.h | 9 +++-- include/vki/vki-ppc64-linux.h | 9 +++-- include/vki/vki-x86-linux.h | 2 ++ memcheck/tests/memalign_test.c | 8 +++++ memcheck/tests/memalign_test.stderr.exp | 4 +-- 15 files changed, 99 insertions(+), 21 deletions(-) diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c index 42355dd9d6..f422864b68 100644 --- a/coregrind/m_aspacemgr/aspacemgr-common.c +++ b/coregrind/m_aspacemgr/aspacemgr-common.c @@ -151,8 +151,10 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot, SysRes res; aspacem_assert(VG_IS_PAGE_ALIGNED(offset)); # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) + /* mmap2 uses 4096 chunks even if actual page size is bigger. */ + aspacem_assert((offset % 4096) == 0); res = VG_(do_syscall6)(__NR_mmap2, (UWord)start, length, - prot, flags, fd, offset / VKI_PAGE_SIZE); + prot, flags, fd, offset / 4096); # elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 7aba9e68bc..4b267cdcd6 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -895,6 +895,11 @@ static void print_preamble(Bool logging_to_fd, const char* toolname) LibVEX_ppVexArch ( vex_arch ), LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps ) ); + VG_(message)( + Vg_DebugMsg, + "Page sizes: currently %d, max supported %d\n", + (Int)VKI_PAGE_SIZE, (Int)VKI_MAX_PAGE_SIZE + ); VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir)); } } @@ -1256,6 +1261,11 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) // p: logging, plausible-stack //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Starting the address space manager\n"); + vg_assert(VKI_PAGE_SIZE == 4096 || VKI_PAGE_SIZE == 65536); + vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536); + vg_assert(VKI_PAGE_SIZE <= VKI_MAX_PAGE_SIZE); + vg_assert(VKI_PAGE_SIZE == (1 << VKI_PAGE_SHIFT)); + vg_assert(VKI_MAX_PAGE_SIZE == (1 << VKI_MAX_PAGE_SHIFT)); the_iicii.clstack_top = VG_(am_startup)( the_iicii.sp_at_startup ); VG_(debugLog)(1, "main", "Address space manager is running\n"); @@ -2249,6 +2259,13 @@ asm("\n" #error "_start: needs implementation on this platform" #endif +/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 +/* This is in order to get AT_NULL and AT_PAGESIZE. */ +#include +/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ + /* Avoid compiler warnings: this fn _is_ used, but labelling it 'static' causes gcc to complain it isn't. */ void _start_in_C_linux ( UWord* pArgc ); @@ -2264,6 +2281,25 @@ void _start_in_C_linux ( UWord* pArgc ) the_iicii.sp_at_startup = (Addr)pArgc; +# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) + { + /* ppc/ppc64 can be configured with different page sizes. + Determine this early. This is an ugly hack and really should + be moved into valgrind_main. */ + UWord *sp = &pArgc[1+argc+1]; + while (*sp++ != 0) + ; + for (; *sp != AT_NULL && *sp != AT_PAGESZ; sp += 2); + if (*sp == AT_PAGESZ) { + VKI_PAGE_SIZE = sp[1]; + for (VKI_PAGE_SHIFT = 12; + VKI_PAGE_SHIFT <= VKI_MAX_PAGE_SHIFT; VKI_PAGE_SHIFT++) + if (VKI_PAGE_SIZE == (1UL << VKI_PAGE_SHIFT)) + break; + } + } +# endif + r = valgrind_main( (Int)argc, argv, envp ); /* NOTREACHED */ VG_(exit)(r); diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index 95ba9cc26b..0a8e6be264 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -45,7 +45,7 @@ ------------------------------------------------------------------ */ #include "pub_core_basics.h" -#include "pub_core_vki.h" // VKI_EINVAL, VKI_ENOMEM, VKI_PAGE_SIZE +#include "pub_core_vki.h" // VKI_EINVAL, VKI_ENOMEM #include "pub_core_clreq.h" // for VALGRIND_INTERNAL_PRINTF, // VALGRIND_NON_SIMD_CALL[12] #include "pub_core_debuginfo.h" // needed for pub_core_redir.h :( @@ -455,7 +455,12 @@ MEMALIGN(m_libc_soname, memalign); void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ); \ void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ) \ { \ - return VG_REPLACE_FUNCTION_ZU(m_libc_soname,memalign)(VKI_PAGE_SIZE, size); \ + static int pszB = 0; \ + extern int getpagesize (void); \ + if (pszB == 0) \ + pszB = getpagesize(); \ + return VG_REPLACE_FUNCTION_ZU(m_libc_soname,memalign) \ + ((SizeT)pszB, size); \ } VALLOC(m_libc_soname, valloc); diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c index 4f2d416c77..f7fd293ca8 100644 --- a/coregrind/m_syswrap/syswrap-ppc32-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c @@ -673,7 +673,7 @@ PRE(sys_mmap2) SysRes r; // Exactly like old_mmap() except: - // - the file offset is specified in pagesize units rather than bytes, + // - the file offset is specified in 4K units rather than bytes, // so that it can be used for files bigger than 2^32 bytes. PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )", ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 ); @@ -683,7 +683,7 @@ PRE(sys_mmap2) unsigned long, fd, unsigned long, offset); r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, - VKI_PAGE_SIZE * (Off64T)ARG6 ); + 4096 * (Off64T)ARG6 ); SET_STATUS_from_SysRes(r); } diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c index 8350daadd5..c9b78d5ae7 100644 --- a/coregrind/m_syswrap/syswrap-ppc64-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c @@ -701,7 +701,7 @@ PRE(sys_mmap) //zz SysRes r; //zz //zz // Exactly like old_mmap() except: -//zz // - the file offset is specified in pagesize units rather than bytes, +//zz // - the file offset is specified in 4K units rather than bytes, //zz // so that it can be used for files bigger than 2^32 bytes. //zz PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )", //zz ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 ); @@ -711,7 +711,7 @@ PRE(sys_mmap) //zz unsigned long, fd, unsigned long, offset); //zz //zz r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, -//zz VKI_PAGE_SIZE * (Off64T)ARG6 ); +//zz 4096 * (Off64T)ARG6 ); //zz SET_STATUS_from_SysRes(r); //zz } //zz diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 1980d87502..a5d239cb48 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -1300,6 +1300,9 @@ PRE(sys_mmap2) // - all 6 args are passed in regs, rather than in a memory-block. // - the file offset is specified in pagesize units rather than bytes, // so that it can be used for files bigger than 2^32 bytes. + // pagesize or 4K-size units in offset? For ppc32/64-linux, this is + // 4K-sized. Assert that the page size is 4K here for safety. + vg_assert(VKI_PAGE_SIZE == 4096); PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )", ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 ); PRE_REG_READ6(long, "mmap2", @@ -1308,7 +1311,7 @@ PRE(sys_mmap2) unsigned long, fd, unsigned long, offset); r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, - VKI_PAGE_SIZE * (Off64T)ARG6 ); + 4096 * (Off64T)ARG6 ); SET_STATUS_from_SysRes(r); } diff --git a/coregrind/m_ume.c b/coregrind/m_ume.c index 380727d94a..339bf60684 100644 --- a/coregrind/m_ume.c +++ b/coregrind/m_ume.c @@ -565,7 +565,7 @@ static Int do_exec_inner(const HChar* exe, ExeInfo* info); /* returns: 0 = success, non-0 is failure */ static Int load_script(Int fd, const HChar* name, ExeInfo* info) { - Char hdr[VKI_PAGE_SIZE]; + Char hdr[VKI_MAX_PAGE_SIZE]; Int len = VKI_PAGE_SIZE; Int eol; Char* interp; @@ -640,7 +640,7 @@ SysRes VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd) { Int fd, ret; SysRes res; - Char buf[VKI_PAGE_SIZE]; + Char buf[VKI_MAX_PAGE_SIZE]; SizeT bufsz = VKI_PAGE_SIZE, fsz; // Check it's readable diff --git a/coregrind/m_vki.c b/coregrind/m_vki.c index 7cd88e7aae..80357469cd 100644 --- a/coregrind/m_vki.c +++ b/coregrind/m_vki.c @@ -35,7 +35,16 @@ /* We have pub_{core,tool}_vki.h. This is the matching implementation for that interface. In fact there is no implementation, as the sole purpose of the module is to export types and constants - describing the kernel interface, so this file is empty. */ + describing the kernel interface, so this file is nearly empty. */ + + +/* ppc32/64-linux determines page size at startup, hence m_vki is + the logical place to store that info. */ + +#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +unsigned long VKI_PAGE_SHIFT = 12; +unsigned long VKI_PAGE_SIZE = 1UL << 12; +#endif /*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h index 63a65867d8..13aa9c93c9 100644 --- a/coregrind/pub_core_aspacemgr.h +++ b/coregrind/pub_core_aspacemgr.h @@ -368,8 +368,13 @@ extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, // stacks. The address space manager provides and suitably // protects such stacks. -#define VG_STACK_GUARD_SZB 8192 // 2 pages -#define VG_STACK_ACTIVE_SZB 65536 // 16 pages +#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages +# define VG_STACK_ACTIVE_SZB 131072 // 2 or 32 pages +#else +# define VG_STACK_GUARD_SZB 8192 // 2 pages +# define VG_STACK_ACTIVE_SZB 65536 // 16 pages +#endif typedef struct { diff --git a/include/vki/vki-amd64-linux.h b/include/vki/vki-amd64-linux.h index 3bb9efd7d1..8e2d31df90 100644 --- a/include/vki/vki-amd64-linux.h +++ b/include/vki/vki-amd64-linux.h @@ -59,6 +59,8 @@ typedef unsigned int vki_u32; #define VKI_PAGE_SHIFT 12 #define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE //---------------------------------------------------------------------- // From linux-2.6.9/include/asm-x86_64/signal.h diff --git a/include/vki/vki-ppc32-linux.h b/include/vki/vki-ppc32-linux.h index 827e13268e..1155980cc8 100644 --- a/include/vki/vki-ppc32-linux.h +++ b/include/vki/vki-ppc32-linux.h @@ -61,9 +61,12 @@ typedef struct { // From linux-2.6.9/include/asm-ppc/page.h //---------------------------------------------------------------------- -/* PAGE_SHIFT determines the page size */ -#define VKI_PAGE_SHIFT 12 -#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +/* PAGE_SHIFT determines the page size, unfortunately + page size might vary between 32-bit and 64-bit ppc kernels */ +extern unsigned long VKI_PAGE_SHIFT; +extern unsigned long VKI_PAGE_SIZE; +#define VKI_MAX_PAGE_SHIFT 16 +#define VKI_MAX_PAGE_SIZE (1UL << VKI_MAX_PAGE_SHIFT) //---------------------------------------------------------------------- // From linux-2.6.9/include/asm-ppc/signal.h diff --git a/include/vki/vki-ppc64-linux.h b/include/vki/vki-ppc64-linux.h index 4f1882bad3..7fc7aeed45 100644 --- a/include/vki/vki-ppc64-linux.h +++ b/include/vki/vki-ppc64-linux.h @@ -62,9 +62,12 @@ typedef unsigned int vki_u32; // From linux-2.6.13/include/asm-ppc64/page.h //---------------------------------------------------------------------- -/* PAGE_SHIFT determines the page size */ -#define VKI_PAGE_SHIFT 12 -#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +/* PAGE_SHIFT determines the page size, unfortunately + page size might vary between 32-bit and 64-bit ppc kernels */ +extern unsigned long VKI_PAGE_SHIFT; +extern unsigned long VKI_PAGE_SIZE; +#define VKI_MAX_PAGE_SHIFT 16 +#define VKI_MAX_PAGE_SIZE (1UL << VKI_MAX_PAGE_SHIFT) //---------------------------------------------------------------------- // From linux-2.6.13/include/asm-ppc64/signal.h diff --git a/include/vki/vki-x86-linux.h b/include/vki/vki-x86-linux.h index a3686206da..5d81c710d9 100644 --- a/include/vki/vki-x86-linux.h +++ b/include/vki/vki-x86-linux.h @@ -60,6 +60,8 @@ typedef unsigned int vki_u32; /* PAGE_SHIFT determines the page size */ #define VKI_PAGE_SHIFT 12 #define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE //---------------------------------------------------------------------- // From linux-2.6.8.1/include/asm-i386/signal.h diff --git a/memcheck/tests/memalign_test.c b/memcheck/tests/memalign_test.c index a24808c55a..a9c8784cc8 100644 --- a/memcheck/tests/memalign_test.c +++ b/memcheck/tests/memalign_test.c @@ -1,13 +1,21 @@ #include #include +#include +#include int main ( void ) { void* a[10]; int i; + unsigned long pszB = sysconf(_SC_PAGE_SIZE); + assert(sizeof(long) == sizeof(void*)); + assert(pszB == 4096 || pszB == 65536); + for (i = 0; i < 10; i++) { a[i] = valloc(11111 * (i+1)); + /* check valloc really is returning page-aligned memory */ + assert( (((unsigned long)(a[i])) % pszB) == 0 ); // printf("I acquire %p\n", a[i]); } for (i = 0; i < 10; i++) { diff --git a/memcheck/tests/memalign_test.stderr.exp b/memcheck/tests/memalign_test.stderr.exp index 4eb281cdb2..461980d803 100644 --- a/memcheck/tests/memalign_test.stderr.exp +++ b/memcheck/tests/memalign_test.stderr.exp @@ -1,6 +1,6 @@ Invalid free() / delete / delete[] at 0x........: free (vg_replace_malloc.c:...) - by 0x........: main (memalign_test.c:17) + by 0x........: main (memalign_test.c:25) Address 0x........ is 0 bytes inside a block of size 111,110 free'd at 0x........: free (vg_replace_malloc.c:...) - by 0x........: main (memalign_test.c:15) + by 0x........: main (memalign_test.c:23) -- 2.47.2