Skip to content

Commit df24e17

Browse files
committed
parisc: Add vDSO support
Add minimal vDSO support, which provides the signal trampoline helpers, but none of the userspace syscall helpers like time wrappers. The big benefit of this vDSO implementation is, that we now don't need an executeable stack any longer. PA-RISC is one of the last architectures where an executeable stack was needed in oder to implement the signal trampolines by putting assembly instructions on the stack which then gets executed. Instead the kernel will provide the relevant code in the vDSO page and only put the pointers to the signal information on the stack. By dropping the need for executable stacks we avoid running into issues with applications which want non executable stacks for security reasons. Additionally, alternative stacks on memory areas without exec permissions are supported too. This code is based on an initial implementation by Randolph Chung from 2006: https://lore.kernel.org/linux-parisc/4544A34A.6080700@tausq.org/ I did the porting and lifted the code to current code base. Dave fixed the unwind code so that gdb and glibc are able to backtrace through the code. An additional patch to gdb will be pushed upstream by Dave. Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Dave Anglin <dave.anglin@bell.net> Cc: Randolph Chung <randolph@tausq.org> Signed-off-by: Helge Deller <deller@gmx.de>
1 parent 14615ec commit df24e17

32 files changed

Lines changed: 1149 additions & 165 deletions

arch/parisc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ config PARISC
1010
select ARCH_HAS_ELF_RANDOMIZE
1111
select ARCH_HAS_STRICT_KERNEL_RWX
1212
select ARCH_HAS_UBSAN_SANITIZE_ALL
13+
select ARCH_HAS_PTE_SPECIAL
1314
select ARCH_NO_SG_CHAIN
1415
select ARCH_SUPPORTS_HUGETLBFS if PA20
1516
select ARCH_SUPPORTS_MEMORY_FAILURE

arch/parisc/Makefile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ endif
4444

4545
export LD_BFD
4646

47+
# Set default 32 bits cross compilers for vdso
48+
CC_ARCHES_32 = hppa hppa2.0 hppa1.1
49+
CC_SUFFIXES = linux linux-gnu unknown-linux-gnu
50+
CROSS32_COMPILE := $(call cc-cross-prefix, \
51+
$(foreach a,$(CC_ARCHES_32), \
52+
$(foreach s,$(CC_SUFFIXES),$(a)-$(s)-)))
53+
CROSS32CC := $(CROSS32_COMPILE)gcc
54+
export CROSS32CC
55+
56+
# Set default cross compiler for kernel build
4757
ifdef cross_compiling
4858
ifeq ($(CROSS_COMPILE),)
4959
CC_SUFFIXES = linux linux-gnu unknown-linux-gnu
@@ -163,6 +173,26 @@ vmlinuz: vmlinux
163173
@$(KGZIP) -cf -9 $< > $@
164174
endif
165175

176+
ifeq ($(KBUILD_EXTMOD),)
177+
# We need to generate vdso-offsets.h before compiling certain files in kernel/.
178+
# In order to do that, we should use the archprepare target, but we can't since
179+
# asm-offsets.h is included in some files used to generate vdso-offsets.h, and
180+
# asm-offsets.h is built in prepare0, for which archprepare is a dependency.
181+
# Therefore we need to generate the header after prepare0 has been made, hence
182+
# this hack.
183+
prepare: vdso_prepare
184+
vdso_prepare: prepare0
185+
$(if $(CONFIG_64BIT),$(Q)$(MAKE) \
186+
$(build)=arch/parisc/kernel/vdso64 include/generated/vdso64-offsets.h)
187+
$(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 include/generated/vdso32-offsets.h
188+
endif
189+
190+
PHONY += vdso_install
191+
192+
vdso_install:
193+
$(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso $@
194+
$(if $(CONFIG_COMPAT_VDSO), \
195+
$(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 $@)
166196
install:
167197
$(CONFIG_SHELL) $(srctree)/arch/parisc/install.sh \
168198
$(KERNELRELEASE) vmlinux System.map "$(INSTALL_PATH)"

arch/parisc/include/asm/elf.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,4 +359,19 @@ struct mm_struct;
359359
extern unsigned long arch_randomize_brk(struct mm_struct *);
360360
#define arch_randomize_brk arch_randomize_brk
361361

362+
363+
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
364+
struct linux_binprm;
365+
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
366+
int executable_stack);
367+
#define VDSO_AUX_ENT(a, b) NEW_AUX_ENT(a, b)
368+
#define VDSO_CURRENT_BASE current->mm->context.vdso_base
369+
370+
#define ARCH_DLINFO \
371+
do { \
372+
if (VDSO_CURRENT_BASE) { \
373+
NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);\
374+
} \
375+
} while (0)
376+
362377
#endif

arch/parisc/include/asm/mmu.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#ifndef _PARISC_MMU_H_
33
#define _PARISC_MMU_H_
44

5-
/* On parisc, we store the space id here */
6-
typedef unsigned long mm_context_t;
5+
typedef struct {
6+
unsigned long space_id;
7+
unsigned long vdso_base;
8+
} mm_context_t;
79

810
#endif /* _PARISC_MMU_H_ */

arch/parisc/include/asm/mmu_context.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,30 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
2020
{
2121
BUG_ON(atomic_read(&mm->mm_users) != 1);
2222

23-
mm->context = alloc_sid();
23+
mm->context.space_id = alloc_sid();
2424
return 0;
2525
}
2626

2727
#define destroy_context destroy_context
2828
static inline void
2929
destroy_context(struct mm_struct *mm)
3030
{
31-
free_sid(mm->context);
32-
mm->context = 0;
31+
free_sid(mm->context.space_id);
32+
mm->context.space_id = 0;
3333
}
3434

3535
static inline unsigned long __space_to_prot(mm_context_t context)
3636
{
3737
#if SPACEID_SHIFT == 0
38-
return context << 1;
38+
return context.space_id << 1;
3939
#else
40-
return context >> (SPACEID_SHIFT - 1);
40+
return context.space_id >> (SPACEID_SHIFT - 1);
4141
#endif
4242
}
4343

4444
static inline void load_context(mm_context_t context)
4545
{
46-
mtsp(context, 3);
46+
mtsp(context.space_id, 3);
4747
mtctl(__space_to_prot(context), 8);
4848
}
4949

@@ -89,8 +89,8 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
8989

9090
BUG_ON(next == &init_mm); /* Should never happen */
9191

92-
if (next->context == 0)
93-
next->context = alloc_sid();
92+
if (next->context.space_id == 0)
93+
next->context.space_id = alloc_sid();
9494

9595
switch_mm(prev,next,current);
9696
}

