parisc: Restore possibility to execute 64-bit applications
authorHelge Deller <deller@gmx.de>
Thu, 16 Aug 2018 20:39:50 +0000 (22:39 +0200)
committerHelge Deller <deller@gmx.de>
Fri, 17 Aug 2018 14:45:24 +0000 (16:45 +0200)
Executing 64-bit applications was broken. This patch restores this
support and cleans up some code paths.

Signed-off-by: Helge Deller <deller@gmx.de>
arch/parisc/include/asm/elf.h
arch/parisc/include/asm/processor.h
arch/parisc/include/asm/traps.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/traps.c

index f019d3ec0c1cd81f7361f30ddcf6af7b3f3bb9e0..d00973aab7f186972151adbdb5f23090cb5f8d73 100644 (file)
@@ -235,6 +235,7 @@ typedef unsigned long elf_greg_t;
 #define SET_PERSONALITY(ex) \
 ({     \
        set_personality((current->personality & ~PER_MASK) | PER_LINUX); \
+       clear_thread_flag(TIF_32BIT); \
        current->thread.map_base = DEFAULT_MAP_BASE; \
        current->thread.task_size = DEFAULT_TASK_SIZE; \
  })
@@ -243,9 +244,11 @@ typedef unsigned long elf_greg_t;
 
 #define COMPAT_SET_PERSONALITY(ex) \
 ({     \
-       set_thread_flag(TIF_32BIT); \
-       current->thread.map_base = DEFAULT_MAP_BASE32; \
-       current->thread.task_size = DEFAULT_TASK_SIZE32; \
+       if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
+               set_thread_flag(TIF_32BIT); \
+               current->thread.map_base = DEFAULT_MAP_BASE32; \
+               current->thread.task_size = DEFAULT_TASK_SIZE32; \
+       } else clear_thread_flag(TIF_32BIT); \
  })
 
 /*
index 2dbe5580a1a4420ba693329a0f2622f68f759276..2bd5e695bdadd9d12ebf903a18ed56637e58ecb6 100644 (file)
@@ -256,11 +256,7 @@ on downward growing arches, it looks like this:
  * it in here from the current->personality
  */
 
-#ifdef CONFIG_64BIT
-#define USER_WIDE_MODE (!test_thread_flag(TIF_32BIT))
-#else
-#define USER_WIDE_MODE 0
-#endif
+#define USER_WIDE_MODE (!is_32bit_task())
 
 #define start_thread(regs, new_pc, new_sp) do {                \
        elf_addr_t *sp = (elf_addr_t *)new_sp;          \
index e00013248907e771a12b8543be2326d0f3c7980c..8ecc1f0c0483d5a4a60dd44c08b6e49b9d3b776e 100644 (file)
@@ -2,7 +2,9 @@
 #ifndef __ASM_TRAPS_H
 #define __ASM_TRAPS_H
 
-#ifdef __KERNEL__
+#define PARISC_ITLB_TRAP       6 /* defined by architecture. Do not change. */
+
+#if !defined(__ASSEMBLY__)
 struct pt_regs;
 
 /* traps.c */
index c7508f5717fb511ee463fc9aac83270a00d71cc4..e170365941f8e06c55d83039ef1534bfc34472a0 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/signal.h>
 #include <asm/unistd.h>
 #include <asm/ldcw.h>
+#include <asm/traps.h>
 #include <asm/thread_info.h>
 
 #include <linux/linkage.h>
@@ -692,7 +693,7 @@ ENTRY(fault_vector_20)
        def              3
        extint           4
        def              5
-       itlb_20          6
+       itlb_20          PARISC_ITLB_TRAP
        def              7
        def              8
        def              9
@@ -735,7 +736,7 @@ ENTRY(fault_vector_11)
        def              3
        extint           4
        def              5
-       itlb_11          6
+       itlb_11          PARISC_ITLB_TRAP
        def              7
        def              8
        def              9
@@ -1068,21 +1069,12 @@ ENTRY_CFI(intr_save)            /* for os_hpmc */
        save_specials   %r29
 
        /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
+       cmpib,COND(=),n        PARISC_ITLB_TRAP,%r26,skip_save_ior
 
-       /*
-        * FIXME: 1) Use a #define for the hardwired "6" below (and in
-        *           traps.c.
-        *        2) Once we start executing code above 4 Gb, we need
-        *           to adjust iasq/iaoq here in the same way we
-        *           adjust isr/ior below.
-        */
-
-       cmpib,COND(=),n        6,%r26,skip_save_ior
 
-
-       mfctl           %cr20, %r16 /* isr */
+       mfctl           %isr, %r16
        nop             /* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */
-       mfctl           %cr21, %r17 /* ior */
+       mfctl           %ior, %r17
 
 
 #ifdef CONFIG_64BIT
@@ -1094,22 +1086,34 @@ ENTRY_CFI(intr_save)            /* for os_hpmc */
        extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
        depdi           0,1,2,%r17
 
-       /*
-        * FIXME: This code has hardwired assumptions about the split
-        *        between space bits and offset bits. This will change
-        *        when we allow alternate page sizes.
-        */
-
-       /* adjust isr/ior. */
-       extrd,u         %r16,63,SPACEID_SHIFT,%r1       /* get high bits from isr for ior */
-       depd            %r1,31,SPACEID_SHIFT,%r17       /* deposit them into ior */
-       depdi           0,63,SPACEID_SHIFT,%r16         /* clear them from isr */
+       /* adjust isr/ior: get high bits from isr and deposit in ior */
+       space_adjust    %r16,%r17,%r1
 #endif
        STREG           %r16, PT_ISR(%r29)
        STREG           %r17, PT_IOR(%r29)
 
+#if 0 && defined(CONFIG_64BIT)
+       /* Revisit when we have 64-bit code above 4Gb */
+       b,n             intr_save2
 
 skip_save_ior:
+       /* We have a itlb miss, and when executing code above 4 Gb on ILP64, we
+        * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
+        * above.
+        */
+       extrd,u,*       %r8,PSW_W_BIT,1,%r1
+       cmpib,COND(=),n 1,%r1,intr_save2
+       LDREG           PT_IASQ0(%r29), %r16
+       LDREG           PT_IAOQ0(%r29), %r17
+       /* adjust iasq/iaoq */
+       space_adjust    %r16,%r17,%r1
+       STREG           %r16, PT_IASQ0(%r29)
+       STREG           %r17, PT_IAOQ0(%r29)
+#else
+skip_save_ior:
+#endif
+
+intr_save2:
        virt_map
        save_general    %r29
 
index 43b308cfdf532264d73e64ba5037950dd5a24fcb..376ea0d1b2759d2657741f8f8683f77e61a71b2d 100644 (file)
@@ -156,11 +156,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        int do_color_align, last_mmap;
        struct vm_unmapped_area_info info;
 
-#ifdef CONFIG_64BIT
-       /* This should only ever run for 32-bit processes.  */
-       BUG_ON(!test_thread_flag(TIF_32BIT));
-#endif
-
        /* requested length too big for entire address space */
        if (len > TASK_SIZE)
                return -ENOMEM;
index 318815212518962bec3bf8391abd791ad30f6879..9372a41c8812a6828802bc858b657b53988b0cf5 100644 (file)
@@ -557,7 +557,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
                cpu_lpmc(5, regs);
                return;
 
-       case  6:
+       case  PARISC_ITLB_TRAP:
                /* Instruction TLB miss fault/Instruction page fault */
                fault_address = regs->iaoq[0];
                fault_space   = regs->iasq[0];