Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar:
"Misc fixes:

- early_idt_handlers[] fix that fixes the build with bleeding edge
tooling

- build warning fix on GCC 5.1

- vm86 fix plus self-test to make it harder to break it again"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/asm/irq: Stop relying on magic JMP behavior for early_idt_handlers
x86/asm/entry/32, selftests: Add a selftest for kernel entries from VM86 mode
x86/boot: Add CONFIG_PARAVIRT_SPINLOCKS quirk to arch/x86/boot/compressed/misc.h
x86/asm/entry/32: Really make user_mode() work correctly for VM86 mode

+166 -36
+5 -6
arch/x86/boot/compressed/misc.h
··· 2 2 #define BOOT_COMPRESSED_MISC_H 3 3 4 4 /* 5 - * we have to be careful, because no indirections are allowed here, and 6 - * paravirt_ops is a kind of one. As it will only run in baremetal anyway, 7 - * we just keep it from happening 5 + * Special hack: we have to be careful, because no indirections are allowed here, 6 + * and paravirt_ops is a kind of one. As it will only run in baremetal anyway, 7 + * we just keep it from happening. (This list needs to be extended when new 8 + * paravirt and debugging variants are added.) 8 9 */ 9 10 #undef CONFIG_PARAVIRT 11 + #undef CONFIG_PARAVIRT_SPINLOCKS 10 12 #undef CONFIG_KASAN 11 - #ifdef CONFIG_X86_32 12 - #define _ASM_X86_DESC_H 1 13 - #endif 14 13 15 14 #include <linux/linkage.h> 16 15 #include <linux/screen_info.h>
+1 -1
arch/x86/include/asm/ptrace.h
··· 107 107 static inline int user_mode(struct pt_regs *regs) 108 108 { 109 109 #ifdef CONFIG_X86_32 110 - return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL; 110 + return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL; 111 111 #else 112 112 return !!(regs->cs & 3); 113 113 #endif
+12 -2
arch/x86/include/asm/segment.h
··· 231 231 #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES* 8) 232 232 233 233 #ifdef __KERNEL__ 234 + 235 + /* 236 + * early_idt_handler_array is an array of entry points referenced in the 237 + * early IDT. For simplicity, it's a real array with one entry point 238 + * every nine bytes. That leaves room for an optional 'push $0' if the 239 + * vector has no error code (two bytes), a 'push $vector_number' (two 240 + * bytes), and a jump to the common entry code (up to five bytes). 241 + */ 242 + #define EARLY_IDT_HANDLER_SIZE 9 243 + 234 244 #ifndef __ASSEMBLY__ 235 245 236 - extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; 246 + extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE]; 237 247 #ifdef CONFIG_TRACING 238 - # define trace_early_idt_handlers early_idt_handlers 248 + # define trace_early_idt_handler_array early_idt_handler_array 239 249 #endif 240 250 241 251 /*
+1 -1
arch/x86/kernel/head64.c
··· 167 167 clear_bss(); 168 168 169 169 for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) 170 - set_intr_gate(i, early_idt_handlers[i]); 170 + set_intr_gate(i, early_idt_handler_array[i]); 171 171 load_idt((const struct desc_ptr *)&idt_descr); 172 172 173 173 copy_bootdata(__va(real_mode_data));
+18 -15
arch/x86/kernel/head_32.S
··· 478 478 __INIT 479 479 setup_once: 480 480 /* 481 - * Set up a idt with 256 entries pointing to ignore_int, 482 - * interrupt gates. It doesn't actually load idt - that needs 483 - * to be done on each CPU. Interrupts are enabled elsewhere, 484 - * when we can be relatively sure everything is ok. 481 + * Set up a idt with 256 interrupt gates that push zero if there 482 + * is no error code and then jump to early_idt_handler_common. 483 + * It doesn't actually load the idt - that needs to be done on 484 + * each CPU. Interrupts are enabled elsewhere, when we can be 485 + * relatively sure everything is ok. 485 486 */ 486 487 487 488 movl $idt_table,%edi 488 - movl $early_idt_handlers,%eax 489 + movl $early_idt_handler_array,%eax 489 490 movl $NUM_EXCEPTION_VECTORS,%ecx 490 491 1: 491 492 movl %eax,(%edi) 492 493 movl %eax,4(%edi) 493 494 /* interrupt gate, dpl=0, present */ 494 495 movl $(0x8E000000 + __KERNEL_CS),2(%edi) 495 - addl $9,%eax 496 + addl $EARLY_IDT_HANDLER_SIZE,%eax 496 497 addl $8,%edi 497 498 loop 1b 498 499 ··· 525 524 andl $0,setup_once_ref /* Once is enough, thanks */ 526 525 ret 527 526 528 - ENTRY(early_idt_handlers) 527 + ENTRY(early_idt_handler_array) 529 528 # 36(%esp) %eflags 530 529 # 32(%esp) %cs 531 530 # 28(%esp) %eip 532 531 # 24(%rsp) error code 533 532 i = 0 534 533 .rept NUM_EXCEPTION_VECTORS 535 - .if (EXCEPTION_ERRCODE_MASK >> i) & 1 536 - ASM_NOP2 537 - .else 534 + .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 538 535 pushl $0 # Dummy error code, to make stack frame uniform 539 536 .endif 540 537 pushl $i # 20(%esp) Vector number 541 - jmp early_idt_handler 538 + jmp early_idt_handler_common 542 539 i = i + 1 540 + .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc 543 541 .endr 544 - ENDPROC(early_idt_handlers) 542 + ENDPROC(early_idt_handler_array) 545 543 546 - /* This is global to keep gas from relaxing the jumps */ 547 - ENTRY(early_idt_handler) 544 + early_idt_handler_common: 545 + /* 546 + * The stack is the hardware frame, an error code or zero, and the 547 + * vector number. 548 + */ 548 549 cld 549 550 550 551 cmpl $2,(%esp) # X86_TRAP_NMI ··· 606 603 is_nmi: 607 604 addl $8,%esp /* drop vector number and error code */ 608 605 iret 609 - ENDPROC(early_idt_handler) 606 + ENDPROC(early_idt_handler_common) 610 607 611 608 /* This is the default interrupt "handler" :-) */ 612 609 ALIGN
+11 -9
arch/x86/kernel/head_64.S
··· 321 321 jmp bad_address 322 322 323 323 __INIT 324 - .globl early_idt_handlers 325 - early_idt_handlers: 324 + ENTRY(early_idt_handler_array) 326 325 # 104(%rsp) %rflags 327 326 # 96(%rsp) %cs 328 327 # 88(%rsp) %rip 329 328 # 80(%rsp) error code 330 329 i = 0 331 330 .rept NUM_EXCEPTION_VECTORS 332 - .if (EXCEPTION_ERRCODE_MASK >> i) & 1 333 - ASM_NOP2 334 - .else 331 + .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 335 332 pushq $0 # Dummy error code, to make stack frame uniform 336 333 .endif 337 334 pushq $i # 72(%rsp) Vector number 338 - jmp early_idt_handler 335 + jmp early_idt_handler_common 339 336 i = i + 1 337 + .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc 340 338 .endr 339 + ENDPROC(early_idt_handler_array) 341 340 342 - /* This is global to keep gas from relaxing the jumps */ 343 - ENTRY(early_idt_handler) 341 + early_idt_handler_common: 342 + /* 343 + * The stack is the hardware frame, an error code or zero, and the 344 + * vector number. 345 + */ 344 346 cld 345 347 346 348 cmpl $2,(%rsp) # X86_TRAP_NMI ··· 414 412 is_nmi: 415 413 addq $16,%rsp # drop vector number and error code 416 414 INTERRUPT_RETURN 417 - ENDPROC(early_idt_handler) 415 + ENDPROC(early_idt_handler_common) 418 416 419 417 __INITDATA 420 418
+4 -2
tools/testing/selftests/x86/Makefile
··· 5 5 .PHONY: all all_32 all_64 warn_32bit_failure clean 6 6 7 7 TARGETS_C_BOTHBITS := sigreturn single_step_syscall 8 + TARGETS_C_32BIT_ONLY := entry_from_vm86 8 9 9 - BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32) 10 + TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 11 + BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) 10 12 BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64) 11 13 12 14 CFLAGS := -O2 -g -std=gnu99 -pthread -Wall ··· 34 32 clean: 35 33 $(RM) $(BINARIES_32) $(BINARIES_64) 36 34 37 - $(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c 35 + $(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c 38 36 $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl 39 37 40 38 $(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
+114
tools/testing/selftests/x86/entry_from_vm86.c
··· 1 + /* 2 + * entry_from_vm86.c - tests kernel entries from vm86 mode 3 + * Copyright (c) 2014-2015 Andrew Lutomirski 4 + * 5 + * This exercises a few paths that need to special-case vm86 mode. 6 + * 7 + * GPL v2. 8 + */ 9 + 10 + #define _GNU_SOURCE 11 + 12 + #include <assert.h> 13 + #include <stdlib.h> 14 + #include <sys/syscall.h> 15 + #include <sys/signal.h> 16 + #include <sys/ucontext.h> 17 + #include <unistd.h> 18 + #include <stdio.h> 19 + #include <string.h> 20 + #include <inttypes.h> 21 + #include <sys/mman.h> 22 + #include <err.h> 23 + #include <stddef.h> 24 + #include <stdbool.h> 25 + #include <errno.h> 26 + #include <sys/vm86.h> 27 + 28 + static unsigned long load_addr = 0x10000; 29 + static int nerrs = 0; 30 + 31 + asm ( 32 + ".pushsection .rodata\n\t" 33 + ".type vmcode_bound, @object\n\t" 34 + "vmcode:\n\t" 35 + "vmcode_bound:\n\t" 36 + ".code16\n\t" 37 + "bound %ax, (2048)\n\t" 38 + "int3\n\t" 39 + "vmcode_sysenter:\n\t" 40 + "sysenter\n\t" 41 + ".size vmcode, . - vmcode\n\t" 42 + "end_vmcode:\n\t" 43 + ".code32\n\t" 44 + ".popsection" 45 + ); 46 + 47 + extern unsigned char vmcode[], end_vmcode[]; 48 + extern unsigned char vmcode_bound[], vmcode_sysenter[]; 49 + 50 + static void do_test(struct vm86plus_struct *v86, unsigned long eip, 51 + const char *text) 52 + { 53 + long ret; 54 + 55 + printf("[RUN]\t%s from vm86 mode\n", text); 56 + v86->regs.eip = eip; 57 + ret = vm86(VM86_ENTER, v86); 58 + 59 + if (ret == -1 && errno == ENOSYS) { 60 + printf("[SKIP]\tvm86 not supported\n"); 61 + return; 62 + } 63 + 64 + if (VM86_TYPE(ret) == VM86_INTx) { 65 + char trapname[32]; 66 + int trapno = VM86_ARG(ret); 67 + if (trapno == 13) 68 + strcpy(trapname, "GP"); 69 + else if (trapno == 5) 70 + strcpy(trapname, "BR"); 71 + else if (trapno == 14) 72 + strcpy(trapname, "PF"); 73 + else 74 + sprintf(trapname, "%d", trapno); 75 + 76 + printf("[OK]\tExited vm86 mode due to #%s\n", trapname); 77 + } else if (VM86_TYPE(ret) == VM86_UNKNOWN) { 78 + printf("[OK]\tExited vm86 mode due to unhandled GP fault\n"); 79 + } else { 80 + printf("[OK]\tExited vm86 mode due to type %ld, arg %ld\n", 81 + VM86_TYPE(ret), VM86_ARG(ret)); 82 + } 83 + } 84 + 85 + int main(void) 86 + { 87 + struct vm86plus_struct v86; 88 + unsigned char *addr = mmap((void *)load_addr, 4096, 89 + PROT_READ | PROT_WRITE | PROT_EXEC, 90 + MAP_ANONYMOUS | MAP_PRIVATE, -1,0); 91 + if (addr != (unsigned char *)load_addr) 92 + err(1, "mmap"); 93 + 94 + memcpy(addr, vmcode, end_vmcode - vmcode); 95 + addr[2048] = 2; 96 + addr[2050] = 3; 97 + 98 + memset(&v86, 0, sizeof(v86)); 99 + 100 + v86.regs.cs = load_addr / 16; 101 + v86.regs.ss = load_addr / 16; 102 + v86.regs.ds = load_addr / 16; 103 + v86.regs.es = load_addr / 16; 104 + 105 + assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ 106 + 107 + /* #BR -- should deliver SIG??? */ 108 + do_test(&v86, vmcode_bound - vmcode, "#BR"); 109 + 110 + /* SYSENTER -- should cause #GP or #UD depending on CPU */ 111 + do_test(&v86, vmcode_sysenter - vmcode, "SYSENTER"); 112 + 113 + return (nerrs == 0 ? 0 : 1); 114 + }