This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] RFC: PowerPC: Add Program Priority Register support


On Mon, Feb 27, 2012 at 6:13 PM, Adhemerval Zanella
<azanella@linux.vnet.ibm.com> wrote:
> This patch adds save/restore for the Priority Program Register (PPR) for ISA 2.03+
> for POWER machines. The PPR register is a special register that controls the program
> priority. It is documented on latest ISA 2.06 (Book II Chapter 3.1) and it can be
> used to improve lock performance by setting an higher priority on critical sections
> and an lower priority on lock holding.
>
> Although a program can easily set its priority using the 'or %1,%1,%1' the kernel
> does not save neither restore its value on syscalls. This patch addresses this
> limitation.

The kernel will eventually save/restore the PPR on context switch.  I
presume, that at that time you'll have an assume kernel check which
will nop the save/restore PPR macros that you've defined here?

> --
>
> 2012-02-27 ÂAdhemerval Zanella Â<azanella@linux.vnet.ibm.com>
>
> Â Â Â Â* elf/stackguard-macros.h: Updated stack_guard offset value.
> Â Â Â Â* nptl/sysdeps/powerpc/tls.h: Added PPR value to TCB.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/Makefile: Added sys/platform.h install.
> Â Â Â Â* nptl/sysdeps/powerpc/tcb-offsets.sym: Calculating PPR offset on TCB.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Added PPR support
> Â Â Â Âfor ISA 2.03+.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/syscall.S: Likewise.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/sys/platform.h: New file: platform
> Â Â Â Âspecific macros for PPR set.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/Makefile: Added tst-saveppr test.
> Â Â Â Â* sysdeps/unix/sysv/linux/powerpc/tst-saveppr.c: New file: test if PPR is
> Â Â Â Âset/retored in syscalls.
>
>
> diff --git a/elf/stackguard-macros.h b/elf/stackguard-macros.h
> index a9889cf..5763870 100644
> --- a/elf/stackguard-macros.h
> +++ b/elf/stackguard-macros.h
> @@ -11,7 +11,7 @@
> Â ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; })
> Â#elif defined __powerpc__
> Â# define STACK_CHK_GUARD \
> - Â({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; })
> + Â({ uintptr_t x; asm ("lwz %0,-28684(2)" : "=r" (x)); x; })
> Â#elif defined __sparc__ && defined __arch64__
> Â# define STACK_CHK_GUARD \
> Â ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; })
> diff --git a/nptl/sysdeps/powerpc/tcb-offsets.sym b/nptl/sysdeps/powerpc/tcb-offsets.sym
> index 8ac133d..3f65249 100644
> --- a/nptl/sysdeps/powerpc/tcb-offsets.sym
> +++ b/nptl/sysdeps/powerpc/tcb-offsets.sym
> @@ -14,7 +14,9 @@ MULTIPLE_THREADS_OFFSET Â Â Â Â Â Â Â thread_offsetof (header.multiple_threads)
> Â#endif
> ÂPID Â Â Â Â Â Â Â Â Â Â Â Â Â Âthread_offsetof (pid)
> ÂTID Â Â Â Â Â Â Â Â Â Â Â Â Â Âthread_offsetof (tid)
> +PPR_OFFSET Â Â Â Â Â Â Â Â Â Â (offsetof (tcbhead_t, ppr) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
> ÂPOINTER_GUARD Â Â Â Â Â Â Â Â Â(offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
> Â#ifndef __ASSUME_PRIVATE_FUTEX
> ÂPRIVATE_FUTEX_OFFSET Â Â Â Â Â thread_offsetof (header.private_futex)
> Â#endif
> +
> diff --git a/nptl/sysdeps/powerpc/tls.h b/nptl/sysdeps/powerpc/tls.h
> index 4c09eec..6ed6e65 100644
> --- a/nptl/sysdeps/powerpc/tls.h
> +++ b/nptl/sysdeps/powerpc/tls.h
> @@ -1,5 +1,5 @@
> Â/* Definition for thread-local data handling. ÂNPTL/PowerPC version.
> - Â Copyright (C) 2003, 2005, 2006, 2007, 2011 Free Software Foundation, Inc.
> + Â Copyright (C) 2003-2012 Free Software Foundation, Inc.
> Â ÂThis file is part of the GNU C Library.
>
> Â ÂThe GNU C Library is free software; you can redistribute it and/or
> @@ -61,6 +61,8 @@ typedef union dtv
> Â Âare private. Â*/
> Âtypedef struct
> Â{
> + Â/* Program Priority Register saved value. Â*/
> + Âuint64_t Âppr;
> Â uintptr_t pointer_guard;
> Â uintptr_t stack_guard;
> Â dtv_t *dtv;
> diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
> index 55311a4..101eaba 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/Makefile
> +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
> @@ -4,6 +4,8 @@ syscall-list-32bit-condition := __WORDSIZE == 32
> Âsyscall-list-64bit-options := -D__powerpc64__
> Âsyscall-list-64bit-condition := __WORDSIZE == 64
>
> +sysdep_headers += sys/platform.h
> +
> Âifeq ($(subdir),rt)
> Âlibrt-routines += rt-sysdep
> Âendif
> @@ -15,3 +17,7 @@ endif
> Âifeq ($(subdir),elf)
> Âsysdep_routines += dl-vdso
> Âendif
> +
> +ifeq ($(subdir),nptl)
> +tests += tst-saveppr
> +endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
> index b0fa372..b10df5d 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
> @@ -1,4 +1,4 @@
> -/* Copyright (C) 1992,1997-2006,2012 Free Software Foundation, Inc.
> +/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
> Â ÂThis file is part of the GNU C Library.
>
> Â ÂThe GNU C Library is free software; you can redistribute it and/or
> @@ -20,6 +20,7 @@
>
> Â#include <sysdeps/unix/powerpc/sysdep.h>
> Â#include <tls.h>
> +#include <tcb-offsets.h>
>
> Â/* Some systen calls got renamed over time, but retained the same semantics.
> Â ÂHandle them here so they can be catched by both C and assembler stubs in
> @@ -177,6 +178,30 @@
> Â# undef INTERNAL_SYSCALL_DECL
> Â# define INTERNAL_SYSCALL_DECL(err) long int err
>
> +/* The Program Priority Register was added in ISA 2.03 */
> +#if defined _ARCH_PWR5X
> +# define SETPPR_BEFORE Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â__asm__ __volatile__( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"cmpdi cr5,2,0\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"beq- cr5,12\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"mfspr 0,896\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"std 0,%[ppr](2)\n\t" : : [ppr]"i"(PPR_OFFSET) : "r0", "cr5")
> +# define SETPPR_AFTER Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"cmpdi cr5,2,0\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"beq- cr5,12\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"ld 0,%[ppr](2)\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â Â"mtspr 896,0\n\t"
> +# define SETPPR_INPUT Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â, [ppr]"i"(PPR_OFFSET)
> +# define SETPPR_CLOBREG Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â, "cr5"
> +#else
> +# define SETPPR_BEFORE
> +# define SETPPR_AFTER
> +# define SETPPR_INPUT
> +# define SETPPR_CLOBREG
> +#endif
> +
> Â# undef INTERNAL_SYSCALL
> Â# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) Â Â Â Â Â Â Â Â Â\
> Â ({ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> @@ -191,15 +216,17 @@
> Â Â register long int r10 __asm__ ("r10"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â register long int r11 __asm__ ("r11"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â register long int r12 __asm__ ("r12"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â ÂSETPPR_BEFORE; Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â LOADARGS_##nr(name, args); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â __asm__ __volatile__ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
>    ("sc  \n\t"                           \
> + Â Â Â SETPPR_AFTER Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â Â Â"mfcr %0" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â Â Â: "=&r" (r0), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â Â Â "=&r" (r3), "=&r" (r4), "=&r" (r5), Â"=&r" (r6), Â"=&r" (r7), Â\
> Â Â Â Â "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) Â\
> -    : ASM_INPUT_##nr                            Â\
> - Â Â Â : "cr0", "ctr", "memory"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â Â : ASM_INPUT_##nr SETPPR_INPUT Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â Â Â : "cr0", "ctr", "memory" SETPPR_CLOBREG); Â Â Â Â Â Â Â Â Â Â Â \
> Â Â err = r0; Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â (int) r3; Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â })
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
> index 0f4fe53..73cb00a 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
> @@ -1,5 +1,4 @@
> -/* Copyright (C) 1992,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2012
> - Â Â Â Free Software Foundation, Inc.
> +/* Copyright (C) 1992-2012 Free Software Foundation, Inc.
> Â ÂThis file is part of the GNU C Library.
>
> Â ÂThe GNU C Library is free software; you can redistribute it and/or
> @@ -23,6 +22,7 @@
>
> Â#include <sysdeps/unix/powerpc/sysdep.h>
> Â#include <tls.h>
> +#include <tcb-offsets.h>
>
> Â/* Define __set_errno() for INLINE_SYSCALL macro below. Â*/
> Â#ifndef __ASSEMBLER__
> @@ -192,6 +192,29 @@
> Â Âgave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
> Â Âthe negation of the return value in the kernel gets reverted. Â*/
>
> +#if defined _ARCH_PWR5X
> +# define SETPPR_BEFORE Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â__asm__ __volatile__( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"cmpdi cr5,13,0\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â Â"beq- cr5,12\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"mfspr 0,896\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"std 0,%[ppr](13)\n\t" : : [ppr]"i"(PPR_OFFSET) : "r0", "cr5")
> +# define SETPPR_AFTER Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"cmpdi cr5,13,0\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> + Â Â"beq- cr5,12\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"ld 0,%[ppr](13)\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â"mtspr 896,0\n\t"
> +# define SETPPR_INPUT Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â,[ppr]"i"(PPR_OFFSET)
> +# define SETPPR_CLOBREG Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â,"cr5"
> +#else
> +# define SETPPR_BEFORE
> +# define SETPPR_AFTER
> +# define SETPPR_INPUT
> +# define SETPPR_CLOBREG
> +#endif
> +
> Â#undef INTERNAL_SYSCALL
> Â#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
> Â ({ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> @@ -202,17 +225,19 @@
> Â Â register long int r6 Â__asm__ ("r6"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â register long int r7 Â__asm__ ("r7"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â register long int r8 Â__asm__ ("r8"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â ÂSETPPR_BEFORE; Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â LOADARGS_##nr (name, ##args); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â __asm__ __volatile__ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â Â ("sc\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â Â SETPPR_AFTER Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â Â Â"mfcr Â%0\n\t" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â Â Â"0:" Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> Â Â Â Â: "=&r" (r0), Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â Â Â Â"=&r" (r3), "=&r" (r4), "=&r" (r5), Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â Â Â Â Â"=&r" (r6), "=&r" (r7), "=&r" (r8) Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> -    : ASM_INPUT_##nr                            Â\
> +    : ASM_INPUT_##nr    ÂSETPPR_INPUT                  Â\
> Â Â Â Â: "r9", "r10", "r11", "r12", Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> - Â Â Â Â "cr0", "ctr", "memory"); Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â\
> + Â Â Â Â "cr0", "ctr", "memory" SETPPR_CLOBREG); Â Â Â Â Â Â Â Â Â Â Â \
> Â Â Â Â Âerr = r0; Â\
> Â Â r3; Â\
> Â })
> diff --git a/sysdeps/unix/sysv/linux/powerpc/sys/platform.h b/sysdeps/unix/sysv/linux/powerpc/sys/platform.h
> new file mode 100644
> index 0000000..52e6bf3
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/sys/platform.h
> @@ -0,0 +1,47 @@
> +/* Copyright (C) 2012 Free Software Foundation, Inc.
> + Â This file is part of the GNU C Library.
> +
> + Â The GNU C Library is free software; you can redistribute it and/or
> + Â modify it under the terms of the GNU Lesser General Public
> + Â License as published by the Free Software Foundation; either
> + Â version 2.1 of the License, or (at your option) any later version.
> +
> + Â The GNU C Library is distributed in the hope that it will be useful,
> + Â but WITHOUT ANY WARRANTY; without even the implied warranty of
> + Â MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ÂSee the GNU
> + Â Lesser General Public License for more details.
> +
> + Â You should have received a copy of the GNU Lesser General Public
> + Â License along with the GNU C Library; if not, see
> + Â <http://www.gnu.org/licenses/>. Â*/
> +
> +/* This file contains platform specific macros and function definitions */
> +
> +#ifndef _PLATFORM_H
> +#define _PLATFORM_H Â Â1
> +
> +/*
> + * ISA 2.05 and beyond support the Program Priority Register (PPR) to adjust
> + * the thread priorities based on lock acquisition, wait and release. The ISA
> + * defines the use of form 'or Rx,Rx,Rx' as the way to modify the PRI field.
> + * The priorities are defined as:
> + * Rx = 2 (medium), Rx = 6 (medium-low/normal), Rx = 1 (low)
> + * This 'or' instruction form is a nop in previous hardware, so it's safe to
> + * use unguarded.
> + */
> +#define PPR_PRIO_MED() \
> + Â ({ \
> + Â Â Â__asm __volatile("or 2,2,2\n"); \
> + Â })
> +#define PPR_PRIO_MED_LOW() \
> + Â ({ \
> + Â Â Â__asm __volatile("or 6,6,6\n"); \
> + Â })
> +#define PPR_PRIO_LOW() \
> + Â ({ \
> + Â Â Â__asm __volatile("or 1,1,1\n"); \
> + Â })
> +#define PPR_PRIO_NORMAL() \
> + Â PPR_PRIO_MED_LOW()
> +
> +#endif

Considering the recent discussion about timebase, these macros
probably belong as GCC built-in functions.  In lieu of their
availability as GCC built-ins, I believe the current consensus is that
these should indeed go in into sysdeps/powerpc/sys/platform/ppc.h.

When GCC support is available you can add a conditional guard based on
built-in support and have the implementation use the built-in instead
of your version.

These should probably be static inlines for the same reason as
described in the timebase discussion.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
> index 880c05b..1563dd6 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
> +++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
> @@ -1,4 +1,4 @@
> -/* Copyright (C) 1991, 1992, 1997, 1999 Free Software Foundation, Inc.
> +/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
> Â ÂThis file is part of the GNU C Library.
>
> Â ÂThe GNU C Library is free software; you can redistribute it and/or
> @@ -18,6 +18,10 @@
> Â#include <sysdep.h>
>
> ÂENTRY (syscall)
> +#if defined _ARCH_PWR5X
> + Â Â Â mfspr r0,896
> + Â Â Â std Âr0,PPR_OFFSET(r13)
> +#endif
>    Âmr  r0,r3
>    Âmr  r3,r4
>    Âmr  r4,r5
> @@ -26,5 +30,9 @@ ENTRY (syscall)
>    Âmr  r7,r8
>    Âmr  r8,r9
> Â Â Â Âsc
> +#if defined _ARCH_PWR5X
> +    ld  r0,PPR_OFFSET(r13)
> + Â Â Â mtspr 896,r0

Is there a reason to use mtspr instead of mtppr (here and in other places)?

> +#endif
> Â Â Â ÂPSEUDO_RET
> ÂPSEUDO_END (syscall)
> diff --git a/sysdeps/unix/sysv/linux/powerpc/tst-saveppr.c b/sysdeps/unix/sysv/linux/powerpc/tst-saveppr.c
> new file mode 100644
> index 0000000..d5e59f1
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/tst-saveppr.c
> @@ -0,0 +1,63 @@
> +/* Test for saving and restoring the PPR register on syscalls.
> + Â Copyright (C) 2012 Free Software Foundation, Inc.
> + Â This file is part of the GNU C Library.
> +
> + Â The GNU C Library is free software; you can redistribute it and/or
> + Â modify it under the terms of the GNU Lesser General Public
> + Â License as published by the Free Software Foundation; either
> + Â version 2.1 of the License, or (at your option) any later version.
> +
> + Â The GNU C Library is distributed in the hope that it will be useful,
> + Â but WITHOUT ANY WARRANTY; without even the implied warranty of
> + Â MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ÂSee the GNU
> + Â Lesser General Public License for more details.
> +
> + Â You should have received a copy of the GNU Lesser General Public
> + Â License along with the GNU C Library; if not, write to the Free
> + Â Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> + Â 02111-1307 USA. Â*/
> +
> +#include <unistd.h>
> +#include <sys/platform.h>
> +
> +/* This program works both on 32 bit and 64 bit environments,
> + Â so we read the 64 bit PPR value word by word. Â*/
> +
> +void
> +get_ppr (unsigned int *low_word, unsigned int *high_word)
> +{
> + Âunsigned int ppr, word1, word2;
> +
> + Âasm ("mfspr Â%0,896\n"
> + Â Â Â "andi. Â%2,%0,0xffff\n"
> + Â Â Â "andis. %1,%0,0xffff\n"
> +    "or   %1,%1,%2\n"
> + Â Â Â "sradi Â%0,%0,32" :
> + Â Â Â "=r" (word1), "=r" (word2), "=r" (ppr) : : "cr0");
> +
> + Â*low_word = word1;
> + Â*high_word = word2;
> +}
> +
> +static int
> +do_test (void)
> +{
> + Âunsigned int low_word_before, high_word_before;
> + Âunsigned int low_word_after, high_word_after;
> +
> + ÂPPR_PRIO_MED_LOW();
> +
> + Âget_ppr (&low_word_before, &high_word_before);
> +
> + Â// force a syscall
> + Âgetpid();
> +

Add a comment about why you added the syscall, i.e. you want to
demonstrate that the PPR save/restore is working properly after a
context switch.

> + Âget_ppr (&low_word_after, &high_word_after);
> +
> + Âreturn !(low_word_before == low_word_after &&
> + Â Â Â Â Âhigh_word_before == high_word_after);

Looking at the ISA, only the PRI field of the PPR (PPR[11:13]) is
modifiable via the "or" instruction shortcuts used to set the program
priority.  The PPR[26:31] and PPR[44:63] fields are marekd
"implementation-specific".

Does the "mtspr 896, Rx" instruction only restore the bits in the PRI
field of the PPR?

I can see how the following check might fail if the non-PRI fields
have changed across the context switch.  Do we know anything about how
these other fields might be used, if at all?

Ryan

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]