Changeset 30826


Ignore:
Timestamp:
Oct 31, 2016, 10:13:47 PM (10 months ago)
Author:
brainslayer
Message:

update

Location:
src/linux/universal/linux-4.4
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • src/linux/universal/linux-4.4/Documentation/x86/exception-tables.txt

    r30821 r30826  
    291291will cause the exception table to not be sorted correctly, and the
    292292exceptions will fail.
    293 
    294 Things changed when 64-bit support was added to x86 Linux. Rather than
    295 double the size of the exception table by expanding the two entries
    296 from 32-bits to 64 bits, a clever trick was used to store addresses
    297 as relative offsets from the table itself. The assembly code changed
    298 from:
    299         .long 1b,3b
    300 to:
    301         .long (from) - .
    302         .long (to) - .
    303 
    304 and the C-code that uses these values converts back to absolute addresses
    305 like this:
    306 
    307         ex_insn_addr(const struct exception_table_entry *x)
    308         {
    309                 return (unsigned long)&x->insn + x->insn;
    310         }
    311 
    312 In v4.6 the exception table entry was expanded with a new field "handler".
    313 This is also 32-bits wide and contains a third relative function
    314 pointer which points to one of:
    315 
    316 1) int ex_handler_default(const struct exception_table_entry *fixup)
    317    This is legacy case that just jumps to the fixup code
    318 2) int ex_handler_fault(const struct exception_table_entry *fixup)
    319    This case provides the fault number of the trap that occurred at
    320    entry->insn. It is used to distinguish page faults from machine
    321    check.
    322 3) int ex_handler_ext(const struct exception_table_entry *fixup)
    323    This case is used for uaccess_err ... we need to set a flag
    324    in the task structure. Before the handler functions existed this
    325    case was handled by adding a large offset to the fixup to tag
    326    it as special.
    327 More functions can easily be added.
  • src/linux/universal/linux-4.4/Makefile

    r30821 r30826  
    11VERSION = 4
    22PATCHLEVEL = 4
    3 SUBLEVEL = 29
    4 EXTRAVERSION =
     3SUBLEVEL = 30
     4EXTRAVERSION = -rc1
    55NAME = Blurry Fish Butt
    66
  • src/linux/universal/linux-4.4/arch/x86/include/asm/asm.h

    r30821 r30826  
    4545/* Exception table entry */
    4646#ifdef __ASSEMBLY__
    47 # define _ASM_EXTABLE_HANDLE(from, to, handler)                 \
     47# define _ASM_EXTABLE(from,to)                                  \
    4848        .pushsection "__ex_table","a" ;                         \
    49         .balign 4 ;                                             \
     49        .balign 8 ;                                             \
    5050        .long (from) - . ;                                      \
    5151        .long (to) - . ;                                        \
    52         .long (handler) - . ;                                   \
    5352        .popsection
    5453
    55 # define _ASM_EXTABLE(from, to)                                 \
    56         _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
    57 
    58 # define _ASM_EXTABLE_FAULT(from, to)                           \
    59         _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
    60 
    61 # define _ASM_EXTABLE_EX(from, to)                              \
    62         _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
     54# define _ASM_EXTABLE_EX(from,to)                               \
     55        .pushsection "__ex_table","a" ;                         \
     56        .balign 8 ;                                             \
     57        .long (from) - . ;                                      \
     58        .long (to) - . + 0x7ffffff0 ;                           \
     59        .popsection
    6360
    6461# define _ASM_NOKPROBE(entry)                                   \
     
    9390
    9491#else
    95 # define _EXPAND_EXTABLE_HANDLE(x) #x
    96 # define _ASM_EXTABLE_HANDLE(from, to, handler)                 \
     92# define _ASM_EXTABLE(from,to)                                  \
    9793        " .pushsection \"__ex_table\",\"a\"\n"                  \
    98         " .balign 4\n"                                          \
     94        " .balign 8\n"                                          \
    9995        " .long (" #from ") - .\n"                              \
    10096        " .long (" #to ") - .\n"                                \
    101         " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n"    \
    10297        " .popsection\n"
    10398
    104 # define _ASM_EXTABLE(from, to)                                 \
    105         _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
    106 
    107 # define _ASM_EXTABLE_FAULT(from, to)                           \
    108         _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
    109 
    110 # define _ASM_EXTABLE_EX(from, to)                              \
    111         _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
    112 
     99# define _ASM_EXTABLE_EX(from,to)                               \
     100        " .pushsection \"__ex_table\",\"a\"\n"                  \
     101        " .balign 8\n"                                          \
     102        " .long (" #from ") - .\n"                              \
     103        " .long (" #to ") - . + 0x7ffffff0\n"                   \
     104        " .popsection\n"
    113105/* For C file, we already have NOKPROBE_SYMBOL macro */
    114106#endif
  • src/linux/universal/linux-4.4/arch/x86/include/asm/uaccess.h

    r30821 r30826  
    9191
    9292/*
    93  * The exception table consists of triples of addresses relative to the
    94  * exception table entry itself. The first address is of an instruction
    95  * that is allowed to fault, the second is the target at which the program
    96  * should continue. The third is a handler function to deal with the fault
    97  * caused by the instruction in the first field.
     93 * The exception table consists of pairs of addresses relative to the
     94 * exception table enty itself: the first is the address of an
     95 * instruction that is allowed to fault, and the second is the address
     96 * at which the program should continue.  No registers are modified,
     97 * so it is entirely up to the continuation code to figure out what to
     98 * do.
    9899 *
    99100 * All the routines below use bits of fixup code that are out of line
     
    104105
    105106struct exception_table_entry {
    106         int insn, fixup, handler;
     107        int insn, fixup;
    107108};
    108109/* This is not the generic standard exception_table_entry format */
     
    110111#define ARCH_HAS_SEARCH_EXTABLE
    111112
    112 extern int fixup_exception(struct pt_regs *regs, int trapnr);
    113 extern bool ex_has_fault_handler(unsigned long ip);
     113extern int fixup_exception(struct pt_regs *regs);
    114114extern int early_fixup_exception(unsigned long *ip);
    115115
     
    395395        asm volatile("1:        mov"itype" %1,%"rtype"0\n"              \
    396396                     "2:\n"                                             \
    397                      ".section .fixup,\"ax\"\n"                         \
    398                      "3:xor"itype" %"rtype"0,%"rtype"0\n"               \
    399                      "  jmp 2b\n"                                       \
    400                      ".previous\n"                                      \
    401                      _ASM_EXTABLE_EX(1b, 3b)                            \
     397                     _ASM_EXTABLE_EX(1b, 2b)                            \
    402398                     : ltype(x) : "m" (__m(addr)))
    403399
  • src/linux/universal/linux-4.4/arch/x86/kernel/kprobes/core.c

    r30821 r30826  
    10011001                 * zero, try to fix up.
    10021002                 */
    1003                 if (fixup_exception(regs, trapnr))
     1003                if (fixup_exception(regs))
    10041004                        return 1;
    10051005
  • src/linux/universal/linux-4.4/arch/x86/kernel/traps.c

    r30821 r30826  
    200200
    201201        if (!user_mode(regs)) {
    202                 if (!fixup_exception(regs, trapnr)) {
     202                if (!fixup_exception(regs)) {
    203203                        tsk->thread.error_code = error_code;
    204204                        tsk->thread.trap_nr = trapnr;
     
    454454        tsk = current;
    455455        if (!user_mode(regs)) {
    456                 if (fixup_exception(regs, X86_TRAP_GP))
     456                if (fixup_exception(regs))
    457457                        return;
    458458
     
    700700
    701701        if (!user_mode(regs)) {
    702                 if (!fixup_exception(regs, trapnr)) {
     702                if (!fixup_exception(regs)) {
    703703                        task->thread.error_code = error_code;
    704704                        task->thread.trap_nr = trapnr;
  • src/linux/universal/linux-4.4/arch/x86/mm/extable.c

    r30821 r30826  
    33#include <linux/sort.h>
    44#include <asm/uaccess.h>
    5 
    6 typedef bool (*ex_handler_t)(const struct exception_table_entry *,
    7                             struct pt_regs *, int);
    85
    96static inline unsigned long
     
    1714        return (unsigned long)&x->fixup + x->fixup;
    1815}
    19 static inline ex_handler_t
    20 ex_fixup_handler(const struct exception_table_entry *x)
     16
     17int fixup_exception(struct pt_regs *regs)
    2118{
    22         return (ex_handler_t)((unsigned long)&x->handler + x->handler);
    23 }
    24 
    25 bool ex_handler_default(const struct exception_table_entry *fixup,
    26                        struct pt_regs *regs, int trapnr)
    27 {
    28         regs->ip = ex_fixup_addr(fixup);
    29         return true;
    30 }
    31 EXPORT_SYMBOL(ex_handler_default);
    32 
    33 bool ex_handler_fault(const struct exception_table_entry *fixup,
    34                      struct pt_regs *regs, int trapnr)
    35 {
    36         regs->ip = ex_fixup_addr(fixup);
    37         regs->ax = trapnr;
    38         return true;
    39 }
    40 EXPORT_SYMBOL_GPL(ex_handler_fault);
    41 
    42 bool ex_handler_ext(const struct exception_table_entry *fixup,
    43                    struct pt_regs *regs, int trapnr)
    44 {
    45         /* Special hack for uaccess_err */
    46         current_thread_info()->uaccess_err = 1;
    47         regs->ip = ex_fixup_addr(fixup);
    48         return true;
    49 }
    50 EXPORT_SYMBOL(ex_handler_ext);
    51 
    52 bool ex_has_fault_handler(unsigned long ip)
    53 {
    54         const struct exception_table_entry *e;
    55         ex_handler_t handler;
    56 
    57         e = search_exception_tables(ip);
    58         if (!e)
    59                 return false;
    60         handler = ex_fixup_handler(e);
    61 
    62         return handler == ex_handler_fault;
    63 }
    64 
    65 int fixup_exception(struct pt_regs *regs, int trapnr)
    66 {
    67         const struct exception_table_entry *e;
    68         ex_handler_t handler;
     19        const struct exception_table_entry *fixup;
     20        unsigned long new_ip;
    6921
    7022#ifdef CONFIG_PNPBIOS
     
    8234#endif
    8335
    84         e = search_exception_tables(regs->ip);
    85         if (!e)
    86                 return 0;
     36        fixup = search_exception_tables(regs->ip);
     37        if (fixup) {
     38                new_ip = ex_fixup_addr(fixup);
    8739
    88         handler = ex_fixup_handler(e);
    89         return handler(e, regs, trapnr);
     40                if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
     41                        /* Special hack for uaccess_err */
     42                        current_thread_info()->uaccess_err = 1;
     43                        new_ip -= 0x7ffffff0;
     44                }
     45                regs->ip = new_ip;
     46                return 1;
     47        }
     48
     49        return 0;
    9050}
    9151
     
    9353int __init early_fixup_exception(unsigned long *ip)
    9454{
    95         const struct exception_table_entry *e;
     55        const struct exception_table_entry *fixup;
    9656        unsigned long new_ip;
    97         ex_handler_t handler;
    9857
    99         e = search_exception_tables(*ip);
    100         if (!e)
    101                 return 0;
     58        fixup = search_exception_tables(*ip);
     59        if (fixup) {
     60                new_ip = ex_fixup_addr(fixup);
    10261
    103         new_ip  = ex_fixup_addr(e);
    104         handler = ex_fixup_handler(e);
     62                if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
     63                        /* uaccess handling not supported during early boot */
     64                        return 0;
     65                }
    10566
    106         /* special handling not supported during early boot */
    107         if (handler != ex_handler_default)
    108                 return 0;
     67                *ip = new_ip;
     68                return 1;
     69        }
    10970
    110         *ip = new_ip;
    111         return 1;
     71        return 0;
    11272}
    11373
     
    174134                p->fixup += i;
    175135                i += 4;
    176                 p->handler += i;
    177                 i += 4;
    178136        }
    179137
     
    187145                i += 4;
    188146                p->fixup -= i;
    189                 i += 4;
    190                 p->handler -= i;
    191147                i += 4;
    192148        }
  • src/linux/universal/linux-4.4/arch/x86/mm/fault.c

    r30821 r30826  
    664664
    665665        /* Are we prepared to handle this kernel fault? */
    666         if (fixup_exception(regs, X86_TRAP_PF)) {
     666        if (fixup_exception(regs)) {
    667667                /*
    668668                 * Any interrupt that takes a fault gets the fixup. This makes
  • src/linux/universal/linux-4.4/scripts/sortextable.c

    r30821 r30826  
    210210}
    211211
    212 static void x86_sort_relative_table(char *extab_image, int image_size)
    213 {
    214         int i;
    215 
    216         i = 0;
    217         while (i < image_size) {
    218                 uint32_t *loc = (uint32_t *)(extab_image + i);
    219 
    220                 w(r(loc) + i, loc);
    221                 w(r(loc + 1) + i + 4, loc + 1);
    222                 w(r(loc + 2) + i + 8, loc + 2);
    223 
    224                 i += sizeof(uint32_t) * 3;
    225         }
    226 
    227         qsort(extab_image, image_size / 12, 12, compare_relative_table);
    228 
    229         i = 0;
    230         while (i < image_size) {
    231                 uint32_t *loc = (uint32_t *)(extab_image + i);
    232 
    233                 w(r(loc) - i, loc);
    234                 w(r(loc + 1) - (i + 4), loc + 1);
    235                 w(r(loc + 2) - (i + 8), loc + 2);
    236 
    237                 i += sizeof(uint32_t) * 3;
    238         }
    239 }
    240 
    241212static void sort_relative_table(char *extab_image, int image_size)
    242213{
     
    311282        case EM_386:
    312283        case EM_X86_64:
    313                 custom_sort = x86_sort_relative_table;
    314                 break;
    315 
    316284        case EM_S390:
    317285                custom_sort = sort_relative_table;
Note: See TracChangeset for help on using the changeset viewer.