arch/parisc/include/asm/pgtable.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
7070
unsigned long flags;
7171

7272
purge_tlb_start(flags);
73-
mtsp(mm->context, 1);
73+
mtsp(mm->context.space_id, 1);
7474
pdtlb(addr);
7575
pitlb(addr);
7676
purge_tlb_end(flags);
@@ -219,9 +219,10 @@ extern void __update_cache(pte_t pte);
219219
#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT))
220220
#define _PAGE_HUGE (1 << xlate_pabit(_PAGE_HPAGE_BIT))
221221
#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT))
222+
#define _PAGE_SPECIAL (_PAGE_DMB)
222223

223224
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
224-
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
225+
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
225226
#define _PAGE_KERNEL_RO (_PAGE_PRESENT | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED)
226227
#define _PAGE_KERNEL_EXEC (_PAGE_KERNEL_RO | _PAGE_EXEC)
227228
#define _PAGE_KERNEL_RWX (_PAGE_KERNEL_EXEC | _PAGE_WRITE)
@@ -348,13 +349,15 @@ static inline void pud_clear(pud_t *pud) {
348349
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
349350
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
350351
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
352+
static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
351353

352354
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
353355
static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
354356
static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
355357
static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
356358
static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
357359
static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
360+
static inline pte_t pte_mkspecial(pte_t pte) { pte_val(pte) |= _PAGE_SPECIAL; return pte; }
358361

359362
/*
360363
* Huge pte definitions.

arch/parisc/include/asm/processor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ on downward growing arches, it looks like this:
236236

237237
#define start_thread(regs, new_pc, new_sp) do { \
238238
elf_addr_t *sp = (elf_addr_t *)new_sp; \
239-
__u32 spaceid = (__u32)current->mm->context; \
239+
__u32 spaceid = (__u32)current->mm->context.space_id; \
240240
elf_addr_t pc = (elf_addr_t)new_pc | 3; \
241241
elf_caddr_t *argv = (elf_caddr_t *)bprm->exec + 1; \
242242
\

arch/parisc/include/asm/rt_sigframe.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,8 @@
22
#ifndef _ASM_PARISC_RT_SIGFRAME_H
33
#define _ASM_PARISC_RT_SIGFRAME_H
44

5-
#define SIGRETURN_TRAMP 4
6-
#define SIGRESTARTBLOCK_TRAMP 5
7-
#define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP)
8-
95
struct rt_sigframe {
10-
/* XXX: Must match trampoline size in arch/parisc/kernel/signal.c
11-
Secondary to that it must protect the ERESTART_RESTARTBLOCK
12-
trampoline we left on the stack (we were bad and didn't
13-
change sp so we could run really fast.) */
14-
unsigned int tramp[TRAMP_SIZE];
6+
unsigned int tramp[2]; /* holds original return address */
157
struct siginfo info;
168
struct ucontext uc;
179
};

arch/parisc/include/asm/tlbflush.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ int __flush_tlb_range(unsigned long sid,
1717
unsigned long start, unsigned long end);
1818

1919
#define flush_tlb_range(vma, start, end) \
20-
__flush_tlb_range((vma)->vm_mm->context, start, end)
20+
__flush_tlb_range((vma)->vm_mm->context.space_id, start, end)
2121

2222
#define flush_tlb_kernel_range(start, end) \
2323
__flush_tlb_range(0, start, end)

arch/parisc/include/asm/unistd.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@
6363
); \
6464
__sys_res = (long)__res; \
6565
} \
66-
if ( (unsigned long)__sys_res >= (unsigned long)-4095 ){ \
67-
errno = -__sys_res; \
68-
__sys_res = -1; \
69-
} \
7066
__sys_res; \
7167
})
7268

0 commit comments

Comments
 (0)