diff options
Diffstat (limited to 'arch')
295 files changed, 6352 insertions, 11299 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 1b704ee54bf..d1004b4d942 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -12,73 +12,22 @@ NM := $(NM) -B LDFLAGS_vmlinux := -static -N #-relax CHECKFLAGS += -D__alpha__ -m64 -cflags-y := -pipe -mno-fp-regs -ffixed-8 - -# Determine if we can use the BWX instructions with GAS. -old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi) - -ifeq ($(old_gas),y) -$(error The assembler '$(AS)' does not support the BWX instruction) -endif - -# Determine if GCC understands the -mcpu= option. -have_mcpu := $(call cc-option-yn, -mcpu=ev5) -have_mcpu_pca56 := $(call cc-option-yn, -mcpu=pca56) -have_mcpu_ev6 := $(call cc-option-yn, -mcpu=ev6) -have_mcpu_ev67 := $(call cc-option-yn, -mcpu=ev67) -have_msmall_data := $(call cc-option-yn, -msmall-data) - -cflags-$(have_msmall_data) += -msmall-data - -# Turn on the proper cpu optimizations. -ifeq ($(have_mcpu),y) - mcpu_done := n - # If GENERIC, make sure to turn off any instruction set extensions that - # the host compiler might have on by default. Given that EV4 and EV5 - # have the same instruction set, prefer EV5 because an EV5 schedule is - # more likely to keep an EV4 processor busy than vice-versa. - ifeq ($(CONFIG_ALPHA_GENERIC),y) - mcpu := ev5 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy) - mcpu := pca56 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_POLARIS)$(have_mcpu_pca56),nyy) - mcpu := pca56 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny) - mcpu := ev4 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV56),ny) - mcpu := ev56 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV5),ny) - mcpu := ev5 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy) - mcpu := ev67 - mcpu_done := y - endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny) - ifeq ($(have_mcpu_ev6),y) - mcpu := ev6 - else - ifeq ($(have_mcpu_pca56),y) - mcpu := pca56 - else - mcpu=ev56 - endif - endif - mcpu_done := y - endif - cflags-$(mcpu_done) += -mcpu=$(mcpu) -endif +cflags-y := -pipe -mno-fp-regs -ffixed-8 -msmall-data + +cpuflags-$(CONFIG_ALPHA_EV67) := -mcpu=ev67 +cpuflags-$(CONFIG_ALPHA_EV6) := -mcpu=ev6 +cpuflags-$(CONFIG_ALPHA_POLARIS) := -mcpu=pca56 +cpuflags-$(CONFIG_ALPHA_SX164) := -mcpu=pca56 +cpuflags-$(CONFIG_ALPHA_EV56) := -mcpu=ev56 +cpuflags-$(CONFIG_ALPHA_EV5) := -mcpu=ev5 +cpuflags-$(CONFIG_ALPHA_EV4) := -mcpu=ev4 +# If GENERIC, make sure to turn off any instruction set extensions that +# the host compiler might have on by default. Given that EV4 and EV5 +# have the same instruction set, prefer EV5 because an EV5 schedule is +# more likely to keep an EV4 processor busy than vice-versa. +cpuflags-$(CONFIG_ALPHA_GENERIC) := -mcpu=ev5 + +cflags-y += $(cpuflags-y) # For TSUNAMI, we must have the assembler not emulate our instructions. diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index debc8f03886..5fc61e281ac 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -917,15 +917,6 @@ sys_pipe: .end sys_pipe .align 4 - .globl sys_ptrace - .ent sys_ptrace -sys_ptrace: - .prologue 0 - mov $sp, $20 - jmp $31, do_sys_ptrace -.end sys_ptrace - - .align 4 .globl sys_execve .ent sys_execve sys_execve: diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 83a78184226..1e9ad52c460 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -260,38 +260,12 @@ void ptrace_disable(struct task_struct *child) ptrace_cancel_bpt(child); } -asmlinkage long -do_sys_ptrace(long request, long pid, long addr, long data, - struct pt_regs *regs) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; size_t copied; long ret; - lock_kernel(); - DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n", - request, pid, addr, data)); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out_notsk; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out_notsk; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out; - switch (request) { /* When I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -301,13 +275,13 @@ do_sys_ptrace(long request, long pid, long addr, long data, if (copied != sizeof(tmp)) break; - regs->r0 = 0; /* special return: no errors */ + force_successful_syscall_return(); ret = tmp; break; /* Read register number ADDR. */ case PTRACE_PEEKUSR: - regs->r0 = 0; /* special return: no errors */ + force_successful_syscall_return(); ret = get_reg(child, addr); DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret)); break; @@ -353,7 +327,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, /* make sure single-step breakpoint is gone. */ ptrace_cancel_bpt(child); wake_up_process(child); - goto out; + break; case PTRACE_SINGLESTEP: /* execute single instruction. */ ret = -EIO; @@ -366,20 +340,12 @@ do_sys_ptrace(long request, long pid, long addr, long data, wake_up_process(child); /* give it a chance to run. */ ret = 0; - goto out; - - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - goto out; + break; default: ret = ptrace_request(child, request, addr, data); - goto out; + break; } - out: - put_task_struct(child); - out_notsk: - unlock_kernel(); return ret; } diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 7af07d3ad5f..55c05b511f4 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -1,4 +1,5 @@ #include <asm-generic/vmlinux.lds.h> +#include <asm/page.h> OUTPUT_FORMAT("elf64-alpha") OUTPUT_ARCH(alpha) @@ -8,138 +9,145 @@ jiffies = jiffies_64; SECTIONS { #ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS - . = 0xfffffc0000310000; + . = 0xfffffc0000310000; #else - . = 0xfffffc0001010000; + . = 0xfffffc0001010000; #endif - _text = .; /* Text and read-only data */ - .text : { + _text = .; /* Text and read-only data */ + .text : { *(.text.head) - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - *(.fixup) - *(.gnu.warning) - } :kernel - _etext = .; /* End of text section */ - - . = ALIGN(16); - __start___ex_table = .; /* Exception table */ - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - NOTES :kernel :note - .dummy : { *(.dummy) } :kernel - - RODATA - - /* Will be freed after init */ - . = ALIGN(8192); /* Init code and data */ - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : { *(.init.data) } - - . = ALIGN(16); - __setup_start = .; - .init.setup : { *(.init.setup) } - __setup_end = .; - - . = ALIGN(8); - __initcall_start = .; - .initcall.init : { - INITCALLS - } - __initcall_end = .; + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + *(.fixup) + *(.gnu.warning) + } :kernel + _etext = .; /* End of text section */ + + /* Exception table */ + . = ALIGN(16); + __ex_table : { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } + + NOTES :kernel :note + .dummy : { + *(.dummy) + } :kernel + + RODATA + + /* Will be freed after init */ + . = ALIGN(PAGE_SIZE); + /* Init code and data */ + __init_begin = .; + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { + *(.init.data) + } + + . = ALIGN(16); + .init.setup : { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + + . = ALIGN(8); + .initcall.init : { + __initcall_start = .; + INITCALLS + __initcall_end = .; + } #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(8192); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; + . = ALIGN(PAGE_SIZE); + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } #endif - . = ALIGN(8); - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - - . = ALIGN(8); - SECURITY_INIT - - PERCPU(8192) - - . = ALIGN(2*8192); - __init_end = .; - /* Freed after init ends here */ - - /* Note 2 page alignment above. */ - .data.init_thread : { *(.data.init_thread) } - - . = ALIGN(8192); - .data.page_aligned : { *(.data.page_aligned) } - - . = ALIGN(64); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - _data = .; - .data : { /* Data */ - DATA_DATA - CONSTRUCTORS - } - - .got : { *(.got) } - .sdata : { *(.sdata) } - - _edata = .; /* End of data section */ - - __bss_start = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : { *(.bss) *(COMMON) } - __bss_stop = .; - - _end = .; - - /* Sections to be discarded */ - /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) } - - .mdebug 0 : { *(.mdebug) } - .note 0 : { *(.note) } - .comment 0 : { *(.comment) } - - /* Stabs debugging sections */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } + . = ALIGN(8); + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + + . = ALIGN(8); + SECURITY_INIT + + PERCPU(PAGE_SIZE) + + . = ALIGN(2 * PAGE_SIZE); + __init_end = .; + /* Freed after init ends here */ + + /* Note 2 page alignment above. */ + .data.init_thread : { + *(.data.init_thread) + } + + . = ALIGN(PAGE_SIZE); + .data.page_aligned : { + *(.data.page_aligned) + } + + . = ALIGN(64); + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } + + _data = .; + /* Data */ + .data : { + DATA_DATA + CONSTRUCTORS + } + + .got : { + *(.got) + } + .sdata : { + *(.sdata) + } + _edata = .; /* End of data section */ + + __bss_start = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + __bss_stop = .; + _end = .; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) + } + + .mdebug 0 : { + *(.mdebug) + } + .note 0 : { + *(.note) + } + + STABS_DEBUG + DWARF_DEBUG } diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index a0e18da594d..25154df3055 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -197,7 +197,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, current->comm, current->pid); if (!user_mode(regs)) goto no_context; - do_exit(SIGKILL); + do_group_exit(SIGKILL); do_sigbus: /* Send a sigbus, regardless of whether we were in kernel diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 78c9f1a3d41..5feee722ea9 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -731,10 +731,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; - case PTRACE_DETACH: - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: ret = ptrace_getregs(child, (void __user *)data); break; diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c index 43bb5e10630..a67a0685664 100644 --- a/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/arch/arm/mach-s3c2410/mach-amlm5900.c @@ -168,13 +168,31 @@ static void __init amlm5900_map_io(void) } #ifdef CONFIG_FB_S3C2410 -static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = { +static struct s3c2410fb_display __initdata amlm5900_lcd_info = { .width = 160, .height = 160, -/* commented out until stn patch is submitted -* .type = S3C2410_LCDCON1_STN4, -*/ + .type = S3C2410_LCDCON1_STN4, + + .pixclock = 680000, /* HCLK = 100MHz */ + .xres = 160, + .yres = 160, + .bpp = 4, + .left_margin = 1 << (4 + 3), + .right_margin = 8 << 3, + .hsync_len = 48, + .upper_margin = 0, + .lower_margin = 0, + + .lcdcon5 = 0x00000001, +}; + +static struct s3c2410fb_mach_info __initdata amlm5900_fb_info = { + + .displays = &amlm5900_lcd_info, + .num_displays = 1, + .default_display = 0, + .gpccon = 0xaaaaaaaa, .gpccon_mask = 0xffffffff, .gpcup = 0x0000ffff, @@ -184,32 +202,6 @@ static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = { .gpdcon_mask = 0xffffffff, .gpdup = 0x0000ffff, .gpdup_mask = 0xffffffff, - - .xres = { - .min = 160, - .max = 160, - .defval = 160, - }, - - .yres = { - .min = 160, - .max = 160, - .defval = 160, - }, - - .bpp = { - .min = 4, - .max = 4, - .defval = 4, - }, - - .regs = { - .lcdcon1 = 0x00008225, - .lcdcon2 = 0x0027c000, - .lcdcon3 = 0x00182708, - .lcdcon4 = 0x00000002, - .lcdcon5 = 0x00000001, - } }; #endif @@ -239,7 +231,7 @@ static void __init amlm5900_init(void) { amlm5900_init_pm(); #ifdef CONFIG_FB_S3C2410 - s3c24xx_fb_set_platdata(&amlm5900_lcd_info); + s3c24xx_fb_set_platdata(&amlm5900_fb_info); #endif platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index bc926992b4e..587864fe25f 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -467,35 +467,70 @@ static struct platform_device bast_device_axpp = { /* LCD/VGA controller */ -static struct s3c2410fb_mach_info __initdata bast_lcd_info = { - .width = 640, - .height = 480, - - .xres = { - .min = 320, - .max = 1024, - .defval = 640, - }, +static struct s3c2410fb_display __initdata bast_lcd_info[] = { + { + .type = S3C2410_LCDCON1_TFT, + .width = 640, + .height = 480, + + .pixclock = 33333, + .xres = 640, + .yres = 480, + .bpp = 4, + .left_margin = 40, + .right_margin = 20, + .hsync_len = 88, + .upper_margin = 30, + .lower_margin = 32, + .vsync_len = 3, - .yres = { - .min = 240, - .max = 600, - .defval = 480, + .lcdcon5 = 0x00014b02, }, + { + .type = S3C2410_LCDCON1_TFT, + .width = 640, + .height = 480, + + .pixclock = 33333, + .xres = 640, + .yres = 480, + .bpp = 8, + .left_margin = 40, + .right_margin = 20, + .hsync_len = 88, + .upper_margin = 30, + .lower_margin = 32, + .vsync_len = 3, - .bpp = { - .min = 4, - .max = 16, - .defval = 8, + .lcdcon5 = 0x00014b02, }, + { + .type = S3C2410_LCDCON1_TFT, + .width = 640, + .height = 480, + + .pixclock = 33333, + .xres = 640, + .yres = 480, + .bpp = 16, + .left_margin = 40, + .right_margin = 20, + .hsync_len = 88, + .upper_margin = 30, + .lower_margin = 32, + .vsync_len = 3, - .regs = { - .lcdcon1 = 0x00000176, - .lcdcon2 = 0x1d77c7c2, - .lcdcon3 = 0x013a7f13, - .lcdcon4 = 0x00000057, .lcdcon5 = 0x00014b02, - } + }, +}; + +/* LCD/VGA controller */ + +static struct s3c2410fb_mach_info __initdata bast_fb_info = { + + .displays = bast_lcd_info, + .num_displays = ARRAY_SIZE(bast_lcd_info), + .default_display = 4, }; /* Standard BAST devices */ @@ -552,7 +587,7 @@ static void __init bast_map_io(void) static void __init bast_init(void) { - s3c24xx_fb_set_platdata(&bast_lcd_info); + s3c24xx_fb_set_platdata(&bast_fb_info); platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 9a172b4ad72..7c1145e87c1 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -133,29 +133,31 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = { /** * Set lcd on or off **/ -static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = { - .fixed_syncs= 1, - .regs={ - .lcdcon1= S3C2410_LCDCON1_TFT16BPP | \ - S3C2410_LCDCON1_TFT | \ - S3C2410_LCDCON1_CLKVAL(0x0C), - - .lcdcon2= S3C2410_LCDCON2_VBPD(7) | \ - S3C2410_LCDCON2_LINEVAL(319) | \ - S3C2410_LCDCON2_VFPD(6) | \ - S3C2410_LCDCON2_VSPW(0), - - .lcdcon3= S3C2410_LCDCON3_HBPD(19) | \ - S3C2410_LCDCON3_HOZVAL(239) | \ - S3C2410_LCDCON3_HFPD(7), - - .lcdcon4= S3C2410_LCDCON4_MVAL(0) | \ - S3C2410_LCDCON4_HSPW(3), - - .lcdcon5= S3C2410_LCDCON5_FRM565 | \ - S3C2410_LCDCON5_INVVLINE | \ - S3C2410_LCDCON5_HWSWP, - }, +static struct s3c2410fb_display h1940_lcd __initdata = { + .lcdcon5= S3C2410_LCDCON5_FRM565 | \ + S3C2410_LCDCON5_INVVLINE | \ + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + .width = 240, + .height = 320, + .pixclock = 260000, + .xres = 240, + .yres = 320, + .bpp = 16, + .left_margin = 20, + .right_margin = 8, + .hsync_len = 4, + .upper_margin = 8, + .lower_margin = 7, + .vsync_len = 1, +}; + +static struct s3c2410fb_mach_info h1940_fb_info __initdata = { + .displays = &h1940_lcd, + .num_displays = 1, + .default_display = 0, + .lpcsel= 0x02, .gpccon= 0xaa940659, .gpccon_mask= 0xffffffff, @@ -165,12 +167,6 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = { .gpdcon_mask= 0xffffffff, .gpdup= 0x0000faff, .gpdup_mask= 0xffffffff, - - .width= 240, - .height= 320, - .xres= {240,240,240}, - .yres= {320,320,320}, - .bpp= {16,16,16}, }; static struct platform_device s3c_device_leds = { @@ -217,7 +213,7 @@ static void __init h1940_init(void) { u32 tmp; - s3c24xx_fb_set_platdata(&h1940_lcdcfg); + s3c24xx_fb_set_platdata(&h1940_fb_info); s3c24xx_udc_set_platdata(&h1940_udc_cfg); /* Turn off suspend on both USB ports, and switch the diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c index e670b1e1631..a1caf4b0ada 100644 --- a/arch/arm/mach-s3c2410/mach-qt2410.c +++ b/arch/arm/mach-s3c2410/mach-qt2410.c @@ -95,157 +95,83 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { /* LCD driver info */ -/* Configuration for 640x480 SHARP LQ080V3DG01 */ -static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ - - .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */ - S3C2410_LCDCON2_LINEVAL(479) | - S3C2410_LCDCON2_VFPD(10) | /* 11 */ - S3C2410_LCDCON2_VSPW(14), /* 15 */ - - .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */ - S3C2410_LCDCON3_HOZVAL(639) | /* 640 */ - S3C2410_LCDCON3_HFPD(115), /* 116 */ - - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(95), /* 96 */ - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, +static struct s3c2410fb_display qt2410_lcd_cfg[] __initdata = { + { + /* Configuration for 640x480 SHARP LQ080V3DG01 */ + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + .width = 640, + .height = 480, + + .pixclock = 40000, /* HCLK/4 */ + .xres = 640, + .yres = 480, + .bpp = 16, + .left_margin = 44, + .right_margin = 116, + .hsync_len = 96, + .upper_margin = 19, + .lower_margin = 11, + .vsync_len = 15, }, - - .lpcsel = ((0xCE6) & ~7) | 1<<4, - - .width = 640, - .height = 480, - - .xres = { - .min = 640, - .max = 640, - .defval = 640, - }, - - .yres = { - .min = 480, - .max = 480, - .defval = 480, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, -}; - -/* Configuration for 480x640 toppoly TD028TTEC1 */ -static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ - - .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */ - S3C2410_LCDCON2_LINEVAL(639) |/* 640 */ - S3C2410_LCDCON2_VFPD(3) | /* 4 */ - S3C2410_LCDCON2_VSPW(1), /* 2 */ - - .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */ - S3C2410_LCDCON3_HOZVAL(479) | /* 479 */ - S3C2410_LCDCON3_HFPD(23), /* 24 */ - - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(7), /* 8 */ - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - }, - - .lpcsel = ((0xCE6) & ~7) | 1<<4, - - .width = 480, - .height = 640, - - .xres = { - .min = 480, - .max = 480, - .defval = 480, + { + /* Configuration for 480x640 toppoly TD028TTEC1 */ + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + .width = 480, + .height = 640, + .pixclock = 40000, /* HCLK/4 */ + .xres = 480, + .yres = 640, + .bpp = 16, + .left_margin = 8, + .right_margin = 24, + .hsync_len = 8, + .upper_margin = 2, + .lower_margin = 4, + .vsync_len = 2, }, - - .yres = { - .min = 640, - .max = 640, - .defval = 640, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, + { + /* Config for 240x320 LCD */ + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + .width = 240, + .height = 320, + .pixclock = 100000, /* HCLK/10 */ + .xres = 240, + .yres = 320, + .bpp = 16, + .left_margin = 13, + .right_margin = 8, + .hsync_len = 4, + .upper_margin = 2, + .lower_margin = 7, + .vsync_len = 4, }, }; -/* Config for 240x320 LCD */ -static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x04), - - .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | - S3C2410_LCDCON2_LINEVAL(319) | - S3C2410_LCDCON2_VFPD(6) | - S3C2410_LCDCON2_VSPW(3), - - .lcdcon3 = S3C2410_LCDCON3_HBPD(12) | - S3C2410_LCDCON3_HOZVAL(239) | - S3C2410_LCDCON3_HFPD(7), - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(3), - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - }, +static struct s3c2410fb_mach_info qt2410_fb_info __initdata = { + .displays = qt2410_lcd_cfg, + .num_displays = ARRAY_SIZE(qt2410_lcd_cfg), + .default_display = 0, .lpcsel = ((0xCE6) & ~7) | 1<<4, - - .width = 240, - .height = 320, - - .xres = { - .min = 240, - .max = 240, - .defval = 240, - }, - - .yres = { - .min = 320, - .max = 320, - .defval = 320, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, }; /* CS8900 */ @@ -408,16 +334,17 @@ static void __init qt2410_machine_init(void) switch (tft_type) { case 'p': /* production */ - s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg); + qt2410_fb_info.default_display = 1; break; case 'b': /* big */ - s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg); + qt2410_fb_info.default_display = 0; break; case 's': /* small */ default: - s3c24xx_fb_set_platdata(&qt2410_lcd_cfg); + qt2410_fb_info.default_display = 2; break; } + s3c24xx_fb_set_platdata(&qt2410_fb_info); s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPB0, 1); diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index b59e6d39f2f..bac40c4878a 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -110,28 +110,32 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = { /* framebuffer lcd controller information */ -static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { - .regs = { - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \ - S3C2410_LCDCON1_TFT | \ - S3C2410_LCDCON1_CLKVAL(0x0C), - - .lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \ - S3C2410_LCDCON2_LINEVAL(319) | \ - S3C2410_LCDCON2_VFPD(6) | \ - S3C2410_LCDCON2_VSPW(2), - - .lcdcon3 = S3C2410_LCDCON3_HBPD(35) | \ - S3C2410_LCDCON3_HOZVAL(239) | \ - S3C2410_LCDCON3_HFPD(35), - - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | \ - S3C2410_LCDCON4_HSPW(7), - - .lcdcon5 = S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_HWSWP, - }, +static struct s3c2410fb_display rx3715_lcdcfg __initdata = { + .lcdcon5 = S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + .width = 240, + .height = 320, + + .pixclock = 260000, + .xres = 240, + .yres = 320, + .bpp = 16, + .left_margin = 36, + .right_margin = 36, + .hsync_len = 8, + .upper_margin = 6, + .lower_margin = 7, + .vsync_len = 3, +}; + +static struct s3c2410fb_mach_info rx3715_fb_info __initdata = { + + .displays = &rx3715_lcdcfg, + .num_displays = 1, + .default_display = 0, .lpcsel = 0xf82, @@ -144,28 +148,6 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { .gpdcon_mask = 0xffc0fff0, .gpdup = 0x0000faff, .gpdup_mask = 0xffffffff, - - .fixed_syncs = 1, - .width = 240, - .height = 320, - - .xres = { - .min = 240, - .max = 240, - .defval = 240, - }, - - .yres = { - .max = 320, - .min = 320, - .defval = 320, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, }; static struct mtd_partition rx3715_nand_part[] = { @@ -224,7 +206,7 @@ static void __init rx3715_init_machine(void) #endif s3c2410_pm_init(); - s3c24xx_fb_set_platdata(&rx3715_lcdcfg); + s3c24xx_fb_set_platdata(&rx3715_fb_info); platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices)); } diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c index 670115b8a12..4552828bf80 100644 --- a/arch/arm/mach-s3c2440/mach-smdk2440.c +++ b/arch/arm/mach-s3c2440/mach-smdk2440.c @@ -103,31 +103,35 @@ static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = { /* LCD driver info */ -static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x04), - - .lcdcon2 = S3C2410_LCDCON2_VBPD(7) | - S3C2410_LCDCON2_LINEVAL(319) | - S3C2410_LCDCON2_VFPD(6) | - S3C2410_LCDCON2_VSPW(3), - - .lcdcon3 = S3C2410_LCDCON3_HBPD(19) | - S3C2410_LCDCON3_HOZVAL(239) | - S3C2410_LCDCON3_HFPD(7), - - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(3), - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - }, +static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = { + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + + .type = S3C2410_LCDCON1_TFT, + + .width = 240, + .height = 320, + + .pixclock = 166667, /* HCLK 60 MHz, divisor 10 */ + .xres = 240, + .yres = 320, + .bpp = 16, + .left_margin = 20, + .right_margin = 8, + .hsync_len = 4, + .upper_margin = 8, + .lower_margin = 7, + .vsync_len = 4, +}; + +static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = { + .displays = &smdk2440_lcd_cfg, + .num_displays = 1, + .default_display = 0, #if 0 /* currently setup by downloader */ @@ -142,28 +146,6 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { #endif .lpcsel = ((0xCE6) & ~7) | 1<<4, - .type = S3C2410_LCDCON1_TFT16BPP, - - .width = 240, - .height = 320, - - .xres = { - .min = 240, - .max = 240, - .defval = 240, - }, - - .yres = { - .min = 320, - .max = 320, - .defval = 320, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, }; static struct platform_device *smdk2440_devices[] __initdata = { @@ -183,7 +165,7 @@ static void __init smdk2440_map_io(void) static void __init smdk2440_machine_init(void) { - s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg); + s3c24xx_fb_set_platdata(&smdk2440_fb_info); platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); smdk_machine_init(); diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 846cce48e2b..59ed1d05b71 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -266,7 +266,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) * the page fault gracefully. */ printk("VM: killing process %s\n", tsk->comm); - do_exit(SIGKILL); + do_group_exit(SIGKILL); return 0; } if (fault & VM_FAULT_SIGBUS) { diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c index 4942ee662e0..20b1c9d8f94 100644 --- a/arch/avr32/kernel/kprobes.c +++ b/arch/avr32/kernel/kprobes.c @@ -22,6 +22,8 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe); static unsigned long kprobe_status; static struct pt_regs jprobe_saved_regs; +struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; + int __kprobes arch_prepare_kprobe(struct kprobe *p) { int ret = 0; diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 39060cbeb2a..9e16b8a447f 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c @@ -227,11 +227,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; - /* Detach a process that was attached */ - case PTRACE_DETACH: - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: ret = ptrace_getregs(child, (void __user *)data); break; diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index ae2d2c593b2..11472f8701b 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c @@ -216,7 +216,7 @@ out_of_memory: } printk("VM: Killing process %s\n", tsk->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 64ce5fea860..85caf9b711a 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -385,12 +385,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - case PTRACE_DETACH: - { /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - } - case PTRACE_GETREGS: { diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index f4f9db698b4..b570ae9b6ca 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -177,10 +177,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; - case PTRACE_DETACH: - ret = ptrace_detach(child, data); - break; - /* Get all GP registers from the child. */ case PTRACE_GETREGS: { int i; diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c index 077e973c33f..575a14bb110 100644 --- a/arch/cris/arch-v10/kernel/time.c +++ b/arch/cris/arch-v10/kernel/time.c @@ -254,8 +254,12 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * it needs to be IRQF_DISABLED to make the jiffies update work properly */ -static struct irqaction irq2 = { timer_interrupt, IRQF_SHARED | IRQF_DISABLED, - CPU_MASK_NONE, "timer", NULL, NULL}; +static struct irqaction irq2 = { + .handler = timer_interrupt, + .flags = IRQF_SHARED | IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "timer", +}; void __init time_init(void) diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 38ece0cd47c..2df60529a8a 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -245,10 +245,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - case PTRACE_DETACH: - ret = ptrace_detach(child, data); - break; - /* Get all GP registers from the child. */ case PTRACE_GETREGS: { int i; diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 77e655f2656..697494bc2de 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -63,8 +63,12 @@ static unsigned long irq_regs[NR_CPUS] = static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int send_ipi(int vector, int wait, cpumask_t cpu_mask); -static struct irqaction irq_ipi = { crisv32_ipi_interrupt, IRQF_DISABLED, - CPU_MASK_NONE, "ipi", NULL, NULL}; +static struct irqaction irq_ipi = { + .handler = crisv32_ipi_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "ipi", +}; extern void cris_mmu_init(void); extern void cris_timer_init(void); diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 8672ab7d797..8aab8143069 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -360,7 +360,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, up_read(&mm->mmap_sem); printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c index ed588d73d7d..e83e0bccfab 100644 --- a/arch/frv/kernel/time.c +++ b/arch/frv/kernel/time.c @@ -43,7 +43,10 @@ unsigned long __delay_loops_MHz; static irqreturn_t timer_interrupt(int irq, void *dummy); static struct irqaction timer_irq = { - timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL + .handler = timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "timer", }; static inline int set_rtc_mmss(unsigned long nowtime) diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 6798fa0257b..05093d41d98 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c @@ -259,7 +259,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear up_read(&mm->mmap_sem); printk("VM: killing process %s\n", current->comm); if (user_mode(__frame)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 2e6310b8eab..59b91ac861a 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -54,6 +54,11 @@ config ARCH_HAS_ILOG2_U64 bool default n +config HUGETLB_PAGE_SIZE_VARIABLE + bool + depends on HUGETLB_PAGE + default y + config GENERIC_FIND_NEXT_BIT bool default y @@ -300,6 +305,9 @@ config HOTPLUG_CPU config ARCH_ENABLE_MEMORY_HOTPLUG def_bool y +config ARCH_ENABLE_MEMORY_HOTREMOVE + def_bool y + config SCHED_SMT bool "SMT scheduler support" depends on SMP @@ -348,6 +356,7 @@ config ARCH_FLATMEM_ENABLE config ARCH_SPARSEMEM_ENABLE def_bool y depends on ARCH_DISCONTIGMEM_ENABLE + select SPARSEMEM_VMEMMAP_ENABLE config ARCH_DISCONTIGMEM_DEFAULT def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S index 6d198339bf8..44817d97ab4 100644 --- a/arch/ia64/kernel/gate.lds.S +++ b/arch/ia64/kernel/gate.lds.S @@ -1,7 +1,8 @@ /* - * Linker script for gate DSO. The gate pages are an ELF shared object prelinked to its - * virtual address, with only one read-only segment and one execute-only segment (both fit - * in one page). This script controls its layout. + * Linker script for gate DSO. The gate pages are an ELF shared object + * prelinked to its virtual address, with only one read-only segment and + * one execute-only segment (both fit in one page). This script controls + * its layout. */ @@ -9,72 +10,80 @@ SECTIONS { - . = GATE_ADDR + SIZEOF_HEADERS; - - .hash : { *(.hash) } :readable - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .dynamic : { *(.dynamic) } :readable :dynamic - - /* - * This linker script is used both with -r and with -shared. For the layouts to match, - * we need to skip more than enough space for the dynamic symbol table et al. If this - * amount is insufficient, ld -shared will barf. Just increase it here. - */ - . = GATE_ADDR + 0x500; - - .data.patch : { - __start_gate_mckinley_e9_patchlist = .; - *(.data.patch.mckinley_e9) - __end_gate_mckinley_e9_patchlist = .; - - __start_gate_vtop_patchlist = .; - *(.data.patch.vtop) - __end_gate_vtop_patchlist = .; - - __start_gate_fsyscall_patchlist = .; - *(.data.patch.fsyscall_table) - __end_gate_fsyscall_patchlist = .; - - __start_gate_brl_fsys_bubble_down_patchlist = .; - *(.data.patch.brl_fsys_bubble_down) - __end_gate_brl_fsys_bubble_down_patchlist = .; - } :readable - .IA_64.unwind_info : { *(.IA_64.unwind_info*) } - .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind + . = GATE_ADDR + SIZEOF_HEADERS; + + .hash : { *(.hash) } :readable + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .dynamic : { *(.dynamic) } :readable :dynamic + + /* + * This linker script is used both with -r and with -shared. For + * the layouts to match, we need to skip more than enough space for + * the dynamic symbol table et al. If this amount is insufficient, + * ld -shared will barf. Just increase it here. + */ + . = GATE_ADDR + 0x500; + + .data.patch : { + __start_gate_mckinley_e9_patchlist = .; + *(.data.patch.mckinley_e9) + __end_gate_mckinley_e9_patchlist = .; + + __start_gate_vtop_patchlist = .; + *(.data.patch.vtop) + __end_gate_vtop_patchlist = .; + + __start_gate_fsyscall_patchlist = .; + *(.data.patch.fsyscall_table) + __end_gate_fsyscall_patchlist = .; + + __start_gate_brl_fsys_bubble_down_patchlist = .; + *(.data.patch.brl_fsys_bubble_down) + __end_gate_brl_fsys_bubble_down_patchlist = .; + } :readable + + .IA_64.unwind_info : { *(.IA_64.unwind_info*) } + .IA_64.unwind : { *(.IA_64.unwind*) } :readable :unwind #ifdef HAVE_BUGGY_SEGREL - .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable + .text (GATE_ADDR + PAGE_SIZE) : { *(.text) *(.text.*) } :readable #else - . = ALIGN (PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1)); - .text : { *(.text) *(.text.*) } :epc + . = ALIGN(PERCPU_PAGE_SIZE) + (. & (PERCPU_PAGE_SIZE - 1)); + .text : { *(.text) *(.text.*) } :epc #endif - /DISCARD/ : { - *(.got.plt) *(.got) - *(.data .data.* .gnu.linkonce.d.*) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(__ex_table) - *(__mca_table) - } + /DISCARD/ : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(__ex_table) + *(__mca_table) + } } /* + * ld does not recognize this name token; use the constant. + */ +#define PT_IA_64_UNWIND 0x70000001 + +/* * We must supply the ELF program headers explicitly to get just one * PT_LOAD segment, and set the flags explicitly to make segments read-only. */ PHDRS { - readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */ + readable PT_LOAD FILEHDR PHDRS FLAGS(4); /* PF_R */ #ifndef HAVE_BUGGY_SEGREL - epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */ + epc PT_LOAD FILEHDR PHDRS FLAGS(1); /* PF_X */ #endif - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - unwind 0x70000001; /* PT_IA_64_UNWIND, but ld doesn't match the name */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + unwind PT_IA_64_UNWIND; } /* @@ -82,14 +91,14 @@ PHDRS */ VERSION { - LINUX_2.5 { - global: - __kernel_syscall_via_break; - __kernel_syscall_via_epc; - __kernel_sigtramp; - - local: *; - }; + LINUX_2.5 { + global: + __kernel_syscall_via_break; + __kernel_syscall_via_epc; + __kernel_sigtramp; + + local: *; + }; } /* The ELF entry point can be used to set the AT_SYSINFO value. */ diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 5dc98b5abcf..5fd65d8302c 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -40,6 +40,8 @@ extern void jprobe_inst_return(void); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); +struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; + enum instruction_type {A, I, M, F, B, L, X, u}; static enum instruction_type bundle_encoding[32][3] = { { M, I, I }, /* 00 */ diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 9e392a30d19..777c8d8bd5e 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -528,10 +528,6 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); - - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); - check_for_logical_procs(); if (smp_num_cpucores > 1) printk(KERN_INFO @@ -873,6 +869,14 @@ cpu_init (void) void *cpu_data; cpu_data = per_cpu_init(); + /* + * insert boot cpu into sibling and core mapes + * (must be done after per_cpu area is setup) + */ + if (smp_processor_id() == 0) { + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, cpu_core_map[0]); + } /* * We set ar.k3 so that assembly code in MCA handler can compute diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 308772f7cdd..c57dbce25c1 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -138,7 +138,9 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_possible_map); cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; -cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; +DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map); +EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); + int smp_num_siblings = 1; int smp_num_cpucores = 1; @@ -650,12 +652,12 @@ clear_cpu_sibling_map(int cpu) { int i; - for_each_cpu_mask(i, cpu_sibling_map[cpu]) - cpu_clear(cpu, cpu_sibling_map[i]); + for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) + cpu_clear(cpu, per_cpu(cpu_sibling_map, i)); for_each_cpu_mask(i, cpu_core_map[cpu]) cpu_clear(cpu, cpu_core_map[i]); - cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE; + per_cpu(cpu_sibling_map, cpu) = cpu_core_map[cpu] = CPU_MASK_NONE; } static void @@ -666,7 +668,7 @@ remove_siblinginfo(int cpu) if (cpu_data(cpu)->threads_per_core == 1 && cpu_data(cpu)->cores_per_socket == 1) { cpu_clear(cpu, cpu_core_map[cpu]); - cpu_clear(cpu, cpu_sibling_map[cpu]); + cpu_clear(cpu, per_cpu(cpu_sibling_map, cpu)); return; } @@ -807,8 +809,8 @@ set_cpu_sibling_map(int cpu) cpu_set(i, cpu_core_map[cpu]); cpu_set(cpu, cpu_core_map[i]); if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) { - cpu_set(i, cpu_sibling_map[cpu]); - cpu_set(cpu, cpu_sibling_map[i]); + cpu_set(i, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, per_cpu(cpu_sibling_map, i)); } } } @@ -839,7 +841,7 @@ __cpu_up (unsigned int cpu) if (cpu_data(cpu)->threads_per_core == 1 && cpu_data(cpu)->cores_per_socket == 1) { - cpu_set(cpu, cpu_sibling_map[cpu]); + cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); cpu_set(cpu, cpu_core_map[cpu]); return 0; } diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index c58e933694d..a7be4f20342 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -196,7 +196,7 @@ unsigned long uncached_alloc_page(int starting_nid) nid = starting_nid; do { - if (!node_online(nid)) + if (!node_state(nid, N_HIGH_MEMORY)) continue; uc_pool = &uncached_pools[nid]; if (uc_pool->pool == NULL) @@ -268,7 +268,7 @@ static int __init uncached_init(void) { int nid; - for_each_online_node(nid) { + for_each_node_state(nid, N_ONLINE) { uncached_pools[nid].pool = gen_pool_create(PAGE_SHIFT, nid); mutex_init(&uncached_pools[nid].add_chunk_mutex); } diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 0d34585058c..5628067a74d 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -715,3 +715,11 @@ void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat) scatter_node_data(); } #endif + +#ifdef CONFIG_SPARSEMEM_VMEMMAP +int __meminit vmemmap_populate(struct page *start_page, + unsigned long size, int node) +{ + return vmemmap_populate_basepages(start_page, size, node); +} +#endif diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 9150ffaff9e..32f26253c4e 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -281,6 +281,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re } printk(KERN_CRIT "VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; } diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index a9ff685aea2..d3ce8f3bcaa 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -194,6 +194,6 @@ static int __init hugetlb_setup_sz(char *str) * override here with new page shift. */ ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2); - return 1; + return 0; } -__setup("hugepagesz=", hugetlb_setup_sz); +early_param("hugepagesz", hugetlb_setup_sz); diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index c14abefabaf..3e10152abbf 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -54,15 +54,12 @@ struct page *zero_page_memmap_ptr; /* map entry for zero page */ EXPORT_SYMBOL(zero_page_memmap_ptr); void -lazy_mmu_prot_update (pte_t pte) +__ia64_sync_icache_dcache (pte_t pte) { unsigned long addr; struct page *page; unsigned long order; - if (!pte_exec(pte)) - return; /* not an executable page... */ - page = pte_page(pte); addr = (unsigned long) page_address(page); @@ -721,10 +718,21 @@ int arch_add_memory(int nid, u64 start, u64 size) return ret; } - +#ifdef CONFIG_MEMORY_HOTREMOVE int remove_memory(u64 start, u64 size) { - return -EINVAL; + unsigned long start_pfn, end_pfn; + unsigned long timeout = 120 * HZ; + int ret; + start_pfn = start >> PAGE_SHIFT; + end_pfn = start_pfn + (size >> PAGE_SHIFT); + ret = offline_pages(start_pfn, end_pfn, timeout); + if (ret) + goto out; + /* we can free mem_map at this point */ +out: + return ret; } EXPORT_SYMBOL_GPL(remove_memory); +#endif /* CONFIG_MEMORY_HOTREMOVE */ #endif diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 62a51429306..ed4d0756c5d 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -570,7 +570,7 @@ withdraw_debug_trap(struct pt_regs *regs) } } -static void +void init_debug_traps(struct task_struct *child) { struct debug_trap *p = &child->thread.debug_trap; @@ -593,8 +593,8 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -static int -do_ptrace(long request, struct task_struct *child, long addr, long data) +long +arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; @@ -704,14 +704,6 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) break; } - /* - * detach a process that was attached. - */ - case PTRACE_DETACH: - ret = 0; - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: ret = ptrace_getregs(child, (void __user *)data); break; @@ -728,42 +720,6 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - if (ret == 0) - init_debug_traps(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - - return ret; -} - /* notification of system call entry/exit * - triggered by current->work.syscall_trace */ diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 3858c9f39ba..994cc155635 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -228,8 +228,12 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, - "MFT2", NULL, NULL }; +struct irqaction irq0 = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "MFT2", +}; void __init time_init(void) { diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c index 676a1c443d2..70a766aad3e 100644 --- a/arch/m32r/mm/fault.c +++ b/arch/m32r/mm/fault.c @@ -278,7 +278,7 @@ out_of_memory: } printk("VM: killing process %s\n", tsk->comm); if (error_code & ACE_USERMODE) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index e792d3cba4c..2075543c2d9 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -226,10 +226,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); break; - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: /* Get all gp regs from the child. */ for (i = 0; i < 19; i++) { tmp = get_reg(child, i); diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index 578b48f47b9..eaa61868115 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -188,7 +188,7 @@ out_of_memory: printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); no_context: current->thread.signo = SIGBUS; diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 7f14f70a1b8..0c7aee1682c 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -425,7 +425,7 @@ static int __init jmr3927_rtc_init(void) .flags = IORESOURCE_MEM, }; struct platform_device *dev; - dev = platform_device_register_simple("ds1742", -1, &res, 1); + dev = platform_device_register_simple("rtc-ds1742", -1, &res, 1); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } device_initcall(jmr3927_rtc_init); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 58aa6fec114..999f7853de2 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -435,10 +435,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); break; - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - case PTRACE_GET_THREAD_AREA: ret = put_user(task_thread_info(child)->tp_value, (unsigned long __user *) data); diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 521771b373d..5699c7713e2 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -180,7 +180,7 @@ out_of_memory: } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index acaf613358c..b97102a1c63 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c @@ -963,7 +963,7 @@ static int __init toshiba_rbtx4927_rtc_init(void) .flags = IORESOURCE_MEM, }; struct platform_device *dev = - platform_device_register_simple("ds1742", -1, &res, 1); + platform_device_register_simple("rtc-ds1742", -1, &res, 1); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } device_initcall(toshiba_rbtx4927_rtc_init); diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 26ec774c502..49c63797078 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -329,10 +329,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* give it a chance to run. */ goto out_wake; - case PTRACE_DETACH: - ret = ptrace_detach(child, data); - goto out_tsk; - case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned int __user *) data); goto out_tsk; diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 7899ab87785..1c091b415cd 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -263,6 +263,6 @@ no_context: up_read(&mm->mmap_sem); printk(KERN_CRIT "VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 037664d496d..5e001ad588a 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -295,6 +295,7 @@ config ARCH_FLATMEM_ENABLE config ARCH_SPARSEMEM_ENABLE def_bool y depends on PPC64 + select SPARSEMEM_VMEMMAP_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 440f5a87271..5338e485571 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -38,6 +38,8 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); +struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; + int __kprobes arch_prepare_kprobe(struct kprobe *p) { int ret = 0; diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index cf7732cdd6c..3e17d154d0d 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -505,10 +505,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = ptrace_set_debugreg(child, addr, data); break; - case PTRACE_DETACH: - ret = ptrace_detach(child, data); - break; - #ifdef CONFIG_PPC64 case PTRACE_GETREGS64: #endif diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 36c90ba2d31..2de00f870ed 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -413,16 +413,28 @@ void __init smp_setup_cpu_maps(void) of_node_put(dn); } + vdso_data->processorCount = num_present_cpus(); +#endif /* CONFIG_PPC64 */ +} + +/* + * Being that cpu_sibling_map is now a per_cpu array, then it cannot + * be initialized until the per_cpu areas have been created. This + * function is now called from setup_per_cpu_areas(). + */ +void __init smp_setup_cpu_sibling_map(void) +{ +#if defined(CONFIG_PPC64) + int cpu; + /* * Do the sibling map; assume only two threads per processor. */ for_each_possible_cpu(cpu) { - cpu_set(cpu, cpu_sibling_map[cpu]); + cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); if (cpu_has_feature(CPU_FTR_SMT)) - cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); + cpu_set(cpu ^ 0x1, per_cpu(cpu_sibling_map, cpu)); } - - vdso_data->processorCount = num_present_cpus(); #endif /* CONFIG_PPC64 */ } #endif /* CONFIG_SMP */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 008ab6823b0..0e014550b83 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -597,6 +597,9 @@ void __init setup_per_cpu_areas(void) paca[i].data_offset = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); } + + /* Now that per_cpu is setup, initialize cpu_sibling_map */ + smp_setup_cpu_sibling_map(); } #endif diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d30f08fa029..338950aeb6f 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -61,11 +61,11 @@ struct thread_info *secondary_ti; cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; -cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; +DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); -EXPORT_SYMBOL(cpu_sibling_map); +EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); /* SMP operations for this machine */ struct smp_ops_t *smp_ops; diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S index 26e138c4ce1..9352ab5200e 100644 --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S @@ -1,130 +1,147 @@ - /* * This is the infamous ld script for the 32 bits vdso * library */ #include <asm/vdso.h> -/* Default link addresses for the vDSOs */ OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") OUTPUT_ARCH(powerpc:common) ENTRY(_start) SECTIONS { - . = VDSO32_LBASE + SIZEOF_HEADERS; - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - .note : { *(.note.*) } :text :note - - . = ALIGN (16); - .text : - { - *(.text .stub .text.* .gnu.linkonce.t.*) - } - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - . = ALIGN(8); - __ftr_fixup : { - *(__ftr_fixup) - } + . = VDSO32_LBASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .note : { *(.note.*) } :text :note + + . = ALIGN(16); + .text : { + *(.text .stub .text.* .gnu.linkonce.t.*) + } + PROVIDE(__etext = .); + PROVIDE(_etext = .); + PROVIDE(etext = .); + + . = ALIGN(8); + __ftr_fixup : { *(__ftr_fixup) } #ifdef CONFIG_PPC64 - . = ALIGN(8); - __fw_ftr_fixup : { - *(__fw_ftr_fixup) - } + . = ALIGN(8); + __fw_ftr_fixup : { *(__fw_ftr_fixup) } #endif - /* Other stuff is appended to the text segment: */ - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .gcc_except_table : { *(.gcc_except_table) } - .fixup : { *(.fixup) } - - .dynamic : { *(.dynamic) } :text :dynamic - .got : { *(.got) } - .plt : { *(.plt) } - - _end = .; - __end = .; - PROVIDE (end = .); - - - /* Stabs debugging sections are here too - */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - - /DISCARD/ : { *(.note.GNU-stack) } - /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.* .sdata*) } - /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) } + /* + * Other stuff is appended to the text segment: + */ + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .gcc_except_table : { *(.gcc_except_table) } + .fixup : { *(.fixup) } + + .dynamic : { *(.dynamic) } :text :dynamic + .got : { *(.got) } + .plt : { *(.plt) } + + _end = .; + __end = .; + PROVIDE(end = .); + + /* + * Stabs debugging sections are here too. + */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* + * DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. + */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /DISCARD/ : { + *(.note.GNU-stack) + *(.data .data.* .gnu.linkonce.d.* .sdata*) + *(.bss .sbss .dynbss .dynsbss) + } } +/* + * Very old versions of ld do not recognize this name token; use the constant. + */ +#define PT_GNU_EH_FRAME 0x6474e550 +/* + * We must supply the ELF program headers explicitly to get just one + * PT_LOAD segment, and set the flags explicitly to make segments read-only. + */ PHDRS { - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - note PT_NOTE FLAGS(4); /* PF_R */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + note PT_NOTE FLAGS(4); /* PF_R */ + eh_frame_hdr PT_GNU_EH_FRAME; } - /* * This controls what symbols we export from the DSO. */ VERSION { - VDSO_VERSION_STRING { - global: - __kernel_datapage_offset; /* Has to be there for the kernel to find */ - __kernel_get_syscall_map; - __kernel_gettimeofday; - __kernel_clock_gettime; - __kernel_clock_getres; - __kernel_get_tbfreq; - __kernel_sync_dicache; - __kernel_sync_dicache_p5; - __kernel_sigtramp32; - __kernel_sigtramp_rt32; - local: *; - }; + VDSO_VERSION_STRING { + global: + /* + * Has to be there for the kernel to find + */ + __kernel_datapage_offset; + + __kernel_get_syscall_map; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + __kernel_get_tbfreq; + __kernel_sync_dicache; + __kernel_sync_dicache_p5; + __kernel_sigtramp32; + __kernel_sigtramp_rt32; + + local: *; + }; } diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S index 2d70f35d50b..932b3fdb34b 100644 --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S @@ -10,100 +10,114 @@ ENTRY(_start) SECTIONS { - . = VDSO64_LBASE + SIZEOF_HEADERS; - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - .note : { *(.note.*) } :text :note - - . = ALIGN (16); - .text : - { - *(.text .stub .text.* .gnu.linkonce.t.*) - *(.sfpr .glink) - } :text - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - . = ALIGN(8); - __ftr_fixup : { - *(__ftr_fixup) - } - - . = ALIGN(8); - __fw_ftr_fixup : { - *(__fw_ftr_fixup) - } - - /* Other stuff is appended to the text segment: */ - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .gcc_except_table : { *(.gcc_except_table) } - - .opd ALIGN(8) : { KEEP (*(.opd)) } - .got ALIGN(8) : { *(.got .toc) } - .rela.dyn ALIGN(8) : { *(.rela.dyn) } - - .dynamic : { *(.dynamic) } :text :dynamic - - _end = .; - PROVIDE (end = .); - - /* Stabs debugging sections are here too - */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sectio/ns. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - - /DISCARD/ : { *(.note.GNU-stack) } - /DISCARD/ : { *(.branch_lt) } - /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.*) } - /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) } + . = VDSO64_LBASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .note : { *(.note.*) } :text :note + + . = ALIGN(16); + .text : { + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.sfpr .glink) + } :text + PROVIDE(__etext = .); + PROVIDE(_etext = .); + PROVIDE(etext = .); + + . = ALIGN(8); + __ftr_fixup : { *(__ftr_fixup) } + + . = ALIGN(8); + __fw_ftr_fixup : { *(__fw_ftr_fixup) } + + /* + * Other stuff is appended to the text segment: + */ + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .gcc_except_table : { *(.gcc_except_table) } + + .opd ALIGN(8) : { KEEP (*(.opd)) } + .got ALIGN(8) : { *(.got .toc) } + .rela.dyn ALIGN(8) : { *(.rela.dyn) } + + .dynamic : { *(.dynamic) } :text :dynamic + + _end = .; + PROVIDE(end = .); + + /* + * Stabs debugging sections are here too. + */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* + * DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. + */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /DISCARD/ : { + *(.note.GNU-stack) + *(.branch_lt) + *(.data .data.* .gnu.linkonce.d.* .sdata*) + *(.bss .sbss .dynbss .dynsbss) + } } +/* + * Very old versions of ld do not recognize this name token; use the constant. + */ +#define PT_GNU_EH_FRAME 0x6474e550 + +/* + * We must supply the ELF program headers explicitly to get just one + * PT_LOAD segment, and set the flags explicitly to make segments read-only. + */ PHDRS { - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - note PT_NOTE FLAGS(4); /* PF_R */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + note PT_NOTE FLAGS(4); /* PF_R */ + eh_frame_hdr PT_GNU_EH_FRAME; } /* @@ -111,17 +125,22 @@ PHDRS */ VERSION { - VDSO_VERSION_STRING { - global: - __kernel_datapage_offset; /* Has to be there for the kernel to find */ - __kernel_get_syscall_map; - __kernel_gettimeofday; - __kernel_clock_gettime; - __kernel_clock_getres; - __kernel_get_tbfreq; - __kernel_sync_dicache; - __kernel_sync_dicache_p5; - __kernel_sigtramp_rt64; - local: *; - }; + VDSO_VERSION_STRING { + global: + /* + * Has to be there for the kernel to find + */ + __kernel_datapage_offset; + + __kernel_get_syscall_map; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + __kernel_get_tbfreq; + __kernel_sync_dicache; + __kernel_sync_dicache_p5; + __kernel_sigtramp_rt64; + + local: *; + }; } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index fa90f6561b9..29ed495444f 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -183,3 +183,70 @@ void pgtable_cache_init(void) zero_ctor); } } + +#ifdef CONFIG_SPARSEMEM_VMEMMAP +/* + * Given an address within the vmemmap, determine the pfn of the page that + * represents the start of the section it is within. Note that we have to + * do this by hand as the proffered address may not be correctly aligned. + * Subtraction of non-aligned pointers produces undefined results. + */ +unsigned long __meminit vmemmap_section_start(unsigned long page) +{ + unsigned long offset = page - ((unsigned long)(vmemmap)); + + /* Return the pfn of the start of the section. */ + return (offset / sizeof(struct page)) & PAGE_SECTION_MASK; +} + +/* + * Check if this vmemmap page is already initialised. If any section + * which overlaps this vmemmap page is initialised then this page is + * initialised already. + */ +int __meminit vmemmap_populated(unsigned long start, int page_size) +{ + unsigned long end = start + page_size; + + for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page))) + if (pfn_valid(vmemmap_section_start(start))) + return 1; + + return 0; +} + +int __meminit vmemmap_populate(struct page *start_page, + unsigned long nr_pages, int node) +{ + unsigned long mode_rw; + unsigned long start = (unsigned long)start_page; + unsigned long end = (unsigned long)(start_page + nr_pages); + unsigned long page_size = 1 << mmu_psize_defs[mmu_linear_psize].shift; + + mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; + + /* Align to the page size of the linear mapping. */ + start = _ALIGN_DOWN(start, page_size); + + for (; start < end; start += page_size) { + int mapped; + void *p; + + if (vmemmap_populated(start, page_size)) + continue; + + p = vmemmap_alloc_block(page_size, node); + if (!p) + return -ENOMEM; + + printk(KERN_WARNING "vmemmap %08lx allocated at %p, " + "physical %p.\n", start, p, __pa(p)); + + mapped = htab_bolt_mapping(start, start + page_size, + __pa(p), mode_rw, mmu_linear_psize); + BUG_ON(mapped < 0); + } + + return 0; +} +#endif diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 32dcfc9b008..81eb96ec13b 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -129,51 +129,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) return __add_pages(zone, start_pfn, nr_pages); } -/* - * First pass at this code will check to determine if the remove - * request is within the RMO. Do not allow removal within the RMO. - */ -int __devinit remove_memory(u64 start, u64 size) -{ - struct zone *zone; - unsigned long start_pfn, end_pfn, nr_pages; - - start_pfn = start >> PAGE_SHIFT; - nr_pages = size >> PAGE_SHIFT; - end_pfn = start_pfn + nr_pages; - - printk("%s(): Attempting to remove memoy in range " - "%lx to %lx\n", __func__, start, start+size); - /* - * check for range within RMO - */ - zone = page_zone(pfn_to_page(start_pfn)); - - printk("%s(): memory will be removed from " - "the %s zone\n", __func__, zone->name); - - /* - * not handling removing memory ranges that - * overlap multiple zones yet - */ - if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages)) - goto overlap; - - /* make sure it is NOT in RMO */ - if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) { - printk("%s(): range to be removed must NOT be in RMO!\n", - __func__); - goto in_rmo; - } - - return __remove_pages(zone, start_pfn, nr_pages); - -overlap: - printk("%s(): memory range to be removed overlaps " - "multiple zones!!!\n", __func__); -in_rmo: - return -1; -} #endif /* CONFIG_MEMORY_HOTPLUG */ void show_mem(void) diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index 5123e9d4164..13d5a87f13b 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -117,7 +117,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cur = cbe_freqs[cur_pmode].frequency; #ifdef CONFIG_SMP - policy->cpus = cpu_sibling_map[policy->cpu]; + policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); #endif cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index b98244e277f..94913ddcf76 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -297,7 +297,7 @@ out_of_memory: } printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); return SIGKILL; do_sigbus: diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index e40373d9fbc..c5549a20628 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -33,6 +33,8 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); +struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; + int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* Make sure the probe isn't going on a difficult instruction */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index f4503ca2763..1d81bf9488a 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -683,11 +683,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) wake_up_process(child); return 0; - case PTRACE_DETACH: - /* detach a process that was attached. */ - return ptrace_detach(child, data); - - /* Do requests that differ for 31/64 bit */ default: #ifdef CONFIG_COMPAT diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 4c1ac341ec8..14c241ccdd4 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -218,7 +218,7 @@ static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code, } printk("VM: killing process %s\n", tsk->comm); if (regs->psw.mask & PSW_MASK_PSTATE) - do_exit(SIGKILL); + do_group_exit(SIGKILL); do_no_context(regs, error_code, address); return 0; } diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index f64a2d2416d..ac725f0aeb7 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -211,10 +211,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - #ifdef CONFIG_SH_DSP case PTRACE_GETDSPREGS: { unsigned long dp; diff --git a/arch/sh/kernel/vsyscall/vsyscall.lds.S b/arch/sh/kernel/vsyscall/vsyscall.lds.S index b13c3d439fe..c9bf2af35d3 100644 --- a/arch/sh/kernel/vsyscall/vsyscall.lds.S +++ b/arch/sh/kernel/vsyscall/vsyscall.lds.S @@ -17,45 +17,52 @@ ENTRY(__kernel_vsyscall); SECTIONS { - . = SIZEOF_HEADERS; + . = SIZEOF_HEADERS; - .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } - /* This linker script is used both with -r and with -shared. - For the layouts to match, we need to skip more than enough - space for the dynamic symbol table et al. If this amount - is insufficient, ld -shared will barf. Just increase it here. */ - . = 0x400; + /* + * This linker script is used both with -r and with -shared. + * For the layouts to match, we need to skip more than enough + * space for the dynamic symbol table et al. If this amount + * is insufficient, ld -shared will barf. Just increase it here. + */ + . = 0x400; - .text : { *(.text) } :text =0x90909090 - .note : { *(.note.*) } :text :note - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .dynamic : { *(.dynamic) } :text :dynamic - .useless : { - *(.got.plt) *(.got) - *(.data .data.* .gnu.linkonce.d.*) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - } :text + .text : { *(.text) } :text =0x90909090 + .note : { *(.note.*) } :text :note + .eh_frame_hdr : { *(.eh_frame_hdr ) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .dynamic : { *(.dynamic) } :text :dynamic + .useless : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + } :text } /* + * Very old versions of ld do not recognize this name token; use the constant. + */ +#define PT_GNU_EH_FRAME 0x6474e550 + +/* * We must supply the ELF program headers explicitly to get just one * PT_LOAD segment, and set the flags explicitly to make segments read-only. */ PHDRS { - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - note PT_NOTE FLAGS(4); /* PF_R */ - eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + note PT_NOTE FLAGS(4); /* PF_R */ + eh_frame_hdr PT_GNU_EH_FRAME; } /* @@ -63,12 +70,12 @@ PHDRS */ VERSION { - LINUX_2.6 { - global: - __kernel_vsyscall; - __kernel_sigreturn; - __kernel_rt_sigreturn; + LINUX_2.6 { + global: + __kernel_vsyscall; + __kernel_sigreturn; + __kernel_rt_sigreturn; - local: *; - }; + local: *; + }; } diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 04a39aa7f1f..4729668ce5b 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -214,7 +214,7 @@ out_of_memory: } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 82b68c789a5..d5e160da64b 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -294,12 +294,6 @@ int arch_add_memory(int nid, u64 start, u64 size) } EXPORT_SYMBOL_GPL(arch_add_memory); -int remove_memory(u64 start, u64 size) -{ - return -EINVAL; -} -EXPORT_SYMBOL_GPL(remove_memory); - #ifdef CONFIG_NUMA int memory_add_physaddr_to_nid(u64 addr) { diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index df06c647746..8a2d339cf76 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -244,10 +244,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - default: ret = ptrace_request(child, request, addr, data); break; diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c index 0d069d82141..dd81c669c79 100644 --- a/arch/sh64/mm/fault.c +++ b/arch/sh64/mm/fault.c @@ -334,7 +334,7 @@ out_of_memory: } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index 50747fe4435..e4d9c8e19df 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c @@ -369,7 +369,7 @@ out_of_memory: up_read(&mm->mmap_sem); printk("VM: killing process %s\n", tsk->comm); if (from_user) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 33dabf588bd..2f22fa90461 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -240,10 +240,10 @@ config ARCH_SELECT_MEMORY_MODEL config ARCH_SPARSEMEM_ENABLE def_bool y + select SPARSEMEM_VMEMMAP_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y - select SPARSEMEM_STATIC source "mm/Kconfig" diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index c93a15b785f..d94f901d321 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -42,6 +42,8 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); +struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; + int __kprobes arch_prepare_kprobe(struct kprobe *p) { p->ainsn.insn[0] = *p->addr; diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S index d4024ac0d61..964527d2ffa 100644 --- a/arch/sparc64/kernel/ktlb.S +++ b/arch/sparc64/kernel/ktlb.S @@ -226,6 +226,15 @@ kvmap_dtlb_load: ba,pt %xcc, sun4v_dtlb_load mov %g5, %g3 +kvmap_vmemmap: + sub %g4, %g5, %g5 + srlx %g5, 22, %g5 + sethi %hi(vmemmap_table), %g1 + sllx %g5, 3, %g5 + or %g1, %lo(vmemmap_table), %g1 + ba,pt %xcc, kvmap_dtlb_load + ldx [%g1 + %g5], %g5 + kvmap_dtlb_nonlinear: /* Catch kernel NULL pointer derefs. */ sethi %hi(PAGE_SIZE), %g5 @@ -233,6 +242,13 @@ kvmap_dtlb_nonlinear: bleu,pn %xcc, kvmap_dtlb_longpath nop + /* Do not use the TSB for vmemmap. */ + mov (VMEMMAP_BASE >> 24), %g5 + sllx %g5, 24, %g5 + cmp %g4,%g5 + bgeu,pn %xcc, kvmap_vmemmap + nop + KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load) kvmap_dtlb_tsbmiss: diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index c73b7a48b03..407d74a8a54 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -52,14 +52,13 @@ int sparc64_multi_core __read_mostly; cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE; cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; -cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly = - { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; +DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE; cpumask_t cpu_core_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; EXPORT_SYMBOL(cpu_possible_map); EXPORT_SYMBOL(cpu_online_map); -EXPORT_SYMBOL(cpu_sibling_map); +EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); EXPORT_SYMBOL(cpu_core_map); static cpumask_t smp_commenced_mask; @@ -1261,16 +1260,16 @@ void __devinit smp_fill_in_sib_core_maps(void) for_each_present_cpu(i) { unsigned int j; - cpus_clear(cpu_sibling_map[i]); + cpus_clear(per_cpu(cpu_sibling_map, i)); if (cpu_data(i).proc_id == -1) { - cpu_set(i, cpu_sibling_map[i]); + cpu_set(i, per_cpu(cpu_sibling_map, i)); continue; } for_each_present_cpu(j) { if (cpu_data(i).proc_id == cpu_data(j).proc_id) - cpu_set(j, cpu_sibling_map[i]); + cpu_set(j, per_cpu(cpu_sibling_map, i)); } } } @@ -1342,9 +1341,9 @@ int __cpu_disable(void) cpu_clear(cpu, cpu_core_map[i]); cpus_clear(cpu_core_map[cpu]); - for_each_cpu_mask(i, cpu_sibling_map[cpu]) - cpu_clear(cpu, cpu_sibling_map[i]); - cpus_clear(cpu_sibling_map[cpu]); + for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) + cpu_clear(cpu, per_cpu(cpu_sibling_map, i)); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); c = &cpu_data(cpu); diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 9f7740eee8d..e2027f27c0f 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -463,7 +463,7 @@ out_of_memory: up_read(&mm->mmap_sem); printk("VM: killing process %s\n", current->comm); if (!(regs->tstate & TSTATE_PRIV)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto handle_kernel_fault; intr_or_no_mm: diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index f0ab9aab308..100c4456ed1 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1645,6 +1645,58 @@ EXPORT_SYMBOL(_PAGE_E); unsigned long _PAGE_CACHE __read_mostly; EXPORT_SYMBOL(_PAGE_CACHE); +#ifdef CONFIG_SPARSEMEM_VMEMMAP + +#define VMEMMAP_CHUNK_SHIFT 22 +#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) +#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) +#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) + +#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ + sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) +unsigned long vmemmap_table[VMEMMAP_SIZE]; + +int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) +{ + unsigned long vstart = (unsigned long) start; + unsigned long vend = (unsigned long) (start + nr); + unsigned long phys_start = (vstart - VMEMMAP_BASE); + unsigned long phys_end = (vend - VMEMMAP_BASE); + unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK; + unsigned long end = VMEMMAP_ALIGN(phys_end); + unsigned long pte_base; + + pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U | + _PAGE_CP_4U | _PAGE_CV_4U | + _PAGE_P_4U | _PAGE_W_4U); + if (tlb_type == hypervisor) + pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V | + _PAGE_CP_4V | _PAGE_CV_4V | + _PAGE_P_4V | _PAGE_W_4V); + + for (; addr < end; addr += VMEMMAP_CHUNK) { + unsigned long *vmem_pp = + vmemmap_table + (addr >> VMEMMAP_CHUNK_SHIFT); + void *block; + + if (!(*vmem_pp & _PAGE_VALID)) { + block = vmemmap_alloc_block(1UL << 22, node); + if (!block) + return -ENOMEM; + + *vmem_pp = pte_base | __pa(block); + + printk(KERN_INFO "[%p-%p] page_structs=%lu " + "node=%d entry=%lu/%lu\n", start, block, nr, + node, + addr >> VMEMMAP_CHUNK_SHIFT, + VMEMMAP_SIZE >> VMEMMAP_CHUNK_SHIFT); + } + } + return 0; +} +#endif /* CONFIG_SPARSEMEM_VMEMMAP */ + static void prot_init_common(unsigned long page_none, unsigned long page_shared, unsigned long page_copy, @@ -1909,9 +1961,4 @@ void online_page(struct page *page) num_physpages++; } -int remove_memory(u64 start, u64 size) -{ - return -EINVAL; -} - #endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/arch/um/Kconfig b/arch/um/Kconfig index e6ff3026654..740d8a922e4 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -55,6 +55,14 @@ config GENERIC_BUG default y depends on BUG +config GENERIC_TIME + bool + default y + +config GENERIC_CLOCKEVENTS + bool + default y + # Used in kernel/irq/manage.c and include/linux/irq.h config IRQ_RELEASE_METHOD bool @@ -62,63 +70,25 @@ config IRQ_RELEASE_METHOD menu "UML-specific options" -config MODE_TT - bool "Tracing thread support (DEPRECATED)" - default n - depends on BROKEN - help - This option controls whether tracing thread support is compiled - into UML. This option is largely obsolete, given that skas0 provides - skas security and performance without needing to patch the host. - It is safe to say 'N' here; saying 'Y' may cause additional problems - with the resulting binary even if you run UML in SKAS mode, and running - in TT mode is strongly *NOT RECOMMENDED*. - config STATIC_LINK bool "Force a static link" default n - depends on !MODE_TT help - If CONFIG_MODE_TT is disabled, then this option gives you the ability - to force a static link of UML. Normally, if only skas mode is built - in to UML, it will be linked as a shared binary. This is inconvenient - for use in a chroot jail. So, if you intend to run UML inside a - chroot, and you disable CONFIG_MODE_TT, you probably want to say Y - here. - Additionally, this option enables using higher memory spaces (up to - 2.75G) for UML - disabling CONFIG_MODE_TT and enabling this option leads - to best results for this. - -config KERNEL_HALF_GIGS - int "Kernel address space size (in .5G units)" - default "1" - depends on MODE_TT - help - This determines the amount of address space that UML will allocate for - its own, measured in half Gigabyte units. The default is 1. - Change this only if you need to boot UML with an unusually large amount - of physical memory. - -config MODE_SKAS - bool "Separate Kernel Address Space support" if MODE_TT - default y - help - This option controls whether skas (separate kernel address space) - support is compiled in. - Unless you have specific needs to use TT mode (which applies almost only - to developers), you should say Y here. - SKAS mode will make use of the SKAS3 patch if it is applied on the host - (and your UML will run in SKAS3 mode), but if no SKAS patch is applied - on the host it will run in SKAS0 mode, which is anyway faster than TT - mode. + This option gives you the ability to force a static link of UML. + Normally, UML is linked as a shared binary. This is inconvenient for + use in a chroot jail. So, if you intend to run UML inside a chroot, + you probably want to say Y here. + Additionally, this option enables using higher memory spaces (up to + 2.75G) for UML. source "arch/um/Kconfig.arch" source "mm/Kconfig" +source "kernel/time/Kconfig" config LD_SCRIPT_STATIC bool default y - depends on MODE_TT || STATIC_LINK + depends on STATIC_LINK config LD_SCRIPT_DYN bool @@ -128,18 +98,18 @@ config LD_SCRIPT_DYN config NET bool "Networking support" help - Unless you really know what you are doing, you should say Y here. - The reason is that some programs need kernel networking support even - when running on a stand-alone machine that isn't connected to any - other computer. If you are upgrading from an older kernel, you - should consider updating your networking tools too because changes - in the kernel and the tools often go hand in hand. The tools are - contained in the package net-tools, the location and version number - of which are given in <file:Documentation/Changes>. + Unless you really know what you are doing, you should say Y here. + The reason is that some programs need kernel networking support even + when running on a stand-alone machine that isn't connected to any + other computer. If you are upgrading from an older kernel, you + should consider updating your networking tools too because changes + in the kernel and the tools often go hand in hand. The tools are + contained in the package net-tools, the location and version number + of which are given in <file:Documentation/Changes>. - For a general introduction to Linux networking, it is highly - recommended to read the NET-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. + For a general introduction to Linux networking, it is highly + recommended to read the NET-HOWTO, available from + <http://www.tldp.org/docs.html#howto>. source "fs/Kconfig.binfmt" @@ -147,99 +117,99 @@ source "fs/Kconfig.binfmt" config HOSTFS tristate "Host filesystem" help - While the User-Mode Linux port uses its own root file system for - booting and normal file access, this module lets the UML user - access files stored on the host. It does not require any - network connection between the Host and UML. An example use of - this might be: + While the User-Mode Linux port uses its own root file system for + booting and normal file access, this module lets the UML user + access files stored on the host. It does not require any + network connection between the Host and UML. An example use of + this might be: - mount none /tmp/fromhost -t hostfs -o /tmp/umlshare + mount none /tmp/fromhost -t hostfs -o /tmp/umlshare - where /tmp/fromhost is an empty directory inside UML and - /tmp/umlshare is a directory on the host with files the UML user - wishes to access. + where /tmp/fromhost is an empty directory inside UML and + /tmp/umlshare is a directory on the host with files the UML user + wishes to access. - For more information, see - <http://user-mode-linux.sourceforge.net/hostfs.html>. + For more information, see + <http://user-mode-linux.sourceforge.net/hostfs.html>. - If you'd like to be able to work with files stored on the host, - say Y or M here; otherwise say N. + If you'd like to be able to work with files stored on the host, + say Y or M here; otherwise say N. config HPPFS tristate "HoneyPot ProcFS (EXPERIMENTAL)" depends on EXPERIMENTAL help - hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc - entries to be overridden, removed, or fabricated from the host. - Its purpose is to allow a UML to appear to be a physical machine - by removing or changing anything in /proc which gives away the - identity of a UML. + hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc + entries to be overridden, removed, or fabricated from the host. + Its purpose is to allow a UML to appear to be a physical machine + by removing or changing anything in /proc which gives away the + identity of a UML. - See <http://user-mode-linux.sf.net/hppfs.html> for more information. + See <http://user-mode-linux.sf.net/hppfs.html> for more information. - You only need this if you are setting up a UML honeypot. Otherwise, - it is safe to say 'N' here. + You only need this if you are setting up a UML honeypot. Otherwise, + it is safe to say 'N' here. config MCONSOLE bool "Management console" default y help - The user mode linux management console is a low-level interface to - the kernel, somewhat like the i386 SysRq interface. Since there is - a full-blown operating system running under every user mode linux - instance, there is much greater flexibility possible than with the - SysRq mechanism. + The user mode linux management console is a low-level interface to + the kernel, somewhat like the i386 SysRq interface. Since there is + a full-blown operating system running under every user mode linux + instance, there is much greater flexibility possible than with the + SysRq mechanism. - If you answer 'Y' to this option, to use this feature, you need the - mconsole client (called uml_mconsole) which is present in CVS in - 2.4.5-9um and later (path /tools/mconsole), and is also in the - distribution RPM package in 2.4.6 and later. + If you answer 'Y' to this option, to use this feature, you need the + mconsole client (called uml_mconsole) which is present in CVS in + 2.4.5-9um and later (path /tools/mconsole), and is also in the + distribution RPM package in 2.4.6 and later. - It is safe to say 'Y' here. + It is safe to say 'Y' here. config MAGIC_SYSRQ bool "Magic SysRq key" depends on MCONSOLE - ---help--- - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). A key for each of the - possible requests is provided. + help + If you say Y here, you will have some control over the system even + if the system crashes for example during kernel debugging (e.g., you + will be able to flush the buffer cache to disk, reboot the system + immediately or dump some status information). A key for each of the + possible requests is provided. - This is the feature normally accomplished by pressing a key - while holding SysRq (Alt+PrintScreen). + This is the feature normally accomplished by pressing a key + while holding SysRq (Alt+PrintScreen). - On UML, this is accomplished by sending a "sysrq" command with - mconsole, followed by the letter for the requested command. + On UML, this is accomplished by sending a "sysrq" command with + mconsole, followed by the letter for the requested command. - The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y - unless you really know what this hack does. + The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y + unless you really know what this hack does. config SMP bool "Symmetric multi-processing support (EXPERIMENTAL)" default n #SMP_BROKEN is for x86_64. - depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) + depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) help - This option enables UML SMP support. - It is NOT related to having a real SMP box. Not directly, at least. + This option enables UML SMP support. + It is NOT related to having a real SMP box. Not directly, at least. - UML implements virtual SMP by allowing as many processes to run - simultaneously on the host as there are virtual processors configured. + UML implements virtual SMP by allowing as many processes to run + simultaneously on the host as there are virtual processors configured. - Obviously, if the host is a uniprocessor, those processes will - timeshare, but, inside UML, will appear to be running simultaneously. - If the host is a multiprocessor, then UML processes may run - simultaneously, depending on the host scheduler. + Obviously, if the host is a uniprocessor, those processes will + timeshare, but, inside UML, will appear to be running simultaneously. + If the host is a multiprocessor, then UML processes may run + simultaneously, depending on the host scheduler. - This, however, is supported only in TT mode. So, if you use the SKAS - patch on your host, switching to TT mode and enabling SMP usually gives - you worse performances. - Also, since the support for SMP has been under-developed, there could - be some bugs being exposed by enabling SMP. + This, however, is supported only in TT mode. So, if you use the SKAS + patch on your host, switching to TT mode and enabling SMP usually + gives you worse performances. + Also, since the support for SMP has been under-developed, there could + be some bugs being exposed by enabling SMP. - If you don't know what to do, say N. + If you don't know what to do, say N. config NR_CPUS int "Maximum number of CPUs (2-32)" @@ -251,29 +221,24 @@ config NEST_LEVEL int "Nesting level" default "0" help - This is set to the number of layers of UMLs that this UML will be run - in. Normally, this is zero, meaning that it will run directly on the - host. Setting it to one will build a UML that can run inside a UML - that is running on the host. Generally, if you intend this UML to run - inside another UML, set CONFIG_NEST_LEVEL to one more than the host - UML. - - Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to - greater than one, then the guest UML should have its CONFIG_NEST_LEVEL - set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. - Only change this if you are running nested UMLs. + This is set to the number of layers of UMLs that this UML will be run + in. Normally, this is zero, meaning that it will run directly on the + host. Setting it to one will build a UML that can run inside a UML + that is running on the host. Generally, if you intend this UML to run + inside another UML, set CONFIG_NEST_LEVEL to one more than the host + UML. config HIGHMEM bool "Highmem support (EXPERIMENTAL)" depends on !64BIT && EXPERIMENTAL default n help - This was used to allow UML to run with big amounts of memory. - Currently it is unstable, so if unsure say N. + This was used to allow UML to run with big amounts of memory. + Currently it is unstable, so if unsure say N. - To use big amounts of memory, it is recommended to disable TT mode (i.e. - CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) - - this should allow the guest to use up to 2.75G of memory. + To use big amounts of memory, it is recommended enable static + linking (i.e. CONFIG_STATIC_LINK) - this should allow the + guest to use up to 2.75G of memory. config KERNEL_STACK_ORDER int "Kernel stack size order" @@ -281,20 +246,9 @@ config KERNEL_STACK_ORDER range 1 10 if 64BIT default 0 if !64BIT help - This option determines the size of UML kernel stacks. They will - be 1 << order pages. The default is OK unless you're running Valgrind - on UML, in which case, set this to 3. - -config UML_REAL_TIME_CLOCK - bool "Real-time Clock" - default y - help - This option makes UML time deltas match wall clock deltas. This should - normally be enabled. The exception would be if you are debugging with - UML and spend long times with UML stopped at a breakpoint. In this - case, when UML is restarted, it will call the timer enough times to make - up for the time spent at the breakpoint. This could result in a - noticeable lag. If this is a problem, then disable this option. + This option determines the size of UML kernel stacks. They will + be 1 << order pages. The default is OK unless you're running Valgrind + on UML, in which case, set this to 3. endmenu diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index a5b079d5e86..9a78d354f0b 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -5,7 +5,7 @@ config STDERR_CONSOLE bool "stderr console" default y help - console driver which dumps all printk messages to stderr. + console driver which dumps all printk messages to stderr. config STDIO_CONSOLE bool @@ -14,60 +14,58 @@ config STDIO_CONSOLE config SSL bool "Virtual serial line" help - The User-Mode Linux environment allows you to create virtual serial - lines on the UML that are usually made to show up on the host as - ttys or ptys. + The User-Mode Linux environment allows you to create virtual serial + lines on the UML that are usually made to show up on the host as + ttys or ptys. - See <http://user-mode-linux.sourceforge.net/input.html> for more - information and command line examples of how to use this facility. + See <http://user-mode-linux.sourceforge.net/input.html> for more + information and command line examples of how to use this facility. - Unless you have a specific reason for disabling this, say Y. + Unless you have a specific reason for disabling this, say Y. config NULL_CHAN bool "null channel support" help - This option enables support for attaching UML consoles and serial - lines to a device similar to /dev/null. Data written to it disappears - and there is never any data to be read. + This option enables support for attaching UML consoles and serial + lines to a device similar to /dev/null. Data written to it disappears + and there is never any data to be read. config PORT_CHAN bool "port channel support" help - This option enables support for attaching UML consoles and serial - lines to host portals. They may be accessed with 'telnet <host> - <port number>'. Any number of consoles and serial lines may be - attached to a single portal, although what UML device you get when - you telnet to that portal will be unpredictable. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to host portals. They may be accessed with 'telnet <host> + <port number>'. Any number of consoles and serial lines may be + attached to a single portal, although what UML device you get when + you telnet to that portal will be unpredictable. + It is safe to say 'Y' here. config PTY_CHAN bool "pty channel support" help - This option enables support for attaching UML consoles and serial - lines to host pseudo-terminals. Access to both traditional - pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled - with this option. The assignment of UML devices to host devices - will be announced in the kernel message log. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to host pseudo-terminals. Access to both traditional + pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled + with this option. The assignment of UML devices to host devices + will be announced in the kernel message log. + It is safe to say 'Y' here. config TTY_CHAN bool "tty channel support" help - This option enables support for attaching UML consoles and serial - lines to host terminals. Access to both virtual consoles - (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and - /dev/pts/*) are controlled by this option. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to host terminals. Access to both virtual consoles + (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and + /dev/pts/*) are controlled by this option. + It is safe to say 'Y' here. config XTERM_CHAN bool "xterm channel support" help - This option enables support for attaching UML consoles and serial - lines to xterms. Each UML device so assigned will be brought up in - its own xterm. - If you disable this option, then CONFIG_PT_PROXY will be disabled as - well, since UML's gdb currently requires an xterm. - It is safe to say 'Y' here. + This option enables support for attaching UML consoles and serial + lines to xterms. Each UML device so assigned will be brought up in + its own xterm. + It is safe to say 'Y' here. config NOCONFIG_CHAN bool @@ -77,39 +75,39 @@ config CON_ZERO_CHAN string "Default main console channel initialization" default "fd:0,fd:1" help - This is the string describing the channel to which the main console - will be attached by default. This value can be overridden from the - command line. The default value is "fd:0,fd:1", which attaches the - main console to stdin and stdout. - It is safe to leave this unchanged. + This is the string describing the channel to which the main console + will be attached by default. This value can be overridden from the + command line. The default value is "fd:0,fd:1", which attaches the + main console to stdin and stdout. + It is safe to leave this unchanged. config CON_CHAN string "Default console channel initialization" default "xterm" help - This is the string describing the channel to which all consoles - except the main console will be attached by default. This value can - be overridden from the command line. The default value is "xterm", - which brings them up in xterms. - It is safe to leave this unchanged, although you may wish to change - this if you expect the UML that you build to be run in environments - which don't have X or xterm available. + This is the string describing the channel to which all consoles + except the main console will be attached by default. This value can + be overridden from the command line. The default value is "xterm", + which brings them up in xterms. + It is safe to leave this unchanged, although you may wish to change + this if you expect the UML that you build to be run in environments + which don't have X or xterm available. config SSL_CHAN string "Default serial line channel initialization" default "pty" help - This is the string describing the channel to which the serial lines - will be attached by default. This value can be overridden from the - command line. The default value is "pty", which attaches them to - traditional pseudo-terminals. - It is safe to leave this unchanged, although you may wish to change - this if you expect the UML that you build to be run in environments - which don't have a set of /dev/pty* devices. + This is the string describing the channel to which the serial lines + will be attached by default. This value can be overridden from the + command line. The default value is "pty", which attaches them to + traditional pseudo-terminals. + It is safe to leave this unchanged, although you may wish to change + this if you expect the UML that you build to be run in environments + which don't have a set of /dev/pty* devices. config UNIX98_PTYS bool "Unix98 PTY support" - ---help--- + help A pseudo terminal (PTY) is a software device consisting of two halves: a master and a slave. The slave device behaves identical to a physical terminal; the master device is used by a process to @@ -132,7 +130,7 @@ config UNIX98_PTYS config LEGACY_PTYS bool "Legacy (BSD) PTY support" default y - ---help--- + help A pseudo terminal (PTY) is a software device consisting of two halves: a master and a slave. The slave device behaves identical to a physical terminal; the master device is used by a process to @@ -170,7 +168,7 @@ config LEGACY_PTY_COUNT int "Maximum number of legacy PTY in use" depends on LEGACY_PTYS default "256" - ---help--- + help The maximum number of legacy PTYs that can be used at any one time. The default is 256, and should be more than enough. Embedded systems may want to reduce this to save memory. @@ -196,10 +194,10 @@ config UML_WATCHDOG config UML_SOUND tristate "Sound support" help - This option enables UML sound support. If enabled, it will pull in - soundcore and the UML hostaudio relay, which acts as a intermediary - between the host's dsp and mixer devices and the UML sound system. - It is safe to say 'Y' here. + This option enables UML sound support. If enabled, it will pull in + soundcore and the UML hostaudio relay, which acts as a intermediary + between the host's dsp and mixer devices and the UML sound system. + It is safe to say 'Y' here. config SOUND tristate @@ -217,22 +215,21 @@ config HW_RANDOM config UML_RANDOM tristate "Hardware random number generator" help - This option enables UML's "hardware" random number generator. It - attaches itself to the host's /dev/random, supplying as much entropy - as the host has, rather than the small amount the UML gets from its - own drivers. It registers itself as a standard hardware random number - generator, major 10, minor 183, and the canonical device name is - /dev/hwrng. - The way to make use of this is to install the rng-tools package - (check your distro, or download from - http://sourceforge.net/projects/gkernel/). rngd periodically reads - /dev/hwrng and injects the entropy into /dev/random. + This option enables UML's "hardware" random number generator. It + attaches itself to the host's /dev/random, supplying as much entropy + as the host has, rather than the small amount the UML gets from its + own drivers. It registers itself as a standard hardware random number + generator, major 10, minor 183, and the canonical device name is + /dev/hwrng. + The way to make use of this is to install the rng-tools package + (check your distro, or download from + http://sourceforge.net/projects/gkernel/). rngd periodically reads + /dev/hwrng and injects the entropy into /dev/random. config MMAPPER tristate "iomem emulation driver" help - This driver allows a host file to be used as emulated IO memory inside - UML. + This driver allows a host file to be used as emulated IO memory inside + UML. endmenu - diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index c86f5eb29fd..1f6462ffd3e 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -2,50 +2,31 @@ menu "Kernel hacking" source "lib/Kconfig.debug" -config CMDLINE_ON_HOST - bool "Show command line arguments on the host in TT mode" - depends on MODE_TT - default !DEBUG_INFO - help - This controls whether arguments in guest processes should be shown on - the host's ps output. - Enabling this option hinders debugging on some recent GDB versions - (because GDB gets "confused" when we do an execvp()). So probably you - should disable it. - -config PT_PROXY - bool "Enable ptrace proxy" - depends on XTERM_CHAN && DEBUG_INFO && MODE_TT - help - This option enables a debugging interface which allows gdb to debug - the kernel without needing to actually attach to kernel threads. - If you want to do kernel debugging, say Y here; otherwise say N. - config GPROF bool "Enable gprof support" - depends on DEBUG_INFO && MODE_SKAS && !MODE_TT + depends on DEBUG_INFO help - This allows profiling of a User-Mode Linux kernel with the gprof - utility. + This allows profiling of a User-Mode Linux kernel with the gprof + utility. - See <http://user-mode-linux.sourceforge.net/gprof.html> for more - details. + See <http://user-mode-linux.sourceforge.net/gprof.html> for more + details. - If you're involved in UML kernel development and want to use gprof, - say Y. If you're unsure, say N. + If you're involved in UML kernel development and want to use gprof, + say Y. If you're unsure, say N. config GCOV bool "Enable gcov support" - depends on DEBUG_INFO && MODE_SKAS + depends on DEBUG_INFO help - This option allows developers to retrieve coverage data from a UML - session. + This option allows developers to retrieve coverage data from a UML + session. - See <http://user-mode-linux.sourceforge.net/gprof.html> for more - details. + See <http://user-mode-linux.sourceforge.net/gprof.html> for more + details. - If you're involved in UML kernel development and want to use gcov, - say Y. If you're unsure, say N. + If you're involved in UML kernel development and want to use gcov, + say Y. If you're unsure, say N. config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index d6cffb27fff..9876d80d85d 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -65,20 +65,6 @@ config 3_LEVEL_PGTABLES However, this it experimental on 32-bit architectures, so if unsure say N (on x86-64 it's automatically enabled, instead, as it's safe there). -config STUB_CODE - hex - default 0xbfffe000 if !HOST_VMSPLIT_2G - default 0x7fffe000 if HOST_VMSPLIT_2G - -config STUB_DATA - hex - default 0xbffff000 if !HOST_VMSPLIT_2G - default 0x7ffff000 if HOST_VMSPLIT_2G - -config STUB_START - hex - default STUB_CODE - config ARCH_HAS_SC_SIGNALS bool default y diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net index 14a04ebdeae..66e50026ade 100644 --- a/arch/um/Kconfig.net +++ b/arch/um/Kconfig.net @@ -108,6 +108,28 @@ config UML_NET_DAEMON more than one without conflict. If you don't need UML networking, say N. +config UML_NET_VDE + bool "VDE transport" + depends on UML_NET + help + This User-Mode Linux network transport allows one or more running + UMLs on a single host to communicate with each other and also + with the rest of the world using Virtual Distributed Ethernet, + an improved fork of uml_switch. + + You must have libvdeplug installed in order to build the vde + transport into UML. + + To use this form of networking, you will need to run vde_switch + on the host. + + For more information, see <http://wiki.virtualsquare.org/> + That site has a good overview of what VDE is and also examples + of the UML command line to use to enable VDE networking. + + If you need UML networking with VDE, + say Y. + config UML_NET_MCAST bool "Multicast transport" depends on UML_NET diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64 index f60e9e50642..d632e9a89cc 100644 --- a/arch/um/Kconfig.x86_64 +++ b/arch/um/Kconfig.x86_64 @@ -17,24 +17,12 @@ config SEMAPHORE_SLEEPERS config TOP_ADDR hex - default 0x80000000 + default 0x7fc0000000 config 3_LEVEL_PGTABLES bool default y -config STUB_CODE - hex - default 0x7fbfffe000 - -config STUB_DATA - hex - default 0x7fbffff000 - -config STUB_START - hex - default STUB_CODE - config ARCH_HAS_SC_SIGNALS bool default n diff --git a/arch/um/Makefile b/arch/um/Makefile index 0666729eb97..ab22fdeedf2 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -2,7 +2,7 @@ # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. # -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # @@ -31,18 +31,9 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h -um-modes-$(CONFIG_MODE_TT) += tt -um-modes-$(CONFIG_MODE_SKAS) += skas +MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/skas -MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ - -I$(srctree)/$(ARCH_DIR)/include/$(mode)) - -MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ - $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) - -ifneq ($(MAKEFILES-INCL),) - include $(MAKEFILES-INCL) -endif +include $(srctree)/$(ARCH_DIR)/Makefile-skas ARCH_INCLUDE := -I$(ARCH_DIR)/include ifneq ($(KBUILD_SRC),) @@ -60,7 +51,8 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ - -Din6addr_loopback=kernel_in6addr_loopback + -Din6addr_loopback=kernel_in6addr_loopback \ + -Din6addr_any=kernel_in6addr_any AFLAGS += $(ARCH_INCLUDE) @@ -88,9 +80,8 @@ CFLAGS += $(call cc-option,-fno-unit-at-a-time,) # included; the values here are meaningless CONFIG_NEST_LEVEL ?= 0 -CONFIG_KERNEL_HALF_GIGS ?= 0 -SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) +SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000) PHONY += linux @@ -123,7 +114,6 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) $(call cc-option, -fno-stack-protector,) \ $(call cc-option, -fno-stack-protector-all,) -CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT CONFIG_KERNEL_STACK_ORDER ?= 2 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) @@ -131,13 +121,10 @@ ifndef START START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] ) endif -CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \ - -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ - -DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \ - -DKERNEL_STACK_SIZE=$(STACK_SIZE) \ - -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o +CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ + -DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE) -#The wrappers will select whether using "malloc" or the kernel allocator. +# The wrappers will select whether using "malloc" or the kernel allocator. LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) @@ -150,8 +137,8 @@ define cmd_vmlinux__ FORCE ,$^) ; rm -f linux endef -#When cleaning we don't include .config, so we don't include -#TT or skas makefiles and don't clean skas_ptregs.h. +# When cleaning we don't include .config, so we don't include +# TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ $(ARCH_DIR)/include/user_constants.h \ $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 60107ed4905..ae61e3c271e 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -2,11 +2,7 @@ core-y += arch/um/sys-i386/ arch/x86/crypto/ TOP_ADDR := $(CONFIG_TOP_ADDR) -ifeq ($(CONFIG_MODE_SKAS),y) - ifneq ($(CONFIG_MODE_TT),y) - START := 0x8048000 - endif -endif +START := 0x8048000 LDFLAGS += -m elf_i386 ELF_ARCH := $(SUBARCH) diff --git a/arch/um/defconfig b/arch/um/defconfig index 1e0f677c2f4..f609edede06 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -12,9 +12,7 @@ CONFIG_IRQ_RELEASE_METHOD=y # # UML-specific options # -# CONFIG_MODE_TT is not set # CONFIG_STATIC_LINK is not set -CONFIG_MODE_SKAS=y # # Host processor type and features @@ -61,9 +59,6 @@ CONFIG_SEMAPHORE_SLEEPERS=y # CONFIG_HOST_2G_2G is not set CONFIG_TOP_ADDR=0xc0000000 # CONFIG_3_LEVEL_PGTABLES is not set -CONFIG_STUB_CODE=0xbfffe000 -CONFIG_STUB_DATA=0xbffff000 -CONFIG_STUB_START=0xbfffe000 CONFIG_ARCH_HAS_SC_SIGNALS=y CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y CONFIG_GENERIC_HWEIGHT=y @@ -75,6 +70,9 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_LD_SCRIPT_DYN=y CONFIG_NET=y CONFIG_BINFMT_ELF=y @@ -82,11 +80,10 @@ CONFIG_BINFMT_MISC=m # CONFIG_HOSTFS is not set # CONFIG_HPPFS is not set CONFIG_MCONSOLE=y -# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ=y CONFIG_NEST_LEVEL=0 # CONFIG_HIGHMEM is not set CONFIG_KERNEL_STACK_ORDER=0 -CONFIG_UML_REAL_TIME_CLOCK=y # # Code maturity level options diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index de17d4c6e02..634968150bd 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -19,10 +19,16 @@ harddog-objs := harddog_kern.o harddog_user.o LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) -targets := pcap_kern.o pcap_user.o +LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a) + +targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o) + +$(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o + $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_vde.o) + #XXX: The call below does not work because the flags are added before the # object name, so nothing from the library gets linked. #$(call if_changed,ld) @@ -37,6 +43,7 @@ obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o obj-$(CONFIG_UML_NET_DAEMON) += daemon.o +obj-$(CONFIG_UML_NET_VDE) += vde.o obj-$(CONFIG_UML_NET_MCAST) += mcast.o obj-$(CONFIG_UML_NET_PCAP) += pcap.o obj-$(CONFIG_UML_NET) += net.o @@ -54,6 +61,6 @@ obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o obj-$(CONFIG_UML_RANDOM) += random.o # pcap_user.o must be added explicitly. -USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o +USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 629b00e3b0b..db3082b4da4 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -1,28 +1,19 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include <linux/stddef.h> -#include <linux/kernel.h> -#include <linux/list.h> #include <linux/slab.h> #include <linux/tty.h> -#include <linux/string.h> #include <linux/tty_flip.h> -#include <asm/irq.h> #include "chan_kern.h" -#include "kern.h" -#include "irq_user.h" -#include "sigio.h" -#include "line.h" #include "os.h" #ifdef CONFIG_NOCONFIG_CHAN static void *not_configged_init(char *str, int device, const struct chan_opts *opts) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return NULL; } @@ -30,34 +21,34 @@ static void *not_configged_init(char *str, int device, static int not_configged_open(int input, int output, int primary, void *data, char **dev_out) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return -ENODEV; } static void not_configged_close(int fd, void *data) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); } static int not_configged_read(int fd, char *c_out, void *data) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return -EIO; } static int not_configged_write(int fd, const char *buf, int len, void *data) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return -EIO; } static int not_configged_console_write(int fd, const char *buf, int len) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return -EIO; } @@ -65,14 +56,14 @@ static int not_configged_console_write(int fd, const char *buf, int len) static int not_configged_window_size(int fd, void *data, unsigned short *rows, unsigned short *cols) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return -ENODEV; } static void not_configged_free(void *data) { - printk("Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); } @@ -89,64 +80,17 @@ static const struct chan_ops not_configged_ops = { }; #endif /* CONFIG_NOCONFIG_CHAN */ -void generic_close(int fd, void *unused) -{ - os_close_file(fd); -} - -int generic_read(int fd, char *c_out, void *unused) -{ - int n; - - n = os_read_file(fd, c_out, sizeof(*c_out)); - - if(n == -EAGAIN) - return 0; - else if(n == 0) - return -EIO; - return n; -} - -/* XXX Trivial wrapper around os_write_file */ - -int generic_write(int fd, const char *buf, int n, void *unused) -{ - return os_write_file(fd, buf, n); -} - -int generic_window_size(int fd, void *unused, unsigned short *rows_out, - unsigned short *cols_out) -{ - int rows, cols; - int ret; - - ret = os_window_size(fd, &rows, &cols); - if(ret < 0) - return ret; - - ret = ((*rows_out != rows) || (*cols_out != cols)); - - *rows_out = rows; - *cols_out = cols; - - return ret; -} - -void generic_free(void *data) -{ - kfree(data); -} - static void tty_receive_char(struct tty_struct *tty, char ch) { - if(tty == NULL) return; + if (tty == NULL) + return; - if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { - if(ch == STOP_CHAR(tty)){ + if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { + if (ch == STOP_CHAR(tty)) { stop_tty(tty); return; } - else if(ch == START_CHAR(tty)){ + else if (ch == START_CHAR(tty)) { start_tty(tty); return; } @@ -159,14 +103,14 @@ static int open_one_chan(struct chan *chan) { int fd, err; - if(chan->opened) + if (chan->opened) return 0; - if(chan->ops->open == NULL) + if (chan->ops->open == NULL) fd = 0; else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, chan->data, &chan->dev); - if(fd < 0) + if (fd < 0) return fd; err = os_set_fd_block(fd, 0); @@ -187,10 +131,10 @@ int open_chan(struct list_head *chans) struct chan *chan; int ret, err = 0; - list_for_each(ele, chans){ + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); ret = open_one_chan(chan); - if(chan->primary) + if (chan->primary) err = ret; } return err; @@ -201,9 +145,9 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) struct list_head *ele; struct chan *chan; - list_for_each(ele, chans){ + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(chan->primary && chan->output && chan->ops->winch){ + if (chan->primary && chan->output && chan->ops->winch) { register_winch(chan->fd, tty); return; } @@ -216,7 +160,7 @@ int enable_chan(struct line *line) struct chan *chan; int err; - list_for_each(ele, &line->chan_list){ + list_for_each(ele, &line->chan_list) { chan = list_entry(ele, struct chan, list); err = open_one_chan(chan); if (err) { @@ -226,7 +170,7 @@ int enable_chan(struct line *line) continue; } - if(chan->enabled) + if (chan->enabled) continue; err = line_setup_irq(chan->fd, chan->input, chan->output, line, chan); @@ -263,12 +207,12 @@ void free_irqs(void) list_splice_init(&irqs_to_free, &list); spin_unlock_irqrestore(&irqs_to_free_lock, flags); - list_for_each(ele, &list){ + list_for_each(ele, &list) { chan = list_entry(ele, struct chan, free_list); - if(chan->input) + if (chan->input) free_irq(chan->line->driver->read_irq, chan); - if(chan->output) + if (chan->output) free_irq(chan->line->driver->write_irq, chan); chan->enabled = 0; } @@ -278,22 +222,22 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) { unsigned long flags; - if(!chan->opened) + if (!chan->opened) return; - if(delay_free_irq){ + if (delay_free_irq) { spin_lock_irqsave(&irqs_to_free_lock, flags); list_add(&chan->free_list, &irqs_to_free); spin_unlock_irqrestore(&irqs_to_free_lock, flags); } else { - if(chan->input) + if (chan->input) free_irq(chan->line->driver->read_irq, chan); - if(chan->output) + if (chan->output) free_irq(chan->line->driver->write_irq, chan); chan->enabled = 0; } - if(chan->ops->close != NULL) + if (chan->ops->close != NULL) (*chan->ops->close)(chan->fd, chan->data); chan->opened = 0; @@ -322,7 +266,7 @@ void deactivate_chan(struct list_head *chans, int irq) list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(chan->enabled && chan->input) + if (chan->enabled && chan->input) deactivate_fd(chan->fd, irq); } } @@ -335,7 +279,7 @@ void reactivate_chan(struct list_head *chans, int irq) list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(chan->enabled && chan->input) + if (chan->enabled && chan->input) reactivate_fd(chan->fd, irq); } } @@ -347,10 +291,14 @@ int write_chan(struct list_head *chans, const char *buf, int len, struct chan *chan = NULL; int n, ret = 0; + if (len == 0) + return 0; + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); if (!chan->output || (chan->ops->write == NULL)) continue; + n = chan->ops->write(chan->fd, buf, len, chan->data); if (chan->primary) { ret = n; @@ -367,12 +315,14 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) struct chan *chan; int n, ret = 0; - list_for_each(ele, chans){ + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(!chan->output || (chan->ops->console_write == NULL)) + if (!chan->output || (chan->ops->console_write == NULL)) continue; + n = chan->ops->console_write(chan->fd, buf, len); - if(chan->primary) ret = n; + if (chan->primary) + ret = n; } return ret; } @@ -382,10 +332,11 @@ int console_open_chan(struct line *line, struct console *co) int err; err = open_chan(&line->chan_list); - if(err) + if (err) return err; - printk("Console initialized on /dev/%s%d\n", co->name, co->index); + printk(KERN_INFO "Console initialized on /dev/%s%d\n", co->name, + co->index); return 0; } @@ -395,10 +346,10 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, struct list_head *ele; struct chan *chan; - list_for_each(ele, chans){ + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(chan->primary){ - if(chan->ops->window_size == NULL) + if (chan->primary) { + if (chan->ops->window_size == NULL) return 0; return chan->ops->window_size(chan->fd, chan->data, rows_out, cols_out); @@ -413,10 +364,11 @@ static void free_one_chan(struct chan *chan, int delay_free_irq) close_one_chan(chan, delay_free_irq); - if(chan->ops->free != NULL) + if (chan->ops->free != NULL) (*chan->ops->free)(chan->data); - if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); + if (chan->primary && chan->output) + ignore_sigio_fd(chan->fd); kfree(chan); } @@ -425,7 +377,7 @@ static void free_chan(struct list_head *chans, int delay_free_irq) struct list_head *ele, *next; struct chan *chan; - list_for_each_safe(ele, next, chans){ + list_for_each_safe(ele, next, chans) { chan = list_entry(ele, struct chan, list); free_one_chan(chan, delay_free_irq); } @@ -436,14 +388,14 @@ static int one_chan_config_string(struct chan *chan, char *str, int size, { int n = 0; - if(chan == NULL){ + if (chan == NULL) { CONFIG_CHUNK(str, size, n, "none", 1); return n; } CONFIG_CHUNK(str, size, n, chan->ops->type, 0); - if(chan->dev == NULL){ + if (chan->dev == NULL) { CONFIG_CHUNK(str, size, n, "", 1); return n; } @@ -463,7 +415,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, str += n; size -= n; - if(in == out){ + if (in == out) { CONFIG_CHUNK(str, size, n, "", 1); return n; } @@ -483,13 +435,13 @@ int chan_config_string(struct list_head *chans, char *str, int size, struct list_head *ele; struct chan *chan, *in = NULL, *out = NULL; - list_for_each(ele, chans){ + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(!chan->primary) + if (!chan->primary) continue; - if(chan->input) + if (chan->input) in = chan; - if(chan->output) + if (chan->output) out = chan; } @@ -548,27 +500,27 @@ static struct chan *parse_chan(struct line *line, char *str, int device, ops = NULL; data = NULL; - for(i = 0; i < ARRAY_SIZE(chan_table); i++){ + for(i = 0; i < ARRAY_SIZE(chan_table); i++) { entry = &chan_table[i]; - if(!strncmp(str, entry->key, strlen(entry->key))){ + if (!strncmp(str, entry->key, strlen(entry->key))) { ops = entry->ops; str += strlen(entry->key); break; } } - if(ops == NULL){ + if (ops == NULL) { *error_out = "No match for configured backends"; return NULL; } data = (*ops->init)(str, device, opts); - if(data == NULL){ + if (data == NULL) { *error_out = "Configuration failed"; return NULL; } chan = kmalloc(sizeof(*chan), GFP_ATOMIC); - if(chan == NULL){ + if (chan == NULL) { *error_out = "Memory allocation failed"; return NULL; } @@ -594,26 +546,26 @@ int parse_chan_pair(char *str, struct line *line, int device, struct chan *new, *chan; char *in, *out; - if(!list_empty(chans)){ + if (!list_empty(chans)) { chan = list_entry(chans->next, struct chan, list); free_chan(chans, 0); INIT_LIST_HEAD(chans); } out = strchr(str, ','); - if(out != NULL){ + if (out != NULL) { in = str; *out = '\0'; out++; new = parse_chan(line, in, device, opts, error_out); - if(new == NULL) + if (new == NULL) return -1; new->input = 1; list_add(&new->list, chans); new = parse_chan(line, out, device, opts, error_out); - if(new == NULL) + if (new == NULL) return -1; list_add(&new->list, chans); @@ -621,7 +573,7 @@ int parse_chan_pair(char *str, struct line *line, int device, } else { new = parse_chan(line, str, device, opts, error_out); - if(new == NULL) + if (new == NULL) return -1; list_add(&new->list, chans); @@ -636,9 +588,9 @@ int chan_out_fd(struct list_head *chans) struct list_head *ele; struct chan *chan; - list_for_each(ele, chans){ + list_for_each(ele, chans) { chan = list_entry(ele, struct chan, list); - if(chan->primary && chan->output) + if (chan->primary && chan->output) return chan->fd; } return -1; @@ -652,23 +604,25 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task, int err; char c; - list_for_each_safe(ele, next, chans){ + list_for_each_safe(ele, next, chans) { chan = list_entry(ele, struct chan, list); - if(!chan->input || (chan->ops->read == NULL)) continue; + if (!chan->input || (chan->ops->read == NULL)) + continue; do { if (tty && !tty_buffer_request_room(tty, 1)) { schedule_delayed_work(task, 1); goto out; } err = chan->ops->read(chan->fd, &c, chan->data); - if(err > 0) + if (err > 0) tty_receive_char(tty, c); - } while(err > 0); + } while (err > 0); - if(err == 0) reactivate_fd(chan->fd, irq); - if(err == -EIO){ - if(chan->primary){ - if(tty != NULL) + if (err == 0) + reactivate_fd(chan->fd, irq); + if (err == -EIO) { + if (chan->primary) { + if (tty != NULL) tty_hangup(tty); close_chan(chans, 1); return; @@ -677,5 +631,6 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task, } } out: - if(tty) tty_flip_buffer_push(tty); + if (tty) + tty_flip_buffer_push(tty); } diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 4d438f36ea2..b88e93b3a39 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -1,51 +1,107 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) +/* + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include <unistd.h> #include <stdlib.h> +#include <unistd.h> #include <errno.h> -#include <termios.h> -#include <string.h> -#include <signal.h> #include <sched.h> -#include <sys/stat.h> +#include <signal.h> +#include <termios.h> #include <sys/ioctl.h> -#include <sys/socket.h> -#include "kern_util.h" #include "chan_user.h" -#include "user.h" #include "os.h" -#include "choose-mode.h" -#include "mode.h" +#include "um_malloc.h" +#include "user.h" + +void generic_close(int fd, void *unused) +{ + close(fd); +} + +int generic_read(int fd, char *c_out, void *unused) +{ + int n; + + n = read(fd, c_out, sizeof(*c_out)); + if (n > 0) + return n; + else if (errno == EAGAIN) + return 0; + else if (n == 0) + return -EIO; + return -errno; +} + +/* XXX Trivial wrapper around write */ + +int generic_write(int fd, const char *buf, int n, void *unused) +{ + int err; + + err = write(fd, buf, n); + if (err > 0) + return err; + else if (errno == EAGAIN) + return 0; + else if (err == 0) + return -EIO; + return -errno; +} + +int generic_window_size(int fd, void *unused, unsigned short *rows_out, + unsigned short *cols_out) +{ + struct winsize size; + int ret; + + if (ioctl(fd, TIOCGWINSZ, &size) < 0) + return -errno; + + ret = ((*rows_out != size.ws_row) || (*cols_out != size.ws_col)); + + *rows_out = size.ws_row; + *cols_out = size.ws_col; + + return ret; +} + +void generic_free(void *data) +{ + kfree(data); +} int generic_console_write(int fd, const char *buf, int n) { struct termios save, new; int err; - if(isatty(fd)){ + if (isatty(fd)) { CATCH_EINTR(err = tcgetattr(fd, &save)); if (err) goto error; new = save; - /* The terminal becomes a bit less raw, to handle \n also as + /* + * The terminal becomes a bit less raw, to handle \n also as * "Carriage Return", not only as "New Line". Otherwise, the new - * line won't start at the first column.*/ + * line won't start at the first column. + */ new.c_oflag |= OPOST; CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new)); if (err) goto error; } err = generic_write(fd, buf, n, NULL); - /* Restore raw mode, in any case; we *must* ignore any error apart - * EINTR, except for debug.*/ - if(isatty(fd)) + /* + * Restore raw mode, in any case; we *must* ignore any error apart + * EINTR, except for debug. + */ + if (isatty(fd)) CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); - return(err); + return err; error: - return(-errno); + return -errno; } /* @@ -82,62 +138,73 @@ static int winch_thread(void *arg) struct winch_data *data = arg; sigset_t sigs; int pty_fd, pipe_fd; - int count, err; + int count; char c = 1; pty_fd = data->pty_fd; pipe_fd = data->pipe_fd; - count = os_write_file(pipe_fd, &c, sizeof(c)); - if(count != sizeof(c)) - printk("winch_thread : failed to write synchronization " - "byte, err = %d\n", -count); + count = write(pipe_fd, &c, sizeof(c)); + if (count != sizeof(c)) + printk(UM_KERN_ERR "winch_thread : failed to write " + "synchronization byte, err = %d\n", -count); - /* We are not using SIG_IGN on purpose, so don't fix it as I thought to + /* + * We are not using SIG_IGN on purpose, so don't fix it as I thought to * do! If using SIG_IGN, the sigsuspend() call below would not stop on - * SIGWINCH. */ + * SIGWINCH. + */ signal(SIGWINCH, winch_handler); sigfillset(&sigs); /* Block all signals possible. */ - if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){ - printk("winch_thread : sigprocmask failed, errno = %d\n", - errno); + if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0) { + printk(UM_KERN_ERR "winch_thread : sigprocmask failed, " + "errno = %d\n", errno); exit(1); } /* In sigsuspend(), block anything else than SIGWINCH. */ sigdelset(&sigs, SIGWINCH); - if(setsid() < 0){ - printk("winch_thread : setsid failed, errno = %d\n", errno); + if (setsid() < 0) { + printk(UM_KERN_ERR "winch_thread : setsid failed, errno = %d\n", + errno); + exit(1); + } + + if (ioctl(pty_fd, TIOCSCTTY, 0) < 0) { + printk(UM_KERN_ERR "winch_thread : TIOCSCTTY failed on " + "fd %d err = %d\n", pty_fd, errno); exit(1); } - err = os_new_tty_pgrp(pty_fd, os_getpid()); - if(err < 0){ - printk("winch_thread : new_tty_pgrp failed on fd %d, " - "err = %d\n", pty_fd, -err); + if (tcsetpgrp(pty_fd, os_getpid()) < 0) { + printk(UM_KERN_ERR "winch_thread : tcsetpgrp failed on " + "fd %d err = %d\n", pty_fd, errno); exit(1); } - /* These are synchronization calls between various UML threads on the + /* + * These are synchronization calls between various UML threads on the * host - since they are not different kernel threads, we cannot use * kernel semaphores. We don't use SysV semaphores because they are - * persistent. */ - count = os_read_file(pipe_fd, &c, sizeof(c)); - if(count != sizeof(c)) - printk("winch_thread : failed to read synchronization byte, " - "err = %d\n", -count); - - while(1){ - /* This will be interrupted by SIGWINCH only, since + * persistent. + */ + count = read(pipe_fd, &c, sizeof(c)); + if (count != sizeof(c)) + printk(UM_KERN_ERR "winch_thread : failed to read " + "synchronization byte, err = %d\n", errno); + + while(1) { + /* + * This will be interrupted by SIGWINCH only, since * other signals are blocked. */ sigsuspend(&sigs); - count = os_write_file(pipe_fd, &c, sizeof(c)); - if(count != sizeof(c)) - printk("winch_thread : write failed, err = %d\n", - -count); + count = write(pipe_fd, &c, sizeof(c)); + if (count != sizeof(c)) + printk(UM_KERN_ERR "winch_thread : write failed, " + "err = %d\n", errno); } } @@ -149,44 +216,49 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, char c; err = os_pipe(fds, 1, 1); - if(err < 0){ - printk("winch_tramp : os_pipe failed, err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "winch_tramp : os_pipe failed, err = %d\n", + -err); goto out; } data = ((struct winch_data) { .pty_fd = fd, .pipe_fd = fds[1] } ); - /* CLONE_FILES so this thread doesn't hold open files which are open + /* + * CLONE_FILES so this thread doesn't hold open files which are open * now, but later closed in a different thread. This is a * problem with /dev/net/tun, which if held open by this * thread, prevents the TUN/TAP device from being reused. */ err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out); - if(err < 0){ - printk("fork of winch_thread failed - errno = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "fork of winch_thread failed - errno = %d\n", + -err); goto out_close; } *fd_out = fds[0]; - n = os_read_file(fds[0], &c, sizeof(c)); - if(n != sizeof(c)){ - printk("winch_tramp : failed to read synchronization byte\n"); - printk("read failed, err = %d\n", -n); - printk("fd %d will not support SIGWINCH\n", fd); - err = -EINVAL; + n = read(fds[0], &c, sizeof(c)); + if (n != sizeof(c)) { + printk(UM_KERN_ERR "winch_tramp : failed to read " + "synchronization byte\n"); + printk(UM_KERN_ERR "read failed, err = %d\n", errno); + printk(UM_KERN_ERR "fd %d will not support SIGWINCH\n", fd); + err = -EINVAL; goto out_close; } if (os_set_fd_block(*fd_out, 0)) { - printk("winch_tramp: failed to set thread_fd non-blocking.\n"); + printk(UM_KERN_ERR "winch_tramp: failed to set thread_fd " + "non-blocking.\n"); goto out_close; } return err; out_close: - os_close_file(fds[1]); - os_close_file(fds[0]); + close(fds[1]); + close(fds[0]); out: return err; } @@ -197,21 +269,20 @@ void register_winch(int fd, struct tty_struct *tty) int pid, thread, count, thread_fd = -1; char c = 1; - if(!isatty(fd)) + if (!isatty(fd)) return; pid = tcgetpgrp(fd); - if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) && - (pid == -1)) { + if (!is_skas_winch(pid, fd, tty) && (pid == -1)) { thread = winch_tramp(fd, tty, &thread_fd, &stack); if (thread < 0) return; register_winch_irq(thread_fd, fd, thread, tty, stack); - count = os_write_file(thread_fd, &c, sizeof(c)); - if(count != sizeof(c)) - printk("register_winch : failed to write " - "synchronization byte, err = %d\n", -count); + count = write(thread_fd, &c, sizeof(c)); + if (count != sizeof(c)) + printk(UM_KERN_ERR "register_winch : failed to write " + "synchronization byte, err = %d\n", errno); } } diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 0ec4052db9c..93f227a25ba 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c @@ -1,17 +1,18 @@ -#include <stddef.h> -#include <string.h> -#include <errno.h> -/* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines +/* + * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) + * Licensed under the GPL + */ + +/* + * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines * that. */ #include <unistd.h> #include <byteswap.h> -#include <sys/time.h> -#include <sys/param.h> -#include <sys/user.h> - -#include "os.h" - +#include <errno.h> +#include <string.h> +#include <arpa/inet.h> +#include <asm/types.h> #include "cow.h" #include "cow_sys.h" @@ -28,7 +29,8 @@ struct cow_header_v1 { __s32 sectorsize; } __attribute__((packed)); -/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in +/* + * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in * case other systems have different values for MAXPATHLEN. * * The same must hold for V2 - we want file format compatibility, not anything @@ -46,7 +48,8 @@ struct cow_header_v2 { __s32 sectorsize; } __attribute__((packed)); -/* Changes from V2 - +/* + * Changes from V2 - * PATH_LEN_V3 as described above * Explicitly specify field bit lengths for systems with different * lengths for the usual C types. Not sure whether char or @@ -70,7 +73,8 @@ struct cow_header_v2 { * Fixed (finally!) the rounding bug */ -/* Until Dec2005, __attribute__((packed)) was left out from the below +/* + * Until Dec2005, __attribute__((packed)) was left out from the below * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to * align size to 8-byte alignment. This shifted all fields above (no padding * was present on 32-bit, no other padding was added). @@ -122,7 +126,7 @@ void cow_sizes(int version, __u64 size, int sectorsize, int align, int bitmap_offset, unsigned long *bitmap_len_out, int *data_offset_out) { - if(version < 3){ + if (version < 3) { *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); *data_offset_out = bitmap_offset + *bitmap_len_out; @@ -144,46 +148,46 @@ static int absolutize(char *to, int size, char *from) char save_cwd[256], *slash; int remaining; - if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { + if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) { cow_printf("absolutize : unable to get cwd - errno = %d\n", errno); - return(-1); + return -1; } slash = strrchr(from, '/'); - if(slash != NULL){ + if (slash != NULL) { *slash = '\0'; - if(chdir(from)){ + if (chdir(from)) { *slash = '/'; cow_printf("absolutize : Can't cd to '%s' - " "errno = %d\n", from, errno); - return(-1); + return -1; } *slash = '/'; - if(getcwd(to, size) == NULL){ + if (getcwd(to, size) == NULL) { cow_printf("absolutize : unable to get cwd of '%s' - " "errno = %d\n", from, errno); - return(-1); + return -1; } remaining = size - strlen(to); - if(strlen(slash) + 1 > remaining){ + if (strlen(slash) + 1 > remaining) { cow_printf("absolutize : unable to fit '%s' into %d " "chars\n", from, size); - return(-1); + return -1; } strcat(to, slash); } else { - if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ + if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) { cow_printf("absolutize : unable to fit '%s' into %d " "chars\n", from, size); - return(-1); + return -1; } strcpy(to, save_cwd); strcat(to, "/"); strcat(to, from); } chdir(save_cwd); - return(0); + return 0; } int write_cow_header(char *cow_file, int fd, char *backing_file, @@ -194,22 +198,23 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, int err; err = cow_seek_file(fd, 0); - if(err < 0){ + if (err < 0) { cow_printf("write_cow_header - lseek failed, err = %d\n", -err); goto out; } err = -ENOMEM; header = cow_malloc(sizeof(*header)); - if(header == NULL){ - cow_printf("write_cow_header - failed to allocate COW V3 header\n"); + if (header == NULL) { + cow_printf("write_cow_header - failed to allocate COW V3 " + "header\n"); goto out; } header->magic = htonl(COW_MAGIC); header->version = htonl(COW_VERSION); err = -EINVAL; - if(strlen(backing_file) > sizeof(header->backing_file) - 1){ + if (strlen(backing_file) > sizeof(header->backing_file) - 1) { /* Below, %zd is for a size_t value */ cow_printf("Backing file name \"%s\" is too long - names are " "limited to %zd characters\n", backing_file, @@ -217,12 +222,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, goto out_free; } - if(absolutize(header->backing_file, sizeof(header->backing_file), + if (absolutize(header->backing_file, sizeof(header->backing_file), backing_file)) goto out_free; err = os_file_modtime(header->backing_file, &modtime); - if(err < 0){ + if (err < 0) { cow_printf("write_cow_header - backing file '%s' mtime " "request failed, err = %d\n", header->backing_file, -err); @@ -230,7 +235,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, } err = cow_file_size(header->backing_file, size); - if(err < 0){ + if (err < 0) { cow_printf("write_cow_header - couldn't get size of " "backing file '%s', err = %d\n", header->backing_file, -err); @@ -244,7 +249,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, header->cow_format = COW_BITMAP; err = cow_write_file(fd, header, sizeof(*header)); - if(err != sizeof(*header)){ + if (err != sizeof(*header)) { cow_printf("write_cow_header - write of header to " "new COW file '%s' failed, err = %d\n", cow_file, -err); @@ -254,14 +259,14 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, out_free: cow_free(header); out: - return(err); + return err; } int file_reader(__u64 offset, char *buf, int len, void *arg) { int fd = *((int *) arg); - return(pread(fd, buf, len, offset)); + return pread(fd, buf, len, offset); } /* XXX Need to sanity-check the values read from the header */ @@ -278,31 +283,29 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, unsigned long version, magic; header = cow_malloc(sizeof(*header)); - if(header == NULL){ + if (header == NULL) { cow_printf("read_cow_header - Failed to allocate header\n"); - return(-ENOMEM); + return -ENOMEM; } err = -EINVAL; n = (*reader)(0, (char *) header, sizeof(*header), arg); - if(n < offsetof(typeof(header->v1), backing_file)){ + if (n < offsetof(typeof(header->v1), backing_file)) { cow_printf("read_cow_header - short header\n"); goto out; } magic = header->v1.magic; - if(magic == COW_MAGIC) { + if (magic == COW_MAGIC) version = header->v1.version; - } - else if(magic == ntohl(COW_MAGIC)){ + else if (magic == ntohl(COW_MAGIC)) version = ntohl(header->v1.version); - } /* No error printed because the non-COW case comes through here */ else goto out; *version_out = version; - if(version == 1){ - if(n < sizeof(header->v1)){ + if (version == 1) { + if (n < sizeof(header->v1)) { cow_printf("read_cow_header - failed to read V1 " "header\n"); goto out; @@ -314,8 +317,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, *align_out = *sectorsize_out; file = header->v1.backing_file; } - else if(version == 2){ - if(n < sizeof(header->v2)){ + else if (version == 2) { + if (n < sizeof(header->v2)) { cow_printf("read_cow_header - failed to read V2 " "header\n"); goto out; @@ -328,8 +331,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, file = header->v2.backing_file; } /* This is very subtle - see above at union cow_header definition */ - else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){ - if(n < sizeof(header->v3)){ + else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) { + if (n < sizeof(header->v3)) { cow_printf("read_cow_header - failed to read V3 " "header\n"); goto out; @@ -345,17 +348,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); file = header->v3.backing_file; } - else if(version == 3){ + else if (version == 3) { cow_printf("read_cow_header - broken V3 file with" " 64-bit layout - recovering content.\n"); - if(n < sizeof(header->v3_b)){ + if (n < sizeof(header->v3_b)) { cow_printf("read_cow_header - failed to read V3 " "header\n"); goto out; } - /* this was used until Dec2005 - 64bits are needed to represent + /* + * this was used until Dec2005 - 64bits are needed to represent * 2038+. I.e. we can safely do this truncating cast. * * Additionally, we must use ntohl() instead of ntohll(), since @@ -381,7 +385,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, } err = -ENOMEM; *backing_file_out = cow_strdup(file); - if(*backing_file_out == NULL){ + if (*backing_file_out == NULL) { cow_printf("read_cow_header - failed to allocate backing " "file\n"); goto out; @@ -389,7 +393,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, err = 0; out: cow_free(header); - return(err); + return err; } int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, @@ -402,7 +406,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, err = write_cow_header(cow_file, fd, backing_file, sectorsize, alignment, &size); - if(err) + if (err) goto out; *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); @@ -411,17 +415,18 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, offset = *data_offset_out + size - sizeof(zero); err = cow_seek_file(fd, offset); - if(err < 0){ + if (err < 0) { cow_printf("cow bitmap lseek failed : err = %d\n", -err); goto out; } - /* does not really matter how much we write it is just to set EOF + /* + * does not really matter how much we write it is just to set EOF * this also sets the entire COW bitmap * to zero without having to allocate it */ err = cow_write_file(fd, &zero, sizeof(zero)); - if(err != sizeof(zero)){ + if (err != sizeof(zero)) { cow_printf("Write of bitmap to new COW file '%s' failed, " "err = %d\n", cow_file, -err); if (err >= 0) @@ -429,15 +434,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, goto out; } - return(0); - + return 0; out: - return(err); + return err; } - -/* - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h index 3bc3cf6b94a..6e0e891f8a0 100644 --- a/arch/um/drivers/daemon.h +++ b/arch/um/drivers/daemon.h @@ -1,8 +1,11 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ +#ifndef __DAEMON_H__ +#define __DAEMON_H__ + #include "net_user.h" #define SWITCH_VERSION 3 @@ -20,16 +23,7 @@ struct daemon_data { extern const struct net_user_info daemon_user_info; -extern int daemon_user_write(int fd, void *buf, int len, +extern int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +#endif diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index adeece11e59..d53ff52bb40 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c @@ -1,16 +1,14 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ -#include "linux/kernel.h" #include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" +#include <linux/netdevice.h> #include "net_kern.h" -#include "net_user.h" #include "daemon.h" struct daemon_init { @@ -36,25 +34,21 @@ static void daemon_init(struct net_device *dev, void *data) dpri->data_addr = NULL; dpri->local_addr = NULL; - printk("daemon backend (uml_switch version %d) - %s:%s", + printk("daemon backend (uml_switch version %d) - %s:%s", SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); printk("\n"); } -static int daemon_read(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int daemon_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if(*skb == NULL) return(-ENOMEM); - return(net_recvfrom(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + ETH_HEADER_OTHER)); + return net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); } -static int daemon_write(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int daemon_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(daemon_user_write(fd, (*skb)->data, (*skb)->len, - (struct daemon_data *) &lp->user)); + return daemon_user_write(fd, skb->data, skb->len, + (struct daemon_data *) &lp->user); } static const struct net_kern_info daemon_kern_info = { @@ -72,14 +66,14 @@ static int daemon_setup(char *str, char **mac_out, void *data) *init = ((struct daemon_init) { .sock_type = "unix", .ctl_sock = "/tmp/uml.ctl" }); - + remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, NULL); - if(remain != NULL) + if (remain != NULL) printk(KERN_WARNING "daemon_setup : Ignoring data socket " "specification\n"); - - return(1); + + return 1; } static struct transport daemon_transport = { diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 8d2008f0668..f23c109a055 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -1,24 +1,23 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ -#include <errno.h> -#include <unistd.h> #include <stdint.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> #include <sys/socket.h> -#include <sys/un.h> #include <sys/time.h> -#include "net_user.h" +#include <sys/un.h> #include "daemon.h" -#include "kern_util.h" -#include "user.h" +#include "net_user.h" #include "os.h" #include "um_malloc.h" - -#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) +#include "user.h" enum request_type { REQ_NEW_CONTROL }; @@ -36,8 +35,9 @@ static struct sockaddr_un *new_addr(void *name, int len) struct sockaddr_un *sun; sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); - if(sun == NULL){ - printk("new_addr: allocation of sockaddr_un failed\n"); + if (sun == NULL) { + printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " + "failed\n"); return NULL; } sun->sun_family = AF_UNIX; @@ -54,38 +54,39 @@ static int connect_to_switch(struct daemon_data *pri) int fd, n, err; pri->control = socket(AF_UNIX, SOCK_STREAM, 0); - if(pri->control < 0){ + if (pri->control < 0) { err = -errno; - printk("daemon_open : control socket failed, errno = %d\n", - -err); + printk(UM_KERN_ERR "daemon_open : control socket failed, " + "errno = %d\n", -err); return err; } - if(connect(pri->control, (struct sockaddr *) ctl_addr, - sizeof(*ctl_addr)) < 0){ + if (connect(pri->control, (struct sockaddr *) ctl_addr, + sizeof(*ctl_addr)) < 0) { err = -errno; - printk("daemon_open : control connect failed, errno = %d\n", - -err); + printk(UM_KERN_ERR "daemon_open : control connect failed, " + "errno = %d\n", -err); goto out; } fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if(fd < 0){ + if (fd < 0) { err = -errno; - printk("daemon_open : data socket failed, errno = %d\n", - -err); + printk(UM_KERN_ERR "daemon_open : data socket failed, " + "errno = %d\n", -err); goto out; } - if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ + if (bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0) { err = -errno; - printk("daemon_open : data bind failed, errno = %d\n", - -err); + printk(UM_KERN_ERR "daemon_open : data bind failed, " + "errno = %d\n", -err); goto out_close; } sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); - if(sun == NULL){ - printk("new_addr: allocation of sockaddr_un failed\n"); + if (sun == NULL) { + printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " + "failed\n"); err = -ENOMEM; goto out_close; } @@ -94,18 +95,18 @@ static int connect_to_switch(struct daemon_data *pri) req.version = SWITCH_VERSION; req.type = REQ_NEW_CONTROL; req.sock = *local_addr; - n = os_write_file(pri->control, &req, sizeof(req)); - if(n != sizeof(req)){ - printk("daemon_open : control setup request failed, err = %d\n", - -n); + n = write(pri->control, &req, sizeof(req)); + if (n != sizeof(req)) { + printk(UM_KERN_ERR "daemon_open : control setup request " + "failed, err = %d\n", -errno); err = -ENOTCONN; goto out_free; } - n = os_read_file(pri->control, sun, sizeof(*sun)); - if(n != sizeof(*sun)){ - printk("daemon_open : read of data socket failed, err = %d\n", - -n); + n = read(pri->control, sun, sizeof(*sun)); + if (n != sizeof(*sun)) { + printk(UM_KERN_ERR "daemon_open : read of data socket failed, " + "err = %d\n", -errno); err = -ENOTCONN; goto out_free; } @@ -116,9 +117,9 @@ static int connect_to_switch(struct daemon_data *pri) out_free: kfree(sun); out_close: - os_close_file(fd); + close(fd); out: - os_close_file(pri->control); + close(pri->control); return err; } @@ -132,8 +133,8 @@ static int daemon_user_init(void *data, void *dev) int usecs; } name; - if(!strcmp(pri->sock_type, "unix")) - pri->ctl_addr = new_addr(pri->ctl_sock, + if (!strcmp(pri->sock_type, "unix")) + pri->ctl_addr = new_addr(pri->ctl_sock, strlen(pri->ctl_sock) + 1); name.zero = 0; name.pid = os_getpid(); @@ -142,7 +143,7 @@ static int daemon_user_init(void *data, void *dev) pri->local_addr = new_addr(&name, sizeof(name)); pri->dev = dev; pri->fd = connect_to_switch(pri); - if(pri->fd < 0){ + if (pri->fd < 0) { kfree(pri->local_addr); pri->local_addr = NULL; return pri->fd; @@ -161,9 +162,9 @@ static void daemon_remove(void *data) { struct daemon_data *pri = data; - os_close_file(pri->fd); + close(pri->fd); pri->fd = -1; - os_close_file(pri->control); + close(pri->control); pri->control = -1; kfree(pri->data_addr); @@ -181,18 +182,13 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); } -static int daemon_set_mtu(int mtu, void *data) -{ - return mtu; -} - const struct net_user_info daemon_user_info = { .init = daemon_user_init, .open = daemon_open, .close = NULL, .remove = daemon_remove, - .set_mtu = daemon_set_mtu, .add_address = NULL, .delete_address = NULL, - .max_packet = MAX_PACKET - ETH_HEADER_OTHER + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, }; diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 39c01ffd45c..0a2bb5b64b8 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -1,17 +1,18 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <termios.h> #include <errno.h> -#include "user.h" +#include <termios.h> #include "chan_user.h" +#include "kern_constants.h" #include "os.h" #include "um_malloc.h" +#include "user.h" struct fd_chan { int fd; @@ -26,22 +27,26 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts) char *end; int n; - if(*str != ':'){ - printk("fd_init : channel type 'fd' must specify a file " - "descriptor\n"); - return(NULL); + if (*str != ':') { + printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a " + "file descriptor\n"); + return NULL; } str++; n = strtoul(str, &end, 0); - if((*end != '\0') || (end == str)){ - printk("fd_init : couldn't parse file descriptor '%s'\n", str); - return(NULL); + if ((*end != '\0') || (end == str)) { + printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor " + "'%s'\n", str); + return NULL; } + data = kmalloc(sizeof(*data), UM_GFP_KERNEL); - if(data == NULL) return(NULL); + if (data == NULL) + return NULL; + *data = ((struct fd_chan) { .fd = n, .raw = opts->raw }); - return(data); + return data; } static int fd_open(int input, int output, int primary, void *d, char **dev_out) @@ -49,18 +54,18 @@ static int fd_open(int input, int output, int primary, void *d, char **dev_out) struct fd_chan *data = d; int err; - if(data->raw && isatty(data->fd)){ + if (data->raw && isatty(data->fd)) { CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); - if(err) - return(err); + if (err) + return err; err = raw(data->fd); - if(err) - return(err); + if (err) + return err; } sprintf(data->str, "%d", data->fd); *dev_out = data->str; - return(data->fd); + return data->fd; } static void fd_close(int fd, void *d) @@ -68,13 +73,14 @@ static void fd_close(int fd, void *d) struct fd_chan *data = d; int err; - if(data->raw && isatty(fd)){ - CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); - if(err) - printk("Failed to restore terminal state - " - "errno = %d\n", -err); - data->raw = 0; - } + if (!data->raw || !isatty(fd)) + return; + + CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); + if (err) + printk(UM_KERN_ERR "Failed to restore terminal state - " + "errno = %d\n", -err); + data->raw = 0; } const struct chan_ops fd_ops = { @@ -89,14 +95,3 @@ const struct chan_ops fd_ops = { .free = generic_free, .winch = 1, }; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 55601687b3b..a9ad4bd6d95 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -69,7 +69,7 @@ static int harddog_open(struct inode *inode, struct file *file) spin_lock(&lock); if(timer_alive) goto err; -#ifdef CONFIG_HARDDOG_NOWAYOUT +#ifdef CONFIG_WATCHDOG_NOWAYOUT __module_get(THIS_MODULE); #endif diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index 1171790f742..b56f8e0196a 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -1,16 +1,13 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <stdio.h> #include <unistd.h> #include <errno.h> -#include "user.h" -#include "mconsole.h" #include "os.h" -#include "choose-mode.h" -#include "mode.h" +#include "user.h" struct dog_data { int stdin; @@ -25,10 +22,10 @@ static void pre_exec(void *d) dup2(data->stdin, 0); dup2(data->stdout, 1); dup2(data->stdout, 2); - os_close_file(data->stdin); - os_close_file(data->stdout); - os_close_file(data->close_me[0]); - os_close_file(data->close_me[1]); + close(data->stdin); + close(data->stdout); + close(data->close_me[0]); + close(data->close_me[1]); } int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) @@ -42,13 +39,13 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) char **args = NULL; err = os_pipe(in_fds, 1, 0); - if(err < 0){ + if (err < 0) { printk("harddog_open - os_pipe failed, err = %d\n", -err); goto out; } err = os_pipe(out_fds, 1, 0); - if(err < 0){ + if (err < 0) { printk("harddog_open - os_pipe failed, err = %d\n", -err); goto out_close_in; } @@ -58,37 +55,37 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) data.close_me[0] = out_fds[1]; data.close_me[1] = in_fds[0]; - if(sock != NULL){ + if (sock != NULL) { mconsole_args[2] = sock; args = mconsole_args; } else { /* XXX The os_getpid() is not SMP correct */ - sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); + sprintf(pid_buf, "%d", os_getpid()); args = pid_args; } pid = run_helper(pre_exec, &data, args); - os_close_file(out_fds[0]); - os_close_file(in_fds[1]); + close(out_fds[0]); + close(in_fds[1]); - if(pid < 0){ + if (pid < 0) { err = -pid; printk("harddog_open - run_helper failed, errno = %d\n", -err); goto out_close_out; } - n = os_read_file(in_fds[0], &c, sizeof(c)); - if(n == 0){ + n = read(in_fds[0], &c, sizeof(c)); + if (n == 0) { printk("harddog_open - EOF on watchdog pipe\n"); helper_wait(pid); err = -EIO; goto out_close_out; } - else if(n < 0){ + else if (n < 0) { printk("harddog_open - read of watchdog pipe failed, " - "err = %d\n", -n); + "err = %d\n", errno); helper_wait(pid); err = n; goto out_close_out; @@ -98,19 +95,19 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) return 0; out_close_in: - os_close_file(in_fds[0]); - os_close_file(in_fds[1]); + close(in_fds[0]); + close(in_fds[1]); out_close_out: - os_close_file(out_fds[0]); - os_close_file(out_fds[1]); + close(out_fds[0]); + close(out_fds[1]); out: return err; } void stop_watchdog(int in_fd, int out_fd) { - os_close_file(in_fd); - os_close_file(out_fd); + close(in_fd); + close(out_fd); } int ping_watchdog(int fd) @@ -118,10 +115,11 @@ int ping_watchdog(int fd) int n; char c = '\n'; - n = os_write_file(fd, &c, sizeof(c)); - if(n != sizeof(c)){ - printk("ping_watchdog - write failed, err = %d\n", -n); - if(n < 0) + n = write(fd, &c, sizeof(c)); + if (n != sizeof(c)) { + printk("ping_watchdog - write failed, ret = %d, err = %d\n", + n, errno); + if (n < 0) return n; return -EIO; } diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 10e08a8c17c..ff1b22b69e9 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -1,16 +1,14 @@ -/* - * Copyright (C) 2002 Steve Schmidtke +/* + * Copyright (C) 2002 Steve Schmidtke * Licensed under the GPL */ +#include "linux/fs.h" #include "linux/module.h" -#include "linux/init.h" #include "linux/slab.h" -#include "linux/fs.h" #include "linux/sound.h" #include "linux/soundcard.h" #include "asm/uaccess.h" -#include "kern_util.h" #include "init.h" #include "os.h" @@ -25,7 +23,8 @@ struct hostmixer_state { #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" -/* Changed either at boot time or module load time. At boot, this is +/* + * Changed either at boot time or module load time. At boot, this is * single-threaded; at module load, multiple modules would each have * their own copy of these variables. */ @@ -44,7 +43,7 @@ static char *mixer = HOSTAUDIO_DEV_MIXER; static int set_dsp(char *name, int *add) { dsp = name; - return(0); + return 0; } __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP); @@ -52,7 +51,7 @@ __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP); static int set_mixer(char *name, int *add) { mixer = name; - return(0); + return 0; } __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); @@ -77,23 +76,23 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer, int err; #ifdef DEBUG - printk("hostaudio: read called, count = %d\n", count); + printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); - if(kbuf == NULL) - return(-ENOMEM); + if (kbuf == NULL) + return -ENOMEM; err = os_read_file(state->fd, kbuf, count); - if(err < 0) + if (err < 0) goto out; - if(copy_to_user(buffer, kbuf, err)) + if (copy_to_user(buffer, kbuf, err)) err = -EFAULT; out: kfree(kbuf); - return(err); + return err; } static ssize_t hostaudio_write(struct file *file, const char __user *buffer, @@ -104,40 +103,40 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer, int err; #ifdef DEBUG - printk("hostaudio: write called, count = %d\n", count); + printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); - if(kbuf == NULL) - return(-ENOMEM); + if (kbuf == NULL) + return -ENOMEM; err = -EFAULT; - if(copy_from_user(kbuf, buffer, count)) + if (copy_from_user(kbuf, buffer, count)) goto out; err = os_write_file(state->fd, kbuf, count); - if(err < 0) + if (err < 0) goto out; *ppos += err; out: kfree(kbuf); - return(err); + return err; } -static unsigned int hostaudio_poll(struct file *file, +static unsigned int hostaudio_poll(struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0; #ifdef DEBUG - printk("hostaudio: poll called (unimplemented)\n"); + printk(KERN_DEBUG "hostaudio: poll called (unimplemented)\n"); #endif - return(mask); + return mask; } -static int hostaudio_ioctl(struct inode *inode, struct file *file, +static int hostaudio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hostaudio_state *state = file->private_data; @@ -145,7 +144,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, int err; #ifdef DEBUG - printk("hostaudio: ioctl called, cmd = %u\n", cmd); + printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u\n", cmd); #endif switch(cmd){ case SNDCTL_DSP_SPEED: @@ -154,8 +153,8 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_CHANNELS: case SNDCTL_DSP_SUBDIVIDE: case SNDCTL_DSP_SETFRAGMENT: - if(get_user(data, (int __user *) arg)) - return(-EFAULT); + if (get_user(data, (int __user *) arg)) + return EFAULT; break; default: break; @@ -170,14 +169,14 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_CHANNELS: case SNDCTL_DSP_SUBDIVIDE: case SNDCTL_DSP_SETFRAGMENT: - if(put_user(data, (int __user *) arg)) - return(-EFAULT); + if (put_user(data, (int __user *) arg)) + return -EFAULT; break; default: break; } - return(err); + return err; } static int hostaudio_open(struct inode *inode, struct file *file) @@ -187,24 +186,26 @@ static int hostaudio_open(struct inode *inode, struct file *file) int ret; #ifdef DEBUG - printk("hostaudio: open called (host: %s)\n", dsp); + printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); #endif state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); - if(state == NULL) - return(-ENOMEM); + if (state == NULL) + return -ENOMEM; - if(file->f_mode & FMODE_READ) r = 1; - if(file->f_mode & FMODE_WRITE) w = 1; + if (file->f_mode & FMODE_READ) + r = 1; + if (file->f_mode & FMODE_WRITE) + w = 1; ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); - if(ret < 0){ + if (ret < 0) { kfree(state); - return(ret); + return ret; } state->fd = ret; file->private_data = state; - return(0); + return 0; } static int hostaudio_release(struct inode *inode, struct file *file) @@ -212,26 +213,26 @@ static int hostaudio_release(struct inode *inode, struct file *file) struct hostaudio_state *state = file->private_data; #ifdef DEBUG - printk("hostaudio: release called\n"); + printk(KERN_DEBUG "hostaudio: release called\n"); #endif os_close_file(state->fd); kfree(state); - return(0); + return 0; } /* /dev/mixer file operations */ -static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, +static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hostmixer_state *state = file->private_data; #ifdef DEBUG - printk("hostmixer: ioctl called\n"); + printk(KERN_DEBUG "hostmixer: ioctl called\n"); #endif - return(os_ioctl_generic(state->fd, cmd, arg)); + return os_ioctl_generic(state->fd, cmd, arg); } static int hostmixer_open_mixdev(struct inode *inode, struct file *file) @@ -241,26 +242,29 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) int ret; #ifdef DEBUG - printk("hostmixer: open called (host: %s)\n", mixer); + printk(KERN_DEBUG "hostmixer: open called (host: %s)\n", mixer); #endif state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); - if(state == NULL) return(-ENOMEM); + if (state == NULL) + return -ENOMEM; - if(file->f_mode & FMODE_READ) r = 1; - if(file->f_mode & FMODE_WRITE) w = 1; + if (file->f_mode & FMODE_READ) + r = 1; + if (file->f_mode & FMODE_WRITE) + w = 1; ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); - - if(ret < 0){ - printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", - dsp, -ret); + + if (ret < 0) { + printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " + "err = %d\n", dsp, -ret); kfree(state); - return(ret); + return ret; } file->private_data = state; - return(0); + return 0; } static int hostmixer_release(struct inode *inode, struct file *file) @@ -268,13 +272,13 @@ static int hostmixer_release(struct inode *inode, struct file *file) struct hostmixer_state *state = file->private_data; #ifdef DEBUG - printk("hostmixer: release called\n"); + printk(KERN_DEBUG "hostmixer: release called\n"); #endif os_close_file(state->fd); kfree(state); - return(0); + return 0; } /* kernel module operations */ @@ -314,13 +318,13 @@ static int __init hostaudio_init_module(void) dsp, mixer); module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); - if(module_data.dev_audio < 0){ + if (module_data.dev_audio < 0) { printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); return -ENODEV; } module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); - if(module_data.dev_mixer < 0){ + if (module_data.dev_mixer < 0) { printk(KERN_ERR "hostmixer: couldn't register mixer " "device!\n"); unregister_sound_dsp(module_data.dev_audio); diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 3e0b68e297f..76fe0b0da99 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -1,22 +1,14 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/sched.h" -#include "linux/slab.h" -#include "linux/list.h" +#include "linux/irqreturn.h" #include "linux/kd.h" -#include "linux/interrupt.h" -#include "asm/uaccess.h" #include "chan_kern.h" +#include "irq_kern.h" #include "irq_user.h" -#include "line.h" -#include "kern.h" -#include "kern_util.h" #include "os.h" -#include "irq_kern.h" #define LINE_BUFSIZE 4096 @@ -35,12 +27,13 @@ static void line_timer_cb(struct work_struct *work) { struct line *line = container_of(work, struct line, task.work); - if(!line->throttled) + if (!line->throttled) chan_interrupt(&line->chan_list, &line->task, line->tty, line->driver->read_irq); } -/* Returns the free space inside the ring buffer of this line. +/* + * Returns the free space inside the ring buffer of this line. * * Should be called while holding line->lock (this does not modify datas). */ @@ -107,11 +100,12 @@ static int buffer_data(struct line *line, const char *buf, int len) { int end, room; - if(line->buffer == NULL){ + if (line->buffer == NULL) { line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); if (line->buffer == NULL) { - printk("buffer_data - atomic allocation failed\n"); - return(0); + printk(KERN_ERR "buffer_data - atomic allocation " + "failed\n"); + return 0; } line->head = line->buffer; line->tail = line->buffer; @@ -122,7 +116,7 @@ static int buffer_data(struct line *line, const char *buf, int len) end = line->buffer + LINE_BUFSIZE - line->tail; - if (len < end){ + if (len < end) { memcpy(line->tail, buf, len); line->tail += len; } @@ -162,8 +156,10 @@ static int flush_buffer(struct line *line) if (n < 0) return n; if (n == count) { - /* We have flushed from ->head to buffer end, now we - * must flush only from the beginning to ->tail.*/ + /* + * We have flushed from ->head to buffer end, now we + * must flush only from the beginning to ->tail. + */ line->head = line->buffer; } else { line->head += n; @@ -175,7 +171,7 @@ static int flush_buffer(struct line *line) n = write_chan(&line->chan_list, line->head, count, line->driver->write_irq); - if(n < 0) + if (n < 0) return n; line->head += n; @@ -189,19 +185,18 @@ void line_flush_buffer(struct tty_struct *tty) int err; /*XXX: copied from line_write, verify if it is correct!*/ - if(tty->stopped) + if (tty->stopped) return; spin_lock_irqsave(&line->lock, flags); err = flush_buffer(line); - /*if (err == 1) - err = 0;*/ spin_unlock_irqrestore(&line->lock, flags); - //return err; } -/* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer - * and ->write. Hope it's not that bad.*/ +/* + * We map both ->flush_chars and ->put_char (which go in pair) onto + * ->flush_buffer and ->write. Hope it's not that bad. + */ void line_flush_chars(struct tty_struct *tty) { line_flush_buffer(tty); @@ -216,18 +211,15 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) { struct line *line = tty->driver_data; unsigned long flags; - int n, err, ret = 0; + int n, ret = 0; - if(tty->stopped) + if (tty->stopped) return 0; spin_lock_irqsave(&line->lock, flags); - if (line->head != line->tail) { + if (line->head != line->tail) ret = buffer_data(line, buf, len); - err = flush_buffer(line); - if (err <= 0 && (err != -EAGAIN || !ret)) - ret = err; - } else { + else { n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); if (n < 0) { @@ -257,17 +249,17 @@ static const struct { } tty_ioctls[] = { /* don't print these, they flood the log ... */ { TCGETS, NULL, "TCGETS" }, - { TCSETS, NULL, "TCSETS" }, - { TCSETSW, NULL, "TCSETSW" }, - { TCFLSH, NULL, "TCFLSH" }, - { TCSBRK, NULL, "TCSBRK" }, + { TCSETS, NULL, "TCSETS" }, + { TCSETSW, NULL, "TCSETSW" }, + { TCFLSH, NULL, "TCFLSH" }, + { TCSBRK, NULL, "TCSBRK" }, /* general tty stuff */ - { TCSETSF, KERN_DEBUG, "TCSETSF" }, - { TCGETA, KERN_DEBUG, "TCGETA" }, - { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, - { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, - { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, + { TCSETSF, KERN_DEBUG, "TCSETSF" }, + { TCGETA, KERN_DEBUG, "TCGETA" }, + { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, + { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, + { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, /* linux-specific ones */ { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, @@ -324,12 +316,7 @@ int line_ioctl(struct tty_struct *tty, struct file * file, for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) if (cmd == tty_ioctls[i].cmd) break; - if (i < ARRAY_SIZE(tty_ioctls)) { - if (NULL != tty_ioctls[i].level) - printk("%s%s: %s: ioctl %s called\n", - tty_ioctls[i].level, __FUNCTION__, - tty->name, tty_ioctls[i].name); - } else { + if (i == ARRAY_SIZE(tty_ioctls)) { printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", __FUNCTION__, tty->name, cmd); } @@ -355,11 +342,12 @@ void line_unthrottle(struct tty_struct *tty) chan_interrupt(&line->chan_list, &line->task, tty, line->driver->read_irq); - /* Maybe there is enough stuff pending that calling the interrupt + /* + * Maybe there is enough stuff pending that calling the interrupt * throttles us again. In this case, line->throttled will be 1 * again and we shouldn't turn the interrupt back on. */ - if(!line->throttled) + if (!line->throttled) reactivate_chan(&line->chan_list, line->driver->read_irq); } @@ -370,27 +358,30 @@ static irqreturn_t line_write_interrupt(int irq, void *data) struct tty_struct *tty = line->tty; int err; - /* Interrupts are disabled here because we registered the interrupt with - * IRQF_DISABLED (see line_setup_irq).*/ + /* + * Interrupts are disabled here because we registered the interrupt with + * IRQF_DISABLED (see line_setup_irq). + */ spin_lock(&line->lock); err = flush_buffer(line); if (err == 0) { return IRQ_NONE; - } else if(err < 0) { + } else if (err < 0) { line->head = line->buffer; line->tail = line->buffer; } spin_unlock(&line->lock); - if(tty == NULL) + if (tty == NULL) return IRQ_NONE; if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && (tty->ldisc.write_wakeup != NULL)) (tty->ldisc.write_wakeup)(tty); - /* BLOCKING mode + /* + * BLOCKING mode * In blocking mode, everything sleeps on tty->write_wait. * Sleeping in the console driver would break non-blocking * writes. @@ -420,7 +411,8 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) return err; } -/* Normally, a driver like this can rely mostly on the tty layer +/* + * Normally, a driver like this can rely mostly on the tty layer * locking, particularly when it comes to the driver structure. * However, in this case, mconsole requests can come in "from the * side", and race with opens and closes. @@ -442,11 +434,11 @@ int line_open(struct line *lines, struct tty_struct *tty) int err = -ENODEV; spin_lock(&line->count_lock); - if(!line->valid) + if (!line->valid) goto out_unlock; err = 0; - if(tty->count > 1) + if (tty->count > 1) goto out_unlock; spin_unlock(&line->count_lock); @@ -460,7 +452,7 @@ int line_open(struct line *lines, struct tty_struct *tty) INIT_DELAYED_WORK(&line->task, line_timer_cb); - if(!line->sigio){ + if (!line->sigio) { chan_enable_winch(&line->chan_list, tty); line->sigio = 1; } @@ -481,20 +473,21 @@ void line_close(struct tty_struct *tty, struct file * filp) { struct line *line = tty->driver_data; - /* If line_open fails (and tty->driver_data is never set), + /* + * If line_open fails (and tty->driver_data is never set), * tty_open will call line_close. So just return in this case. */ - if(line == NULL) + if (line == NULL) return; /* We ignore the error anyway! */ flush_buffer(line); spin_lock(&line->count_lock); - if(!line->valid) + if (!line->valid) goto out_unlock; - if(tty->count > 1) + if (tty->count > 1) goto out_unlock; spin_unlock(&line->count_lock); @@ -502,10 +495,10 @@ void line_close(struct tty_struct *tty, struct file * filp) line->tty = NULL; tty->driver_data = NULL; - if(line->sigio){ + if (line->sigio) { unregister_winch(tty); line->sigio = 0; - } + } return; @@ -529,12 +522,12 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio, spin_lock(&line->count_lock); - if(line->tty != NULL){ + if (line->tty != NULL) { *error_out = "Device is already open"; goto out; } - if (line->init_pri <= init_prio){ + if (line->init_pri <= init_prio) { line->init_pri = init_prio; if (!strcmp(init, "none")) line->valid = 0; @@ -549,7 +542,8 @@ out: return err; } -/* Common setup code for both startup command line and mconsole initialization. +/* + * Common setup code for both startup command line and mconsole initialization. * @lines contains the array (of size @num) to modify; * @init is the setup string; * @error_out is an error string in the case of failure; @@ -561,14 +555,16 @@ int line_setup(struct line *lines, unsigned int num, char *init, int i, n, err; char *end; - if(*init == '=') { - /* We said con=/ssl= instead of con#=, so we are configuring all - * consoles at once.*/ + if (*init == '=') { + /* + * We said con=/ssl= instead of con#=, so we are configuring all + * consoles at once. + */ n = -1; } else { n = simple_strtoul(init, &end, 0); - if(*end != '='){ + if (*end != '=') { *error_out = "Couldn't parse device number"; return -EINVAL; } @@ -580,16 +576,16 @@ int line_setup(struct line *lines, unsigned int num, char *init, *error_out = "Device number out of range"; return -EINVAL; } - else if (n >= 0){ + else if (n >= 0) { err = setup_one_line(lines, n, init, INIT_ONE, error_out); - if(err) + if (err) return err; } else { - for(i = 0; i < num; i++){ + for(i = 0; i < num; i++) { err = setup_one_line(lines, i, init, INIT_ALL, error_out); - if(err) + if (err) return err; } } @@ -603,18 +599,18 @@ int line_config(struct line *lines, unsigned int num, char *str, char *new; int n; - if(*str == '='){ + if (*str == '=') { *error_out = "Can't configure all devices from mconsole"; return -EINVAL; } new = kstrdup(str, GFP_KERNEL); - if(new == NULL){ + if (new == NULL) { *error_out = "Failed to allocate memory"; return -ENOMEM; } n = line_setup(lines, num, new, error_out); - if(n < 0) + if (n < 0) return n; line = &lines[n]; @@ -629,12 +625,12 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, int dev, n = 0; dev = simple_strtoul(name, &end, 0); - if((*end != '\0') || (end == name)){ + if ((*end != '\0') || (end == name)) { *error_out = "line_get_config failed to parse device number"; return 0; } - if((dev < 0) || (dev >= num)){ + if ((dev < 0) || (dev >= num)) { *error_out = "device number out of range"; return 0; } @@ -642,9 +638,9 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, line = &lines[dev]; spin_lock(&line->count_lock); - if(!line->valid) + if (!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); - else if(line->tty == NULL) + else if (line->tty == NULL) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); spin_unlock(&line->count_lock); @@ -655,16 +651,16 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, int line_id(char **str, int *start_out, int *end_out) { char *end; - int n; + int n; n = simple_strtoul(*str, &end, 0); - if((*end != '\0') || (end == *str)) - return -1; + if ((*end != '\0') || (end == *str)) + return -1; - *str = end; - *start_out = n; - *end_out = n; - return n; + *str = end; + *start_out = n; + *end_out = n; + return n; } int line_remove(struct line *lines, unsigned int num, int n, char **error_out) @@ -674,7 +670,7 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) sprintf(config, "%d=none", n); err = line_setup(lines, num, config, error_out); - if(err >= 0) + if (err >= 0) err = 0; return err; } @@ -700,14 +696,14 @@ struct tty_driver *register_lines(struct line_driver *line_driver, tty_set_operations(driver, ops); if (tty_register_driver(driver)) { - printk("%s: can't register %s driver\n", - __FUNCTION__,line_driver->name); + printk(KERN_ERR "register_lines : can't register %s driver\n", + line_driver->name); put_tty_driver(driver); return NULL; } - for(i = 0; i < nlines; i++){ - if(!lines[i].valid) + for(i = 0; i < nlines; i++) { + if (!lines[i].valid) tty_unregister_device(driver, i); } @@ -724,20 +720,20 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) char *error; int i; - for(i = 0; i < nlines; i++){ + for(i = 0; i < nlines; i++) { line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); - if(line->init_str == NULL) + if (line->init_str == NULL) continue; line->init_str = kstrdup(line->init_str, GFP_KERNEL); - if(line->init_str == NULL) - printk("lines_init - kstrdup returned NULL\n"); + if (line->init_str == NULL) + printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); - if(parse_chan_pair(line->init_str, line, i, opts, &error)){ - printk("parse_chan_pair failed for device %d : %s\n", - i, error); + if (parse_chan_pair(line->init_str, line, i, opts, &error)) { + printk(KERN_ERR "parse_chan_pair failed for " + "device %d : %s\n", i, error); line->valid = 0; } } @@ -775,14 +771,14 @@ static irqreturn_t winch_interrupt(int irq, void *data) int err; char c; - if(winch->fd != -1){ + if (winch->fd != -1) { err = generic_read(winch->fd, &c, NULL); - if(err < 0){ - if(err != -EAGAIN){ - printk("winch_interrupt : read failed, " - "errno = %d\n", -err); - printk("fd %d is losing SIGWINCH support\n", - winch->tty_fd); + if (err < 0) { + if (err != -EAGAIN) { + printk(KERN_ERR "winch_interrupt : " + "read failed, errno = %d\n", -err); + printk(KERN_ERR "fd %d is losing SIGWINCH " + "support\n", winch->tty_fd); free_winch(winch, 0); return IRQ_HANDLED; } @@ -797,7 +793,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) kill_pgrp(tty->pgrp, SIGWINCH, 1); } out: - if(winch->fd != -1) + if (winch->fd != -1) reactivate_fd(winch->fd, WINCH_IRQ); return IRQ_HANDLED; } @@ -809,7 +805,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, winch = kmalloc(sizeof(*winch), GFP_KERNEL); if (winch == NULL) { - printk("register_winch_irq - kmalloc failed\n"); + printk(KERN_ERR "register_winch_irq - kmalloc failed\n"); goto cleanup; } @@ -823,7 +819,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "winch", winch) < 0) { - printk("register_winch_irq - failed to register IRQ\n"); + printk(KERN_ERR "register_winch_irq - failed to register " + "IRQ\n"); goto out_free; } @@ -849,13 +846,13 @@ static void unregister_winch(struct tty_struct *tty) spin_lock(&winch_handler_lock); - list_for_each(ele, &winch_handlers){ + list_for_each(ele, &winch_handlers) { winch = list_entry(ele, struct winch, list); - if(winch->tty == tty){ + if (winch->tty == tty) { free_winch(winch, 1); break; - } - } + } + } spin_unlock(&winch_handler_lock); } @@ -866,7 +863,7 @@ static void winch_cleanup(void) spin_lock(&winch_handler_lock); - list_for_each_safe(ele, next, &winch_handlers){ + list_for_each_safe(ele, next, &winch_handlers) { winch = list_entry(ele, struct winch, list); free_winch(winch, 1); } @@ -881,13 +878,13 @@ char *add_xterm_umid(char *base) int len; umid = get_umid(); - if(*umid == '\0') + if (*umid == '\0') return base; len = strlen(base) + strlen(" ()") + strlen(umid) + 1; title = kmalloc(len, GFP_KERNEL); - if(title == NULL){ - printk("Failed to allocate buffer for xterm title\n"); + if (title == NULL) { + printk(KERN_ERR "Failed to allocate buffer for xterm title\n"); return base; } diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h index bc56af9d3e5..6fa282e896b 100644 --- a/arch/um/drivers/mcast.h +++ b/arch/um/drivers/mcast.h @@ -1,8 +1,11 @@ /* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ +#ifndef __DRIVERS_MCAST_H +#define __DRIVERS_MCAST_H + #include "net_user.h" struct mcast_data { @@ -18,13 +21,4 @@ extern const struct net_user_info mcast_user_info; extern int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +#endif diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index e6b8e0dd72a..822092f149b 100644 --- a/arch/um/drivers/mcast_kern.c +++ b/arch/um/drivers/mcast_kern.c @@ -1,24 +1,20 @@ /* * user-mode-linux networking multicast transport * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * * based on the existing uml-networking code, which is - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * * Licensed under the GPL. */ -#include "linux/kernel.h" #include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" -#include "linux/in.h" -#include "linux/inet.h" -#include "net_kern.h" -#include "net_user.h" +#include <linux/netdevice.h> #include "mcast.h" +#include "net_kern.h" struct mcast_init { char *addr; @@ -39,26 +35,20 @@ static void mcast_init(struct net_device *dev, void *data) dpri->ttl = init->ttl; dpri->dev = dev; - printk("mcast backend "); - printk("multicast address: %s:%u, TTL:%u ", + printk("mcast backend multicast address: %s:%u, TTL:%u\n", dpri->addr, dpri->port, dpri->ttl); - - printk("\n"); } -static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) +static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if(*skb == NULL) return(-ENOMEM); - return(net_recvfrom(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + ETH_HEADER_OTHER)); + return net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); } -static int mcast_write(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return mcast_user_write(fd, (*skb)->data, (*skb)->len, - (struct mcast_data *) &lp->user); + return mcast_user_write(fd, skb->data, skb->len, + (struct mcast_data *) &lp->user); } static const struct net_kern_info mcast_kern_info = { @@ -81,34 +71,34 @@ int mcast_setup(char *str, char **mac_out, void *data) remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, NULL); - if(remain != NULL){ + if (remain != NULL) { printk(KERN_ERR "mcast_setup - Extra garbage on " "specification : '%s'\n", remain); - return(0); + return 0; } - - if(port_str != NULL){ + + if (port_str != NULL) { init->port = simple_strtoul(port_str, &last, 10); - if((*last != '\0') || (last == port_str)){ - printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", + if ((*last != '\0') || (last == port_str)) { + printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", port_str); - return(0); + return 0; } } - if(ttl_str != NULL){ + if (ttl_str != NULL) { init->ttl = simple_strtoul(ttl_str, &last, 10); - if((*last != '\0') || (last == ttl_str)){ - printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", + if ((*last != '\0') || (last == ttl_str)) { + printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", ttl_str); - return(0); + return 0; } } printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, init->port, init->ttl); - return(1); + return 1; } static struct transport mcast_transport = { diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 236a3dfc297..5f647d7a729 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -1,9 +1,10 @@ /* * user-mode-linux networking multicast transport + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> * * based on the existing uml-networking code, which is - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * @@ -11,28 +12,22 @@ * */ -#include <errno.h> #include <unistd.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/time.h> +#include <errno.h> #include <netinet/in.h> -#include "net_user.h" #include "mcast.h" -#include "kern_util.h" -#include "user.h" -#include "os.h" +#include "net_user.h" #include "um_malloc.h" - -#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) +#include "user.h" static struct sockaddr_in *new_addr(char *addr, unsigned short port) { struct sockaddr_in *sin; sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); - if(sin == NULL){ - printk("new_addr: allocation of sockaddr_in failed\n"); + if (sin == NULL) { + printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " + "failed\n"); return NULL; } sin->sin_family = AF_INET; @@ -71,17 +66,17 @@ static int mcast_open(void *data) fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0){ + if (fd < 0) { err = -errno; - printk("mcast_open : data socket failed, errno = %d\n", - errno); + printk(UM_KERN_ERR "mcast_open : data socket failed, " + "errno = %d\n", errno); goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { err = -errno; - printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", - errno); + printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " + "errno = %d\n", errno); goto out_close; } @@ -89,45 +84,46 @@ static int mcast_open(void *data) if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, sizeof(pri->ttl)) < 0) { err = -errno; - printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", - errno); + printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, " + "error = %d\n", errno); goto out_close; } /* set LOOP, so data does get fed back to local sockets */ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { err = -errno; - printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", - errno); + printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, " + "error = %d\n", errno); goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { err = -errno; - printk("mcast_open : data bind failed, errno = %d\n", errno); + printk(UM_KERN_ERR "mcast_open : data bind failed, " + "errno = %d\n", errno); goto out_close; } /* subscribe to the multicast group */ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, + if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { err = -errno; - printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", - errno); - printk("There appears not to be a multicast-capable network " - "interface on the host.\n"); - printk("eth0 should be configured in order to use the " - "multicast transport.\n"); + printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, " + "error = %d\n", errno); + printk(UM_KERN_ERR "There appears not to be a multicast-" + "capable network interface on the host.\n"); + printk(UM_KERN_ERR "eth0 should be configured in order to use " + "the multicast transport.\n"); goto out_close; } return fd; out_close: - os_close_file(fd); + close(fd); out: return err; } @@ -142,11 +138,11 @@ static void mcast_close(int fd, void *data) mreq.imr_interface.s_addr = 0; if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { - printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n", - errno); + printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " + "error = %d\n", errno); } - os_close_file(fd); + close(fd); } int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) @@ -156,18 +152,13 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); } -static int mcast_set_mtu(int mtu, void *data) -{ - return mtu; -} - const struct net_user_info mcast_user_info = { .init = mcast_user_init, .open = mcast_open, .close = mcast_close, .remove = mcast_remove, - .set_mtu = mcast_set_mtu, .add_address = NULL, .delete_address = NULL, - .max_packet = MAX_PACKET - ETH_HEADER_OTHER + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, }; diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d8709050740..0f3c7d14a6e 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -1,44 +1,35 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/slab.h" -#include "linux/init.h" -#include "linux/notifier.h" -#include "linux/reboot.h" -#include "linux/utsname.h" +#include "linux/console.h" #include "linux/ctype.h" #include "linux/interrupt.h" -#include "linux/sysrq.h" -#include "linux/workqueue.h" +#include "linux/list.h" +#include "linux/mm.h" #include "linux/module.h" -#include "linux/file.h" -#include "linux/fs.h" -#include "linux/namei.h" +#include "linux/notifier.h" +#include "linux/reboot.h" #include "linux/proc_fs.h" +#include "linux/slab.h" #include "linux/syscalls.h" -#include "linux/list.h" -#include "linux/mm.h" -#include "linux/console.h" -#include "asm/irq.h" +#include "linux/utsname.h" +#include "linux/workqueue.h" #include "asm/uaccess.h" +#include "init.h" +#include "irq_kern.h" +#include "irq_user.h" #include "kern_util.h" -#include "kern.h" #include "mconsole.h" #include "mconsole_kern.h" -#include "irq_user.h" -#include "init.h" #include "os.h" -#include "irq_kern.h" -#include "choose-mode.h" static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) { - return(mconsole_unlink_socket()); + return mconsole_unlink_socket(); } @@ -59,10 +50,9 @@ static void mc_work_proc(struct work_struct *unused) struct mconsole_entry *req; unsigned long flags; - while(!list_empty(&mc_requests)){ + while (!list_empty(&mc_requests)) { local_irq_save(flags); - req = list_entry(mc_requests.next, struct mconsole_entry, - list); + req = list_entry(mc_requests.next, struct mconsole_entry, list); list_del(&req->list); local_irq_restore(flags); req->request.cmd->handler(&req->request); @@ -80,12 +70,12 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) static struct mc_request req; /* that's OK */ fd = (long) dev_id; - while (mconsole_get_request(fd, &req)){ - if(req.cmd->context == MCONSOLE_INTR) + while (mconsole_get_request(fd, &req)) { + if (req.cmd->context == MCONSOLE_INTR) (*req.cmd->handler)(&req); else { new = kmalloc(sizeof(*new), GFP_NOWAIT); - if(new == NULL) + if (new == NULL) mconsole_reply(&req, "Out of memory", 1, 0); else { new->request = req; @@ -94,10 +84,10 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) } } } - if(!list_empty(&mc_requests)) + if (!list_empty(&mc_requests)) schedule_work(&mconsole_work); reactivate_fd(fd, MCONSOLE_IRQ); - return(IRQ_HANDLED); + return IRQ_HANDLED; } void mconsole_version(struct mc_request *req) @@ -105,8 +95,8 @@ void mconsole_version(struct mc_request *req) char version[256]; sprintf(version, "%s %s %s %s %s", utsname()->sysname, - utsname()->nodename, utsname()->release, - utsname()->version, utsname()->machine); + utsname()->nodename, utsname()->release, utsname()->version, + utsname()->machine); mconsole_reply(req, version, 0, 0); } @@ -118,7 +108,7 @@ void mconsole_log(struct mc_request *req) ptr += strlen("log "); len = req->len - (ptr - req->request.data); - printk("%.*s", len, ptr); + printk(KERN_WARNING "%.*s", len, ptr); mconsole_reply(req, "", 0, 0); } @@ -137,17 +127,17 @@ void mconsole_proc(struct mc_request *req) char *ptr = req->request.data, *buf; ptr += strlen("proc"); - while(isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; proc = get_fs_type("proc"); - if(proc == NULL){ + if (proc == NULL) { mconsole_reply(req, "procfs not registered", 1, 0); goto out; } super = (*proc->get_sb)(proc, 0, NULL, NULL); put_filesystem(proc); - if(super == NULL){ + if (super == NULL) { mconsole_reply(req, "Failed to get procfs superblock", 1, 0); goto out; } @@ -162,29 +152,29 @@ void mconsole_proc(struct mc_request *req) * if commenting out these two calls + the below read cycle. To * make UML crash again, it was enough to readd either one.*/ err = link_path_walk(ptr, &nd); - if(err){ + if (err) { mconsole_reply(req, "Failed to look up file", 1, 0); goto out_kill; } file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); - if(IS_ERR(file)){ + if (IS_ERR(file)) { mconsole_reply(req, "Failed to open file", 1, 0); goto out_kill; } /*END*/ buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if(buf == NULL){ + if (buf == NULL) { mconsole_reply(req, "Failed to allocate buffer", 1, 0); goto out_fput; } - if((file->f_op != NULL) && (file->f_op->read != NULL)){ + if ((file->f_op != NULL) && (file->f_op->read != NULL)) { do { n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, &file->f_pos); - if(n >= 0){ + if (n >= 0) { buf[n] = '\0'; mconsole_reply(req, buf, 0, (n > 0)); } @@ -193,7 +183,7 @@ void mconsole_proc(struct mc_request *req) 1, 0); goto out_free; } - } while(n > 0); + } while (n > 0); } else mconsole_reply(req, "", 0, 0); @@ -217,18 +207,19 @@ void mconsole_proc(struct mc_request *req) char *ptr = req->request.data; ptr += strlen("proc"); - while(isspace(*ptr)) ptr++; + while (isspace(*ptr)) + ptr++; snprintf(path, sizeof(path), "/proc/%s", ptr); fd = sys_open(path, 0, 0); if (fd < 0) { mconsole_reply(req, "Failed to open file", 1, 0); - printk("open %s: %d\n",path,fd); + printk(KERN_ERR "open %s: %d\n",path,fd); goto out; } buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if(buf == NULL){ + if (buf == NULL) { mconsole_reply(req, "Failed to allocate buffer", 1, 0); goto out_close; } @@ -239,7 +230,7 @@ void mconsole_proc(struct mc_request *req) mconsole_reply(req, "Read of file failed", 1, 0); goto out_free; } - /*Begin the file content on his own line.*/ + /* Begin the file content on his own line. */ if (first_chunk) { mconsole_reply(req, "\n", 0, 1); first_chunk = 0; @@ -351,12 +342,12 @@ static struct mc_device *mconsole_find_dev(char *name) struct list_head *ele; struct mc_device *dev; - list_for_each(ele, &mconsole_devices){ + list_for_each(ele, &mconsole_devices) { dev = list_entry(ele, struct mc_device, list); - if(!strncmp(name, dev->name, strlen(dev->name))) - return(dev); + if (!strncmp(name, dev->name, strlen(dev->name))) + return dev; } - return(NULL); + return NULL; } #define UNPLUGGED_PER_PAGE \ @@ -378,15 +369,15 @@ static int mem_config(char *str, char **error_out) int err = -EINVAL, i, add; char *ret; - if(str[0] != '='){ + if (str[0] != '=') { *error_out = "Expected '=' after 'mem'"; goto out; } str++; - if(str[0] == '-') + if (str[0] == '-') add = 0; - else if(str[0] == '+'){ + else if (str[0] == '+') { add = 1; } else { @@ -396,7 +387,7 @@ static int mem_config(char *str, char **error_out) str++; diff = memparse(str, &ret); - if(*ret != '\0'){ + if (*ret != '\0') { *error_out = "Failed to parse memory increment"; goto out; } @@ -404,17 +395,17 @@ static int mem_config(char *str, char **error_out) diff /= PAGE_SIZE; down(&plug_mem_mutex); - for(i = 0; i < diff; i++){ + for (i = 0; i < diff; i++) { struct unplugged_pages *unplugged; void *addr; - if(add){ - if(list_empty(&unplugged_pages)) + if (add) { + if (list_empty(&unplugged_pages)) break; unplugged = list_entry(unplugged_pages.next, struct unplugged_pages, list); - if(unplug_index > 0) + if (unplug_index > 0) addr = unplugged->pages[--unplug_index]; else { list_del(&unplugged->list); @@ -429,11 +420,11 @@ static int mem_config(char *str, char **error_out) struct page *page; page = alloc_page(GFP_ATOMIC); - if(page == NULL) + if (page == NULL) break; unplugged = page_address(page); - if(unplug_index == UNPLUGGED_PER_PAGE){ + if (unplug_index == UNPLUGGED_PER_PAGE) { list_add(&unplugged->list, &unplugged_pages); unplug_index = 0; } @@ -445,9 +436,9 @@ static int mem_config(char *str, char **error_out) struct unplugged_pages, list); err = os_drop_memory(addr, PAGE_SIZE); - if(err){ - printk("Failed to release memory - " - "errno = %d\n", err); + if (err) { + printk(KERN_ERR "Failed to release " + "memory - errno = %d\n", err); *error_out = "Failed to release memory"; goto out_unlock; } @@ -501,10 +492,10 @@ static struct mc_device mem_mc = { static int __init mem_mc_init(void) { - if(can_drop_memory()) + if (can_drop_memory()) mconsole_register_dev(&mem_mc); - else printk("Can't release memory to the host - memory hotplug won't " - "be supported\n"); + else printk(KERN_ERR "Can't release memory to the host - memory " + "hotplug won't be supported\n"); return 0; } @@ -519,7 +510,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, char default_buf[CONFIG_BUF_SIZE], *error, *buf; int n, size; - if(get_config == NULL){ + if (get_config == NULL) { mconsole_reply(req, "No get_config routine defined", 1, 0); return; } @@ -528,30 +519,30 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, size = ARRAY_SIZE(default_buf); buf = default_buf; - while(1){ + while (1) { n = (*get_config)(name, buf, size, &error); - if(error != NULL){ + if (error != NULL) { mconsole_reply(req, error, 1, 0); goto out; } - if(n <= size){ + if (n <= size) { mconsole_reply(req, buf, 0, 0); goto out; } - if(buf != default_buf) + if (buf != default_buf) kfree(buf); size = n; buf = kmalloc(size, GFP_KERNEL); - if(buf == NULL){ + if (buf == NULL) { mconsole_reply(req, "Failed to allocate buffer", 1, 0); return; } } out: - if(buf != default_buf) + if (buf != default_buf) kfree(buf); } @@ -562,19 +553,20 @@ void mconsole_config(struct mc_request *req) int err; ptr += strlen("config"); - while(isspace(*ptr)) ptr++; + while (isspace(*ptr)) + ptr++; dev = mconsole_find_dev(ptr); - if(dev == NULL){ + if (dev == NULL) { mconsole_reply(req, "Bad configuration option", 1, 0); return; } name = &ptr[strlen(dev->name)]; ptr = name; - while((*ptr != '=') && (*ptr != '\0')) + while ((*ptr != '=') && (*ptr != '\0')) ptr++; - if(*ptr == '='){ + if (*ptr == '=') { err = (*dev->config)(name, &error_string); mconsole_reply(req, error_string, err, 0); } @@ -589,9 +581,9 @@ void mconsole_remove(struct mc_request *req) int err, start, end, n; ptr += strlen("remove"); - while(isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; dev = mconsole_find_dev(ptr); - if(dev == NULL){ + if (dev == NULL) { mconsole_reply(req, "Bad remove option", 1, 0); return; } @@ -600,11 +592,11 @@ void mconsole_remove(struct mc_request *req) err = 1; n = (*dev->id)(&ptr, &start, &end); - if(n < 0){ + if (n < 0) { err_msg = "Couldn't parse device number"; goto out; } - else if((n < start) || (n > end)){ + else if ((n < start) || (n > end)) { sprintf(error, "Invalid device number - must be between " "%d and %d", start, end); err_msg = error; @@ -613,16 +605,16 @@ void mconsole_remove(struct mc_request *req) err_msg = NULL; err = (*dev->remove)(n, &err_msg); - switch(err){ + switch(err) { case 0: err_msg = ""; break; case -ENODEV: - if(err_msg == NULL) + if (err_msg == NULL) err_msg = "Device doesn't exist"; break; case -EBUSY: - if(err_msg == NULL) + if (err_msg == NULL) err_msg = "Device is currently open"; break; default: @@ -640,35 +632,28 @@ struct mconsole_output { static DEFINE_SPINLOCK(client_lock); static LIST_HEAD(clients); static char console_buf[MCONSOLE_MAX_DATA]; -static int console_index = 0; static void console_write(struct console *console, const char *string, - unsigned len) + unsigned int len) { struct list_head *ele; int n; - if(list_empty(&clients)) + if (list_empty(&clients)) return; - while(1){ - n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index); - strncpy(&console_buf[console_index], string, n); - console_index += n; + while (len > 0) { + n = min((size_t) len, ARRAY_SIZE(console_buf)); + strncpy(console_buf, string, n); string += n; len -= n; - if(len == 0) - return; - list_for_each(ele, &clients){ + list_for_each(ele, &clients) { struct mconsole_output *entry; entry = list_entry(ele, struct mconsole_output, list); - mconsole_reply_len(entry->req, console_buf, - console_index, 0, 1); + mconsole_reply_len(entry->req, console_buf, n, 0, 1); } - - console_index = 0; } } @@ -698,8 +683,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *), (*proc)(arg); - mconsole_reply_len(req, console_buf, console_index, 0, 0); - console_index = 0; + mconsole_reply_len(req, "", 0, 0, 0); spin_lock_irqsave(&client_lock, flags); list_del(&entry.list); @@ -707,6 +691,9 @@ static void with_console(struct mc_request *req, void (*proc)(void *), } #ifdef CONFIG_MAGIC_SYSRQ + +#include <linux/sysrq.h> + static void sysrq_proc(void *arg) { char *op = arg; @@ -718,12 +705,13 @@ void mconsole_sysrq(struct mc_request *req) char *ptr = req->request.data; ptr += strlen("sysrq"); - while(isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; - /* With 'b', the system will shut down without a chance to reply, + /* + * With 'b', the system will shut down without a chance to reply, * so in this case, we reply first. */ - if(*ptr == 'b') + if (*ptr == 'b') mconsole_reply(req, "", 0, 0); with_console(req, sysrq_proc, ptr); @@ -735,8 +723,6 @@ void mconsole_sysrq(struct mc_request *req) } #endif -#ifdef CONFIG_MODE_SKAS - static void stack_proc(void *arg) { struct task_struct *from = current, *to = arg; @@ -745,29 +731,34 @@ static void stack_proc(void *arg) switch_to(from, to, from); } -/* Mconsole stack trace +/* + * Mconsole stack trace * Added by Allan Graves, Jeff Dike * Dumps a stacks registers to the linux console. * Usage stack <pid>. */ -static void do_stack_trace(struct mc_request *req) +void mconsole_stack(struct mc_request *req) { char *ptr = req->request.data; int pid_requested= -1; struct task_struct *from = NULL; struct task_struct *to = NULL; - /* Would be nice: + /* + * Would be nice: * 1) Send showregs output to mconsole. * 2) Add a way to stack dump all pids. */ ptr += strlen("stack"); - while(isspace(*ptr)) ptr++; + while (isspace(*ptr)) + ptr++; - /* Should really check for multiple pids or reject bad args here */ + /* + * Should really check for multiple pids or reject bad args here + */ /* What do the arguments in mconsole_reply mean? */ - if(sscanf(ptr, "%d", &pid_requested) == 0){ + if (sscanf(ptr, "%d", &pid_requested) == 0) { mconsole_reply(req, "Please specify a pid", 1, 0); return; } @@ -775,25 +766,15 @@ static void do_stack_trace(struct mc_request *req) from = current; to = find_task_by_pid(pid_requested); - if((to == NULL) || (pid_requested == 0)) { + if ((to == NULL) || (pid_requested == 0)) { mconsole_reply(req, "Couldn't find that pid", 1, 0); return; } with_console(req, stack_proc, to); } -#endif /* CONFIG_MODE_SKAS */ -void mconsole_stack(struct mc_request *req) -{ - /* This command doesn't work in TT mode, so let's check and then - * get out of here - */ - CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", - 1, 0), - do_stack_trace(req)); -} - -/* Changed by mconsole_setup, which is __setup, and called before SMP is +/* + * Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ static char *notify_socket = NULL; @@ -805,13 +786,14 @@ static int __init mconsole_init(void) int err; char file[256]; - if(umid_file_name("mconsole", file, sizeof(file))) return(-1); + if (umid_file_name("mconsole", file, sizeof(file))) + return -1; snprintf(mconsole_socket_name, sizeof(file), "%s", file); sock = os_create_unix_socket(file, sizeof(file), 1); - if (sock < 0){ - printk("Failed to initialize management console\n"); - return(1); + if (sock < 0) { + printk(KERN_ERR "Failed to initialize management console\n"); + return 1; } register_reboot_notifier(&reboot_notifier); @@ -819,14 +801,14 @@ static int __init mconsole_init(void) err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "mconsole", (void *)sock); - if (err){ - printk("Failed to get IRQ for management console\n"); - return(1); + if (err) { + printk(KERN_ERR "Failed to get IRQ for management console\n"); + return 1; } - if(notify_socket != NULL){ + if (notify_socket != NULL) { notify_socket = kstrdup(notify_socket, GFP_KERNEL); - if(notify_socket != NULL) + if (notify_socket != NULL) mconsole_notify(notify_socket, MCONSOLE_SOCKET, mconsole_socket_name, strlen(mconsole_socket_name) + 1); @@ -834,9 +816,9 @@ static int __init mconsole_init(void) "string\n"); } - printk("mconsole (version %d) initialized on %s\n", + printk(KERN_INFO "mconsole (version %d) initialized on %s\n", MCONSOLE_VERSION, mconsole_socket_name); - return(0); + return 0; } __initcall(mconsole_init); @@ -847,10 +829,10 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, char *buf; buf = kmalloc(count + 1, GFP_KERNEL); - if(buf == NULL) - return(-ENOMEM); + if (buf == NULL) + return -ENOMEM; - if(copy_from_user(buf, buffer, count)){ + if (copy_from_user(buf, buffer, count)) { count = -EFAULT; goto out; } @@ -860,24 +842,26 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); out: kfree(buf); - return(count); + return count; } static int create_proc_mconsole(void) { struct proc_dir_entry *ent; - if(notify_socket == NULL) return(0); + if (notify_socket == NULL) + return 0; ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); - if(ent == NULL){ - printk(KERN_INFO "create_proc_mconsole : create_proc_entry failed\n"); - return(0); + if (ent == NULL) { + printk(KERN_INFO "create_proc_mconsole : create_proc_entry " + "failed\n"); + return 0; } ent->read_proc = NULL; ent->write_proc = write_proc_mconsole; - return(0); + return 0; } static DEFINE_SPINLOCK(notify_spinlock); @@ -894,19 +878,19 @@ void unlock_notify(void) __initcall(create_proc_mconsole); -#define NOTIFY "=notify:" +#define NOTIFY "notify:" static int mconsole_setup(char *str) { - if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ + if (!strncmp(str, NOTIFY, strlen(NOTIFY))) { str += strlen(NOTIFY); notify_socket = str; } else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); - return(1); + return 1; } -__setup("mconsole", mconsole_setup); +__setup("mconsole=", mconsole_setup); __uml_help(mconsole_setup, "mconsole=notify:<socket>\n" @@ -921,11 +905,12 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1, { char *message = ptr; - if(notify_socket == NULL) return(0); + if (notify_socket == NULL) + return 0; mconsole_notify(notify_socket, MCONSOLE_PANIC, message, strlen(message) + 1); - return(0); + return 0; } static struct notifier_block panic_exit_notifier = { @@ -938,14 +923,14 @@ static int add_notifier(void) { atomic_notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); - return(0); + return 0; } __initcall(add_notifier); char *mconsole_notify_socket(void) { - return(notify_socket); + return notify_socket; } EXPORT_SYMBOL(mconsole_notify_socket); diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index f31e71546e5..430c024a19b 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -1,25 +1,22 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdio.h> -#include <stdlib.h> #include <errno.h> -#include <signal.h> +#include <string.h> +#include <unistd.h> #include <sys/socket.h> -#include <sys/types.h> #include <sys/uio.h> #include <sys/un.h> -#include <unistd.h> -#include "user.h" -#include "sysdep/ptrace.h" +#include "kern_constants.h" #include "mconsole.h" -#include "os.h" +#include "user.h" static struct mconsole_command commands[] = { - /* With uts namespaces, uts information becomes process-specific, so + /* + * With uts namespaces, uts information becomes process-specific, so * we need a process context. If we try handling this in interrupt * context, we may hit an exiting process without a valid uts * namespace. @@ -36,7 +33,7 @@ static struct mconsole_command commands[] = { { "go", mconsole_go, MCONSOLE_INTR }, { "log", mconsole_log, MCONSOLE_INTR }, { "proc", mconsole_proc, MCONSOLE_PROC }, - { "stack", mconsole_stack, MCONSOLE_INTR }, + { "stack", mconsole_stack, MCONSOLE_INTR }, }; /* Initialized in mconsole_init, which is an initcall */ @@ -44,21 +41,21 @@ char mconsole_socket_name[256]; int mconsole_reply_v0(struct mc_request *req, char *reply) { - struct iovec iov; - struct msghdr msg; + struct iovec iov; + struct msghdr msg; - iov.iov_base = reply; - iov.iov_len = strlen(reply); + iov.iov_base = reply; + iov.iov_len = strlen(reply); - msg.msg_name = &(req->origin); - msg.msg_namelen = req->originlen; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; + msg.msg_name = &(req->origin); + msg.msg_namelen = req->originlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; - return sendmsg(req->originating_fd, &msg, 0); + return sendmsg(req->originating_fd, &msg, 0); } static struct mconsole_command *mconsole_parse(struct mc_request *req) @@ -66,10 +63,10 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req) struct mconsole_command *cmd; int i; - for(i = 0; i < ARRAY_SIZE(commands); i++){ + for (i = 0; i < ARRAY_SIZE(commands); i++) { cmd = &commands[i]; - if(!strncmp(req->request.data, cmd->command, - strlen(cmd->command))){ + if (!strncmp(req->request.data, cmd->command, + strlen(cmd->command))) { return cmd; } } @@ -94,9 +91,9 @@ int mconsole_get_request(int fd, struct mc_request *req) req->originating_fd = fd; - if(req->request.magic != MCONSOLE_MAGIC){ + if (req->request.magic != MCONSOLE_MAGIC) { /* Unversioned request */ - len = MIN(sizeof(req->request.data) - 1, + len = MIN(sizeof(req->request.data) - 1, strlen((char *) &req->request)); memmove(req->request.data, &req->request, len); req->request.data[len] = '\0'; @@ -107,32 +104,33 @@ int mconsole_get_request(int fd, struct mc_request *req) mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " "not supported by this driver"); - return(0); + return 0; } - if(req->request.len >= MCONSOLE_MAX_DATA){ + if (req->request.len >= MCONSOLE_MAX_DATA) { mconsole_reply(req, "Request too large", 1, 0); - return(0); + return 0; } - if(req->request.version != MCONSOLE_VERSION){ - mconsole_reply(req, "This driver only supports version " - STRING(MCONSOLE_VERSION) " clients", 1, 0); + if (req->request.version != MCONSOLE_VERSION) { + mconsole_reply(req, "This driver only supports version " + STRING(MCONSOLE_VERSION) " clients", 1, 0); } - + req->request.data[req->request.len] = '\0'; req->cmd = mconsole_parse(req); - if(req->cmd == NULL){ + if (req->cmd == NULL) { mconsole_reply(req, "Unknown command", 1, 0); - return(0); + return 0; } - return(1); + return 1; } int mconsole_reply_len(struct mc_request *req, const char *str, int total, int err, int more) { - /* XXX This is a stack consumption problem. It'd be nice to + /* + * XXX This is a stack consumption problem. It'd be nice to * make it global and serialize access to it, but there are a * ton of callers to this function. */ @@ -147,7 +145,7 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, len = MIN(total, MCONSOLE_MAX_DATA - 1); - if(len == total) reply.more = more; + if (len == total) reply.more = more; else reply.more = 1; memcpy(reply.data, str, len); @@ -161,9 +159,10 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, n = sendto(req->originating_fd, &reply, len, 0, (struct sockaddr *) req->origin, req->originlen); - if(n < 0) return(-errno); - } while(total > 0); - return(0); + if (n < 0) + return -errno; + } while (total > 0); + return 0; } int mconsole_reply(struct mc_request *req, const char *str, int err, int more) @@ -187,18 +186,18 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) int n, err = 0; lock_notify(); - if(notify_sock < 0){ + if (notify_sock < 0) { notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if(notify_sock < 0){ + if (notify_sock < 0) { err = -errno; - printk("mconsole_notify - socket failed, errno = %d\n", - err); + printk(UM_KERN_ERR "mconsole_notify - socket failed, " + "errno = %d\n", errno); } } unlock_notify(); - - if(err) - return(err); + + if (err) + return err; target.sun_family = AF_UNIX; strcpy(target.sun_path, sock_name); @@ -212,22 +211,12 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) err = 0; len = sizeof(packet) + packet.len - sizeof(packet.data); - n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, + n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, sizeof(target)); - if(n < 0){ + if (n < 0) { err = -errno; - printk("mconsole_notify - sendto failed, errno = %d\n", errno); + printk(UM_KERN_ERR "mconsole_notify - sendto failed, " + "errno = %d\n", errno); } - return(err); + return err; } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 867666a0233..67b2f55a602 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -9,27 +9,29 @@ * */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mm.h> +#include <linux/stddef.h> +#include <linux/types.h> #include <linux/fs.h> +#include <linux/init.h> #include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mm.h> #include <asm/uaccess.h> #include "mem_user.h" - + /* These are set in mmapper_init, which is called at boot time */ static unsigned long mmapper_size; -static unsigned long p_buf = 0; -static char *v_buf = NULL; +static unsigned long p_buf; +static char *v_buf; -static ssize_t -mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +static ssize_t mmapper_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) { return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size); } -static ssize_t -mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +static ssize_t mmapper_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { if (*ppos > mmapper_size) return -EINVAL; @@ -39,48 +41,46 @@ mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *p if (copy_from_user(&v_buf[*ppos], buf, count)) return -EFAULT; - + return count; } -static int -mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int mmapper_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { - return(-ENOIOCTLCMD); + return -ENOIOCTLCMD; } -static int -mmapper_mmap(struct file *file, struct vm_area_struct * vma) +static int mmapper_mmap(struct file *file, struct vm_area_struct *vma) { int ret = -EINVAL; int size; if (vma->vm_pgoff != 0) goto out; - + size = vma->vm_end - vma->vm_start; - if(size > mmapper_size) return(-EFAULT); + if (size > mmapper_size) + return -EFAULT; - /* XXX A comment above remap_pfn_range says it should only be + /* + * XXX A comment above remap_pfn_range says it should only be * called when the mm semaphore is held */ if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size, - vma->vm_page_prot)) + vma->vm_page_prot)) goto out; ret = 0; out: return ret; } -static int -mmapper_open(struct inode *inode, struct file *file) +static int mmapper_open(struct inode *inode, struct file *file) { return 0; } -static int -mmapper_release(struct inode *inode, struct file *file) +static int mmapper_release(struct inode *inode, struct file *file) { return 0; } @@ -95,7 +95,9 @@ static const struct file_operations mmapper_fops = { .release = mmapper_release, }; -/* No locking needed - only used (and modified) by below initcall and exitcall. */ +/* + * No locking needed - only used (and modified) by below initcall and exitcall. + */ static struct miscdevice mmapper_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "mmapper", @@ -109,13 +111,13 @@ static int __init mmapper_init(void) printk(KERN_INFO "Mapper v0.1\n"); v_buf = (char *) find_iomem("mmapper", &mmapper_size); - if(mmapper_size == 0){ + if (mmapper_size == 0) { printk(KERN_ERR "mmapper_init - find_iomem failed\n"); goto out; } err = misc_register(&mmapper_dev); - if(err){ + if (err) { printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", err); goto out; @@ -136,9 +138,3 @@ module_exit(mmapper_exit); MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); -/* - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index d35d0c1ee7f..8c01fa81a1a 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -1,33 +1,28 @@ /* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ -#include "linux/kernel.h" -#include "linux/netdevice.h" -#include "linux/rtnetlink.h" -#include "linux/skbuff.h" -#include "linux/socket.h" -#include "linux/spinlock.h" -#include "linux/module.h" -#include "linux/init.h" -#include "linux/etherdevice.h" -#include "linux/list.h" -#include "linux/inetdevice.h" -#include "linux/ctype.h" -#include "linux/bootmem.h" -#include "linux/ethtool.h" -#include "linux/platform_device.h" -#include "asm/uaccess.h" -#include "kern_util.h" -#include "net_kern.h" -#include "net_user.h" -#include "mconsole_kern.h" +#include <linux/bootmem.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/inetdevice.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/netdevice.h> +#include <linux/platform_device.h> +#include <linux/rtnetlink.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> #include "init.h" -#include "irq_user.h" #include "irq_kern.h" +#include "irq_user.h" +#include "mconsole_kern.h" +#include "net_kern.h" +#include "net_user.h" static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) { @@ -39,6 +34,46 @@ static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) static DEFINE_SPINLOCK(opened_lock); static LIST_HEAD(opened); +/* + * The drop_skb is used when we can't allocate an skb. The + * packet is read into drop_skb in order to get the data off the + * connection to the host. + * It is reallocated whenever a maximum packet size is seen which is + * larger than any seen before. update_drop_skb is called from + * eth_configure when a new interface is added. + */ +static DEFINE_SPINLOCK(drop_lock); +static struct sk_buff *drop_skb; +static int drop_max; + +static int update_drop_skb(int max) +{ + struct sk_buff *new; + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&drop_lock, flags); + + if (max <= drop_max) + goto out; + + err = -ENOMEM; + new = dev_alloc_skb(max); + if (new == NULL) + goto out; + + skb_put(new, max); + + kfree_skb(drop_skb); + drop_skb = new; + drop_max = max; + err = 0; +out: + spin_unlock_irqrestore(&drop_lock, flags); + + return err; +} + static int uml_net_rx(struct net_device *dev) { struct uml_net_private *lp = dev->priv; @@ -46,16 +81,19 @@ static int uml_net_rx(struct net_device *dev) struct sk_buff *skb; /* If we can't allocate memory, try again next round. */ - skb = dev_alloc_skb(dev->mtu); + skb = dev_alloc_skb(lp->max_packet); if (skb == NULL) { + drop_skb->dev = dev; + /* Read a packet into drop_skb and don't do anything with it. */ + (*lp->read)(lp->fd, drop_skb, lp); lp->stats.rx_dropped++; return 0; } skb->dev = dev; - skb_put(skb, dev->mtu); + skb_put(skb, lp->max_packet); skb_reset_mac_header(skb); - pkt_len = (*lp->read)(lp->fd, &skb, lp); + pkt_len = (*lp->read)(lp->fd, skb, lp); if (pkt_len > 0) { skb_trim(skb, pkt_len); @@ -84,12 +122,12 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) struct uml_net_private *lp = dev->priv; int err; - if(!netif_running(dev)) - return(IRQ_NONE); + if (!netif_running(dev)) + return IRQ_NONE; spin_lock(&lp->lock); - while((err = uml_net_rx(dev)) > 0) ; - if(err < 0) { + while ((err = uml_net_rx(dev)) > 0) ; + if (err < 0) { printk(KERN_ERR "Device '%s' read returned %d, shutting it down\n", dev->name, err); @@ -115,20 +153,20 @@ static int uml_net_open(struct net_device *dev) struct uml_net_private *lp = dev->priv; int err; - if(lp->fd >= 0){ + if (lp->fd >= 0) { err = -ENXIO; goto out; } lp->fd = (*lp->open)(&lp->user); - if(lp->fd < 0){ + if (lp->fd < 0) { err = lp->fd; goto out; } err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, IRQF_DISABLED | IRQF_SHARED, dev->name, dev); - if(err != 0){ + if (err != 0) { printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); err = -ENETUNREACH; goto out_close; @@ -141,7 +179,7 @@ static int uml_net_open(struct net_device *dev) * is full when we get here. In this case, new data is never queued, * SIGIOs never arrive, and the net never works. */ - while((err = uml_net_rx(dev)) > 0) ; + while ((err = uml_net_rx(dev)) > 0) ; spin_lock(&opened_lock); list_add(&lp->list, &opened); @@ -149,7 +187,7 @@ static int uml_net_open(struct net_device *dev) return 0; out_close: - if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); + if (lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; out: return err; @@ -162,7 +200,7 @@ static int uml_net_close(struct net_device *dev) netif_stop_queue(dev); free_irq(dev->irq, dev); - if(lp->close != NULL) + if (lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; @@ -183,9 +221,9 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); - len = (*lp->write)(lp->fd, &skb, lp); + len = (*lp->write)(lp->fd, skb, lp); - if(len == skb->len) { + if (len == skb->len) { lp->stats.tx_packets++; lp->stats.tx_bytes += skb->len; dev->trans_start = jiffies; @@ -194,7 +232,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) /* this is normally done in the interrupt when tx finishes */ netif_wake_queue(dev); } - else if(len == 0){ + else if (len == 0) { netif_start_queue(dev); lp->stats.tx_dropped++; } @@ -218,8 +256,10 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev) static void uml_net_set_multicast_list(struct net_device *dev) { - if (dev->flags & IFF_PROMISC) return; - else if (dev->mc_count) dev->flags |= IFF_ALLMULTI; + if (dev->flags & IFF_PROMISC) + return; + else if (dev->mc_count) + dev->flags |= IFF_ALLMULTI; else dev->flags &= ~IFF_ALLMULTI; } @@ -243,22 +283,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr) static int uml_net_change_mtu(struct net_device *dev, int new_mtu) { - struct uml_net_private *lp = dev->priv; - int err = 0; - - spin_lock_irq(&lp->lock); - - new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); - if(new_mtu < 0){ - err = new_mtu; - goto out; - } - dev->mtu = new_mtu; - out: - spin_unlock_irq(&lp->lock); - return err; + return 0; } static void uml_net_get_drvinfo(struct net_device *dev, @@ -288,13 +315,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name) char *end; int i; - if(str == NULL) + if (str == NULL) goto random; - for(i=0;i<6;i++){ + for (i = 0;i < 6; i++) { addr[i] = simple_strtoul(str, &end, 16); - if((end == str) || - ((*end != ':') && (*end != ',') && (*end != '\0'))){ + if ((end == str) || + ((*end != ':') && (*end != ',') && (*end != '\0'))) { printk(KERN_ERR "setup_etheraddr: failed to parse '%s' " "as an ethernet address\n", str); @@ -349,7 +376,7 @@ static void net_device_release(struct device *dev) struct net_device *netdev = device->dev; struct uml_net_private *lp = netdev->priv; - if(lp->remove != NULL) + if (lp->remove != NULL) (*lp->remove)(&lp->user); list_del(&device->list); kfree(device); @@ -413,7 +440,7 @@ static void eth_configure(int n, void *init, char *mac, device->pdev.name = DRIVER_NAME; device->pdev.dev.release = net_device_release; device->pdev.dev.driver_data = device; - if(platform_device_register(&device->pdev)) + if (platform_device_register(&device->pdev)) goto out_free_netdev; SET_NETDEV_DEV(dev,&device->pdev.dev); @@ -430,6 +457,7 @@ static void eth_configure(int n, void *init, char *mac, .dev = dev, .fd = -1, .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, + .max_packet = transport->user->max_packet, .protocol = transport->kern->protocol, .open = transport->user->open, .close = transport->user->close, @@ -437,8 +465,7 @@ static void eth_configure(int n, void *init, char *mac, .read = transport->kern->read, .write = transport->kern->write, .add_address = transport->user->add_address, - .delete_address = transport->user->delete_address, - .set_mtu = transport->user->set_mtu }); + .delete_address = transport->user->delete_address }); init_timer(&lp->tl); spin_lock_init(&lp->lock); @@ -450,7 +477,7 @@ static void eth_configure(int n, void *init, char *mac, goto out_unregister; set_ether_mac(dev, device->mac); - dev->mtu = transport->user->max_packet; + dev->mtu = transport->user->mtu; dev->open = uml_net_open; dev->hard_start_xmit = uml_net_start_xmit; dev->stop = uml_net_close; @@ -463,6 +490,10 @@ static void eth_configure(int n, void *init, char *mac, dev->watchdog_timeo = (HZ >> 1); dev->irq = UM_ETH_IRQ; + err = update_drop_skb(lp->max_packet); + if (err) + goto out_undo_user_init; + rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); @@ -493,9 +524,9 @@ static struct uml_net *find_device(int n) struct list_head *ele; spin_lock(&devices_lock); - list_for_each(ele, &devices){ + list_for_each(ele, &devices) { device = list_entry(ele, struct uml_net, list); - if(device->index == n) + if (device->index == n) goto out; } device = NULL; @@ -511,19 +542,19 @@ static int eth_parse(char *str, int *index_out, char **str_out, int n, err = -EINVAL;; n = simple_strtoul(str, &end, 0); - if(end == str){ + if (end == str) { *error_out = "Bad device number"; return err; } str = end; - if(*str != '='){ + if (*str != '=') { *error_out = "Expected '=' after device number"; return err; } str++; - if(find_device(n)){ + if (find_device(n)) { *error_out = "Device already configured"; return err; } @@ -551,20 +582,20 @@ static int check_transport(struct transport *transport, char *eth, int n, int len; len = strlen(transport->name); - if(strncmp(eth, transport->name, len)) + if (strncmp(eth, transport->name, len)) return 0; eth += len; - if(*eth == ',') + if (*eth == ',') eth++; - else if(*eth != '\0') + else if (*eth != '\0') return 0; *init_out = kmalloc(transport->setup_size, GFP_KERNEL); - if(*init_out == NULL) + if (*init_out == NULL) return 1; - if(!transport->setup(eth, mac_out, *init_out)){ + if (!transport->setup(eth, mac_out, *init_out)) { kfree(*init_out); *init_out = NULL; } @@ -584,13 +615,13 @@ void register_transport(struct transport *new) list_add(&new->list, &transports); spin_unlock(&transports_lock); - list_for_each_safe(ele, next, ð_cmd_line){ + list_for_each_safe(ele, next, ð_cmd_line) { eth = list_entry(ele, struct eth_init, list); match = check_transport(new, eth->init, eth->index, &init, &mac); - if(!match) + if (!match) continue; - else if(init != NULL){ + else if (init != NULL) { eth_configure(eth->index, init, mac, new); kfree(init); } @@ -607,11 +638,11 @@ static int eth_setup_common(char *str, int index) int found = 0; spin_lock(&transports_lock); - list_for_each(ele, &transports){ + list_for_each(ele, &transports) { transport = list_entry(ele, struct transport, list); - if(!check_transport(transport, str, index, &init, &mac)) + if (!check_transport(transport, str, index, &init, &mac)) continue; - if(init != NULL){ + if (init != NULL) { eth_configure(index, init, mac, transport); kfree(init); } @@ -630,15 +661,15 @@ static int __init eth_setup(char *str) int n, err; err = eth_parse(str, &n, &str, &error); - if(err){ + if (err) { printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n", str, error); return 1; } new = alloc_bootmem(sizeof(*new)); - if (new == NULL){ - printk("eth_init : alloc_bootmem failed\n"); + if (new == NULL) { + printk(KERN_ERR "eth_init : alloc_bootmem failed\n"); return 1; } @@ -661,36 +692,36 @@ static int net_config(char *str, char **error_out) int n, err; err = eth_parse(str, &n, &str, error_out); - if(err) + if (err) return err; /* This string is broken up and the pieces used by the underlying * driver. So, it is freed only if eth_setup_common fails. */ str = kstrdup(str, GFP_KERNEL); - if(str == NULL){ + if (str == NULL) { *error_out = "net_config failed to strdup string"; return -ENOMEM; } err = !eth_setup_common(str, n); - if(err) + if (err) kfree(str); - return(err); + return err; } static int net_id(char **str, int *start_out, int *end_out) { - char *end; - int n; + char *end; + int n; n = simple_strtoul(*str, &end, 0); - if((*end != '\0') || (end == *str)) + if ((*end != '\0') || (end == *str)) return -1; - *start_out = n; - *end_out = n; - *str = end; - return n; + *start_out = n; + *end_out = n; + *str = end; + return n; } static int net_remove(int n, char **error_out) @@ -700,12 +731,12 @@ static int net_remove(int n, char **error_out) struct uml_net_private *lp; device = find_device(n); - if(device == NULL) + if (device == NULL) return -ENODEV; dev = device->dev; lp = dev->priv; - if(lp->fd > 0) + if (lp->fd > 0) return -EBUSY; unregister_netdev(dev); platform_device_unregister(&device->pdev); @@ -731,13 +762,13 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, void (*proc)(unsigned char *, unsigned char *, void *); unsigned char addr_buf[4], netmask_buf[4]; - if(dev->open != uml_net_open) + if (dev->open != uml_net_open) return NOTIFY_DONE; lp = dev->priv; proc = NULL; - switch (event){ + switch (event) { case NETDEV_UP: proc = lp->add_address; break; @@ -745,7 +776,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, proc = lp->delete_address; break; } - if(proc != NULL){ + if (proc != NULL) { memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf)); memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); (*proc)(addr_buf, netmask_buf, &lp->user); @@ -773,13 +804,13 @@ static int uml_net_init(void) * addresses which have already been set up get handled properly. */ spin_lock(&opened_lock); - list_for_each(ele, &opened){ + list_for_each(ele, &opened) { lp = list_entry(ele, struct uml_net_private, list); ip = lp->dev->ip_ptr; - if(ip == NULL) + if (ip == NULL) continue; in = ip->ifa_list; - while(in != NULL){ + while (in != NULL) { uml_inetaddr_event(NULL, NETDEV_UP, in); in = in->ifa_next; } @@ -797,12 +828,12 @@ static void close_devices(void) struct uml_net_private *lp; spin_lock(&opened_lock); - list_for_each(ele, &opened){ + list_for_each(ele, &opened) { lp = list_entry(ele, struct uml_net_private, list); free_irq(lp->dev->irq, lp->dev); - if((lp->close != NULL) && (lp->fd >= 0)) + if ((lp->close != NULL) && (lp->fd >= 0)) (*lp->close)(lp->fd, &lp->user); - if(lp->remove != NULL) + if (lp->remove != NULL) (*lp->remove)(&lp->user); } spin_unlock(&opened_lock); @@ -810,19 +841,6 @@ static void close_devices(void) __uml_exitcall(close_devices); -struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) -{ - if((skb != NULL) && (skb_tailroom(skb) < extra)){ - struct sk_buff *skb2; - - skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); - dev_kfree_skb(skb); - skb = skb2; - } - if(skb != NULL) skb_put(skb, extra); - return(skb); -} - void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, void *), void *arg) @@ -832,9 +850,9 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, struct in_ifaddr *in; unsigned char address[4], netmask[4]; - if(ip == NULL) return; + if (ip == NULL) return; in = ip->ifa_list; - while(in != NULL){ + while (in != NULL) { memcpy(address, &in->ifa_address, sizeof(address)); memcpy(netmask, &in->ifa_mask, sizeof(netmask)); (*cb)(address, netmask, arg); @@ -849,15 +867,15 @@ int dev_netmask(void *d, void *m) struct in_ifaddr *in; __be32 *mask_out = m; - if(ip == NULL) - return(1); + if (ip == NULL) + return 1; in = ip->ifa_list; - if(in == NULL) - return(1); + if (in == NULL) + return 1; *mask_out = in->ifa_mask; - return(0); + return 0; } void *get_output_buffer(int *len_out) @@ -865,7 +883,7 @@ void *get_output_buffer(int *len_out) void *ret; ret = (void *) __get_free_pages(GFP_KERNEL, 0); - if(ret) *len_out = PAGE_SIZE; + if (ret) *len_out = PAGE_SIZE; else *len_out = 0; return ret; } @@ -881,16 +899,16 @@ int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, char *remain; remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); - if(remain != NULL){ - printk("tap_setup_common - Extra garbage on specification : " - "'%s'\n", remain); - return(1); + if (remain != NULL) { + printk(KERN_ERR "tap_setup_common - Extra garbage on " + "specification : '%s'\n", remain); + return 1; } - return(0); + return 0; } unsigned short eth_protocol(struct sk_buff *skb) { - return(eth_type_trans(skb, skb->dev)); + return eth_type_trans(skb, skb->dev); } diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index da946e3e1bf..90d7f2e8ead 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -1,34 +1,32 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stddef.h> -#include <stdarg.h> -#include <unistd.h> #include <stdio.h> +#include <unistd.h> +#include <stdarg.h> #include <errno.h> -#include <stdlib.h> +#include <stddef.h> #include <string.h> #include <sys/socket.h> #include <sys/wait.h> -#include <sys/time.h> -#include "user.h" -#include "kern_util.h" #include "net_user.h" +#include "kern_constants.h" #include "os.h" #include "um_malloc.h" -#include "kern_constants.h" +#include "user.h" int tap_open_common(void *dev, char *gate_addr) { int tap_addr[4]; - if(gate_addr == NULL) + if (gate_addr == NULL) return 0; - if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], - &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ - printk("Invalid tap IP address - '%s'\n", gate_addr); + if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], + &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) { + printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n", + gate_addr); return -EINVAL; } return 0; @@ -38,15 +36,15 @@ void tap_check_ips(char *gate_addr, unsigned char *eth_addr) { int tap_addr[4]; - if((gate_addr != NULL) && - (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], - &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && - (eth_addr[0] == tap_addr[0]) && - (eth_addr[1] == tap_addr[1]) && - (eth_addr[2] == tap_addr[2]) && - (eth_addr[3] == tap_addr[3])){ - printk("The tap IP address and the UML eth IP address" - " must be different\n"); + if ((gate_addr != NULL) && + (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], + &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && + (eth_addr[0] == tap_addr[0]) && + (eth_addr[1] == tap_addr[1]) && + (eth_addr[2] == tap_addr[2]) && + (eth_addr[3] == tap_addr[3])) { + printk(UM_KERN_ERR "The tap IP address and the UML eth IP " + "address must be different\n"); } } @@ -57,24 +55,28 @@ void read_output(int fd, char *output, int len) char c; char *str; - if(output == NULL){ + if (output == NULL) { output = &c; len = sizeof(c); } - + *output = '\0'; - ret = os_read_file(fd, &remain, sizeof(remain)); + ret = read(fd, &remain, sizeof(remain)); if (ret != sizeof(remain)) { + if (ret < 0) + ret = -errno; expected = sizeof(remain); str = "length"; goto err; } - while(remain != 0){ + while (remain != 0) { expected = (remain < len) ? remain : len; - ret = os_read_file(fd, output, expected); + ret = read(fd, output, expected); if (ret != expected) { + if (ret < 0) + ret = -errno; str = "data"; goto err; } @@ -85,20 +87,22 @@ void read_output(int fd, char *output, int len) err: if (ret < 0) - printk("read_output - read of %s failed, errno = %d\n", str, -ret); + printk(UM_KERN_ERR "read_output - read of %s failed, " + "errno = %d\n", str, -ret); else - printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected); + printk(UM_KERN_ERR "read_output - read of %s failed, read only " + "%d of %d bytes\n", str, ret, expected); } int net_read(int fd, void *buf, int len) { int n; - n = os_read_file(fd, buf, len); + n = read(fd, buf, len); - if(n == -EAGAIN) + if ((n < 0) && (errno == EAGAIN)) return 0; - else if(n == 0) + else if (n == 0) return -ENOTCONN; return n; } @@ -108,12 +112,12 @@ int net_recvfrom(int fd, void *buf, int len) int n; CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL)); - if(n < 0){ - if(errno == EAGAIN) + if (n < 0) { + if (errno == EAGAIN) return 0; return -errno; } - else if(n == 0) + else if (n == 0) return -ENOTCONN; return n; } @@ -122,11 +126,11 @@ int net_write(int fd, void *buf, int len) { int n; - n = os_write_file(fd, buf, len); + n = write(fd, buf, len); - if(n == -EAGAIN) + if ((n < 0) && (errno == EAGAIN)) return 0; - else if(n == 0) + else if (n == 0) return -ENOTCONN; return n; } @@ -136,12 +140,12 @@ int net_send(int fd, void *buf, int len) int n; CATCH_EINTR(n = send(fd, buf, len, 0)); - if(n < 0){ - if(errno == EAGAIN) + if (n < 0) { + if (errno == EAGAIN) return 0; return -errno; } - else if(n == 0) + else if (n == 0) return -ENOTCONN; return n; } @@ -152,12 +156,12 @@ int net_sendto(int fd, void *buf, int len, void *to, int sock_len) CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to, sock_len)); - if(n < 0){ - if(errno == EAGAIN) + if (n < 0) { + if (errno == EAGAIN) return 0; return -errno; } - else if(n == 0) + else if (n == 0) return -ENOTCONN; return n; } @@ -171,7 +175,7 @@ static void change_pre_exec(void *arg) { struct change_pre_exec_data *data = arg; - os_close_file(data->close_me); + close(data->close_me); dup2(data->stdout, 1); } @@ -181,8 +185,9 @@ static int change_tramp(char **argv, char *output, int output_len) struct change_pre_exec_data pe_data; err = os_pipe(fds, 1, 0); - if(err < 0){ - printk("change_tramp - pipe failed, err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n", + -err); return err; } pe_data.close_me = fds[0]; @@ -192,8 +197,8 @@ static int change_tramp(char **argv, char *output, int output_len) if (pid > 0) /* Avoid hang as we won't get data in failure case. */ read_output(fds[0], output, output_len); - os_close_file(fds[0]); - os_close_file(fds[1]); + close(fds[0]); + close(fds[1]); if (pid > 0) CATCH_EINTR(err = waitpid(pid, NULL, 0)); @@ -206,25 +211,26 @@ static void change(char *dev, char *what, unsigned char *addr, char addr_buf[sizeof("255.255.255.255\0")]; char netmask_buf[sizeof("255.255.255.255\0")]; char version[sizeof("nnnnn\0")]; - char *argv[] = { "uml_net", version, what, dev, addr_buf, + char *argv[] = { "uml_net", version, what, dev, addr_buf, netmask_buf, NULL }; char *output; int output_len, pid; sprintf(version, "%d", UML_NET_VERSION); sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); - sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], + sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], netmask[2], netmask[3]); output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); - if(output == NULL) - printk("change : failed to allocate output buffer\n"); + if (output == NULL) + printk(UM_KERN_ERR "change : failed to allocate output " + "buffer\n"); pid = change_tramp(argv, output, output_len); - if(pid < 0) return; + if (pid < 0) return; - if(output != NULL){ + if (output != NULL) { printk("%s", output); kfree(output); } @@ -246,13 +252,13 @@ char *split_if_spec(char *str, ...) va_list ap; va_start(ap, str); - while((arg = va_arg(ap, char **)) != NULL){ - if(*str == '\0') + while ((arg = va_arg(ap, char **)) != NULL) { + if (*str == '\0') return NULL; end = strchr(str, ','); - if(end != str) + if (end != str) *arg = str; - if(end == NULL) + if (end == NULL) return NULL; *end++ = '\0'; str = end; diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index 9016c68beee..21ad3d7932b 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c @@ -1,10 +1,11 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include <stdlib.h> +#include <stddef.h> #include <errno.h> +#include <fcntl.h> #include "chan_user.h" #include "os.h" @@ -13,19 +14,23 @@ static int null_chan; static void *null_init(char *str, int device, const struct chan_opts *opts) { - return(&null_chan); + return &null_chan; } static int null_open(int input, int output, int primary, void *d, char **dev_out) { + int fd; + *dev_out = NULL; - return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); + + fd = open(DEV_NULL, O_RDWR); + return (fd < 0) ? -errno : fd; } static int null_read(int fd, char *c_out, void *unused) { - return(-ENODEV); + return -ENODEV; } static void null_free(void *data) @@ -44,14 +49,3 @@ const struct chan_ops null_ops = { .free = null_free, .winch = 0, }; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index c329931673d..3a750dd39be 100644 --- a/arch/um/drivers/pcap_kern.c +++ b/arch/um/drivers/pcap_kern.c @@ -1,13 +1,11 @@ /* - * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL. */ #include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" +#include <linux/netdevice.h> #include "net_kern.h" -#include "net_user.h" #include "pcap_user.h" struct pcap_init { @@ -33,19 +31,14 @@ void pcap_init(struct net_device *dev, void *data) printk("pcap backend, host interface %s\n", ppri->host_if); } -static int pcap_read(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if(*skb == NULL) - return -ENOMEM; - - return pcap_user_read(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + ETH_HEADER_OTHER, + return pcap_user_read(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER, (struct pcap_data *) &lp->user); } -static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) +static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { return -EPERM; } @@ -71,28 +64,29 @@ int pcap_setup(char *str, char **mac_out, void *data) remain = split_if_spec(str, &host_if, &init->filter, &options[0], &options[1], mac_out, NULL); - if(remain != NULL){ + if (remain != NULL) { printk(KERN_ERR "pcap_setup - Extra garbage on " "specification : '%s'\n", remain); return 0; } - if(host_if != NULL) + if (host_if != NULL) init->host_if = host_if; - for(i = 0; i < ARRAY_SIZE(options); i++){ - if(options[i] == NULL) + for (i = 0; i < ARRAY_SIZE(options); i++) { + if (options[i] == NULL) continue; - if(!strcmp(options[i], "promisc")) + if (!strcmp(options[i], "promisc")) init->promisc = 1; - else if(!strcmp(options[i], "nopromisc")) + else if (!strcmp(options[i], "nopromisc")) init->promisc = 0; - else if(!strcmp(options[i], "optimize")) + else if (!strcmp(options[i], "optimize")) init->optimize = 1; - else if(!strcmp(options[i], "nooptimize")) + else if (!strcmp(options[i], "nooptimize")) init->optimize = 0; else { - printk("pcap_setup : bad option - '%s'\n", options[i]); + printk(KERN_ERR "pcap_setup : bad option - '%s'\n", + options[i]); return 0; } } diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index 1316456e2a2..e9809356c53 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c @@ -1,21 +1,17 @@ /* - * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL. */ -#include <unistd.h> -#include <stdlib.h> -#include <string.h> #include <errno.h> #include <pcap.h> +#include <string.h> #include <asm/types.h> #include "net_user.h" #include "pcap_user.h" -#include "user.h" -#include "um_malloc.h" #include "kern_constants.h" - -#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) +#include "um_malloc.h" +#include "user.h" #define PCAP_FD(p) (*(int *)(p)) @@ -25,8 +21,9 @@ static int pcap_user_init(void *data, void *dev) pcap_t *p; char errors[PCAP_ERRBUF_SIZE]; - p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); - if(p == NULL){ + p = pcap_open_live(pri->host_if, ETH_MAX_PACKET + ETH_HEADER_OTHER, + pri->promisc, 0, errors); + if (p == NULL) { printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - " "'%s'\n", errors); return -EINVAL; @@ -43,50 +40,55 @@ static int pcap_open(void *data) __u32 netmask; int err; - if(pri->pcap == NULL) + if (pri->pcap == NULL) return -ENODEV; - if(pri->filter != NULL){ + if (pri->filter != NULL) { err = dev_netmask(pri->dev, &netmask); - if(err < 0){ + if (err < 0) { printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n"); return -EIO; } - pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL); - if(pri->compiled == NULL){ + pri->compiled = kmalloc(sizeof(struct bpf_program), + UM_GFP_KERNEL); + if (pri->compiled == NULL) { printk(UM_KERN_ERR "pcap_open : kmalloc failed\n"); return -ENOMEM; } - err = pcap_compile(pri->pcap, - (struct bpf_program *) pri->compiled, + err = pcap_compile(pri->pcap, + (struct bpf_program *) pri->compiled, pri->filter, pri->optimize, netmask); - if(err < 0){ + if (err < 0) { printk(UM_KERN_ERR "pcap_open : pcap_compile failed - " "'%s'\n", pcap_geterr(pri->pcap)); - return -EIO; + goto out; } err = pcap_setfilter(pri->pcap, pri->compiled); - if(err < 0){ + if (err < 0) { printk(UM_KERN_ERR "pcap_open : pcap_setfilter " "failed - '%s'\n", pcap_geterr(pri->pcap)); - return -EIO; + goto out; } } return PCAP_FD(pri->pcap); + + out: + kfree(pri->compiled); + return -EIO; } static void pcap_remove(void *data) { struct pcap_data *pri = data; - if(pri->compiled != NULL) + if (pri->compiled != NULL) pcap_freecode(pri->compiled); - if(pri->pcap != NULL) + if (pri->pcap != NULL) pcap_close(pri->pcap); } @@ -95,7 +97,7 @@ struct pcap_handler_data { int len; }; -static void handler(u_char *data, const struct pcap_pkthdr *header, +static void handler(u_char *data, const struct pcap_pkthdr *header, const u_char *packet) { int len; @@ -115,12 +117,12 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) int n; n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); - if(n < 0){ + if (n < 0) { printk(UM_KERN_ERR "pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); return -EIO; } - else if(n == 0) + else if (n == 0) return 0; return hdata.len; } @@ -130,8 +132,8 @@ const struct net_user_info pcap_user_info = { .open = pcap_open, .close = NULL, .remove = pcap_remove, - .set_mtu = NULL, .add_address = NULL, .delete_address = NULL, - .max_packet = MAX_PACKET - ETH_HEADER_OTHER + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, }; diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 1c8efd95c42..330543b3129 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -1,24 +1,16 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include "linux/list.h" -#include "linux/sched.h" -#include "linux/slab.h" +#include "linux/completion.h" #include "linux/interrupt.h" -#include "linux/spinlock.h" -#include "linux/errno.h" +#include "linux/list.h" #include "asm/atomic.h" -#include "asm/semaphore.h" -#include "asm/errno.h" -#include "kern_util.h" -#include "kern.h" -#include "irq_user.h" -#include "irq_kern.h" -#include "port.h" #include "init.h" +#include "irq_kern.h" #include "os.h" +#include "port.h" struct port_list { struct list_head list; @@ -53,8 +45,8 @@ static irqreturn_t pipe_interrupt(int irq, void *data) int fd; fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); - if(fd < 0){ - if(fd == -EAGAIN) + if (fd < 0) { + if (fd == -EAGAIN) return IRQ_NONE; printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", @@ -81,18 +73,18 @@ static irqreturn_t pipe_interrupt(int irq, void *data) static int port_accept(struct port_list *port) { struct connection *conn; - int fd, socket[2], pid, ret = 0; + int fd, socket[2], pid; fd = port_connection(port->fd, socket, &pid); - if(fd < 0){ - if(fd != -EAGAIN) + if (fd < 0) { + if (fd != -EAGAIN) printk(KERN_ERR "port_accept : port_connection " "returned %d\n", -fd); goto out; } conn = kmalloc(sizeof(*conn), GFP_ATOMIC); - if(conn == NULL){ + if (conn == NULL) { printk(KERN_ERR "port_accept : failed to allocate " "connection\n"); goto out_close; @@ -104,17 +96,17 @@ static int port_accept(struct port_list *port) .telnetd_pid = pid, .port = port }); - if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, + if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "telnetd", conn)){ + "telnetd", conn)) { printk(KERN_ERR "port_accept : failed to get IRQ for " "telnetd\n"); goto out_free; } - if(atomic_read(&port->wait_count) == 0){ + if (atomic_read(&port->wait_count) == 0) { os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); - printk("No one waiting for port\n"); + printk(KERN_ERR "No one waiting for port\n"); } list_add(&conn->list, &port->pending); return 1; @@ -123,28 +115,29 @@ static int port_accept(struct port_list *port) kfree(conn); out_close: os_close_file(fd); - if(pid != -1) - os_kill_process(pid, 1); + os_kill_process(pid, 1); out: - return ret; + return 0; } static DECLARE_MUTEX(ports_sem); static LIST_HEAD(ports); -void port_work_proc(struct work_struct *unused) +static void port_work_proc(struct work_struct *unused) { struct port_list *port; struct list_head *ele; unsigned long flags; local_irq_save(flags); - list_for_each(ele, &ports){ + list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); - if(!port->has_connection) + if (!port->has_connection) continue; + reactivate_fd(port->fd, ACCEPT_IRQ); - while(port_accept(port)) ; + while (port_accept(port)) + ; port->has_connection = 0; } local_irq_restore(flags); @@ -169,25 +162,27 @@ void *port_data(int port_num) int fd; down(&ports_sem); - list_for_each(ele, &ports){ + list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); - if(port->port == port_num) goto found; + if (port->port == port_num) + goto found; } port = kmalloc(sizeof(struct port_list), GFP_KERNEL); - if(port == NULL){ + if (port == NULL) { printk(KERN_ERR "Allocation of port list failed\n"); goto out; } fd = port_listen_fd(port_num); - if(fd < 0){ + if (fd < 0) { printk(KERN_ERR "binding to port %d failed, errno = %d\n", port_num, -fd); goto out_free; } - if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, + + if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "port", port)){ + "port", port)) { printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); goto out_close; } @@ -206,7 +201,7 @@ void *port_data(int port_num) found: dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); - if(dev == NULL){ + if (dev == NULL) { printk(KERN_ERR "Allocation of port device entry failed\n"); goto out; } @@ -216,10 +211,10 @@ void *port_data(int port_num) .telnetd_pid = -1 }); goto out; - out_free: - kfree(port); out_close: os_close_file(fd); + out_free: + kfree(port); out: up(&ports_sem); return dev; @@ -233,9 +228,9 @@ int port_wait(void *data) int fd; atomic_inc(&port->wait_count); - while(1){ + while (1) { fd = -ERESTARTSYS; - if(wait_for_completion_interruptible(&port->done)) + if (wait_for_completion_interruptible(&port->done)) goto out; spin_lock(&port->lock); @@ -258,7 +253,8 @@ int port_wait(void *data) */ free_irq(TELNETD_IRQ, conn); - if(conn->fd >= 0) break; + if (conn->fd >= 0) + break; os_close_file(conn->fd); kfree(conn); } @@ -276,9 +272,9 @@ void port_remove_dev(void *d) { struct port_dev *dev = d; - if(dev->helper_pid != -1) + if (dev->helper_pid != -1) os_kill_process(dev->helper_pid, 0); - if(dev->telnetd_pid != -1) + if (dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid, 1); dev->helper_pid = -1; dev->telnetd_pid = -1; @@ -297,7 +293,7 @@ static void free_port(void) struct list_head *ele; struct port_list *port; - list_for_each(ele, &ports){ + list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); free_irq_by_fd(port->fd); os_close_file(port->fd); diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index c799b00012c..addd7590265 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -1,24 +1,20 @@ /* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ #include <stdio.h> -#include <stddef.h> #include <stdlib.h> -#include <string.h> #include <errno.h> -#include <unistd.h> #include <termios.h> -#include <sys/socket.h> -#include <sys/un.h> +#include <unistd.h> #include <netinet/in.h> -#include "kern_util.h" -#include "user.h" #include "chan_user.h" -#include "port.h" +#include "kern_constants.h" #include "os.h" +#include "port.h" #include "um_malloc.h" +#include "user.h" struct port_chan { int raw; @@ -34,24 +30,25 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) char *end; int port; - if(*str != ':'){ - printk("port_init : channel type 'port' must specify a " - "port number\n"); + if (*str != ':') { + printk(UM_KERN_ERR "port_init : channel type 'port' must " + "specify a port number\n"); return NULL; } str++; port = strtoul(str, &end, 0); - if((*end != '\0') || (end == str)){ - printk("port_init : couldn't parse port '%s'\n", str); + if ((*end != '\0') || (end == str)) { + printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n", + str); return NULL; } kern_data = port_data(port); - if(kern_data == NULL) + if (kern_data == NULL) return NULL; data = kmalloc(sizeof(*data), UM_GFP_KERNEL); - if(data == NULL) + if (data == NULL) goto err; *data = ((struct port_chan) { .raw = opts->raw, @@ -79,13 +76,13 @@ static int port_open(int input, int output, int primary, void *d, int fd, err; fd = port_wait(data->kernel_data); - if((fd >= 0) && data->raw){ + if ((fd >= 0) && data->raw) { CATCH_EINTR(err = tcgetattr(fd, &data->tt)); - if(err) + if (err) return err; err = raw(fd); - if(err) + if (err) return err; } *dev_out = data->dev; @@ -119,11 +116,11 @@ int port_listen_fd(int port) int fd, err, arg; fd = socket(PF_INET, SOCK_STREAM, 0); - if(fd == -1) + if (fd == -1) return -errno; arg = 1; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) { err = -errno; goto out; } @@ -131,23 +128,23 @@ int port_listen_fd(int port) addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); - if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = -errno; goto out; } - if(listen(fd, 1) < 0){ + if (listen(fd, 1) < 0) { err = -errno; goto out; } err = os_set_fd_block(fd, 0); - if(err < 0) + if (err < 0) goto out; return fd; out: - os_close_file(fd); + close(fd); return err; } @@ -163,10 +160,10 @@ void port_pre_exec(void *arg) dup2(data->sock_fd, 0); dup2(data->sock_fd, 1); dup2(data->sock_fd, 2); - os_close_file(data->sock_fd); + close(data->sock_fd); dup2(data->pipe_fd, 3); - os_shutdown_socket(3, 1, 0); - os_close_file(data->pipe_fd); + shutdown(3, SHUT_RD); + close(data->pipe_fd); } int port_connection(int fd, int *socket, int *pid_out) @@ -176,12 +173,12 @@ int port_connection(int fd, int *socket, int *pid_out) "/usr/lib/uml/port-helper", NULL }; struct port_pre_exec_data data; - new = os_accept_connection(fd); - if(new < 0) - return new; + new = accept(fd, NULL, 0); + if (new < 0) + return -errno; err = os_pipe(socket, 0, 0); - if(err < 0) + if (err < 0) goto out_close; data = ((struct port_pre_exec_data) @@ -189,18 +186,18 @@ int port_connection(int fd, int *socket, int *pid_out) .pipe_fd = socket[1] }); err = run_helper(port_pre_exec, &data, argv); - if(err < 0) + if (err < 0) goto out_shutdown; *pid_out = err; return new; out_shutdown: - os_shutdown_socket(socket[0], 1, 1); - os_close_file(socket[0]); - os_shutdown_socket(socket[1], 1, 1); - os_close_file(socket[1]); + shutdown(socket[0], SHUT_RDWR); + close(socket[0]); + shutdown(socket[1], SHUT_RDWR); + close(socket[1]); out_close: - os_close_file(new); + close(new); return err; } diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 1e3fd619a83..49c79dda604 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -6,16 +6,16 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <string.h> -#include <fcntl.h> #include <errno.h> +#include <fcntl.h> +#include <string.h> #include <termios.h> #include <sys/stat.h> #include "chan_user.h" -#include "os.h" -#include "user.h" #include "kern_constants.h" +#include "os.h" #include "um_malloc.h" +#include "user.h" struct pty_chan { void (*announce)(char *dev_name, int dev); @@ -33,7 +33,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts) if (data == NULL) return NULL; - *data = ((struct pty_chan) { .announce = opts->announce, + *data = ((struct pty_chan) { .announce = opts->announce, .dev = device, .raw = opts->raw }); return data; @@ -56,11 +56,11 @@ static int pts_open(int input, int output, int primary, void *d, if (data->raw) { CATCH_EINTR(err = tcgetattr(fd, &data->tt)); if (err) - return err; + goto out_close; err = raw(fd); if (err) - return err; + goto out_close; } dev = ptsname(fd); @@ -71,6 +71,10 @@ static int pts_open(int input, int output, int primary, void *d, (*data->announce)(dev, data->dev); return fd; + +out_close: + close(fd); + return err; } static int getmaster(char *line) @@ -97,7 +101,7 @@ static int getmaster(char *line) *tp = 't'; err = access(line, R_OK | W_OK); *tp = 'p'; - if(!err) + if (!err) return master; close(master); } @@ -119,12 +123,14 @@ static int pty_open(int input, int output, int primary, void *d, if (fd < 0) return fd; - if(data->raw){ + if (data->raw) { err = raw(fd); - if (err) + if (err) { + close(fd); return err; + } } - + if (data->announce) (*data->announce)(dev, data->dev); diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 125c44f7763..ae67e7158e7 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c @@ -1,11 +1,12 @@ -#include "linux/kernel.h" -#include "linux/stddef.h" -#include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/if_arp.h" +/* + * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL. + */ + +#include <linux/if_arp.h> +#include <linux/init.h> +#include <linux/netdevice.h> #include "net_kern.h" -#include "net_user.h" -#include "kern.h" #include "slip.h" struct slip_init { @@ -43,21 +44,19 @@ void slip_init(struct net_device *dev, void *data) static unsigned short slip_protocol(struct sk_buff *skbuff) { - return(htons(ETH_P_IP)); + return htons(ETH_P_IP); } -static int slip_read(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int slip_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(slip_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, - (struct slip_data *) &lp->user)); + return slip_user_read(fd, skb_mac_header(skb), skb->dev->mtu, + (struct slip_data *) &lp->user); } -static int slip_write(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int slip_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(slip_user_write(fd, (*skb)->data, (*skb)->len, - (struct slip_data *) &lp->user)); + return slip_user_write(fd, skb->data, skb->len, + (struct slip_data *) &lp->user); } const struct net_kern_info slip_kern_info = { @@ -71,12 +70,11 @@ static int slip_setup(char *str, char **mac_out, void *data) { struct slip_init *init = data; - *init = ((struct slip_init) - { .gate_addr = NULL }); + *init = ((struct slip_init) { .gate_addr = NULL }); - if(str[0] != '\0') + if (str[0] != '\0') init->gate_addr = str; - return(1); + return 1; } static struct transport slip_transport = { diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index c0b73c28cff..5f06204d687 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -1,21 +1,22 @@ +/* + * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL. + */ + #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <stddef.h> -#include <sched.h> -#include <string.h> #include <errno.h> +#include <fcntl.h> +#include <string.h> #include <sys/termios.h> #include <sys/wait.h> -#include <sys/signal.h> -#include "kern_util.h" -#include "user.h" +#include "kern_constants.h" #include "net_user.h" -#include "slip.h" -#include "slip_common.h" #include "os.h" +#include "slip.h" #include "um_malloc.h" -#include "kern_constants.h" +#include "user.h" static int slip_user_init(void *data, void *dev) { @@ -31,8 +32,9 @@ static int set_up_tty(int fd) struct termios tios; if (tcgetattr(fd, &tios) < 0) { - printk("could not get initial terminal attributes\n"); - return(-1); + printk(UM_KERN_ERR "could not get initial terminal " + "attributes\n"); + return -1; } tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; @@ -48,10 +50,10 @@ static int set_up_tty(int fd) cfsetispeed(&tios, B38400); if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { - printk("failed to set terminal attributes\n"); - return(-1); + printk(UM_KERN_ERR "failed to set terminal attributes\n"); + return -1; } - return(0); + return 0; } struct slip_pre_exec_data { @@ -64,9 +66,11 @@ static void slip_pre_exec(void *arg) { struct slip_pre_exec_data *data = arg; - if(data->stdin >= 0) dup2(data->stdin, 0); + if (data->stdin >= 0) + dup2(data->stdin, 0); dup2(data->stdout, 1); - if(data->close_me >= 0) os_close_file(data->close_me); + if (data->close_me >= 0) + close(data->close_me); } static int slip_tramp(char **argv, int fd) @@ -76,8 +80,9 @@ static int slip_tramp(char **argv, int fd) int status, pid, fds[2], err, output_len; err = os_pipe(fds, 1, 0); - if(err < 0){ - printk("slip_tramp : pipe failed, err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "slip_tramp : pipe failed, err = %d\n", + -err); goto out; } @@ -86,41 +91,42 @@ static int slip_tramp(char **argv, int fd) pe_data.stdout = fds[1]; pe_data.close_me = fds[0]; err = run_helper(slip_pre_exec, &pe_data, argv); - if(err < 0) + if (err < 0) goto out_close; pid = err; output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); - if(output == NULL){ - printk("slip_tramp : failed to allocate output buffer\n"); + if (output == NULL) { + printk(UM_KERN_ERR "slip_tramp : failed to allocate output " + "buffer\n"); os_kill_process(pid, 1); err = -ENOMEM; goto out_free; } - os_close_file(fds[1]); + close(fds[1]); read_output(fds[0], output, output_len); printk("%s", output); CATCH_EINTR(err = waitpid(pid, &status, 0)); - if(err < 0) + if (err < 0) err = errno; - else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ - printk("'%s' didn't exit with status 0\n", argv[0]); + else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { + printk(UM_KERN_ERR "'%s' didn't exit with status 0\n", argv[0]); err = -EINVAL; } else err = 0; - os_close_file(fds[0]); + close(fds[0]); out_free: kfree(output); return err; out_close: - os_close_file(fds[0]); - os_close_file(fds[1]); + close(fds[0]); + close(fds[1]); out: return err; } @@ -130,60 +136,64 @@ static int slip_open(void *data) struct slip_data *pri = data; char version_buf[sizeof("nnnnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; - char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, + char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, NULL }; int sfd, mfd, err; err = get_pty(); - if(err < 0){ - printk("slip-open : Failed to open pty, err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "slip-open : Failed to open pty, err = %d\n", + -err); goto out; } mfd = err; - err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); - if(err < 0){ - printk("Couldn't open tty for slip line, err = %d\n", -err); + err = open(ptsname(mfd), O_RDWR, 0); + if (err < 0) { + printk(UM_KERN_ERR "Couldn't open tty for slip line, " + "err = %d\n", -err); goto out_close; } sfd = err; - if(set_up_tty(sfd)) + if (set_up_tty(sfd)) goto out_close2; pri->slave = sfd; pri->slip.pos = 0; pri->slip.esc = 0; - if(pri->gate_addr != NULL){ + if (pri->gate_addr != NULL) { sprintf(version_buf, "%d", UML_NET_VERSION); strcpy(gate_buf, pri->gate_addr); err = slip_tramp(argv, sfd); - if(err < 0){ - printk("slip_tramp failed - err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "slip_tramp failed - err = %d\n", + -err); goto out_close2; } err = os_get_ifname(pri->slave, pri->name); - if(err < 0){ - printk("get_ifname failed, err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "get_ifname failed, err = %d\n", + -err); goto out_close2; } iter_addresses(pri->dev, open_addr, pri->name); } else { err = os_set_slip(sfd); - if(err < 0){ - printk("Failed to set slip discipline encapsulation - " - "err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "Failed to set slip discipline " + "encapsulation - err = %d\n", -err); goto out_close2; } } - return(mfd); + return mfd; out_close2: - os_close_file(sfd); + close(sfd); out_close: - os_close_file(mfd); + close(mfd); out: return err; } @@ -192,21 +202,21 @@ static void slip_close(int fd, void *data) { struct slip_data *pri = data; char version_buf[sizeof("nnnnn\0")]; - char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, + char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, NULL }; int err; - if(pri->gate_addr != NULL) + if (pri->gate_addr != NULL) iter_addresses(pri->dev, close_addr, pri->name); sprintf(version_buf, "%d", UML_NET_VERSION); err = slip_tramp(argv, pri->slave); - if(err != 0) - printk("slip_tramp failed - errno = %d\n", -err); - os_close_file(fd); - os_close_file(pri->slave); + if (err != 0) + printk(UM_KERN_ERR "slip_tramp failed - errno = %d\n", -err); + close(fd); + close(pri->slave); pri->slave = -1; } @@ -220,17 +230,13 @@ int slip_user_write(int fd, void *buf, int len, struct slip_data *pri) return slip_proto_write(fd, buf, len, &pri->slip); } -static int slip_set_mtu(int mtu, void *data) -{ - return(mtu); -} - static void slip_add_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct slip_data *pri = data; - if(pri->slave < 0) return; + if (pri->slave < 0) + return; open_addr(addr, netmask, pri->name); } @@ -239,7 +245,8 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask, { struct slip_data *pri = data; - if(pri->slave < 0) return; + if (pri->slave < 0) + return; close_addr(addr, netmask, pri->name); } @@ -248,8 +255,8 @@ const struct net_user_info slip_user_info = { .open = slip_open, .close = slip_close, .remove = NULL, - .set_mtu = slip_set_mtu, .add_address = slip_add_addr, .delete_address = slip_del_addr, - .max_packet = BUF_SIZE + .mtu = BUF_SIZE, + .max_packet = BUF_SIZE, }; diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index 0a0324a6d29..240ee650865 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c @@ -1,11 +1,14 @@ -#include "linux/kernel.h" -#include "linux/stddef.h" +/* + * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL. + */ + +#include <linux/if_arp.h> #include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/if_arp.h" +#include <linux/netdevice.h> +#include <linux/string.h> #include "net_kern.h" #include "net_user.h" -#include "kern.h" #include "slirp.h" struct slirp_init { @@ -39,29 +42,26 @@ void slirp_init(struct net_device *dev, void *data) dev->tx_queue_len = 256; dev->flags = IFF_NOARP; printk("SLIRP backend - command line:"); - for(i=0;spri->argw.argv[i]!=NULL;i++) { + for (i = 0; spri->argw.argv[i] != NULL; i++) printk(" '%s'",spri->argw.argv[i]); - } printk("\n"); } static unsigned short slirp_protocol(struct sk_buff *skbuff) { - return(htons(ETH_P_IP)); + return htons(ETH_P_IP); } -static int slirp_read(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(slirp_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, - (struct slirp_data *) &lp->user)); + return slirp_user_read(fd, skb_mac_header(skb), skb->dev->mtu, + (struct slirp_data *) &lp->user); } -static int slirp_write(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(slirp_user_write(fd, (*skb)->data, (*skb)->len, - (struct slirp_data *) &lp->user)); + return slirp_user_write(fd, skb->data, skb->len, + (struct slirp_data *) &lp->user); } const struct net_kern_info slirp_kern_info = { @@ -76,31 +76,32 @@ static int slirp_setup(char *str, char **mac_out, void *data) struct slirp_init *init = data; int i=0; - *init = ((struct slirp_init) - { .argw = { { "slirp", NULL } } }); + *init = ((struct slirp_init) { .argw = { { "slirp", NULL } } }); str = split_if_spec(str, mac_out, NULL); - if(str == NULL) { /* no command line given after MAC addr */ - return(1); - } + if (str == NULL) /* no command line given after MAC addr */ + return 1; do { - if(i>=SLIRP_MAX_ARGS-1) { - printk("slirp_setup: truncating slirp arguments\n"); + if (i >= SLIRP_MAX_ARGS - 1) { + printk(KERN_WARNING "slirp_setup: truncating slirp " + "arguments\n"); break; } init->argw.argv[i++] = str; while(*str && *str!=',') { - if(*str=='_') *str=' '; + if (*str == '_') + *str=' '; str++; } - if(*str!=',') + if (*str != ',') break; - *str++='\0'; - } while(1); - init->argw.argv[i]=NULL; - return(1); + *str++ = '\0'; + } while (1); + + init->argw.argv[i] = NULL; + return 1; } static struct transport slirp_transport = { diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index 0e462f64f22..1865089ff41 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c @@ -1,18 +1,17 @@ -#include <stdio.h> -#include <stdlib.h> +/* + * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL. + */ + #include <unistd.h> -#include <stddef.h> -#include <sched.h> -#include <string.h> #include <errno.h> +#include <string.h> #include <sys/wait.h> -#include <sys/signal.h> -#include "kern_util.h" -#include "user.h" +#include "kern_constants.h" #include "net_user.h" -#include "slirp.h" -#include "slip_common.h" #include "os.h" +#include "slirp.h" +#include "user.h" static int slirp_user_init(void *data, void *dev) { @@ -31,8 +30,10 @@ static void slirp_pre_exec(void *arg) { struct slirp_pre_exec_data *data = arg; - if(data->stdin != -1) dup2(data->stdin, 0); - if(data->stdout != -1) dup2(data->stdout, 1); + if (data->stdin != -1) + dup2(data->stdin, 0); + if (data->stdout != -1) + dup2(data->stdout, 1); } static int slirp_tramp(char **argv, int fd) @@ -44,7 +45,7 @@ static int slirp_tramp(char **argv, int fd) pe_data.stdout = fd; pid = run_helper(slirp_pre_exec, &pe_data, argv); - return(pid); + return pid; } static int slirp_open(void *data) @@ -53,12 +54,12 @@ static int slirp_open(void *data) int fds[2], pid, err; err = os_pipe(fds, 1, 1); - if(err) - return(err); + if (err) + return err; err = slirp_tramp(pri->argw.argv, fds[1]); - if(err < 0){ - printk("slirp_tramp failed - errno = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "slirp_tramp failed - errno = %d\n", -err); goto out; } pid = err; @@ -68,10 +69,10 @@ static int slirp_open(void *data) pri->slip.esc = 0; pri->pid = err; - return(fds[0]); + return fds[0]; out: - os_close_file(fds[0]); - os_close_file(fds[1]); + close(fds[0]); + close(fds[1]); return err; } @@ -80,31 +81,33 @@ static void slirp_close(int fd, void *data) struct slirp_data *pri = data; int status,err; - os_close_file(fd); - os_close_file(pri->slave); + close(fd); + close(pri->slave); pri->slave = -1; - if(pri->pid<1) { - printk("slirp_close: no child process to shut down\n"); + if (pri->pid<1) { + printk(UM_KERN_ERR "slirp_close: no child process to shut " + "down\n"); return; } #if 0 - if(kill(pri->pid, SIGHUP)<0) { - printk("slirp_close: sending hangup to %d failed (%d)\n", - pri->pid, errno); + if (kill(pri->pid, SIGHUP)<0) { + printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed " + "(%d)\n", pri->pid, errno); } #endif CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); - if(err < 0) { - printk("slirp_close: waitpid returned %d\n", errno); + if (err < 0) { + printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno); return; } - if(err == 0) { - printk("slirp_close: process %d has not exited\n", pri->pid); + if (err == 0) { + printk(UM_KERN_ERR "slirp_close: process %d has not exited\n", + pri->pid); return; } @@ -121,18 +124,13 @@ int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) return slip_proto_write(fd, buf, len, &pri->slip); } -static int slirp_set_mtu(int mtu, void *data) -{ - return(mtu); -} - const struct net_user_info slirp_user_info = { .init = slirp_user_init, .open = slirp_open, .close = slirp_close, .remove = NULL, - .set_mtu = slirp_set_mtu, .add_address = NULL, .delete_address = NULL, - .max_packet = BUF_SIZE + .mtu = BUF_SIZE, + .max_packet = BUF_SIZE, }; diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index a9f87e19c5b..c930fedc517 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include <stdio.h> -#include <termios.h> #include <errno.h> -#include <unistd.h> +#include <fcntl.h> +#include <termios.h> #include "chan_user.h" -#include "user.h" +#include "kern_constants.h" #include "os.h" #include "um_malloc.h" +#include "user.h" struct tty_chan { char *dev; @@ -22,15 +22,15 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) { struct tty_chan *data; - if(*str != ':'){ - printk("tty_init : channel type 'tty' must specify " + if (*str != ':') { + printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify " "a device\n"); return NULL; } str++; data = kmalloc(sizeof(*data), UM_GFP_KERNEL); - if(data == NULL) + if (data == NULL) return NULL; *data = ((struct tty_chan) { .dev = str, .raw = opts->raw }); @@ -42,19 +42,26 @@ static int tty_open(int input, int output, int primary, void *d, char **dev_out) { struct tty_chan *data = d; - int fd, err; + int fd, err, mode = 0; + + if (input && output) + mode = O_RDWR; + else if (input) + mode = O_RDONLY; + else if (output) + mode = O_WRONLY; - fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); - if(fd < 0) - return fd; + fd = open(data->dev, mode); + if (fd < 0) + return -errno; - if(data->raw){ + if (data->raw) { CATCH_EINTR(err = tcgetattr(fd, &data->tt)); - if(err) + if (err) return err; err = raw(fd); - if(err) + if (err) return err; } diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0eabe73c964..25b248a0250 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -615,7 +615,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long)); err = -ENOMEM; - ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); + ubd_dev->cow.bitmap = vmalloc(ubd_dev->cow.bitmap_len); if(ubd_dev->cow.bitmap == NULL){ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); goto error; diff --git a/arch/um/drivers/vde.h b/arch/um/drivers/vde.h new file mode 100644 index 00000000000..fc3a05902ba --- /dev/null +++ b/arch/um/drivers/vde.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). + * Licensed under the GPL. + */ + +#ifndef __UM_VDE_H__ +#define __UM_VDE_H__ + +struct vde_data { + char *vde_switch; + char *descr; + void *args; + void *conn; + void *dev; +}; + +struct vde_init { + char *vde_switch; + char *descr; + int port; + char *group; + int mode; +}; + +extern const struct net_user_info vde_user_info; + +extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init); + +extern int vde_user_read(void *conn, void *buf, int len); +extern int vde_user_write(void *conn, void *buf, int len); + +#endif diff --git a/arch/um/drivers/vde_kern.c b/arch/um/drivers/vde_kern.c new file mode 100644 index 00000000000..add7e722def --- /dev/null +++ b/arch/um/drivers/vde_kern.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). + * Licensed under the GPL. + * + * Transport usage: + * ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description> + * + */ + +#include "linux/init.h" +#include <linux/netdevice.h> +#include "net_kern.h" +#include "net_user.h" +#include "vde.h" + +static void vde_init(struct net_device *dev, void *data) +{ + struct vde_init *init = data; + struct uml_net_private *pri; + struct vde_data *vpri; + + pri = dev->priv; + vpri = (struct vde_data *) pri->user; + + vpri->vde_switch = init->vde_switch; + vpri->descr = init->descr ? init->descr : "UML vde_transport"; + vpri->args = NULL; + vpri->conn = NULL; + vpri->dev = dev; + + printk("vde backend - %s, ", vpri->vde_switch ? + vpri->vde_switch : "(default socket)"); + + vde_init_libstuff(vpri, init); + + printk("\n"); +} + +static int vde_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + struct vde_data *pri = (struct vde_data *) &lp->user; + + if (pri->conn != NULL) + return vde_user_read(pri->conn, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); + + printk(KERN_ERR "vde_read - we have no VDECONN to read from"); + return -EBADF; +} + +static int vde_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + struct vde_data *pri = (struct vde_data *) &lp->user; + + if (pri->conn != NULL) + return vde_user_write((void *)pri->conn, skb->data, + skb->len); + + printk(KERN_ERR "vde_write - we have no VDECONN to write to"); + return -EBADF; +} + +static const struct net_kern_info vde_kern_info = { + .init = vde_init, + .protocol = eth_protocol, + .read = vde_read, + .write = vde_write, +}; + +static int vde_setup(char *str, char **mac_out, void *data) +{ + struct vde_init *init = data; + char *remain, *port_str = NULL, *mode_str = NULL, *last; + + *init = ((struct vde_init) + { .vde_switch = NULL, + .descr = NULL, + .port = 0, + .group = NULL, + .mode = 0 }); + + remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str, + &init->group, &mode_str, &init->descr, NULL); + + if (remain != NULL) + printk(KERN_WARNING "vde_setup - Ignoring extra data :" + "'%s'\n", remain); + + if (port_str != NULL) { + init->port = simple_strtoul(port_str, &last, 10); + if ((*last != '\0') || (last == port_str)) { + printk(KERN_ERR "vde_setup - Bad port : '%s'\n", + port_str); + return 0; + } + } + + if (mode_str != NULL) { + init->mode = simple_strtoul(mode_str, &last, 8); + if ((*last != '\0') || (last == mode_str)) { + printk(KERN_ERR "vde_setup - Bad mode : '%s'\n", + mode_str); + return 0; + } + } + + printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ? + init->vde_switch : "(default socket)"); + + return 1; +} + +static struct transport vde_transport = { + .list = LIST_HEAD_INIT(vde_transport.list), + .name = "vde", + .setup = vde_setup, + .user = &vde_user_info, + .kern = &vde_kern_info, + .private_size = sizeof(struct vde_data), + .setup_size = sizeof(struct vde_init), +}; + +static int register_vde(void) +{ + register_transport(&vde_transport); + return 0; +} + +late_initcall(register_vde); diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c new file mode 100644 index 00000000000..d9941fe5f93 --- /dev/null +++ b/arch/um/drivers/vde_user.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). + * Licensed under the GPL. + */ + +#include <stddef.h> +#include <errno.h> +#include <libvdeplug.h> +#include "kern_constants.h" +#include "net_user.h" +#include "um_malloc.h" +#include "user.h" +#include "vde.h" + +static int vde_user_init(void *data, void *dev) +{ + struct vde_data *pri = data; + VDECONN *conn = NULL; + int err = -EINVAL; + + pri->dev = dev; + + conn = vde_open(pri->vde_switch, pri->descr, pri->args); + + if (conn == NULL) { + err = -errno; + printk(UM_KERN_ERR "vde_user_init: vde_open failed, " + "errno = %d\n", errno); + return err; + } + + printk(UM_KERN_INFO "vde backend - connection opened\n"); + + pri->conn = conn; + + return 0; +} + +static int vde_user_open(void *data) +{ + struct vde_data *pri = data; + + if (pri->conn != NULL) + return vde_datafd(pri->conn); + + printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open"); + return -EINVAL; +} + +static void vde_remove(void *data) +{ + struct vde_data *pri = data; + + if (pri->conn != NULL) { + printk(UM_KERN_INFO "vde backend - closing connection\n"); + vde_close(pri->conn); + pri->conn = NULL; + kfree(pri->args); + pri->args = NULL; + return; + } + + printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove"); +} + +const struct net_user_info vde_user_info = { + .init = vde_user_init, + .open = vde_user_open, + .close = NULL, + .remove = vde_remove, + .add_address = NULL, + .delete_address = NULL, + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, +}; + +void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init) +{ + struct vde_open_args *args; + + vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL); + if (vpri->args == NULL) { + printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args" + "allocation failed"); + return; + } + + args = vpri->args; + + args->port = init->port; + args->group = init->group; + args->mode = init->mode ? init->mode : 0700; + + args->port ? printk(UM_KERN_INFO "port %d", args->port) : + printk(UM_KERN_INFO "undefined port"); +} + +int vde_user_read(void *conn, void *buf, int len) +{ + VDECONN *vconn = conn; + int rv; + + if (vconn == NULL) + return 0; + + rv = vde_recv(vconn, buf, len, 0); + if (rv < 0) { + if (errno == EAGAIN) + return 0; + return -errno; + } + else if (rv == 0) + return -ENOTCONN; + + return rv; +} + +int vde_user_write(void *conn, void *buf, int len) +{ + VDECONN *vconn = conn; + + if (vconn == NULL) + return 0; + + return vde_send(vconn, buf, len, 0); +} + diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index fd817e54154..8a1c18a9b24 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -1,20 +1,21 @@ -/* +/* * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdlib.h> +#include <stddef.h> #include <stdio.h> +#include <stdlib.h> #include <unistd.h> -#include <string.h> #include <errno.h> +#include <string.h> #include <termios.h> #include "chan_user.h" +#include "kern_constants.h" #include "os.h" -#include "init.h" +#include "um_malloc.h" #include "user.h" #include "xterm.h" -#include "kern_constants.h" struct xterm_chan { int pid; @@ -29,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts) { struct xterm_chan *data; - data = malloc(sizeof(*data)); + data = kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; *data = ((struct xterm_chan) { .pid = -1, @@ -95,8 +96,10 @@ static int xterm_open(int input, int output, int primary, void *d, if (access(argv[4], X_OK) < 0) argv[4] = "port-helper"; - /* Check that DISPLAY is set, this doesn't guarantee the xterm - * will work but w/o it we can be pretty sure it won't. */ + /* + * Check that DISPLAY is set, this doesn't guarantee the xterm + * will work but w/o it we can be pretty sure it won't. + */ if (getenv("DISPLAY") == NULL) { printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n"); return -ENODEV; @@ -195,7 +198,7 @@ static int xterm_open(int input, int output, int primary, void *d, static void xterm_close(int fd, void *d) { struct xterm_chan *data = d; - + if (data->pid != -1) os_kill_process(data->pid, 1); data->pid = -1; @@ -207,11 +210,6 @@ static void xterm_close(int fd, void *d) os_close_file(fd); } -static void xterm_free(void *d) -{ - free(d); -} - const struct chan_ops xterm_ops = { .type = "xterm", .init = xterm_init, @@ -221,6 +219,6 @@ const struct chan_ops xterm_ops = { .write = generic_write, .console_write = generic_console_write, .window_size = generic_window_size, - .free = xterm_free, + .free = generic_free, .winch = 1, }; diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h index 10ad52daa8c..49c601ff2ba 100644 --- a/arch/um/include/arch.h +++ b/arch/um/include/arch.h @@ -9,7 +9,7 @@ #include "sysdep/ptrace.h" extern void arch_check_bugs(void); -extern int arch_fixup(unsigned long address, union uml_pt_regs *regs); -extern int arch_handle_signal(int sig, union uml_pt_regs *regs); +extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); +extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); #endif diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index fccf187bf4e..a5cdf953e04 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h @@ -6,6 +6,28 @@ #ifndef __START_H__ #define __START_H__ +#include "uml-config.h" +#include "kern_constants.h" + +/* + * Assembly doesn't want any casting, but C does, so define these + * without casts here, and define new symbols with casts inside the C + * section. + */ +#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE) +#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE) +#define ASM_STUB_START ASM_STUB_CODE + +/* + * This file is included by the assembly stubs, which just want the + * definitions above. + */ +#ifndef __ASSEMBLY__ + +#define STUB_CODE ((unsigned long) ASM_STUB_CODE) +#define STUB_DATA ((unsigned long) ASM_STUB_DATA) +#define STUB_START ((unsigned long) ASM_STUB_START) + #include "sysdep/ptrace.h" struct cpu_task { @@ -28,8 +50,9 @@ extern unsigned long _unprotected_end; extern unsigned long brk_start; extern int linux_main(int argc, char **argv); -extern void set_cmdline(char *cmd); -extern void (*sig_info[])(int, union uml_pt_regs *); +extern void (*sig_info[])(int, struct uml_pt_regs *); + +#endif #endif diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h deleted file mode 100644 index b87b36a87d9..00000000000 --- a/arch/um/include/choose-mode.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __CHOOSE_MODE_H__ -#define __CHOOSE_MODE_H__ - -#include "uml-config.h" - -#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS) -#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas)) - -extern int mode_tt; -static inline void *__choose_mode(void *tt, void *skas) { - return mode_tt ? tt : skas; -} - -#define __CHOOSE_MODE(tt, skas) (*( (typeof(tt) *) __choose_mode(&(tt), &(skas)))) - -#elif defined(UML_CONFIG_MODE_SKAS) -#define CHOOSE_MODE(tt, skas) (skas) - -#elif defined(UML_CONFIG_MODE_TT) -#define CHOOSE_MODE(tt, skas) (tt) - -#else -#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled -#endif - -#define CHOOSE_MODE_PROC(tt, skas, args...) \ - CHOOSE_MODE(tt(args), skas(args)) - -#ifndef __CHOOSE_MODE -#define __CHOOSE_MODE(tt, skas) CHOOSE_MODE(tt, skas) -#endif - -#endif diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 6eee343e53e..0edab695ed4 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h @@ -1,15 +1,13 @@ /* for use by sys-$SUBARCH/kernel-offsets.c */ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE); -#ifdef CONFIG_MODE_TT -OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); -#endif OFFSET(HOST_TASK_REGS, task_struct, thread.regs); OFFSET(HOST_TASK_PID, task_struct, pid); DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); +DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); @@ -34,3 +32,9 @@ DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC); DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); DEFINE(UM_THREAD_SIZE, THREAD_SIZE); + +DEFINE(UM_HZ, HZ); + +DEFINE(UM_USEC_PER_SEC, USEC_PER_SEC); +DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); +DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC); diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h index 15d311b9be9..884a9c17eea 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __IRQ_USER_H__ #define __IRQ_USER_H__ -#include "uml-config.h" +#include "sysdep/ptrace.h" struct irq_fd { struct irq_fd *next; @@ -21,7 +21,7 @@ struct irq_fd { enum { IRQ_READ, IRQ_WRITE }; -extern void sigio_handler(int sig, union uml_pt_regs *regs); +extern void sigio_handler(int sig, struct uml_pt_regs *regs); extern int activate_fd(int irq, int fd, int type, void *dev_id); extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id); extern void free_irq_by_fd(int fd); @@ -30,8 +30,4 @@ extern void deactivate_fd(int fd, int irqnum); extern int deactivate_all_fds(void); extern int activate_ipi(int fd, int pid); -#ifdef CONFIG_MODE_TT -extern void forward_interrupts(int pid); -#endif - #endif diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 6c2be26f1d7..74ce8e5370a 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -8,9 +8,8 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" -#include "uml-config.h" -typedef void (*kern_hndl)(int, union uml_pt_regs *); +typedef void (*kern_hndl)(int, struct uml_pt_regs *); struct kern_handlers { kern_hndl relay_signal; @@ -34,9 +33,6 @@ extern int nsyscalls; UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); -#ifdef UML_CONFIG_MODE_TT -extern unsigned long stack_sp(unsigned long page); -#endif extern int kernel_thread_proc(void *data); extern void syscall_segv(int sig); extern int current_pid(void); @@ -44,7 +40,7 @@ extern unsigned long alloc_stack(int order, int atomic); extern int do_signal(void); extern int is_stack_fault(unsigned long sp); extern unsigned long segv(struct faultinfo fi, unsigned long ip, - int is_user, union uml_pt_regs *regs); + int is_user, struct uml_pt_regs *regs); extern int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out); extern void syscall_ready(void); @@ -57,7 +53,7 @@ extern int need_finish_fork(void); extern void free_stack(unsigned long stack, int order); extern void add_input_request(int op, void (*proc)(int), void *arg); extern char *current_cmd(void); -extern void timer_handler(int sig, union uml_pt_regs *regs); +extern void timer_handler(int sig, struct uml_pt_regs *regs); extern int set_signals(int enable); extern int pid_to_processor_id(int pid); extern void deliver_signals(void *t); @@ -67,9 +63,8 @@ extern void finish_fork(void); extern void paging_init(void); extern void init_flush_vm(void); extern void *syscall_sp(void *t); -extern void syscall_trace(union uml_pt_regs *regs, int entryexit); -extern int hz(void); -extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); +extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); +extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); extern void interrupt_end(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int debugger_signal(int status, int pid); @@ -79,10 +74,9 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop); extern int init_parent_proxy(int pid); extern int singlestepping(void *t); extern void check_stack_overflow(void *ptr); -extern void relay_signal(int sig, union uml_pt_regs *regs); +extern void relay_signal(int sig, struct uml_pt_regs *regs); extern int user_context(unsigned long sp); -extern void timer_irq(union uml_pt_regs *regs); -extern void unprotect_stack(unsigned long stack); +extern void timer_irq(struct uml_pt_regs *regs); extern void do_uml_exitcalls(void); extern int attach_debugger(int idle_pid, int pid, int stop); extern int config_gdb(char *str); @@ -113,11 +107,9 @@ extern void time_init_kern(void); /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ extern int __cant_sleep(void); -extern void sigio_handler(int sig, union uml_pt_regs *regs); - -extern void copy_sc(union uml_pt_regs *regs, void *from); - +extern void sigio_handler(int sig, struct uml_pt_regs *regs); +extern void copy_sc(struct uml_pt_regs *regs, void *from); extern unsigned long to_irq_stack(unsigned long *mask_out); unsigned long from_irq_stack(int nested); - +extern int start_uml(void); #endif diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index b282839c162..c139ae1d682 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -63,7 +63,7 @@ struct mc_request struct mconsole_request request; struct mconsole_command *cmd; - union uml_pt_regs regs; + struct uml_pt_regs regs; }; extern char mconsole_socket_name[]; @@ -96,14 +96,3 @@ extern void lock_notify(void); extern void unlock_notify(void); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h index e8ff0d8fa61..5cd40e99e8d 100644 --- a/arch/um/include/mem.h +++ b/arch/um/include/mem.h @@ -1,18 +1,12 @@ /* - * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __MEM_H__ #define __MEM_H__ -#include "linux/types.h" - -extern int phys_mapping(unsigned long phys, __u64 *offset_out); -extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); -extern int is_remapped(void *virt); -extern int physmem_remove_mapping(void *virt); -extern void physmem_forget_descriptor(int fd); +extern int phys_mapping(unsigned long phys, unsigned long long *offset_out); extern unsigned long uml_physmem; static inline unsigned long to_phys(void *virt) @@ -26,14 +20,3 @@ static inline void *to_virt(unsigned long phys) } #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/mode.h b/arch/um/include/mode.h deleted file mode 100644 index 786cf563eb0..00000000000 --- a/arch/um/include/mode.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_H__ -#define __MODE_H__ - -#include "uml-config.h" - -#ifdef UML_CONFIG_MODE_TT -#include "mode-tt.h" -#endif - -#ifdef UML_CONFIG_MODE_SKAS -#include "mode-skas.h" -#endif - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h deleted file mode 100644 index 88e5e77bf51..00000000000 --- a/arch/um/include/mode_kern.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_KERN_H__ -#define __MODE_KERN_H__ - -#ifdef CONFIG_MODE_TT -#include "mode_kern_tt.h" -#endif - -#ifdef CONFIG_MODE_SKAS -#include "mode_kern_skas.h" -#endif - -#endif diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 9237056b910..d843c7924a7 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -30,24 +30,24 @@ struct uml_net_private { struct work_struct work; int fd; unsigned char mac[ETH_ALEN]; + int max_packet; unsigned short (*protocol)(struct sk_buff *); int (*open)(void *); void (*close)(int, void *); void (*remove)(void *); - int (*read)(int, struct sk_buff **skb, struct uml_net_private *); - int (*write)(int, struct sk_buff **skb, struct uml_net_private *); + int (*read)(int, struct sk_buff *skb, struct uml_net_private *); + int (*write)(int, struct sk_buff *skb, struct uml_net_private *); void (*add_address)(unsigned char *, unsigned char *, void *); void (*delete_address)(unsigned char *, unsigned char *, void *); - int (*set_mtu)(int mtu, void *); char user[0]; }; struct net_kern_info { void (*init)(struct net_device *, void *); unsigned short (*protocol)(struct sk_buff *); - int (*read)(int, struct sk_buff **skb, struct uml_net_private *); - int (*write)(int, struct sk_buff **skb, struct uml_net_private *); + int (*read)(int, struct sk_buff *skb, struct uml_net_private *); + int (*write)(int, struct sk_buff *skb, struct uml_net_private *); }; struct transport { @@ -62,7 +62,6 @@ struct transport { extern struct net_device *ether_init(int); extern unsigned short ether_protocol(struct sk_buff *); -extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); extern int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, char **gate_addr); extern void register_transport(struct transport *new); diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h index cfe7c50634b..63bee158cd8 100644 --- a/arch/um/include/net_user.h +++ b/arch/um/include/net_user.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -18,10 +18,10 @@ struct net_user_info { int (*open)(void *); void (*close)(int, void *); void (*remove)(void *); - int (*set_mtu)(int mtu, void *); void (*add_address)(unsigned char *, unsigned char *, void *); void (*delete_address)(unsigned char *, unsigned char *, void *); int max_packet; + int mtu; }; extern void ether_user_init(void *data, void *dev); diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 930b261ea48..fbf0a87c6ea 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -1,20 +1,18 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __OS_H__ #define __OS_H__ -#include "uml-config.h" -#include "asm/types.h" -#include "../os/include/file.h" -#include "sysdep/ptrace.h" -#include "kern_util.h" -#include "skas/mm_id.h" +#include <stdarg.h> #include "irq_user.h" +#include "kern_util.h" +#include "longjmp.h" +#include "mm_id.h" #include "sysdep/tls.h" -#include "sysdep/archsetjmp.h" +#include "../os/include/file.h" #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) @@ -130,18 +128,15 @@ static inline struct openflags of_cloexec(struct openflags flags) extern int os_stat_file(const char *file_name, struct uml_stat *buf); extern int os_stat_fd(const int fd, struct uml_stat *buf); extern int os_access(const char *file, int mode); -extern void os_print_error(int error, const char* str); extern int os_get_exec_close(int fd, int *close_on_exec); -extern int os_set_exec_close(int fd, int close_on_exec); +extern int os_set_exec_close(int fd); extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); -extern int os_window_size(int fd, int *rows, int *cols); -extern int os_new_tty_pgrp(int fd, int pid); extern int os_get_ifname(int fd, char *namebuf); extern int os_set_slip(int fd); extern int os_set_owner(int fd, int pid); extern int os_mode_fd(int fd, int mode); -extern int os_seek_file(int fd, __u64 offset); +extern int os_seek_file(int fd, unsigned long long offset); extern int os_open_file(char *file, struct openflags flags, int mode); extern int os_read_file(int fd, void *buf, int len); extern int os_write_file(int fd, const void *buf, int count); @@ -179,11 +174,7 @@ extern void check_host_supports_tls(int *supports_tls, int *tls_min); /* Make sure they are clear when running in TT mode. Required by * SEGV_MAYBE_FIXABLE */ -#ifdef UML_CONFIG_MODE_SKAS #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) -#else -#define clear_can_do_skas() do {} while (0) -#endif /* mem.c */ extern int create_mem_file(unsigned long long len); @@ -194,20 +185,13 @@ extern int os_process_parent(int pid); extern void os_stop_process(int pid); extern void os_kill_process(int pid, int reap_child); extern void os_kill_ptraced_process(int pid, int reap_child); -#ifdef UML_CONFIG_MODE_TT -extern void os_usr1_process(int pid); -#endif extern long os_ptrace_ldt(long pid, long addr, long data); extern int os_getpid(void); extern int os_getpgrp(void); -#ifdef UML_CONFIG_MODE_TT -extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); -extern void stop(void); -#endif extern void init_new_thread_signals(void); -extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); +extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr); extern int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x); @@ -218,21 +202,9 @@ extern int os_drop_memory(void *addr, int length); extern int can_drop_memory(void); extern void os_flush_stdout(void); -/* tt.c - * for tt mode only (will be deleted in future...) - */ -extern void forward_ipi(int fd, int pid); -extern void kill_child_dead(int pid); -extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); -extern int protect_memory(unsigned long addr, unsigned long len, - int r, int w, int x, int must_succeed); -extern void forward_pending_sigio(int target); -extern int start_fork_tramp(void *arg, unsigned long temp_stack, - int clone_flags, int (*tramp)(void *)); - /* uaccess.c */ extern unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher, + void **fault_addr, jmp_buf **fault_catcher, void (*op)(void *to, const void *from, int n), int *faulted_out); @@ -255,6 +227,7 @@ extern int set_umid(char *name); extern char *get_umid(void); /* signal.c */ +extern void timer_init(void); extern void set_sigstack(void *sig_stack, int size); extern void remove_sigstack(void); extern void set_handler(int sig, void (*handler)(int), int flags, ...); @@ -266,7 +239,6 @@ extern int set_signals(int enable); /* trap.c */ extern void os_fill_handlinfo(struct kern_handlers h); -extern void do_longjmp(void *p, int val); /* util.c */ extern void stack_protections(unsigned long address); @@ -277,17 +249,12 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...); extern void os_dump_core(void); /* time.c */ -#define BILLION (1000 * 1000 * 1000) - -extern void switch_timers(int to_real); -extern void idle_sleep(int secs); -extern int set_interval(int is_virtual); -#ifdef CONFIG_MODE_TT -extern void enable_timer(void); -#endif -extern void disable_timer(void); +extern void idle_sleep(unsigned long long nsecs); +extern int set_interval(void); +extern int timer_one_shot(int ticks); +extern long long disable_timer(void); extern void uml_idle_timer(void); -extern unsigned long long os_nsecs(void); +extern long long os_nsecs(void); /* skas/mem.c */ extern long run_syscall_stub(struct mm_id * mm_idp, @@ -308,7 +275,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr, extern int is_skas_winch(int pid, int fd, void *data); extern int start_userspace(unsigned long stub_stack); extern int copy_context_skas0(unsigned long stack, int pid); -extern void userspace(union uml_pt_regs *regs); +extern void save_registers(int pid, struct uml_pt_regs *regs); +extern void restore_registers(int pid, struct uml_pt_regs *regs); +extern void userspace(struct uml_pt_regs *regs); extern void map_stub_pages(int fd, unsigned long code, unsigned long data, unsigned long stack); extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index f845b3629a6..0e27406a43a 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h @@ -9,13 +9,15 @@ #include "sysdep/ptrace.h" #include "sysdep/archsetjmp.h" -extern void init_thread_registers(union uml_pt_regs *to); +extern void init_thread_registers(struct uml_pt_regs *to); extern int save_fp_registers(int pid, unsigned long *fp_regs); extern int restore_fp_registers(int pid, unsigned long *fp_regs); -extern void save_registers(int pid, union uml_pt_regs *regs); -extern void restore_registers(int pid, union uml_pt_regs *regs); +extern int save_fpx_registers(int pid, unsigned long *fp_regs); +extern int restore_fpx_registers(int pid, unsigned long *fp_regs); +extern void save_registers(int pid, struct uml_pt_regs *regs); +extern void restore_registers(int pid, struct uml_pt_regs *regs); extern void init_registers(int pid); -extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); +extern void get_safe_registers(unsigned long *regs); extern unsigned long get_thread_reg(int reg, jmp_buf *buf); #endif diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h deleted file mode 100644 index b26986c0c3d..00000000000 --- a/arch/um/include/skas/mmu-skas.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_MMU_H -#define __SKAS_MMU_H - -#include "mm_id.h" -#include "asm/ldt.h" - -struct mmu_context_skas { - struct mm_id id; - unsigned long last_page_table; -#ifdef CONFIG_3_LEVEL_PGTABLES - unsigned long last_pmd; -#endif - uml_ldt_t ldt; -}; - -extern void switch_mm_skas(struct mm_id * mm_idp); - -#endif diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h index 8bc6916bbbb..e065feb000d 100644 --- a/arch/um/include/skas/mode-skas.h +++ b/arch/um/include/skas/mode-skas.h @@ -1,18 +1,11 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ #ifndef __MODE_SKAS_H__ #define __MODE_SKAS_H__ -#include <sysdep/ptrace.h> - -extern unsigned long exec_regs[]; -extern unsigned long exec_fp_regs[]; -extern unsigned long exec_fpx_regs[]; -extern int have_fpx_regs; - extern void kill_off_processes_skas(void); #endif diff --git a/arch/um/include/skas/mode_kern_skas.h b/arch/um/include/skas/mode_kern_skas.h deleted file mode 100644 index 8ee6285dfac..00000000000 --- a/arch/um/include/skas/mode_kern_skas.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_MODE_KERN_H__ -#define __SKAS_MODE_KERN_H__ - -#include "linux/sched.h" -#include "asm/page.h" -#include "asm/ptrace.h" - -extern void flush_thread_skas(void); -extern void switch_to_skas(void *prev, void *next); -extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, - unsigned long esp); -extern int copy_thread_skas(int nr, unsigned long clone_flags, - unsigned long sp, unsigned long stack_top, - struct task_struct *p, struct pt_regs *regs); -extern void release_thread_skas(struct task_struct *task); -extern void init_idle_skas(void); -extern void flush_tlb_kernel_range_skas(unsigned long start, - unsigned long end); -extern void flush_tlb_kernel_vm_skas(void); -extern void __flush_tlb_one_skas(unsigned long addr); -extern void flush_tlb_range_skas(struct vm_area_struct *vma, - unsigned long start, unsigned long end); -extern void flush_tlb_mm_skas(struct mm_struct *mm); -extern void force_flush_all_skas(void); -extern long execute_syscall_skas(void *r); -extern void before_mem_skas(unsigned long unused); -extern unsigned long set_task_sizes_skas(unsigned long *task_size_out); -extern int start_uml_skas(void); -extern int external_pid_skas(struct task_struct *task); -extern int thread_pid_skas(struct task_struct *task); -extern void flush_tlb_page_skas(struct vm_area_struct *vma, - unsigned long address); - -#define kmem_end_skas (host_task_size - 1024 * 1024) - -#endif diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index e88926b1607..b073f8a86bd 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h @@ -1,12 +1,11 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __SKAS_H #define __SKAS_H -#include "mm_id.h" #include "sysdep/ptrace.h" extern int userspace_pid[]; @@ -15,7 +14,7 @@ extern int skas_needs_stub; extern int user_thread(unsigned long stack, int flags); extern void new_thread_handler(void); -extern void handle_syscall(union uml_pt_regs *regs); +extern void handle_syscall(struct uml_pt_regs *regs); extern int new_mm(unsigned long stack); extern void get_skas_faultinfo(int pid, struct faultinfo * fi); extern long execute_syscall_skas(void *r); diff --git a/arch/um/include/skas/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h deleted file mode 100644 index 224a75f4c02..00000000000 --- a/arch/um/include/skas/uaccess-skas.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_UACCESS_H -#define __SKAS_UACCESS_H - -#include "asm/errno.h" - -/* No SKAS-specific checking. */ -#define access_ok_skas(type, addr, size) 0 - -extern int copy_from_user_skas(void *to, const void __user *from, int n); -extern int copy_to_user_skas(void __user *to, const void *from, int n); -extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); -extern int __clear_user_skas(void __user *mem, int len); -extern int clear_user_skas(void __user *mem, int len); -extern int strnlen_user_skas(const void __user *str, int len); - -#endif diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h index 97ec9d894d7..5868526b5ee 100644 --- a/arch/um/include/sysdep-i386/kernel-offsets.h +++ b/arch/um/include/sysdep-i386/kernel-offsets.h @@ -17,6 +17,5 @@ void foo(void) { - OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs); #include <common-offsets.h> } diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h index 52b398bcafc..11c08969d13 100644 --- a/arch/um/include/sysdep-i386/ptrace.h +++ b/arch/um/include/sysdep-i386/ptrace.h @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -9,17 +9,11 @@ #include "uml-config.h" #include "user_constants.h" #include "sysdep/faultinfo.h" -#include "choose-mode.h" #define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long)) #define MAX_REG_OFFSET (UM_FRAME_SIZE) -#ifdef UML_CONFIG_PT_PROXY -extern void update_debugregs(int seq); -#else static inline void update_debugregs(int seq) {} -#endif - /* syscall emulation path in ptrace */ @@ -31,12 +25,6 @@ void set_using_sysemu(int value); int get_using_sysemu(void); extern int sysemu_supported; -#ifdef UML_CONFIG_MODE_TT -#include "sysdep/sc.h" -#endif - -#ifdef UML_CONFIG_MODE_SKAS - #include "skas_ptregs.h" #define REGS_IP(r) ((r)[HOST_IP]) @@ -60,70 +48,36 @@ extern int sysemu_supported; #define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) -#endif #ifndef PTRACE_SYSEMU_SINGLESTEP #define PTRACE_SYSEMU_SINGLESTEP 32 #endif -union uml_pt_regs { -#ifdef UML_CONFIG_MODE_TT - struct tt_regs { - long syscall; - void *sc; - struct faultinfo faultinfo; - } tt; -#endif -#ifdef UML_CONFIG_MODE_SKAS - struct skas_regs { - unsigned long regs[MAX_REG_NR]; - unsigned long fp[HOST_FP_SIZE]; - unsigned long xfp[HOST_XFP_SIZE]; - struct faultinfo faultinfo; - long syscall; - int is_user; - } skas; -#endif +struct uml_pt_regs { + unsigned long gp[MAX_REG_NR]; + struct faultinfo faultinfo; + long syscall; + int is_user; }; #define EMPTY_UML_PT_REGS { } -extern int mode_tt; - -#define UPT_SC(r) ((r)->tt.sc) -#define UPT_IP(r) \ - __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) -#define UPT_SP(r) \ - __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) -#define UPT_EFLAGS(r) \ - __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) -#define UPT_EAX(r) \ - __CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs)) -#define UPT_EBX(r) \ - __CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs)) -#define UPT_ECX(r) \ - __CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs)) -#define UPT_EDX(r) \ - __CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs)) -#define UPT_ESI(r) \ - __CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs)) -#define UPT_EDI(r) \ - __CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs)) -#define UPT_EBP(r) \ - __CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs)) -#define UPT_ORIG_EAX(r) \ - __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) -#define UPT_CS(r) \ - __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) -#define UPT_SS(r) \ - __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) -#define UPT_DS(r) \ - __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) -#define UPT_ES(r) \ - __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) -#define UPT_FS(r) \ - __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) -#define UPT_GS(r) \ - __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) +#define UPT_IP(r) REGS_IP((r)->gp) +#define UPT_SP(r) REGS_SP((r)->gp) +#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) +#define UPT_EAX(r) REGS_EAX((r)->gp) +#define UPT_EBX(r) REGS_EBX((r)->gp) +#define UPT_ECX(r) REGS_ECX((r)->gp) +#define UPT_EDX(r) REGS_EDX((r)->gp) +#define UPT_ESI(r) REGS_ESI((r)->gp) +#define UPT_EDI(r) REGS_EDI((r)->gp) +#define UPT_EBP(r) REGS_EBP((r)->gp) +#define UPT_ORIG_EAX(r) ((r)->syscall) +#define UPT_CS(r) REGS_CS((r)->gp) +#define UPT_SS(r) REGS_SS((r)->gp) +#define UPT_DS(r) REGS_DS((r)->gp) +#define UPT_ES(r) REGS_ES((r)->gp) +#define UPT_FS(r) REGS_FS((r)->gp) +#define UPT_GS(r) REGS_GS((r)->gp) #define UPT_SYSCALL_ARG1(r) UPT_EBX(r) #define UPT_SYSCALL_ARG2(r) UPT_ECX(r) @@ -134,20 +88,19 @@ extern int mode_tt; extern int user_context(unsigned long sp); -#define UPT_IS_USER(r) \ - CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) +#define UPT_IS_USER(r) ((r)->is_user) struct syscall_args { unsigned long args[6]; }; #define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) + { .args = { UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) } } ) #define UPT_REG(regs, reg) \ ({ unsigned long val; \ @@ -175,7 +128,6 @@ struct syscall_args { } \ val; \ }) - #define UPT_SET(regs, reg, val) \ do { \ @@ -204,29 +156,16 @@ struct syscall_args { } while (0) #define UPT_SET_SYSCALL_RETURN(r, res) \ - CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ - REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) + REGS_SET_SYSCALL_RETURN((r)->regs, (res)) -#define UPT_RESTART_SYSCALL(r) \ - CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ - REGS_RESTART_SYSCALL((r)->skas.regs)) +#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) #define UPT_ORIG_SYSCALL(r) UPT_EAX(r) #define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) #define UPT_SYSCALL_RET(r) UPT_EAX(r) -#define UPT_FAULTINFO(r) \ - CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) +#define UPT_FAULTINFO(r) (&(r)->faultinfo) -#endif +extern void arch_init_registers(int pid); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +#endif diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h index 23fd2644d7e..67e77122aa4 100644 --- a/arch/um/include/sysdep-i386/sigcontext.h +++ b/arch/um/include/sysdep-i386/sigcontext.h @@ -1,19 +1,15 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __SYS_SIGCONTEXT_I386_H #define __SYS_SIGCONTEXT_I386_H -#include "uml-config.h" -#include <sysdep/sc.h> +#include "sysdep/sc.h" #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) -#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) - #define GET_FAULTINFO_FROM_SC(fi,sc) \ { \ (fi).cr2 = SC_CR2(sc); \ @@ -21,32 +17,10 @@ (fi).trap_no = SC_TRAPNO(sc); \ } -/* ptrace expects that, at the start of a system call, %eax contains - * -ENOSYS, so this makes it so. - */ -#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) - /* This is Page Fault */ #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) /* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ -#ifdef UML_CONFIG_MODE_SKAS #define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) -#else -#define SEGV_MAYBE_FIXABLE(fi) 0 -#endif - -extern unsigned long *sc_sigmask(void *sc_ptr); -extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); #endif -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index 4fffae75ba5..8c097b87fca 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h @@ -9,7 +9,7 @@ #include <sys/mman.h> #include <asm/ptrace.h> #include <asm/unistd.h> -#include <asm/page.h> +#include "as-layout.h" #include "stub-data.h" #include "kern_constants.h" #include "uml-config.h" @@ -19,7 +19,7 @@ extern void stub_clone_handler(void); #define STUB_SYSCALL_RET EAX #define STUB_MMAP_NR __NR_mmap2 -#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) +#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT) static inline long stub_syscall0(long syscall) { @@ -90,12 +90,12 @@ static inline void remap_stack(int fd, unsigned long offset) { __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" "movl %7, %%ebx ; movl %%eax, (%%ebx)" - : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA), - "c" (UM_KERN_PAGE_SIZE), + : : "g" (STUB_MMAP_NR), "b" (STUB_DATA), + "c" (UM_KERN_PAGE_SIZE), "d" (PROT_READ | PROT_WRITE), - "S" (MAP_FIXED | MAP_SHARED), "D" (fd), - "a" (offset), - "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) + "S" (MAP_FIXED | MAP_SHARED), "D" (fd), + "a" (offset), + "i" (&((struct stub_data *) STUB_DATA)->err) : "memory"); } diff --git a/arch/um/include/sysdep-i386/thread.h b/arch/um/include/sysdep-i386/thread.h deleted file mode 100644 index 243fed44d78..00000000000 --- a/arch/um/include/sysdep-i386/thread.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __UM_THREAD_H -#define __UM_THREAD_H - -#include <kern_constants.h> - -#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS])) -#ifdef UML_CONFIG_MODE_TT -#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) -#endif - -#endif diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h index 62403bd9966..9ea44d111f3 100644 --- a/arch/um/include/sysdep-x86_64/ptrace.h +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -1,5 +1,6 @@ /* * Copyright 2003 PathScale, Inc. + * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * * Licensed under the GPL */ @@ -14,11 +15,6 @@ #define MAX_REG_OFFSET (UM_FRAME_SIZE) #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) -#ifdef UML_CONFIG_MODE_TT -#include "sysdep/sc.h" -#endif - -#ifdef UML_CONFIG_MODE_SKAS #include "skas_ptregs.h" #define REGS_IP(r) ((r)[HOST_IP]) @@ -88,78 +84,51 @@ #define REGS_ERR(r) ((r)->fault_type) -#endif - -#include "choose-mode.h" - -/* XXX */ -union uml_pt_regs { -#ifdef UML_CONFIG_MODE_TT - struct tt_regs { - long syscall; - unsigned long orig_rax; - void *sc; - struct faultinfo faultinfo; - } tt; -#endif -#ifdef UML_CONFIG_MODE_SKAS - struct skas_regs { - unsigned long regs[MAX_REG_NR]; - unsigned long fp[HOST_FP_SIZE]; - struct faultinfo faultinfo; - long syscall; - int is_user; - } skas; -#endif +struct uml_pt_regs { + unsigned long gp[MAX_REG_NR]; + struct faultinfo faultinfo; + long syscall; + int is_user; }; #define EMPTY_UML_PT_REGS { } -/* XXX */ -extern int mode_tt; - -#define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs)) -#define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs)) -#define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs)) -#define UPT_RSI(r) __CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs)) -#define UPT_RDI(r) __CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs)) -#define UPT_RBP(r) __CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs)) -#define UPT_RAX(r) __CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs)) -#define UPT_R8(r) __CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs)) -#define UPT_R9(r) __CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs)) -#define UPT_R10(r) __CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs)) -#define UPT_R11(r) __CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs)) -#define UPT_R12(r) __CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs)) -#define UPT_R13(r) __CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs)) -#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) -#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) -#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) -#define UPT_FS_BASE(r) \ - __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs)) -#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) -#define UPT_GS_BASE(r) \ - __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs)) -#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) -#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) -#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) -#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) -#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) -#define UPT_ORIG_RAX(r) \ - __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) - -#define UPT_IP(r) __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) -#define UPT_SP(r) __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) - -#define UPT_EFLAGS(r) \ - __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) -#define UPT_SC(r) ((r)->tt.sc) -#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) +#define UPT_RBX(r) REGS_RBX((r)->gp) +#define UPT_RCX(r) REGS_RCX((r)->gp) +#define UPT_RDX(r) REGS_RDX((r)->gp) +#define UPT_RSI(r) REGS_RSI((r)->gp) +#define UPT_RDI(r) REGS_RDI((r)->gp) +#define UPT_RBP(r) REGS_RBP((r)->gp) +#define UPT_RAX(r) REGS_RAX((r)->gp) +#define UPT_R8(r) REGS_R8((r)->gp) +#define UPT_R9(r) REGS_R9((r)->gp) +#define UPT_R10(r) REGS_R10((r)->gp) +#define UPT_R11(r) REGS_R11((r)->gp) +#define UPT_R12(r) REGS_R12((r)->gp) +#define UPT_R13(r) REGS_R13((r)->gp) +#define UPT_R14(r) REGS_R14((r)->gp) +#define UPT_R15(r) REGS_R15((r)->gp) +#define UPT_CS(r) REGS_CS((r)->gp) +#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp) +#define UPT_FS(r) REGS_FS((r)->gp) +#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp) +#define UPT_GS(r) REGS_GS((r)->gp) +#define UPT_DS(r) REGS_DS((r)->gp) +#define UPT_ES(r) REGS_ES((r)->gp) +#define UPT_CS(r) REGS_CS((r)->gp) +#define UPT_SS(r) REGS_SS((r)->gp) +#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp) + +#define UPT_IP(r) REGS_IP((r)->gp) +#define UPT_SP(r) REGS_SP((r)->gp) + +#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) +#define UPT_SYSCALL_NR(r) ((r)->syscall) #define UPT_SYSCALL_RET(r) UPT_RAX(r) extern int user_context(unsigned long sp); -#define UPT_IS_USER(r) \ - CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) +#define UPT_IS_USER(r) ((r)->is_user) #define UPT_SYSCALL_ARG1(r) UPT_RDI(r) #define UPT_SYSCALL_ARG2(r) UPT_RSI(r) @@ -173,101 +142,99 @@ struct syscall_args { }; #define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) + { .args = { UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) } } ) #define UPT_REG(regs, reg) \ - ({ unsigned long val; \ - switch(reg){ \ - case R8: val = UPT_R8(regs); break; \ - case R9: val = UPT_R9(regs); break; \ - case R10: val = UPT_R10(regs); break; \ - case R11: val = UPT_R11(regs); break; \ - case R12: val = UPT_R12(regs); break; \ - case R13: val = UPT_R13(regs); break; \ - case R14: val = UPT_R14(regs); break; \ - case R15: val = UPT_R15(regs); break; \ - case RIP: val = UPT_IP(regs); break; \ - case RSP: val = UPT_SP(regs); break; \ - case RAX: val = UPT_RAX(regs); break; \ - case RBX: val = UPT_RBX(regs); break; \ - case RCX: val = UPT_RCX(regs); break; \ - case RDX: val = UPT_RDX(regs); break; \ - case RSI: val = UPT_RSI(regs); break; \ - case RDI: val = UPT_RDI(regs); break; \ - case RBP: val = UPT_RBP(regs); break; \ - case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ - case CS: val = UPT_CS(regs); break; \ - case SS: val = UPT_SS(regs); break; \ - case FS_BASE: val = UPT_FS_BASE(regs); break; \ - case GS_BASE: val = UPT_GS_BASE(regs); break; \ - case DS: val = UPT_DS(regs); break; \ - case ES: val = UPT_ES(regs); break; \ - case FS : val = UPT_FS (regs); break; \ - case GS: val = UPT_GS(regs); break; \ - case EFLAGS: val = UPT_EFLAGS(regs); break; \ - default : \ - panic("Bad register in UPT_REG : %d\n", reg); \ - val = -1; \ - } \ - val; \ - }) + ({ unsigned long val; \ + switch(reg){ \ + case R8: val = UPT_R8(regs); break; \ + case R9: val = UPT_R9(regs); break; \ + case R10: val = UPT_R10(regs); break; \ + case R11: val = UPT_R11(regs); break; \ + case R12: val = UPT_R12(regs); break; \ + case R13: val = UPT_R13(regs); break; \ + case R14: val = UPT_R14(regs); break; \ + case R15: val = UPT_R15(regs); break; \ + case RIP: val = UPT_IP(regs); break; \ + case RSP: val = UPT_SP(regs); break; \ + case RAX: val = UPT_RAX(regs); break; \ + case RBX: val = UPT_RBX(regs); break; \ + case RCX: val = UPT_RCX(regs); break; \ + case RDX: val = UPT_RDX(regs); break; \ + case RSI: val = UPT_RSI(regs); break; \ + case RDI: val = UPT_RDI(regs); break; \ + case RBP: val = UPT_RBP(regs); break; \ + case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ + case CS: val = UPT_CS(regs); break; \ + case SS: val = UPT_SS(regs); break; \ + case FS_BASE: val = UPT_FS_BASE(regs); break; \ + case GS_BASE: val = UPT_GS_BASE(regs); break; \ + case DS: val = UPT_DS(regs); break; \ + case ES: val = UPT_ES(regs); break; \ + case FS : val = UPT_FS (regs); break; \ + case GS: val = UPT_GS(regs); break; \ + case EFLAGS: val = UPT_EFLAGS(regs); break; \ + default : \ + panic("Bad register in UPT_REG : %d\n", reg); \ + val = -1; \ + } \ + val; \ + }) #define UPT_SET(regs, reg, val) \ - ({ unsigned long __upt_val = val; \ - switch(reg){ \ - case R8: UPT_R8(regs) = __upt_val; break; \ - case R9: UPT_R9(regs) = __upt_val; break; \ - case R10: UPT_R10(regs) = __upt_val; break; \ - case R11: UPT_R11(regs) = __upt_val; break; \ - case R12: UPT_R12(regs) = __upt_val; break; \ - case R13: UPT_R13(regs) = __upt_val; break; \ - case R14: UPT_R14(regs) = __upt_val; break; \ - case R15: UPT_R15(regs) = __upt_val; break; \ - case RIP: UPT_IP(regs) = __upt_val; break; \ - case RSP: UPT_SP(regs) = __upt_val; break; \ - case RAX: UPT_RAX(regs) = __upt_val; break; \ - case RBX: UPT_RBX(regs) = __upt_val; break; \ - case RCX: UPT_RCX(regs) = __upt_val; break; \ - case RDX: UPT_RDX(regs) = __upt_val; break; \ - case RSI: UPT_RSI(regs) = __upt_val; break; \ - case RDI: UPT_RDI(regs) = __upt_val; break; \ - case RBP: UPT_RBP(regs) = __upt_val; break; \ - case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ - case CS: UPT_CS(regs) = __upt_val; break; \ - case SS: UPT_SS(regs) = __upt_val; break; \ - case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ - case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ - case DS: UPT_DS(regs) = __upt_val; break; \ - case ES: UPT_ES(regs) = __upt_val; break; \ - case FS: UPT_FS(regs) = __upt_val; break; \ - case GS: UPT_GS(regs) = __upt_val; break; \ - case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ - default : \ - panic("Bad register in UPT_SET : %d\n", reg); \ - break; \ - } \ - __upt_val; \ - }) + ({ unsigned long __upt_val = val; \ + switch(reg){ \ + case R8: UPT_R8(regs) = __upt_val; break; \ + case R9: UPT_R9(regs) = __upt_val; break; \ + case R10: UPT_R10(regs) = __upt_val; break; \ + case R11: UPT_R11(regs) = __upt_val; break; \ + case R12: UPT_R12(regs) = __upt_val; break; \ + case R13: UPT_R13(regs) = __upt_val; break; \ + case R14: UPT_R14(regs) = __upt_val; break; \ + case R15: UPT_R15(regs) = __upt_val; break; \ + case RIP: UPT_IP(regs) = __upt_val; break; \ + case RSP: UPT_SP(regs) = __upt_val; break; \ + case RAX: UPT_RAX(regs) = __upt_val; break; \ + case RBX: UPT_RBX(regs) = __upt_val; break; \ + case RCX: UPT_RCX(regs) = __upt_val; break; \ + case RDX: UPT_RDX(regs) = __upt_val; break; \ + case RSI: UPT_RSI(regs) = __upt_val; break; \ + case RDI: UPT_RDI(regs) = __upt_val; break; \ + case RBP: UPT_RBP(regs) = __upt_val; break; \ + case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ + case CS: UPT_CS(regs) = __upt_val; break; \ + case SS: UPT_SS(regs) = __upt_val; break; \ + case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ + case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ + case DS: UPT_DS(regs) = __upt_val; break; \ + case ES: UPT_ES(regs) = __upt_val; break; \ + case FS: UPT_FS(regs) = __upt_val; break; \ + case GS: UPT_GS(regs) = __upt_val; break; \ + case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ + default : \ + panic("Bad register in UPT_SET : %d\n", reg); \ + break; \ + } \ + __upt_val; \ + }) #define UPT_SET_SYSCALL_RETURN(r, res) \ - CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ - REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) + REGS_SET_SYSCALL_RETURN((r)->regs, (res)) + +#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) -#define UPT_RESTART_SYSCALL(r) \ - CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ - REGS_RESTART_SYSCALL((r)->skas.regs)) +#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas) -#define UPT_SEGV_IS_FIXABLE(r) \ - CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ - REGS_SEGV_IS_FIXABLE(&r->skas)) +#define UPT_FAULTINFO(r) (&(r)->faultinfo) -#define UPT_FAULTINFO(r) \ - CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) +static inline void arch_init_registers(int pid) +{ +} #endif diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h index 41073235e7a..0155133b145 100644 --- a/arch/um/include/sysdep-x86_64/sigcontext.h +++ b/arch/um/include/sysdep-x86_64/sigcontext.h @@ -11,43 +11,17 @@ #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) -#define SC_SET_SYSCALL_RETURN(sc, result) SC_RAX(sc) = (result) - -#define SC_FAULT_ADDR(sc) SC_CR2(sc) -#define SC_FAULT_TYPE(sc) SC_ERR(sc) - -#define GET_FAULTINFO_FROM_SC(fi,sc) \ +#define GET_FAULTINFO_FROM_SC(fi, sc) \ { \ (fi).cr2 = SC_CR2(sc); \ (fi).error_code = SC_ERR(sc); \ (fi).trap_no = SC_TRAPNO(sc); \ } -/* ptrace expects that, at the start of a system call, %eax contains - * -ENOSYS, so this makes it so. - */ - -#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) - /* This is Page Fault */ #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) /* No broken SKAS API, which doesn't pass trap_no, here. */ #define SEGV_MAYBE_FIXABLE(fi) 0 -extern unsigned long *sc_sigmask(void *sc_ptr); - #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ - diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index 92e989f8176..655f9c2de3a 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h @@ -9,6 +9,7 @@ #include <sys/mman.h> #include <asm/unistd.h> #include <sysdep/ptrace_user.h> +#include "as-layout.h" #include "stub-data.h" #include "kern_constants.h" #include "uml-config.h" @@ -94,13 +95,13 @@ static inline void remap_stack(long fd, unsigned long offset) { __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " - "movq %%rax, (%%rbx)": - : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA), - "S" (UM_KERN_PAGE_SIZE), - "d" (PROT_READ | PROT_WRITE), - "g" (MAP_FIXED | MAP_SHARED), "g" (fd), + "movq %%rax, (%%rbx)": + : "a" (STUB_MMAP_NR), "D" (STUB_DATA), + "S" (UM_KERN_PAGE_SIZE), + "d" (PROT_READ | PROT_WRITE), + "g" (MAP_FIXED | MAP_SHARED), "g" (fd), "g" (offset), - "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) + "i" (&((struct stub_data *) STUB_DATA)->err) : __syscall_clobber, "r10", "r8", "r9" ); } diff --git a/arch/um/include/sysdep-x86_64/thread.h b/arch/um/include/sysdep-x86_64/thread.h deleted file mode 100644 index cbef3e1697f..00000000000 --- a/arch/um/include/sysdep-x86_64/thread.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __UM_THREAD_H -#define __UM_THREAD_H - -#include <kern_constants.h> - -#ifdef UML_CONFIG_MODE_TT -#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) -#endif - -#endif diff --git a/arch/um/include/task.h b/arch/um/include/task.h index 6375ba7203c..3fe726b3cf4 100644 --- a/arch/um/include/task.h +++ b/arch/um/include/task.h @@ -3,7 +3,7 @@ #include <kern_constants.h> -#define TASK_REGS(task) ((union uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) +#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) #define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID])) #endif diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h index bcd1a4afb84..ecd2265b301 100644 --- a/arch/um/include/tlb.h +++ b/arch/um/include/tlb.h @@ -8,34 +8,7 @@ #include "um_mmu.h" -struct host_vm_op { - enum { NONE, MMAP, MUNMAP, MPROTECT } type; - union { - struct { - unsigned long addr; - unsigned long len; - unsigned int prot; - int fd; - __u64 offset; - } mmap; - struct { - unsigned long addr; - unsigned long len; - } munmap; - struct { - unsigned long addr; - unsigned long len; - unsigned int prot; - } mprotect; - } u; -}; - extern void force_flush_all(void); -extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force, - int (*do_ops)(union mm_context *, - struct host_vm_op *, int, int, - void **)); extern int flush_tlb_kernel_range_common(unsigned long start, unsigned long end); diff --git a/arch/um/include/tt/debug.h b/arch/um/include/tt/debug.h deleted file mode 100644 index 9778fa83829..00000000000 --- a/arch/um/include/tt/debug.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and - * Lars Brinkhoff. - * Licensed under the GPL - */ - -#ifndef __UML_TT_DEBUG_H -#define __UML_TT_DEBUG_H - -extern int debugger_proxy(int status, pid_t pid); -extern void child_proxy(pid_t pid, int status); -extern void init_proxy (pid_t pid, int waiting, int status); -extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); -extern void fake_child_exit(void); -extern int gdb_config(char *str); -extern int gdb_remove(int unused); - -#endif diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h deleted file mode 100644 index 572a78b2258..00000000000 --- a/arch/um/include/tt/mmu-tt.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_MMU_H -#define __TT_MMU_H - -struct mmu_context_tt { -}; - -#endif diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h deleted file mode 100644 index 2823cd56eea..00000000000 --- a/arch/um/include/tt/mode-tt.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_TT_H__ -#define __MODE_TT_H__ - -#include "sysdep/ptrace.h" - -enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; - -extern int tracing_pid; - -extern int tracer(int (*init_proc)(void *), void *sp); -extern void sig_handler_common_tt(int sig, void *sc); -extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); -extern void reboot_tt(void); -extern void halt_tt(void); -extern int is_tracer_winch(int pid, int fd, void *data); -extern void kill_off_processes_tt(void); - -#endif diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h deleted file mode 100644 index a4fc6305719..00000000000 --- a/arch/um/include/tt/mode_kern_tt.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_MODE_KERN_H__ -#define __TT_MODE_KERN_H__ - -#include "linux/sched.h" -#include "asm/page.h" -#include "asm/ptrace.h" -#include "asm/uaccess.h" - -extern void switch_to_tt(void *prev, void *next); -extern void flush_thread_tt(void); -extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, - unsigned long esp); -extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct *p, - struct pt_regs *regs); -extern void release_thread_tt(struct task_struct *task); -extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); -extern void init_idle_tt(void); -extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); -extern void flush_tlb_kernel_vm_tt(void); -extern void __flush_tlb_one_tt(unsigned long addr); -extern void flush_tlb_range_tt(struct vm_area_struct *vma, - unsigned long start, unsigned long end); -extern void flush_tlb_mm_tt(struct mm_struct *mm); -extern void force_flush_all_tt(void); -extern long execute_syscall_tt(void *r); -extern void before_mem_tt(unsigned long brk_start); -extern unsigned long set_task_sizes_tt(unsigned long *task_size_out); -extern int start_uml_tt(void); -extern int external_pid_tt(struct task_struct *task); -extern int thread_pid_tt(struct task_struct *task); - -#define kmem_end_tt (host_task_size - ABOVE_KMEM) - -#endif diff --git a/arch/um/include/tt/tt.h b/arch/um/include/tt/tt.h deleted file mode 100644 index acb8356e1f9..00000000000 --- a/arch/um/include/tt/tt.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_H__ -#define __TT_H__ - -#include "sysdep/ptrace.h" - -extern int gdb_pid; -extern int debug; -extern int debug_stop; -extern int debug_trace; - -extern int honeypot; - -extern int fork_tramp(void *sig_stack); -extern int do_proc_op(void *t, int proc_id); -extern int tracer(int (*init_proc)(void *), void *sp); -extern void attach_process(int pid); -extern void tracer_panic(char *format, ...) - __attribute__ ((format (printf, 1, 2))); -extern void set_init_pid(int pid); -extern int set_user_mode(void *task); -extern void set_tracing(void *t, int tracing); -extern int is_tracing(void *task); -extern void syscall_handler(int sig, union uml_pt_regs *regs); -extern void exit_kernel(int pid, void *task); -extern void do_syscall(void *task, int pid, int local_using_sysemu); -extern void do_sigtrap(void *task); -extern int is_valid_pid(int pid); -extern void remap_data(void *segment_start, void *segment_end, int w); -extern long execute_syscall_tt(void *r); - -#endif - diff --git a/arch/um/include/tt/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h deleted file mode 100644 index 13a64f61fcf..00000000000 --- a/arch/um/include/tt/uaccess-tt.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __TT_UACCESS_H -#define __TT_UACCESS_H - -#include "linux/string.h" -#include "linux/sched.h" -#include "asm/processor.h" -#include "asm/errno.h" -#include "asm/current.h" -#include "asm/a.out.h" -#include "uml_uaccess.h" - -#define ABOVE_KMEM (16 * 1024 * 1024) - -extern unsigned long end_vm; -extern unsigned long uml_physmem; - -#define is_stack(addr, size) \ - (((unsigned long) (addr) < STACK_TOP) && \ - ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ - (((unsigned long) (addr) + (size)) <= STACK_TOP)) - -#define access_ok_tt(type, addr, size) \ - (is_stack(addr, size)) - -extern int __do_copy_from_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher); -extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, - void **fault_addr, void **fault_catcher); -extern int __do_clear_user(void *mem, size_t len, void **fault_addr, - void **fault_catcher); -extern int __do_strnlen_user(const char *str, unsigned long n, - void **fault_addr, void **fault_catcher); - -extern int copy_from_user_tt(void *to, const void __user *from, int n); -extern int copy_to_user_tt(void __user *to, const void *from, int n); -extern int strncpy_from_user_tt(char *dst, const char __user *src, int count); -extern int __clear_user_tt(void __user *mem, int len); -extern int clear_user_tt(void __user *mem, int len); -extern int strnlen_user_tt(const void __user *str, int len); - -#endif diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h index 0fa64323830..8855d8df512 100644 --- a/arch/um/include/um_mmu.h +++ b/arch/um/include/um_mmu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -7,34 +7,22 @@ #define __ARCH_UM_MMU_H #include "uml-config.h" -#include "choose-mode.h" +#include "mm_id.h" +#include "asm/ldt.h" -#ifdef UML_CONFIG_MODE_TT -#include "mmu-tt.h" +typedef struct mm_context { + struct mm_id id; + unsigned long last_page_table; +#ifdef CONFIG_3_LEVEL_PGTABLES + unsigned long last_pmd; #endif + struct uml_ldt ldt; +} mm_context_t; -#ifdef UML_CONFIG_MODE_SKAS -#include "mmu-skas.h" -#endif +extern void __switch_mm(struct mm_id * mm_idp); -typedef union mm_context { -#ifdef UML_CONFIG_MODE_TT - struct mmu_context_tt tt; -#endif -#ifdef UML_CONFIG_MODE_SKAS - struct mmu_context_skas skas; -#endif -} mm_context_t; +/* Avoid tangled inclusion with asm/ldt.h */ +extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); +extern void free_ldt(struct mm_context *mm); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 5126a99b596..fdfc06b8560 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h @@ -1,26 +1,16 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __ARCH_UM_UACCESS_H #define __ARCH_UM_UACCESS_H -#include "choose-mode.h" - -#ifdef CONFIG_MODE_TT -#include "uaccess-tt.h" -#endif - -#ifdef CONFIG_MODE_SKAS -#include "uaccess-skas.h" -#endif - #include "asm/fixmap.h" #define __under_task_size(addr, size) \ (((unsigned long) (addr) < TASK_SIZE) && \ - (((unsigned long) (addr) + (size)) < TASK_SIZE)) + (((unsigned long) (addr) + (size)) < TASK_SIZE)) #define __access_ok_vsyscall(type, addr, size) \ ((type == VERIFY_READ) && \ @@ -35,20 +25,14 @@ (__addr_range_nowrap(addr, size) && \ (__under_task_size(addr, size) || \ __access_ok_vsyscall(type, addr, size) || \ - segment_eq(get_fs(), KERNEL_DS) || \ - CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) + segment_eq(get_fs(), KERNEL_DS))) -static inline int copy_from_user(void *to, const void __user *from, int n) -{ - return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, - from, n)); -} +extern int copy_from_user(void *to, const void __user *from, int n); +extern int copy_to_user(void __user *to, const void *from, int n); -static inline int copy_to_user(void __user *to, const void *from, int n) -{ - return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, - from, n)); -} +extern int __do_copy_to_user(void *to, const void *from, int n, + void **fault_addr, jmp_buf **fault_catcher); +extern void __do_copy(void *to, const void *from, int n); /* * strncpy_from_user: - Copy a NUL terminated string from userspace. @@ -69,11 +53,7 @@ static inline int copy_to_user(void __user *to, const void *from, int n) * and returns @count. */ -static inline int strncpy_from_user(char *dst, const char __user *src, int count) -{ - return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, - dst, src, count)); -} +extern int strncpy_from_user(char *dst, const char __user *src, int count); /* * __clear_user: - Zero a block of memory in user space, with less checking. @@ -86,10 +66,7 @@ static inline int strncpy_from_user(char *dst, const char __user *src, int count * Returns number of bytes that could not be cleared. * On success, this will be zero. */ -static inline int __clear_user(void *mem, int len) -{ - return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); -} +extern int __clear_user(void __user *mem, int len); /* * clear_user: - Zero a block of memory in user space. @@ -101,10 +78,7 @@ static inline int __clear_user(void *mem, int len) * Returns number of bytes that could not be cleared. * On success, this will be zero. */ -static inline int clear_user(void __user *mem, int len) -{ - return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); -} +extern int clear_user(void __user *mem, int len); /* * strlen_user: - Get the size of a string in user space. @@ -117,20 +91,6 @@ static inline int clear_user(void __user *mem, int len) * On exception, returns 0. * If the string is too long, returns a value greater than @n. */ -static inline int strnlen_user(const void __user *str, long len) -{ - return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); -} +extern int strnlen_user(const void __user *str, int len); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h deleted file mode 100644 index c0df11d06f5..00000000000 --- a/arch/um/include/uml_uaccess.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __UML_UACCESS_H__ -#define __UML_UACCESS_H__ - -extern int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher); -void __do_copy(void *to, const void *from, int n); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/user.h b/arch/um/include/user.h index d380e6d91a9..99033ff28a7 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -14,10 +14,12 @@ */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -/* - * This will provide the size_t definition in both kernel and userspace builds - */ +/* This is to get size_t */ +#ifdef __KERNEL__ #include <linux/types.h> +#else +#include <stddef.h> +#endif extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index c5cf4a0827b..499e5e95e60 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux,intel}.com) # Licensed under the GPL # @@ -9,15 +9,12 @@ clean-files := obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ physmem.o process.o ptrace.o reboot.o sigio.o \ signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ - um_arch.o umid.o + um_arch.o umid.o skas/ obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o -obj-$(CONFIG_MODE_TT) += tt/ -obj-$(CONFIG_MODE_SKAS) += skas/ - USER_OBJS := config.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 41850906116..3866f4960f0 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -10,8 +10,6 @@ SECTIONS PROVIDE (__executable_start = START); . = START + SIZEOF_HEADERS; .interp : { *(.interp) } - /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start - * is remapped.*/ __binary_start = .; . = ALIGN(4096); /* Init code and data */ _text = .; diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index ce6828fd396..8196450451c 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -1,35 +1,44 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/slab.h" +#include "linux/stddef.h" +#include "linux/fs.h" #include "linux/smp_lock.h" #include "linux/ptrace.h" -#include "linux/fs.h" -#include "asm/ptrace.h" -#include "asm/pgtable.h" -#include "asm/tlbflush.h" +#include "linux/sched.h" +#include "asm/current.h" +#include "asm/processor.h" #include "asm/uaccess.h" -#include "kern_util.h" #include "as-layout.h" #include "mem_user.h" -#include "kern.h" -#include "irq_user.h" -#include "tlb.h" +#include "skas.h" #include "os.h" -#include "choose-mode.h" -#include "mode_kern.h" void flush_thread(void) { + void *data = NULL; + unsigned long end = proc_mm ? task_size : STUB_START; + int ret; + arch_flush_thread(¤t->thread.arch); - CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); + + ret = unmap(¤t->mm->context.id, 0, end, 1, &data); + if (ret) { + printk(KERN_ERR "flush_thread - clearing address space failed, " + "err = %d\n", ret); + force_sig(SIGKILL, current); + } + + __switch_mm(¤t->mm->context.id); } void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) { - CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); + set_fs(USER_DS); + PT_REGS_IP(regs) = eip; + PT_REGS_SP(regs) = esp; } #ifdef CONFIG_TTY_LOG @@ -39,7 +48,7 @@ extern void log_exec(char **argv, void *tty); static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { - long error; + long error; #ifdef CONFIG_TTY_LOG struct tty_struct *tty; @@ -49,17 +58,16 @@ static long execve1(char *file, char __user * __user *argv, log_exec(argv, tty); mutex_unlock(&tty_mutex); #endif - error = do_execve(file, argv, env, ¤t->thread.regs); - if (error == 0){ + error = do_execve(file, argv, env, ¤t->thread.regs); + if (error == 0) { task_lock(current); - current->ptrace &= ~PT_DTRACE; + current->ptrace &= ~PT_DTRACE; #ifdef SUBARCH_EXECVE1 SUBARCH_EXECVE1(¤t->thread.regs.regs); #endif task_unlock(current); - set_cmdline(current_cmd()); - } - return(error); + } + return error; } long um_execve(char *file, char __user *__user *argv, char __user *__user *env) @@ -67,9 +75,9 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env) long err; err = execve1(file, argv, env); - if(!err) - do_longjmp(current->thread.exec_buf, 1); - return(err); + if (!err) + UML_LONGJMP(current->thread.exec_buf, 1); + return err; } long sys_execve(char __user *file, char __user *__user *argv, @@ -86,5 +94,5 @@ long sys_execve(char __user *file, char __user *__user *argv, putname(filename); out: unlock_kernel(); - return(error); + return error; } diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index cba516e6c99..dcfceca9505 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -3,16 +3,12 @@ * Licensed under the GPL */ -#include "linux/mm.h" -#include "linux/fs.h" -#include "linux/module.h" #include "linux/sched.h" #include "linux/init_task.h" +#include "linux/fs.h" +#include "linux/module.h" #include "linux/mqueue.h" #include "asm/uaccess.h" -#include "asm/pgtable.h" -#include "mem_user.h" -#include "os.h" static struct fs_struct init_fs = INIT_FS; struct mm_struct init_mm = INIT_MM(init_mm); @@ -46,8 +42,3 @@ union thread_union init_thread_union union thread_union cpu0_irqstack __attribute__((__section__(".data.init_irqstack"))) = { INIT_THREAD_INFO(init_task) }; - -void unprotect_stack(unsigned long stack) -{ - os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0); -} diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index cf0dd9cf8c4..277fce17b08 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -1,37 +1,19 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar */ -#include "linux/kernel.h" -#include "linux/module.h" -#include "linux/smp.h" -#include "linux/kernel_stat.h" +#include "linux/cpumask.h" +#include "linux/hardirq.h" #include "linux/interrupt.h" -#include "linux/random.h" -#include "linux/slab.h" -#include "linux/file.h" -#include "linux/proc_fs.h" -#include "linux/init.h" +#include "linux/kernel_stat.h" +#include "linux/module.h" #include "linux/seq_file.h" -#include "linux/profile.h" -#include "linux/hardirq.h" -#include "asm/irq.h" -#include "asm/hw_irq.h" -#include "asm/atomic.h" -#include "asm/signal.h" -#include "asm/system.h" -#include "asm/errno.h" -#include "asm/uaccess.h" +#include "as-layout.h" #include "kern_util.h" -#include "irq_user.h" -#include "irq_kern.h" #include "os.h" -#include "sigio.h" -#include "misc_constants.h" -#include "as-layout.h" /* * Generic, controller-independent functions: @@ -71,9 +53,8 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) { + } else if (i == NR_IRQS) seq_putc(p, '\n'); - } return 0; } @@ -91,7 +72,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; extern void free_irqs(void); -void sigio_handler(int sig, union uml_pt_regs *regs) +void sigio_handler(int sig, struct uml_pt_regs *regs) { struct irq_fd *irq_fd; int n; @@ -102,11 +83,13 @@ void sigio_handler(int sig, union uml_pt_regs *regs) while (1) { n = os_waiting_for_events(active_fds); if (n <= 0) { - if(n == -EINTR) continue; + if (n == -EINTR) + continue; else break; } - for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { + for (irq_fd = active_fds; irq_fd != NULL; + irq_fd = irq_fd->next) { if (irq_fd->current_events != 0) { irq_fd->current_events = 0; do_IRQ(irq_fd->irq, regs); @@ -138,8 +121,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) if (type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI; - else - events = UM_POLLOUT; + else events = UM_POLLOUT; *new_fd = ((struct irq_fd) { .next = NULL, .id = dev_id, .fd = fd, @@ -153,9 +135,10 @@ int activate_fd(int irq, int fd, int type, void *dev_id) spin_lock_irqsave(&irq_lock, flags); for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { if ((irq_fd->fd == fd) && (irq_fd->type == type)) { - printk("Registering fd %d twice\n", fd); - printk("Irqs : %d, %d\n", irq_fd->irq, irq); - printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id); + printk(KERN_ERR "Registering fd %d twice\n", fd); + printk(KERN_ERR "Irqs : %d, %d\n", irq_fd->irq, irq); + printk(KERN_ERR "Ids : 0x%p, 0x%p\n", irq_fd->id, + dev_id); goto out_unlock; } } @@ -171,7 +154,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) if (n == 0) break; - /* n > 0 + /* + * n > 0 * It means we couldn't put new pollfd to current pollfds * and tmp_fds is NULL or too small for new pollfds array. * Needed size is equal to n as minimum. @@ -197,7 +181,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) spin_unlock_irqrestore(&irq_lock, flags); - /* This calls activate_fd, so it has to be outside the critical + /* + * This calls activate_fd, so it has to be outside the critical * section. */ maybe_sigio_broken(fd, (type == IRQ_READ)); @@ -264,13 +249,14 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) i++; } if (irq == NULL) { - printk("find_irq_by_fd doesn't have descriptor %d\n", fd); + printk(KERN_ERR "find_irq_by_fd doesn't have descriptor %d\n", + fd); goto out; } fdi = os_get_pollfd(i); if ((fdi != -1) && (fdi != fd)) { - printk("find_irq_by_fd - mismatch between active_fds and " - "pollfds, fd %d vs %d, need %d\n", irq->fd, + printk(KERN_ERR "find_irq_by_fd - mismatch between active_fds " + "and pollfds, fd %d vs %d, need %d\n", irq->fd, fdi, fd); irq = NULL; goto out; @@ -306,7 +292,7 @@ void deactivate_fd(int fd, int irqnum) spin_lock_irqsave(&irq_lock, flags); irq = find_irq_by_fd(fd, irqnum, &i); - if(irq == NULL){ + if (irq == NULL) { spin_unlock_irqrestore(&irq_lock, flags); return; } @@ -339,36 +325,12 @@ int deactivate_all_fds(void) return 0; } -#ifdef CONFIG_MODE_TT -void forward_interrupts(int pid) -{ - struct irq_fd *irq; - unsigned long flags; - int err; - - spin_lock_irqsave(&irq_lock, flags); - for (irq = active_fds; irq != NULL; irq = irq->next) { - err = os_set_owner(irq->fd, pid); - if (err < 0) { - /* XXX Just remove the irq rather than - * print out an infinite stream of these - */ - printk("Failed to forward %d to pid %d, err = %d\n", - irq->fd, pid, -err); - } - - irq->pid = pid; - } - spin_unlock_irqrestore(&irq_lock, flags); -} -#endif - /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ -unsigned int do_IRQ(int irq, union uml_pt_regs *regs) +unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); irq_enter(); @@ -396,8 +358,10 @@ int um_request_irq(unsigned int irq, int fd, int type, EXPORT_SYMBOL(um_request_irq); EXPORT_SYMBOL(reactivate_fd); -/* hw_interrupt_type must define (startup || enable) && - * (shutdown || disable) && end */ +/* + * hw_interrupt_type must define (startup || enable) && + * (shutdown || disable) && end + */ static void dummy(unsigned int irq) { } @@ -446,7 +410,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) err = os_pipe(fds, 1, 1); if (err) { - printk("init_aio_irq - os_pipe failed, err = %d\n", -err); + printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n", + -err); goto out; } @@ -454,7 +419,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name, (void *) (long) fds[0]); if (err) { - printk("init_aio_irq - : um_request_irq failed, err = %d\n", + printk(KERN_ERR "init_aio_irq - : um_request_irq failed, " + "err = %d\n", err); goto out_close; } @@ -525,8 +491,9 @@ unsigned long to_irq_stack(unsigned long *mask_out) int nested; mask = xchg(&pending_mask, *mask_out); - if(mask != 0){ - /* If any interrupts come in at this point, we want to + if (mask != 0) { + /* + * If any interrupts come in at this point, we want to * make sure that their bits aren't lost by our * putting our bit in. So, this loop accumulates bits * until xchg returns the same value that we put in. @@ -538,13 +505,13 @@ unsigned long to_irq_stack(unsigned long *mask_out) do { old |= mask; mask = xchg(&pending_mask, old); - } while(mask != old); + } while (mask != old); return 1; } ti = current_thread_info(); nested = (ti->real_thread != NULL); - if(!nested){ + if (!nested) { struct task_struct *task; struct thread_info *tti; diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 7b3e53fb807..1b388b41d95 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -1,22 +1,15 @@ /* - * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include "linux/module.h" -#include "linux/string.h" -#include "linux/smp_lock.h" -#include "linux/spinlock.h" -#include "linux/highmem.h" -#include "asm/current.h" -#include "asm/processor.h" -#include "asm/unistd.h" -#include "asm/pgalloc.h" -#include "asm/pgtable.h" -#include "asm/page.h" +#include "linux/syscalls.h" +#include "asm/a.out.h" #include "asm/tlbflush.h" -#include "kern_util.h" +#include "asm/uaccess.h" #include "as-layout.h" +#include "kern_util.h" #include "mem_user.h" #include "os.h" @@ -34,30 +27,19 @@ EXPORT_SYMBOL(get_kmem_end); EXPORT_SYMBOL(high_physmem); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(um_virt_to_phys); -EXPORT_SYMBOL(mode_tt); EXPORT_SYMBOL(handle_page_fault); EXPORT_SYMBOL(find_iomem); -#ifdef CONFIG_MODE_TT -EXPORT_SYMBOL(stop); -EXPORT_SYMBOL(strncpy_from_user_tt); -EXPORT_SYMBOL(copy_from_user_tt); -EXPORT_SYMBOL(copy_to_user_tt); -#endif - -#ifdef CONFIG_MODE_SKAS -EXPORT_SYMBOL(strnlen_user_skas); -EXPORT_SYMBOL(strncpy_from_user_skas); -EXPORT_SYMBOL(copy_to_user_skas); -EXPORT_SYMBOL(copy_from_user_skas); -EXPORT_SYMBOL(clear_user_skas); -#endif +EXPORT_SYMBOL(strnlen_user); +EXPORT_SYMBOL(strncpy_from_user); +EXPORT_SYMBOL(copy_to_user); +EXPORT_SYMBOL(copy_from_user); +EXPORT_SYMBOL(clear_user); EXPORT_SYMBOL(uml_strdup); EXPORT_SYMBOL(os_stat_fd); EXPORT_SYMBOL(os_stat_file); EXPORT_SYMBOL(os_access); -EXPORT_SYMBOL(os_print_error); EXPORT_SYMBOL(os_get_exec_close); EXPORT_SYMBOL(os_set_exec_close); EXPORT_SYMBOL(os_getpid); @@ -85,9 +67,6 @@ EXPORT_SYMBOL(run_helper); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(dump_thread); -EXPORT_SYMBOL(do_gettimeofday); -EXPORT_SYMBOL(do_settimeofday); - #ifdef CONFIG_SMP /* required for SMP */ diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index d2b11f24269..8456397f5f4 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -17,7 +17,7 @@ #include "as-layout.h" #include "kern.h" #include "mem_user.h" -#include "uml_uaccess.h" +#include "um_uaccess.h" #include "os.h" #include "linux/types.h" #include "linux/string.h" diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 5ee7e851bbc..e66432f4248 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -1,25 +1,17 @@ /* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/mm.h" -#include "linux/rbtree.h" -#include "linux/slab.h" -#include "linux/vmalloc.h" #include "linux/bootmem.h" -#include "linux/module.h" +#include "linux/mm.h" #include "linux/pfn.h" -#include "asm/types.h" -#include "asm/pgtable.h" -#include "kern_util.h" +#include "asm/page.h" #include "as-layout.h" -#include "mode_kern.h" -#include "mem.h" +#include "init.h" +#include "kern.h" #include "mem_user.h" #include "os.h" -#include "kern.h" -#include "init.h" static int physmem_fd = -1; @@ -49,10 +41,10 @@ int __init init_maps(unsigned long physmem, unsigned long iomem, total_len = phys_len + iomem_len + highmem_len; map = alloc_bootmem_low_pages(total_len); - if(map == NULL) + if (map == NULL) return -ENOMEM; - for(i = 0; i < total_pages; i++){ + for (i = 0; i < total_pages; i++) { p = &map[i]; memset(p, 0, sizeof(struct page)); SetPageReserved(p); @@ -68,8 +60,8 @@ static unsigned long kmem_top = 0; unsigned long get_kmem_end(void) { - if(kmem_top == 0) - kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); + if (kmem_top == 0) + kmem_top = host_task_size - 1024 * 1024; return kmem_top; } @@ -81,9 +73,9 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, fd = phys_mapping(phys, &offset); err = os_map_memory((void *) virt, fd, offset, len, r, w, x); - if(err) { - if(err == -ENOMEM) - printk("try increasing the host's " + if (err) { + if (err == -ENOMEM) + printk(KERN_ERR "try increasing the host's " "/proc/sys/vm/max_map_count to <physical " "memory size>/4096\n"); panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " @@ -105,13 +97,16 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, offset = uml_reserved - uml_physmem; err = os_map_memory((void *) uml_reserved, physmem_fd, offset, - len - offset, 1, 1, 0); - if(err < 0){ - os_print_error(err, "Mapping memory"); + len - offset, 1, 1, 1); + if (err < 0) { + printf("setup_physmem - mapping %ld bytes of memory at 0x%p " + "failed - errno = %d\n", len - offset, + (void *) uml_reserved, err); exit(1); } - /* Special kludge - This page will be mapped in to userspace processes + /* + * Special kludge - This page will be mapped in to userspace processes * from physmem_fd, so it needs to be written out there. */ os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); @@ -122,20 +117,20 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, len - bootmap_size - reserve); } -int phys_mapping(unsigned long phys, __u64 *offset_out) +int phys_mapping(unsigned long phys, unsigned long long *offset_out) { int fd = -1; - if(phys < physmem_size){ + if (phys < physmem_size) { fd = physmem_fd; *offset_out = phys; } - else if(phys < __pa(end_iomem)){ + else if (phys < __pa(end_iomem)) { struct iomem_region *region = iomem_regions; - while(region != NULL){ - if((phys >= region->phys) && - (phys < region->phys + region->size)){ + while (region != NULL) { + if ((phys >= region->phys) && + (phys < region->phys + region->size)) { fd = region->fd; *offset_out = phys - region->phys; break; @@ -143,7 +138,7 @@ int phys_mapping(unsigned long phys, __u64 *offset_out) region = region->next; } } - else if(phys < __pa(end_iomem) + highmem){ + else if (phys < __pa(end_iomem) + highmem) { fd = physmem_fd; *offset_out = phys - iomem_size; } @@ -188,8 +183,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out) { struct iomem_region *region = iomem_regions; - while(region != NULL){ - if(!strcmp(region->driver, driver)){ + while (region != NULL) { + if (!strcmp(region->driver, driver)) { *len_out = region->size; return region->virt; } @@ -206,12 +201,12 @@ int setup_iomem(void) unsigned long iomem_start = high_physmem + PAGE_SIZE; int err; - while(region != NULL){ + while (region != NULL) { err = os_map_memory((void *) iomem_start, region->fd, 0, region->size, 1, 1, 0); - if(err) - printk("Mapping iomem region for driver '%s' failed, " - "errno = %d\n", region->driver, -err); + if (err) + printk(KERN_ERR "Mapping iomem region for driver '%s' " + "failed, errno = %d\n", region->driver, -err); else { region->virt = iomem_start; region->phys = __pa(region->virt); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index bfa52f206bb..0eae00b3e58 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -1,53 +1,30 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/sched.h" -#include "linux/interrupt.h" -#include "linux/string.h" +#include "linux/stddef.h" +#include "linux/err.h" +#include "linux/hardirq.h" #include "linux/mm.h" -#include "linux/slab.h" -#include "linux/utsname.h" -#include "linux/fs.h" -#include "linux/utime.h" -#include "linux/smp_lock.h" -#include "linux/module.h" -#include "linux/init.h" -#include "linux/capability.h" -#include "linux/vmalloc.h" -#include "linux/spinlock.h" +#include "linux/personality.h" #include "linux/proc_fs.h" #include "linux/ptrace.h" #include "linux/random.h" -#include "linux/personality.h" -#include "asm/unistd.h" -#include "asm/mman.h" -#include "asm/segment.h" -#include "asm/stat.h" +#include "linux/sched.h" +#include "linux/tick.h" +#include "linux/threads.h" #include "asm/pgtable.h" -#include "asm/processor.h" -#include "asm/tlbflush.h" #include "asm/uaccess.h" -#include "asm/user.h" -#include "kern_util.h" #include "as-layout.h" -#include "kern.h" -#include "signal_kern.h" -#include "init.h" -#include "irq_user.h" -#include "mem_user.h" -#include "tlb.h" -#include "frame_kern.h" -#include "sigcontext.h" +#include "kern_util.h" #include "os.h" -#include "mode.h" -#include "mode_kern.h" -#include "choose-mode.h" +#include "skas.h" +#include "tlb.h" -/* This is a per-cpu array. A processor only modifies its entry and it only +/* + * This is a per-cpu array. A processor only modifies its entry and it only * cares about its entry, so it's OK if another processor is modifying its * entry. */ @@ -55,15 +32,16 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; static inline int external_pid(struct task_struct *task) { - return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task); + /* FIXME: Need to look up userspace_pid by cpu */ + return userspace_pid[0]; } int pid_to_processor_id(int pid) { int i; - for(i = 0; i < ncpus; i++){ - if(cpu_tasks[i].pid == pid) + for(i = 0; i < ncpus; i++) { + if (cpu_tasks[i].pid == pid) return i; } return -1; @@ -82,9 +60,9 @@ unsigned long alloc_stack(int order, int atomic) if (atomic) flags = GFP_ATOMIC; page = __get_free_pages(flags, order); - if(page == 0) + if (page == 0) return 0; - stack_protections(page); + return page; } @@ -105,6 +83,8 @@ static inline void set_current(struct task_struct *task) { external_pid(task), task }); } +extern void arch_switch_to(struct task_struct *from, struct task_struct *to); + void *_switch_to(void *prev, void *next, void *last) { struct task_struct *from = prev; @@ -114,9 +94,14 @@ void *_switch_to(void *prev, void *next, void *last) set_current(to); do { - current->thread.saved_task = NULL ; - CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); - if(current->thread.saved_task) + current->thread.saved_task = NULL; + + switch_threads(&from->thread.switch_buf, + &to->thread.switch_buf); + + arch_switch_to(current->thread.prev_sched, current); + + if (current->thread.saved_task) show_regs(&(current->thread.regs)); next= current->thread.saved_task; prev= current; @@ -128,20 +113,14 @@ void *_switch_to(void *prev, void *next, void *last) void interrupt_end(void) { - if(need_resched()) + if (need_resched()) schedule(); - if(test_tsk_thread_flag(current, TIF_SIGPENDING)) + if (test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); } -void release_thread(struct task_struct *task) -{ - CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); -} - void exit_thread(void) { - unprotect_stack((unsigned long) current_thread); } void *get_current(void) @@ -149,28 +128,99 @@ void *get_current(void) return current; } +extern void schedule_tail(struct task_struct *prev); + +/* + * This is called magically, by its address being stuffed in a jmp_buf + * and being longjmp-d to. + */ +void new_thread_handler(void) +{ + int (*fn)(void *), n; + void *arg; + + if (current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + + fn = current->thread.request.u.thread.proc; + arg = current->thread.request.u.thread.arg; + + /* + * The return value is 1 if the kernel thread execs a process, + * 0 if it just exits + */ + n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); + if (n == 1) { + /* Handle any immediate reschedules or signals */ + interrupt_end(); + userspace(¤t->thread.regs.regs); + } + else do_exit(0); +} + +/* Called magically, see new_thread_handler above */ +void fork_handler(void) +{ + force_flush_all(); + if (current->thread.prev_sched == NULL) + panic("blech"); + + schedule_tail(current->thread.prev_sched); + + /* + * XXX: if interrupt_end() calls schedule, this call to + * arch_switch_to isn't needed. We could want to apply this to + * improve performance. -bb + */ + arch_switch_to(current->thread.prev_sched, current); + + current->thread.prev_sched = NULL; + + /* Handle any immediate reschedules or signals */ + interrupt_end(); + + userspace(¤t->thread.regs.regs); +} + int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { - int ret; + void (*handler)(void); + int ret = 0; p->thread = (struct thread_struct) INIT_THREAD; - ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, - clone_flags, sp, stack_top, p, regs); - if (ret || !current->thread.forking) - goto out; + if (current->thread.forking) { + memcpy(&p->thread.regs.regs, ®s->regs, + sizeof(p->thread.regs.regs)); + REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0); + if (sp != 0) + REGS_SP(p->thread.regs.regs.gp) = sp; - clear_flushed_tls(p); + handler = fork_handler; - /* - * Set a new TLS for the child thread? - */ - if (clone_flags & CLONE_SETTLS) - ret = arch_copy_tls(p); + arch_copy_thread(¤t->thread.arch, &p->thread.arch); + } + else { + init_thread_registers(&p->thread.regs.regs); + p->thread.request.u.thread = current->thread.request.u.thread; + handler = new_thread_handler; + } + + new_thread(task_stack_page(p), &p->thread.switch_buf, handler); + + if (current->thread.forking) { + clear_flushed_tls(p); + + /* + * Set a new TLS for the child thread? + */ + if (clone_flags & CLONE_SETTLS) + ret = arch_copy_tls(p); + } -out: return ret; } @@ -179,39 +229,35 @@ void initial_thread_cb(void (*proc)(void *), void *arg) int save_kmalloc_ok = kmalloc_ok; kmalloc_ok = 0; - CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, - arg); + initial_thread_cb_skas(proc, arg); kmalloc_ok = save_kmalloc_ok; } -#ifdef CONFIG_MODE_TT -unsigned long stack_sp(unsigned long page) -{ - return page + PAGE_SIZE - sizeof(void *); -} -#endif - void default_idle(void) { - CHOOSE_MODE(uml_idle_timer(), (void) 0); + unsigned long long nsecs; - while(1){ + while(1) { /* endless idle loop with no priority at all */ /* * although we are an idle CPU, we do not want to * get into the scheduler unnecessarily. */ - if(need_resched()) + if (need_resched()) schedule(); - idle_sleep(10); + tick_nohz_stop_sched_tick(); + nsecs = disable_timer(); + idle_sleep(nsecs); + tick_nohz_restart_sched_tick(); } } void cpu_idle(void) { - CHOOSE_MODE(init_idle_tt(), init_idle_skas()); + cpu_tasks[current_thread->cpu].pid = os_getpid(); + default_idle(); } void *um_virt_to_phys(struct task_struct *task, unsigned long addr, @@ -223,26 +269,26 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte; pte_t ptent; - if(task->mm == NULL) + if (task->mm == NULL) return ERR_PTR(-EINVAL); pgd = pgd_offset(task->mm, addr); - if(!pgd_present(*pgd)) + if (!pgd_present(*pgd)) return ERR_PTR(-EINVAL); pud = pud_offset(pgd, addr); - if(!pud_present(*pud)) + if (!pud_present(*pud)) return ERR_PTR(-EINVAL); pmd = pmd_offset(pud, addr); - if(!pmd_present(*pmd)) + if (!pmd_present(*pmd)) return ERR_PTR(-EINVAL); pte = pte_offset_kernel(pmd, addr); ptent = *pte; - if(!pte_present(ptent)) + if (!pte_present(ptent)) return ERR_PTR(-EINVAL); - if(pte_out != NULL) + if (pte_out != NULL) *pte_out = ptent; return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK); } @@ -315,7 +361,7 @@ int smp_sigio_handler(void) #ifdef CONFIG_SMP int cpu = current_thread->cpu; IPI_handler(cpu); - if(cpu != 0) + if (cpu != 0) return 1; #endif return 0; @@ -343,7 +389,8 @@ int get_using_sysemu(void) static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) { - if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ + if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) + /* No overflow */ *eof = 1; return strlen(buf); @@ -358,7 +405,8 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned if (tmp[0] >= '0' && tmp[0] <= '2') set_using_sysemu(tmp[0] - '0'); - return count; /*We use the first char, but pretend to write everything*/ + /* We use the first char, but pretend to write everything */ + return count; } int __init make_proc_sysemu(void) @@ -388,10 +436,10 @@ int singlestepping(void * t) struct task_struct *task = t ? t : current; if ( ! (task->ptrace & PT_DTRACE) ) - return(0); + return 0; if (task->thread.singlestep_syscall) - return(1); + return 1; return 2; } diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 6916c8888db..a0eba083306 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -1,35 +1,27 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/mm.h" -#include "linux/errno.h" -#include "linux/smp_lock.h" -#include "linux/security.h" -#include "linux/ptrace.h" #include "linux/audit.h" +#include "linux/ptrace.h" +#include "linux/sched.h" +#include "asm/uaccess.h" #ifdef CONFIG_PROC_MM -#include "linux/proc_mm.h" +#include "proc_mm.h" #endif -#include "asm/ptrace.h" -#include "asm/uaccess.h" -#include "kern_util.h" #include "skas_ptrace.h" -#include "sysdep/ptrace.h" -#include "os.h" static inline void set_singlestepping(struct task_struct *child, int on) { - if (on) - child->ptrace |= PT_DTRACE; - else - child->ptrace &= ~PT_DTRACE; - child->thread.singlestep_syscall = 0; + if (on) + child->ptrace |= PT_DTRACE; + else + child->ptrace &= ~PT_DTRACE; + child->thread.singlestep_syscall = 0; #ifdef SUBARCH_SET_SINGLESTEPPING - SUBARCH_SET_SINGLESTEPPING(child, on); + SUBARCH_SET_SINGLESTEPPING(child, on); #endif } @@ -37,8 +29,8 @@ static inline void set_singlestepping(struct task_struct *child, int on) * Called by kernel/ptrace.c when detaching.. */ void ptrace_disable(struct task_struct *child) -{ - set_singlestepping(child,0); +{ + set_singlestepping(child,0); } extern int peek_user(struct task_struct * child, long addr, long data); @@ -50,40 +42,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) unsigned long __user *p = (void __user *)(unsigned long)data; switch (request) { - /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ + /* read word at location addr. */ + case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: ret = generic_ptrace_peekdata(child, addr, data); break; /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: - ret = peek_user(child, addr, data); - break; + case PTRACE_PEEKUSR: + ret = peek_user(child, addr, data); + break; - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ + /* write the word at location addr. */ + case PTRACE_POKETEXT: case PTRACE_POKEDATA: ret = generic_ptrace_pokedata(child, addr, data); break; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - ret = poke_user(child, addr, data); - break; + /* write the word at location addr in the USER area */ + case PTRACE_POKEUSR: + ret = poke_user(child, addr, data); + break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ + /* continue and stop at next (return from) syscall */ + case PTRACE_SYSCALL: + /* restart after signal. */ + case PTRACE_CONT: { ret = -EIO; if (!valid_signal(data)) break; - set_singlestepping(child, 0); - if (request == PTRACE_SYSCALL) { + set_singlestepping(child, 0); + if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } - else { - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } + else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; wake_up_process(child); ret = 0; @@ -91,8 +83,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: { @@ -100,7 +92,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; - set_singlestepping(child, 0); + set_singlestepping(child, 0); child->exit_code = SIGKILL; wake_up_process(child); break; @@ -111,7 +103,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - set_singlestepping(child, 1); + set_singlestepping(child, 1); child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); @@ -119,11 +111,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - case PTRACE_DETACH: - /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - #ifdef PTRACE_GETREGS case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { @@ -156,22 +143,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) #endif #ifdef PTRACE_GETFPREGS case PTRACE_GETFPREGS: /* Get the child FPU state. */ - ret = get_fpregs(data, child); + ret = get_fpregs((struct user_i387_struct __user *) data, + child); break; #endif #ifdef PTRACE_SETFPREGS case PTRACE_SETFPREGS: /* Set the child FPU state. */ - ret = set_fpregs(data, child); - break; -#endif -#ifdef PTRACE_GETFPXREGS - case PTRACE_GETFPXREGS: /* Get the child FPU state. */ - ret = get_fpxregs(data, child); - break; -#endif -#ifdef PTRACE_SETFPXREGS - case PTRACE_SETFPXREGS: /* Set the child FPU state. */ - ret = set_fpxregs(data, child); + ret = set_fpregs((struct user_i387_struct __user *) data, + child); break; #endif case PTRACE_GET_THREAD_AREA: @@ -185,14 +164,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_FAULTINFO: { - /* Take the info from thread->arch->faultinfo, + /* + * Take the info from thread->arch->faultinfo, * but transfer max. sizeof(struct ptrace_faultinfo). * On i386, ptrace_faultinfo is smaller! */ ret = copy_to_user(p, &child->thread.arch.faultinfo, sizeof(struct ptrace_faultinfo)); - if(ret) - break; break; } @@ -200,12 +178,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_LDT: { struct ptrace_ldt ldt; - if(copy_from_user(&ldt, p, sizeof(ldt))){ + if (copy_from_user(&ldt, p, sizeof(ldt))) { ret = -EIO; break; } - /* This one is confusing, so just punt and return -EIO for + /* + * This one is confusing, so just punt and return -EIO for * now */ ret = -EIO; @@ -217,7 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct mm_struct *old = child->mm; struct mm_struct *new = proc_mm_get_mm(data); - if(IS_ERR(new)){ + if (IS_ERR(new)) { ret = PTR_ERR(new); break; } @@ -231,20 +210,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } #endif #ifdef PTRACE_ARCH_PRCTL - case PTRACE_ARCH_PRCTL: - /* XXX Calls ptrace on the host - needs some SMP thinking */ - ret = arch_prctl_skas(child, data, (void *) addr); - break; + case PTRACE_ARCH_PRCTL: + /* XXX Calls ptrace on the host - needs some SMP thinking */ + ret = arch_prctl(child, data, (void *) addr); + break; #endif default: ret = ptrace_request(child, request, addr, data); + if (ret == -EIO) + ret = subarch_ptrace(child, request, addr, data); break; } return ret; } -void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, +void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, int error_code) { struct siginfo info; @@ -260,10 +241,11 @@ void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, force_sig_info(SIGTRAP, &info, tsk); } -/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and +/* + * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check */ -void syscall_trace(union uml_pt_regs *regs, int entryexit) +void syscall_trace(struct uml_pt_regs *regs, int entryexit) { int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; int tracesysgood; @@ -277,7 +259,7 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) UPT_SYSCALL_ARG3(regs), UPT_SYSCALL_ARG4(regs)); else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), - UPT_SYSCALL_RET(regs)); + UPT_SYSCALL_RET(regs)); } /* Fake a debug trap */ @@ -290,15 +272,18 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) if (!(current->ptrace & PT_PTRACED)) return; - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ + /* + * the 0x80 provides a way for the tracing parent to distinguish + * between a syscall stop and SIGTRAP delivery + */ tracesysgood = (current->ptrace & PT_TRACESYSGOOD); ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); if (entryexit) /* force do_signal() --> is_syscall() */ set_thread_flag(TIF_SIGPENDING); - /* this isn't the same as continuing with a signal, but it will do + /* + * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the * stopping signal is not SIGTRAP. -brl */ diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 7e4305a1fd3..04cebcf0679 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -1,60 +1,53 @@ /* - * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/module.h" #include "linux/sched.h" -#include "asm/smp.h" -#include "kern_util.h" -#include "kern.h" #include "os.h" -#include "mode.h" -#include "choose-mode.h" +#include "skas.h" void (*pm_power_off)(void); -#ifdef CONFIG_SMP -static void kill_idlers(int me) -{ -#ifdef CONFIG_MODE_TT - struct task_struct *p; - int i; - - for(i = 0; i < ARRAY_SIZE(idle_threads); i++){ - p = idle_threads[i]; - if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) - os_kill_process(p->thread.mode.tt.extern_pid, 0); - } -#endif -} -#endif - static void kill_off_processes(void) { - CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas()); -#ifdef CONFIG_SMP - kill_idlers(os_getpid()); -#endif + if(proc_mm) + /* + * FIXME: need to loop over userspace_pids + */ + os_kill_ptraced_process(userspace_pid[0], 1); + else { + struct task_struct *p; + int pid, me; + + me = os_getpid(); + for_each_process(p){ + if(p->mm == NULL) + continue; + + pid = p->mm->context.id.u.pid; + os_kill_ptraced_process(pid, 1); + } + } } void uml_cleanup(void) { - kmalloc_ok = 0; + kmalloc_ok = 0; do_uml_exitcalls(); kill_off_processes(); } void machine_restart(char * __unused) { - uml_cleanup(); - CHOOSE_MODE(reboot_tt(), reboot_skas()); + uml_cleanup(); + reboot_skas(); } void machine_power_off(void) { - uml_cleanup(); - CHOOSE_MODE(halt_tt(), halt_skas()); + uml_cleanup(); + halt_skas(); } void machine_halt(void) diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index c4020c3d785..19cb9773393 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -1,29 +1,17 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/sys.h" -#include "linux/sched.h" -#include "linux/wait.h" -#include "linux/kernel.h" -#include "linux/smp_lock.h" #include "linux/module.h" -#include "linux/slab.h" -#include "linux/tty.h" -#include "linux/binfmts.h" #include "linux/ptrace.h" +#include "linux/sched.h" +#include "asm/siginfo.h" #include "asm/signal.h" -#include "asm/uaccess.h" #include "asm/unistd.h" -#include "asm/ucontext.h" -#include "kern_util.h" -#include "signal_kern.h" -#include "kern.h" #include "frame_kern.h" +#include "kern_util.h" #include "sigcontext.h" -#include "mode.h" EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(unblock_signals); @@ -46,9 +34,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, current_thread_info()->restart_block.fn = do_no_restart_syscall; /* Did we come from a system call? */ - if(PT_REGS_SYSCALL_NR(regs) >= 0){ + if (PT_REGS_SYSCALL_NR(regs) >= 0) { /* If so, check system call restarting.. */ - switch(PT_REGS_SYSCALL_RET(regs)){ + switch(PT_REGS_SYSCALL_RET(regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: PT_REGS_SYSCALL_RET(regs) = -EINTR; @@ -68,17 +56,17 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, } sp = PT_REGS_SP(regs); - if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) + if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; #ifdef CONFIG_ARCH_HAS_SC_SIGNALS - if(!(ka->sa.sa_flags & SA_SIGINFO)) + if (!(ka->sa.sa_flags & SA_SIGINFO)) err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); else #endif err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); - if(err){ + if (err) { spin_lock_irq(¤t->sighand->siglock); current->blocked = *oldset; recalc_sigpending(); @@ -88,7 +76,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); - if(!(ka->sa.sa_flags & SA_NODEFER)) + if (!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); @@ -109,14 +97,16 @@ static int kern_do_signal(struct pt_regs *regs) else oldset = ¤t->blocked; - while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ + while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { handled_sig = 1; /* Whee! Actually deliver the signal. */ - if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ - /* a signal was successfully delivered; the saved + if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { + /* + * a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ + * clear the TIF_RESTORE_SIGMASK flag + */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); break; @@ -124,9 +114,9 @@ static int kern_do_signal(struct pt_regs *regs) } /* Did we come from a system call? */ - if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ + if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { /* Restart the system call - no handlers present */ - switch(PT_REGS_SYSCALL_RET(regs)){ + switch(PT_REGS_SYSCALL_RET(regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: @@ -137,22 +127,25 @@ static int kern_do_signal(struct pt_regs *regs) PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; PT_REGS_RESTART_SYSCALL(regs); break; - } + } } - /* This closes a way to execute a system call on the host. If + /* + * This closes a way to execute a system call on the host. If * you set a breakpoint on a system call instruction and singlestep * from it, the tracing thread used to PTRACE_SINGLESTEP the process * rather than PTRACE_SYSCALL it, allowing the system call to execute * on the host. The tracing thread will check this flag and * PTRACE_SYSCALL if necessary. */ - if(current->ptrace & PT_DTRACE) + if (current->ptrace & PT_DTRACE) current->thread.singlestep_syscall = is_syscall(PT_REGS_IP(¤t->thread.regs)); - /* if there's no signal to deliver, we just put the saved sigmask - * back */ + /* + * if there's no signal to deliver, we just put the saved sigmask + * back + */ if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 3e3fa7e7e3c..0b76d8869c9 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) +# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # -obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o +obj-y := clone.o mmu.o process.o syscall.o uaccess.o # clone.o is in the stub, so it can't be built with profiling # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 47b812b3bca..d119f4f7d89 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -4,6 +4,7 @@ #include <sys/time.h> #include <asm/unistd.h> #include <asm/page.h> +#include "as-layout.h" #include "ptrace_user.h" #include "skas.h" #include "stub-data.h" @@ -21,12 +22,11 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { - struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA; + struct stub_data *data = (struct stub_data *) STUB_DATA; long err; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 - - sizeof(void *)); + STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); if(err != 0) goto out; diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c deleted file mode 100644 index 580eb646894..00000000000 --- a/arch/um/kernel/skas/exec.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/kernel.h" -#include "asm/current.h" -#include "asm/page.h" -#include "asm/signal.h" -#include "asm/ptrace.h" -#include "asm/uaccess.h" -#include "asm/mmu_context.h" -#include "tlb.h" -#include "skas.h" -#include "um_mmu.h" -#include "os.h" - -void flush_thread_skas(void) -{ - void *data = NULL; - unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; - int ret; - - ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data); - if(ret){ - printk("flush_thread_skas - clearing address space failed, " - "err = %d\n", ret); - force_sig(SIGKILL, current); - } - - switch_mm_skas(¤t->mm->context.skas.id); -} - -void start_thread_skas(struct pt_regs *regs, unsigned long eip, - unsigned long esp) -{ - set_fs(USER_DS); - PT_REGS_IP(regs) = eip; - PT_REGS_SP(regs) = esp; -} diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c deleted file mode 100644 index 7c18dfcd7d8..00000000000 --- a/arch/um/kernel/skas/mem.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/mm.h" -#include "asm/pgtable.h" -#include "mem_user.h" -#include "skas.h" - -unsigned long set_task_sizes_skas(unsigned long *task_size_out) -{ - /* Round up to the nearest 4M */ - unsigned long host_task_size = ROUND_4M((unsigned long) - &host_task_size); - - if (!skas_needs_stub) - *task_size_out = host_task_size; - else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; - - return host_task_size; -} diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 2c6d090a2e8..f859ec306cd 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -1,20 +1,13 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/list.h" -#include "linux/spinlock.h" -#include "linux/slab.h" -#include "linux/errno.h" #include "linux/mm.h" -#include "asm/current.h" -#include "asm/segment.h" -#include "asm/mmu.h" +#include "linux/sched.h" #include "asm/pgalloc.h" #include "asm/pgtable.h" -#include "asm/ldt.h" +#include "as-layout.h" #include "os.h" #include "skas.h" @@ -41,10 +34,11 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, if (!pte) goto out_pte; - /* There's an interaction between the skas0 stub pages, stack + /* + * There's an interaction between the skas0 stub pages, stack * randomization, and the BUG at the end of exit_mmap. exit_mmap - * checks that the number of page tables freed is the same as had - * been allocated. If the stack is on the last page table page, + * checks that the number of page tables freed is the same as had + * been allocated. If the stack is on the last page table page, * then the stack pte page will be freed, and if not, it won't. To * avoid having to know where the stack is, or if the process mapped * something at the top of its address space for some other reason, @@ -54,76 +48,77 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, * destroy_context_skas. */ - mm->context.skas.last_page_table = pmd_page_vaddr(*pmd); + mm->context.last_page_table = pmd_page_vaddr(*pmd); #ifdef CONFIG_3_LEVEL_PGTABLES - mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); + mm->context.last_pmd = (unsigned long) __va(pud_val(*pud)); #endif *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); *pte = pte_mkread(*pte); - return(0); + return 0; out_pmd: pud_free(pud); out_pte: pmd_free(pmd); out: - return(-ENOMEM); + return -ENOMEM; } -int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) +int init_new_context(struct task_struct *task, struct mm_struct *mm) { - struct mmu_context_skas *from_mm = NULL; - struct mmu_context_skas *to_mm = &mm->context.skas; + struct mm_context *from_mm = NULL; + struct mm_context *to_mm = &mm->context; unsigned long stack = 0; int ret = -ENOMEM; - if(skas_needs_stub){ + if (skas_needs_stub) { stack = get_zeroed_page(GFP_KERNEL); - if(stack == 0) + if (stack == 0) goto out; - /* This zeros the entry that pgd_alloc didn't, needed since + /* + * This zeros the entry that pgd_alloc didn't, needed since * we are about to reinitialize it, and want mm.nr_ptes to * be accurate. */ mm->pgd[USER_PTRS_PER_PGD] = __pgd(0); - ret = init_stub_pte(mm, CONFIG_STUB_CODE, + ret = init_stub_pte(mm, STUB_CODE, (unsigned long) &__syscall_stub_start); - if(ret) + if (ret) goto out_free; - ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack); - if(ret) + ret = init_stub_pte(mm, STUB_DATA, stack); + if (ret) goto out_free; mm->nr_ptes--; } to_mm->id.stack = stack; - if(current->mm != NULL && current->mm != &init_mm) - from_mm = ¤t->mm->context.skas; + if (current->mm != NULL && current->mm != &init_mm) + from_mm = ¤t->mm->context; - if(proc_mm){ + if (proc_mm) { ret = new_mm(stack); - if(ret < 0){ - printk("init_new_context_skas - new_mm failed, " - "errno = %d\n", ret); + if (ret < 0) { + printk(KERN_ERR "init_new_context_skas - " + "new_mm failed, errno = %d\n", ret); goto out_free; } to_mm->id.u.mm_fd = ret; } else { - if(from_mm) + if (from_mm) to_mm->id.u.pid = copy_context_skas0(stack, from_mm->id.u.pid); else to_mm->id.u.pid = start_userspace(stack); } ret = init_new_ldt(to_mm, from_mm); - if(ret < 0){ - printk("init_new_context_skas - init_ldt" + if (ret < 0) { + printk(KERN_ERR "init_new_context_skas - init_ldt" " failed, errno = %d\n", ret); goto out_free; } @@ -131,22 +126,22 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) return 0; out_free: - if(to_mm->id.stack != 0) + if (to_mm->id.stack != 0) free_page(to_mm->id.stack); out: return ret; } -void destroy_context_skas(struct mm_struct *mm) +void destroy_context(struct mm_struct *mm) { - struct mmu_context_skas *mmu = &mm->context.skas; + struct mm_context *mmu = &mm->context; - if(proc_mm) + if (proc_mm) os_close_file(mmu->id.u.mm_fd); else os_kill_ptraced_process(mmu->id.u.pid, 1); - if(!proc_mm || !ptrace_faultinfo){ + if (!proc_mm || !ptrace_faultinfo) { free_page(mmu->id.stack); pte_lock_deinit(virt_to_page(mmu->last_page_table)); pte_free_kernel((pte_t *) mmu->last_page_table); @@ -155,4 +150,6 @@ void destroy_context_skas(struct mm_struct *mm) pmd_free((pmd_t *) mmu->last_pmd); #endif } + + free_ldt(mmu); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 48051a98525..fce389c2342 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -1,146 +1,26 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/slab.h" -#include "linux/ptrace.h" -#include "linux/proc_fs.h" -#include "linux/file.h" -#include "linux/errno.h" #include "linux/init.h" -#include "asm/uaccess.h" -#include "asm/atomic.h" -#include "kern_util.h" +#include "linux/sched.h" #include "as-layout.h" -#include "skas.h" #include "os.h" -#include "tlb.h" -#include "kern.h" -#include "mode.h" -#include "registers.h" - -void switch_to_skas(void *prev, void *next) -{ - struct task_struct *from, *to; - - from = prev; - to = next; - - /* XXX need to check runqueues[cpu].idle */ - if(current->pid == 0) - switch_timers(0); - - switch_threads(&from->thread.mode.skas.switch_buf, - &to->thread.mode.skas.switch_buf); - - arch_switch_to_skas(current->thread.prev_sched, current); - - if(current->pid == 0) - switch_timers(1); -} - -extern void schedule_tail(struct task_struct *prev); - -/* This is called magically, by its address being stuffed in a jmp_buf - * and being longjmp-d to. - */ -void new_thread_handler(void) -{ - int (*fn)(void *), n; - void *arg; - - if(current->thread.prev_sched != NULL) - schedule_tail(current->thread.prev_sched); - current->thread.prev_sched = NULL; - - fn = current->thread.request.u.thread.proc; - arg = current->thread.request.u.thread.arg; - - /* The return value is 1 if the kernel thread execs a process, - * 0 if it just exits - */ - n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); - if(n == 1){ - /* Handle any immediate reschedules or signals */ - interrupt_end(); - userspace(¤t->thread.regs.regs); - } - else do_exit(0); -} - -void release_thread_skas(struct task_struct *task) -{ -} - -/* Called magically, see new_thread_handler above */ -void fork_handler(void) -{ - force_flush_all(); - if(current->thread.prev_sched == NULL) - panic("blech"); - - schedule_tail(current->thread.prev_sched); - - /* XXX: if interrupt_end() calls schedule, this call to - * arch_switch_to_skas isn't needed. We could want to apply this to - * improve performance. -bb */ - arch_switch_to_skas(current->thread.prev_sched, current); - - current->thread.prev_sched = NULL; - -/* Handle any immediate reschedules or signals */ - interrupt_end(); - - userspace(¤t->thread.regs.regs); -} - -int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, - struct pt_regs *regs) -{ - void (*handler)(void); - - if(current->thread.forking){ - memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, - sizeof(p->thread.regs.regs.skas)); - REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); - if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; - - handler = fork_handler; - - arch_copy_thread(¤t->thread.arch, &p->thread.arch); - } - else { - init_thread_registers(&p->thread.regs.regs); - p->thread.request.u.thread = current->thread.request.u.thread; - handler = new_thread_handler; - } - - new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, - handler); - return(0); -} +#include "skas.h" int new_mm(unsigned long stack) { int fd; fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); - if(fd < 0) - return(fd); + if (fd < 0) + return fd; - if(skas_needs_stub) - map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); + if (skas_needs_stub) + map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); - return(fd); -} - -void init_idle_skas(void) -{ - cpu_tasks[current_thread->cpu].pid = os_getpid(); - default_idle(); + return fd; } extern void start_kernel(void); @@ -158,67 +38,32 @@ static int __init start_kernel_proc(void *unused) cpu_online_map = cpumask_of_cpu(0); #endif start_kernel(); - return(0); + return 0; } extern int userspace_pid[]; extern char cpu0_irqstack[]; -int __init start_uml_skas(void) +int __init start_uml(void) { stack_protections((unsigned long) &cpu0_irqstack); set_sigstack(cpu0_irqstack, THREAD_SIZE); - if(proc_mm) + if (proc_mm) userspace_pid[0] = start_userspace(0); init_new_thread_signals(); init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; - return(start_idle_thread(task_stack_page(&init_task), - &init_task.thread.mode.skas.switch_buf)); -} - -int external_pid_skas(struct task_struct *task) -{ - /* FIXME: Need to look up userspace_pid by cpu */ - return(userspace_pid[0]); -} - -int thread_pid_skas(struct task_struct *task) -{ - /* FIXME: Need to look up userspace_pid by cpu */ - return(userspace_pid[0]); -} - -void kill_off_processes_skas(void) -{ - if(proc_mm) - /* - * FIXME: need to loop over userspace_pids in - * kill_off_processes_skas - */ - os_kill_ptraced_process(userspace_pid[0], 1); - else { - struct task_struct *p; - int pid, me; - - me = os_getpid(); - for_each_process(p){ - if(p->mm == NULL) - continue; - - pid = p->mm->context.skas.id.u.pid; - os_kill_ptraced_process(pid, 1); - } - } + return start_idle_thread(task_stack_page(&init_task), + &init_task.thread.switch_buf); } unsigned long current_stub_stack(void) { - if(current->mm == NULL) - return(0); + if (current->mm == NULL) + return 0; - return(current->mm->context.skas.id.stack); + return current->mm->context.id.stack; } diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 0ae4eea21be..50b476f2b38 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -1,19 +1,15 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sys.h" +#include "linux/kernel.h" #include "linux/ptrace.h" -#include "asm/errno.h" -#include "asm/unistd.h" -#include "asm/ptrace.h" -#include "asm/current.h" -#include "sysdep/syscalls.h" #include "kern_util.h" -#include "syscall.h" +#include "sysdep/ptrace.h" +#include "sysdep/syscalls.h" -void handle_syscall(union uml_pt_regs *r) +void handle_syscall(struct uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs); long result; @@ -24,7 +20,8 @@ void handle_syscall(union uml_pt_regs *r) current->thread.nsyscalls++; nsyscalls++; - /* This should go in the declaration of syscall, but when I do that, + /* + * This should go in the declaration of syscall, but when I do that, * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing * children at all, sometimes hanging when bash doesn't see the first * ls exit. @@ -33,11 +30,11 @@ void handle_syscall(union uml_pt_regs *r) * in case it's a compiler bug. */ syscall = UPT_SYSCALL_NR(r); - if((syscall >= NR_syscalls) || (syscall < 0)) + if ((syscall >= NR_syscalls) || (syscall < 0)) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); - REGS_SET_SYSCALL_RETURN(r->skas.regs, result); + REGS_SET_SYSCALL_RETURN(r->gp, result); syscall_trace(r, 1); } diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c deleted file mode 100644 index c0f0693743b..00000000000 --- a/arch/um/kernel/skas/tlb.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Copyright 2003 PathScale, Inc. - * Licensed under the GPL - */ - -#include "linux/stddef.h" -#include "linux/sched.h" -#include "linux/mm.h" -#include "asm/page.h" -#include "asm/pgtable.h" -#include "asm/mmu.h" -#include "mem_user.h" -#include "mem.h" -#include "skas.h" -#include "os.h" -#include "tlb.h" - -static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, - int finished, void **flush) -{ - struct host_vm_op *op; - int i, ret = 0; - - for(i = 0; i <= last && !ret; i++){ - op = &ops[i]; - switch(op->type){ - case MMAP: - ret = map(&mmu->skas.id, op->u.mmap.addr, - op->u.mmap.len, op->u.mmap.prot, - op->u.mmap.fd, op->u.mmap.offset, finished, - flush); - break; - case MUNMAP: - ret = unmap(&mmu->skas.id, op->u.munmap.addr, - op->u.munmap.len, finished, flush); - break; - case MPROTECT: - ret = protect(&mmu->skas.id, op->u.mprotect.addr, - op->u.mprotect.len, op->u.mprotect.prot, - finished, flush); - break; - default: - printk("Unknown op type %d in do_ops\n", op->type); - break; - } - } - - return ret; -} - -extern int proc_mm; - -static void fix_range(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force) -{ - if(!proc_mm && (end_addr > CONFIG_STUB_START)) - end_addr = CONFIG_STUB_START; - - fix_range_common(mm, start_addr, end_addr, force, do_ops); -} - -void __flush_tlb_one_skas(unsigned long addr) -{ - flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); -} - -void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - if(vma->vm_mm == NULL) - flush_tlb_kernel_range_common(start, end); - else fix_range(vma->vm_mm, start, end, 0); -} - -void flush_tlb_mm_skas(struct mm_struct *mm) -{ - unsigned long end; - - /* Don't bother flushing if this address space is about to be - * destroyed. - */ - if(atomic_read(&mm->mm_users) == 0) - return; - - end = proc_mm ? task_size : CONFIG_STUB_START; - fix_range(mm, 0, end, 0); -} - -void force_flush_all_skas(void) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma = mm->mmap; - - while(vma != NULL) { - fix_range(mm, vma->vm_start, vma->vm_end, 1); - vma = vma->vm_next; - } -} - -void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - struct mm_struct *mm = vma->vm_mm; - void *flush = NULL; - int r, w, x, prot, err = 0; - struct mm_id *mm_id; - - pgd = pgd_offset(mm, address); - if(!pgd_present(*pgd)) - goto kill; - - pud = pud_offset(pgd, address); - if(!pud_present(*pud)) - goto kill; - - pmd = pmd_offset(pud, address); - if(!pmd_present(*pmd)) - goto kill; - - pte = pte_offset_kernel(pmd, address); - - r = pte_read(*pte); - w = pte_write(*pte); - x = pte_exec(*pte); - if (!pte_young(*pte)) { - r = 0; - w = 0; - } else if (!pte_dirty(*pte)) { - w = 0; - } - - mm_id = &mm->context.skas.id; - prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | - (x ? UM_PROT_EXEC : 0)); - if(pte_newpage(*pte)){ - if(pte_present(*pte)){ - unsigned long long offset; - int fd; - - fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); - err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, - 1, &flush); - } - else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); - } - else if(pte_newprot(*pte)) - err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); - - if(err) - goto kill; - - *pte = pte_mkuptodate(*pte); - - return; - -kill: - printk("Failed to flush page for address 0x%lx\n", address); - force_sig(SIGKILL, current); -} - diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 8912cec0fe4..1d8b119f2d0 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -1,18 +1,14 @@ /* - * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/compiler.h" -#include "linux/stddef.h" -#include "linux/kernel.h" -#include "linux/string.h" -#include "linux/fs.h" -#include "linux/hardirq.h" +#include "linux/err.h" #include "linux/highmem.h" +#include "linux/mm.h" +#include "asm/current.h" #include "asm/page.h" #include "asm/pgtable.h" -#include "asm/uaccess.h" #include "kern_util.h" #include "os.h" @@ -27,16 +23,16 @@ static unsigned long maybe_map(unsigned long virt, int is_write) void *phys = um_virt_to_phys(current, virt, &pte); int dummy_code; - if(IS_ERR(phys) || (is_write && !pte_write(pte))){ + if (IS_ERR(phys) || (is_write && !pte_write(pte))) { err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); - if(err) - return(-1UL); + if (err) + return -1UL; phys = um_virt_to_phys(current, virt, NULL); } - if(IS_ERR(phys)) - phys = (void *) -1; + if (IS_ERR(phys)) + phys = (void *) -1; - return((unsigned long) phys); + return (unsigned long) phys; } static int do_op_one_page(unsigned long addr, int len, int is_write, @@ -46,17 +42,18 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, int n; addr = maybe_map(addr, is_write); - if(addr == -1UL) - return(-1); + if (addr == -1UL) + return -1; page = phys_to_page(addr); - addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); + addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + + (addr & ~PAGE_MASK); n = (*op)(addr, len, arg); kunmap_atomic(page, KM_UML_USERCOPY); - return(n); + return n; } static void do_buffer_op(void *jmpbuf, void *arg_ptr) @@ -81,21 +78,21 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) current->thread.fault_catcher = jmpbuf; n = do_op_one_page(addr, size, is_write, op, arg); - if(n != 0){ + if (n != 0) { *res = (n < 0 ? remain : 0); goto out; } addr += size; remain -= size; - if(remain == 0){ + if (remain == 0) { *res = 0; goto out; } - while(addr < ((addr + remain) & PAGE_MASK)){ + while(addr < ((addr + remain) & PAGE_MASK)) { n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); - if(n != 0){ + if (n != 0) { *res = (n < 0 ? remain : 0); goto out; } @@ -103,13 +100,13 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) addr += PAGE_SIZE; remain -= PAGE_SIZE; } - if(remain == 0){ + if (remain == 0) { *res = 0; goto out; } n = do_op_one_page(addr, remain, is_write, op, arg); - if(n != 0) + if (n != 0) *res = (n < 0 ? remain : 0); else *res = 0; out: @@ -124,10 +121,10 @@ static int buffer_op(unsigned long addr, int len, int is_write, faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, &res); - if(!faulted) - return(res); + if (!faulted) + return res; - return(addr + len - (unsigned long) current->thread.fault_addr); + return addr + len - (unsigned long) current->thread.fault_addr; } static int copy_chunk_from_user(unsigned long from, int len, void *arg) @@ -136,19 +133,19 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) memcpy((void *) to, (void *) from, len); *to_ptr += len; - return(0); + return 0; } -int copy_from_user_skas(void *to, const void __user *from, int n) +int copy_from_user(void *to, const void __user *from, int n) { - if(segment_eq(get_fs(), KERNEL_DS)){ + if (segment_eq(get_fs(), KERNEL_DS)) { memcpy(to, (__force void*)from, n); - return(0); + return 0; } - return(access_ok(VERIFY_READ, from, n) ? + return access_ok(VERIFY_READ, from, n) ? buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): - n); + n; } static int copy_chunk_to_user(unsigned long to, int len, void *arg) @@ -157,19 +154,19 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) memcpy((void *) to, (void *) from, len); *from_ptr += len; - return(0); + return 0; } -int copy_to_user_skas(void __user *to, const void *from, int n) +int copy_to_user(void __user *to, const void *from, int n) { - if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy((__force void*)to, from, n); - return(0); + if (segment_eq(get_fs(), KERNEL_DS)) { + memcpy((__force void *) to, from, n); + return 0; } - return(access_ok(VERIFY_WRITE, to, n) ? + return access_ok(VERIFY_WRITE, to, n) ? buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : - n); + n; } static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) @@ -181,51 +178,51 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) n = strnlen(to, len); *to_ptr += n; - if(n < len) - return(1); - return(0); + if (n < len) + return 1; + return 0; } -int strncpy_from_user_skas(char *dst, const char __user *src, int count) +int strncpy_from_user(char *dst, const char __user *src, int count) { int n; char *ptr = dst; - if(segment_eq(get_fs(), KERNEL_DS)){ - strncpy(dst, (__force void*)src, count); - return(strnlen(dst, count)); + if (segment_eq(get_fs(), KERNEL_DS)) { + strncpy(dst, (__force void *) src, count); + return strnlen(dst, count); } - if(!access_ok(VERIFY_READ, src, 1)) - return(-EFAULT); + if (!access_ok(VERIFY_READ, src, 1)) + return -EFAULT; n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, &ptr); - if(n != 0) - return(-EFAULT); - return(strnlen(dst, count)); + if (n != 0) + return -EFAULT; + return strnlen(dst, count); } static int clear_chunk(unsigned long addr, int len, void *unused) { memset((void *) addr, 0, len); - return(0); + return 0; } -int __clear_user_skas(void __user *mem, int len) +int __clear_user(void __user *mem, int len) { - return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); + return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); } -int clear_user_skas(void __user *mem, int len) +int clear_user(void __user *mem, int len) { - if(segment_eq(get_fs(), KERNEL_DS)){ + if (segment_eq(get_fs(), KERNEL_DS)) { memset((__force void*)mem, 0, len); - return(0); + return 0; } - return(access_ok(VERIFY_WRITE, mem, len) ? - buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); + return access_ok(VERIFY_WRITE, mem, len) ? + buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; } static int strnlen_chunk(unsigned long str, int len, void *arg) @@ -235,31 +232,20 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) n = strnlen((void *) str, len); *len_ptr += n; - if(n < len) - return(1); - return(0); + if (n < len) + return 1; + return 0; } -int strnlen_user_skas(const void __user *str, int len) +int strnlen_user(const void __user *str, int len) { int count = 0, n; - if(segment_eq(get_fs(), KERNEL_DS)) - return(strnlen((__force char*)str, len) + 1); + if (segment_eq(get_fs(), KERNEL_DS)) + return strnlen((__force char*)str, len) + 1; n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); - if(n == 0) - return(count + 1); - return(-EFAULT); + if (n == 0) + return count + 1; + return -EFAULT; } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index e6a7778006a..36d89cf8d20 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -56,12 +56,12 @@ void smp_send_stop(void) int i; printk(KERN_INFO "Stopping all CPUs..."); - for(i = 0; i < num_online_cpus(); i++){ - if(i == current_thread->cpu) + for (i = 0; i < num_online_cpus(); i++) { + if (i == current_thread->cpu) continue; os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); } - printk("done\n"); + printk(KERN_INFO "done\n"); } static cpumask_t smp_commenced_mask = CPU_MASK_NONE; @@ -72,7 +72,7 @@ static int idle_proc(void *cpup) int cpu = (int) cpup, err; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); - if(err < 0) + if (err < 0) panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); os_set_fd_async(cpu_data[cpu].ipi_pipe[0], @@ -80,7 +80,7 @@ static int idle_proc(void *cpup) wmb(); if (cpu_test_and_set(cpu, cpu_callin_map)) { - printk("huh, CPU#%d already present??\n", cpu); + printk(KERN_ERR "huh, CPU#%d already present??\n", cpu); BUG(); } @@ -95,12 +95,11 @@ static int idle_proc(void *cpup) static struct task_struct *idle_thread(int cpu) { struct task_struct *new_task; - unsigned char c; current->thread.request.u.thread.proc = idle_proc; current->thread.request.u.thread.arg = (void *) cpu; new_task = fork_idle(cpu); - if(IS_ERR(new_task)) + if (IS_ERR(new_task)) panic("copy_process failed in idle_thread, error = %ld", PTR_ERR(new_task)); @@ -108,9 +107,7 @@ static struct task_struct *idle_thread(int cpu) { .pid = new_task->thread.mode.tt.extern_pid, .task = new_task } ); idle_threads[cpu] = new_task; - CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, - sizeof(c)), - ({ panic("skas mode doesn't support SMP"); })); + panic("skas mode doesn't support SMP"); return new_task; } @@ -129,14 +126,14 @@ void smp_prepare_cpus(unsigned int maxcpus) cpu_set(me, cpu_callin_map); err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); - if(err < 0) + if (err < 0) panic("CPU#0 failed to create IPI pipe, errno = %d", -err); os_set_fd_async(cpu_data[me].ipi_pipe[0], current->thread.mode.tt.extern_pid); - for(cpu = 1; cpu < ncpus; cpu++){ - printk("Booting processor %d...\n", cpu); + for (cpu = 1; cpu < ncpus; cpu++) { + printk(KERN_INFO "Booting processor %d...\n", cpu); idle = idle_thread(cpu); @@ -147,8 +144,8 @@ void smp_prepare_cpus(unsigned int maxcpus) cpu_relax(); if (cpu_isset(cpu, cpu_callin_map)) - printk("done\n"); - else printk("failed\n"); + printk(KERN_INFO "done\n"); + else printk(KERN_INFO "failed\n"); } } @@ -190,13 +187,14 @@ void IPI_handler(int cpu) break; case 'S': - printk("CPU#%d stopping\n", cpu); - while(1) + printk(KERN_INFO "CPU#%d stopping\n", cpu); + while (1) pause(); break; default: - printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); + printk(KERN_ERR "CPU#%d received unknown IPI [%c]!\n", + cpu, c); break; } } diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 7b3b67333ff..b9d92b2089a 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -1,27 +1,17 @@ /* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sched.h" #include "linux/file.h" -#include "linux/smp_lock.h" -#include "linux/mm.h" #include "linux/fs.h" +#include "linux/mm.h" +#include "linux/sched.h" #include "linux/utsname.h" -#include "linux/msg.h" -#include "linux/shm.h" -#include "linux/sys.h" -#include "linux/syscalls.h" -#include "linux/unistd.h" -#include "linux/slab.h" -#include "linux/utime.h" +#include "asm/current.h" #include "asm/mman.h" #include "asm/uaccess.h" -#include "kern_util.h" -#include "sysdep/syscalls.h" -#include "mode_kern.h" -#include "choose-mode.h" +#include "asm/unistd.h" /* Unlocked, I don't care if this is a bit off */ int nsyscalls = 0; @@ -34,7 +24,7 @@ long sys_fork(void) ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); current->thread.forking = 0; - return(ret); + return ret; } long sys_vfork(void) @@ -46,7 +36,7 @@ long sys_vfork(void) UPT_SP(¤t->thread.regs.regs), ¤t->thread.regs, 0, NULL, NULL); current->thread.forking = 0; - return(ret); + return ret; } /* common code for old and new mmaps */ @@ -92,15 +82,15 @@ long old_mmap(unsigned long addr, unsigned long len, */ long sys_pipe(unsigned long __user * fildes) { - int fd[2]; - long error; + int fd[2]; + long error; - error = do_pipe(fd); - if (!error) { + error = do_pipe(fd); + if (!error) { if (copy_to_user(fildes, fd, sizeof(fd))) - error = -EFAULT; - } - return error; + error = -EFAULT; + } + return error; } @@ -124,7 +114,7 @@ long sys_olduname(struct oldold_utsname __user * name) if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) return -EFAULT; - down_read(&uts_sem); + down_read(&uts_sem); error = __copy_to_user(&name->sysname, &utsname()->sysname, __OLD_UTS_LEN); diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 259c49da7ff..1ac746a9eae 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -1,189 +1,126 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/module.h" -#include "linux/unistd.h" -#include "linux/stddef.h" -#include "linux/spinlock.h" -#include "linux/time.h" -#include "linux/sched.h" +#include "linux/clockchips.h" #include "linux/interrupt.h" -#include "linux/init.h" -#include "linux/delay.h" -#include "linux/hrtimer.h" +#include "linux/jiffies.h" +#include "linux/threads.h" #include "asm/irq.h" #include "asm/param.h" -#include "asm/current.h" #include "kern_util.h" -#include "mode.h" #include "os.h" -int hz(void) -{ - return(HZ); -} - /* * Scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) { - return (unsigned long long)jiffies_64 * (1000000000 / HZ); + return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ); } -#ifdef CONFIG_UML_REAL_TIME_CLOCK -static unsigned long long prev_nsecs[NR_CPUS]; -static long long delta[NR_CPUS]; /* Deviation per interval */ -#endif +void timer_handler(int sig, struct uml_pt_regs *regs) +{ + unsigned long flags; + + local_irq_save(flags); + do_IRQ(TIMER_IRQ, regs); + local_irq_restore(flags); +} -void timer_irq(union uml_pt_regs *regs) +static void itimer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { - unsigned long long ticks = 0; -#ifdef CONFIG_UML_REAL_TIME_CLOCK - int c = cpu(); - if(prev_nsecs[c]){ - /* We've had 1 tick */ - unsigned long long nsecs = os_nsecs(); - - delta[c] += nsecs - prev_nsecs[c]; - prev_nsecs[c] = nsecs; - - /* Protect against the host clock being set backwards */ - if(delta[c] < 0) - delta[c] = 0; - - ticks += (delta[c] * HZ) / BILLION; - delta[c] -= (ticks * BILLION) / HZ; - } - else prev_nsecs[c] = os_nsecs(); -#else - ticks = 1; -#endif - while(ticks > 0){ - do_IRQ(TIMER_IRQ, regs); - ticks--; + switch(mode) { + case CLOCK_EVT_MODE_PERIODIC: + set_interval(); + break; + + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_ONESHOT: + disable_timer(); + break; + + case CLOCK_EVT_MODE_RESUME: + break; } } -/* Protects local_offset */ -static DEFINE_SPINLOCK(timer_spinlock); -static unsigned long long local_offset = 0; - -static inline unsigned long long get_time(void) +static int itimer_next_event(unsigned long delta, + struct clock_event_device *evt) { - unsigned long long nsecs; - unsigned long flags; - - spin_lock_irqsave(&timer_spinlock, flags); - nsecs = os_nsecs(); - nsecs += local_offset; - spin_unlock_irqrestore(&timer_spinlock, flags); - - return nsecs; + return timer_one_shot(delta + 1); } -irqreturn_t um_timer(int irq, void *dev) +static struct clock_event_device itimer_clockevent = { + .name = "itimer", + .rating = 250, + .cpumask = CPU_MASK_ALL, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = itimer_set_mode, + .set_next_event = itimer_next_event, + .shift = 32, + .irq = 0, +}; + +static irqreturn_t um_timer(int irq, void *dev) { - unsigned long long nsecs; - unsigned long flags; - - write_seqlock_irqsave(&xtime_lock, flags); - - do_timer(1); - -#ifdef CONFIG_UML_REAL_TIME_CLOCK - nsecs = get_time(); -#else - nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec + - BILLION / HZ; -#endif - xtime.tv_sec = nsecs / NSEC_PER_SEC; - xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; - - write_sequnlock_irqrestore(&xtime_lock, flags); + (*itimer_clockevent.event_handler)(&itimer_clockevent); return IRQ_HANDLED; } -static void register_timer(void) +static cycle_t itimer_read(void) +{ + return os_nsecs(); +} + +static struct clocksource itimer_clocksource = { + .name = "itimer", + .rating = 300, + .read = itimer_read, + .mask = CLOCKSOURCE_MASK(64), + .mult = 1, + .shift = 0, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init setup_itimer(void) { int err; err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); - if(err != 0) + if (err != 0) printk(KERN_ERR "register_timer : request_irq failed - " "errno = %d\n", -err); - err = set_interval(1); - if(err != 0) - printk(KERN_ERR "register_timer : set_interval failed - " - "errno = %d\n", -err); + itimer_clockevent.mult = div_sc(HZ, NSEC_PER_SEC, 32); + itimer_clockevent.max_delta_ns = + clockevent_delta2ns(60 * HZ, &itimer_clockevent); + itimer_clockevent.min_delta_ns = + clockevent_delta2ns(1, &itimer_clockevent); + err = clocksource_register(&itimer_clocksource); + if (err) { + printk(KERN_ERR "clocksource_register returned %d\n", err); + return; + } + clockevents_register_device(&itimer_clockevent); } extern void (*late_time_init)(void); -void time_init(void) +void __init time_init(void) { long long nsecs; - nsecs = os_nsecs(); - set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, - -nsecs % BILLION); - set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION); - late_time_init = register_timer; -} - -void do_gettimeofday(struct timeval *tv) -{ -#ifdef CONFIG_UML_REAL_TIME_CLOCK - unsigned long long nsecs = get_time(); -#else - unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION + - xtime.tv_nsec; -#endif - tv->tv_sec = nsecs / NSEC_PER_SEC; - /* Careful about calculations here - this was originally done as - * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC - * which gave bogus (> 1000000) values. Dunno why, suspect gcc - * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion - * problem that I missed. - */ - nsecs -= tv->tv_sec * NSEC_PER_SEC; - tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; -} - -static inline void set_time(unsigned long long nsecs) -{ - unsigned long long now; - unsigned long flags; - - spin_lock_irqsave(&timer_spinlock, flags); - now = os_nsecs(); - local_offset = nsecs - now; - spin_unlock_irqrestore(&timer_spinlock, flags); - - clock_was_set(); -} - -int do_settimeofday(struct timespec *tv) -{ - set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); - - return 0; -} + timer_init(); -void timer_handler(int sig, union uml_pt_regs *regs) -{ - if(current_thread->cpu == 0) - timer_irq(regs); - local_irq_disable(); - irq_enter(); - update_process_times(CHOOSE_MODE( - (UPT_SC(regs) && user_context(UPT_SP(regs))), - (regs)->skas.is_user)); - irq_exit(); - local_irq_enable(); + nsecs = os_nsecs(); + set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC, + -nsecs % NSEC_PER_SEC); + set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC, + nsecs % NSEC_PER_SEC); + late_time_init = setup_itimer; } diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 8a8d5285144..f4a0e407eee 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -1,130 +1,182 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include "linux/mm.h" -#include "asm/page.h" -#include "asm/pgalloc.h" #include "asm/pgtable.h" #include "asm/tlbflush.h" -#include "choose-mode.h" -#include "mode_kern.h" #include "as-layout.h" -#include "tlb.h" -#include "mem.h" #include "mem_user.h" #include "os.h" +#include "skas.h" +#include "tlb.h" + +struct host_vm_change { + struct host_vm_op { + enum { NONE, MMAP, MUNMAP, MPROTECT } type; + union { + struct { + unsigned long addr; + unsigned long len; + unsigned int prot; + int fd; + __u64 offset; + } mmap; + struct { + unsigned long addr; + unsigned long len; + } munmap; + struct { + unsigned long addr; + unsigned long len; + unsigned int prot; + } mprotect; + } u; + } ops[1]; + int index; + struct mm_id *id; + void *data; + int force; +}; + +#define INIT_HVC(mm, force) \ + ((struct host_vm_change) \ + { .ops = { { .type = NONE } }, \ + .id = &mm->context.id, \ + .data = NULL, \ + .index = 0, \ + .force = force }) + +static int do_ops(struct host_vm_change *hvc, int end, + int finished) +{ + struct host_vm_op *op; + int i, ret = 0; + + for (i = 0; i < end && !ret; i++) { + op = &hvc->ops[i]; + switch(op->type) { + case MMAP: + ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, + op->u.mmap.prot, op->u.mmap.fd, + op->u.mmap.offset, finished, &hvc->data); + break; + case MUNMAP: + ret = unmap(hvc->id, op->u.munmap.addr, + op->u.munmap.len, finished, &hvc->data); + break; + case MPROTECT: + ret = protect(hvc->id, op->u.mprotect.addr, + op->u.mprotect.len, op->u.mprotect.prot, + finished, &hvc->data); + break; + default: + printk(KERN_ERR "Unknown op type %d in do_ops\n", + op->type); + break; + } + } + + return ret; +} static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, - unsigned int prot, struct host_vm_op *ops, int *index, - int last_filled, union mm_context *mmu, void **flush, - int (*do_ops)(union mm_context *, struct host_vm_op *, - int, int, void **)) + unsigned int prot, struct host_vm_change *hvc) { __u64 offset; struct host_vm_op *last; int fd, ret = 0; fd = phys_mapping(phys, &offset); - if(*index != -1){ - last = &ops[*index]; - if((last->type == MMAP) && + if (hvc->index != 0) { + last = &hvc->ops[hvc->index - 1]; + if ((last->type == MMAP) && (last->u.mmap.addr + last->u.mmap.len == virt) && (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) && - (last->u.mmap.offset + last->u.mmap.len == offset)){ + (last->u.mmap.offset + last->u.mmap.len == offset)) { last->u.mmap.len += len; return 0; } } - if(*index == last_filled){ - ret = (*do_ops)(mmu, ops, last_filled, 0, flush); - *index = -1; + if (hvc->index == ARRAY_SIZE(hvc->ops)) { + ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); + hvc->index = 0; } - ops[++*index] = ((struct host_vm_op) { .type = MMAP, - .u = { .mmap = { - .addr = virt, - .len = len, - .prot = prot, - .fd = fd, - .offset = offset } + hvc->ops[hvc->index++] = ((struct host_vm_op) + { .type = MMAP, + .u = { .mmap = { .addr = virt, + .len = len, + .prot = prot, + .fd = fd, + .offset = offset } } }); return ret; } static int add_munmap(unsigned long addr, unsigned long len, - struct host_vm_op *ops, int *index, int last_filled, - union mm_context *mmu, void **flush, - int (*do_ops)(union mm_context *, struct host_vm_op *, - int, int, void **)) + struct host_vm_change *hvc) { struct host_vm_op *last; int ret = 0; - if(*index != -1){ - last = &ops[*index]; - if((last->type == MUNMAP) && - (last->u.munmap.addr + last->u.mmap.len == addr)){ + if (hvc->index != 0) { + last = &hvc->ops[hvc->index - 1]; + if ((last->type == MUNMAP) && + (last->u.munmap.addr + last->u.mmap.len == addr)) { last->u.munmap.len += len; return 0; } } - if(*index == last_filled){ - ret = (*do_ops)(mmu, ops, last_filled, 0, flush); - *index = -1; + if (hvc->index == ARRAY_SIZE(hvc->ops)) { + ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); + hvc->index = 0; } - ops[++*index] = ((struct host_vm_op) { .type = MUNMAP, - .u = { .munmap = { - .addr = addr, - .len = len } } }); + hvc->ops[hvc->index++] = ((struct host_vm_op) + { .type = MUNMAP, + .u = { .munmap = { .addr = addr, + .len = len } } }); return ret; } static int add_mprotect(unsigned long addr, unsigned long len, - unsigned int prot, struct host_vm_op *ops, int *index, - int last_filled, union mm_context *mmu, void **flush, - int (*do_ops)(union mm_context *, struct host_vm_op *, - int, int, void **)) + unsigned int prot, struct host_vm_change *hvc) { struct host_vm_op *last; int ret = 0; - if(*index != -1){ - last = &ops[*index]; - if((last->type == MPROTECT) && + if (hvc->index != 0) { + last = &hvc->ops[hvc->index - 1]; + if ((last->type == MPROTECT) && (last->u.mprotect.addr + last->u.mprotect.len == addr) && - (last->u.mprotect.prot == prot)){ + (last->u.mprotect.prot == prot)) { last->u.mprotect.len += len; return 0; } } - if(*index == last_filled){ - ret = (*do_ops)(mmu, ops, last_filled, 0, flush); - *index = -1; + if (hvc->index == ARRAY_SIZE(hvc->ops)) { + ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); + hvc->index = 0; } - ops[++*index] = ((struct host_vm_op) { .type = MPROTECT, - .u = { .mprotect = { - .addr = addr, - .len = len, - .prot = prot } } }); + hvc->ops[hvc->index++] = ((struct host_vm_op) + { .type = MPROTECT, + .u = { .mprotect = { .addr = addr, + .len = len, + .prot = prot } } }); return ret; } #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) static inline int update_pte_range(pmd_t *pmd, unsigned long addr, - unsigned long end, struct host_vm_op *ops, - int last_op, int *op_index, int force, - union mm_context *mmu, void **flush, - int (*do_ops)(union mm_context *, - struct host_vm_op *, int, int, - void **)) + unsigned long end, + struct host_vm_change *hvc) { pte_t *pte; int r, w, x, prot, ret = 0; @@ -142,29 +194,22 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr, } prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | (x ? UM_PROT_EXEC : 0)); - if(force || pte_newpage(*pte)){ - if(pte_present(*pte)) + if (hvc->force || pte_newpage(*pte)) { + if (pte_present(*pte)) ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, - PAGE_SIZE, prot, ops, op_index, - last_op, mmu, flush, do_ops); - else ret = add_munmap(addr, PAGE_SIZE, ops, op_index, - last_op, mmu, flush, do_ops); + PAGE_SIZE, prot, hvc); + else ret = add_munmap(addr, PAGE_SIZE, hvc); } - else if(pte_newprot(*pte)) - ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index, - last_op, mmu, flush, do_ops); + else if (pte_newprot(*pte)) + ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); *pte = pte_mkuptodate(*pte); } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); return ret; } static inline int update_pmd_range(pud_t *pud, unsigned long addr, - unsigned long end, struct host_vm_op *ops, - int last_op, int *op_index, int force, - union mm_context *mmu, void **flush, - int (*do_ops)(union mm_context *, - struct host_vm_op *, int, int, - void **)) + unsigned long end, + struct host_vm_change *hvc) { pmd_t *pmd; unsigned long next; @@ -173,28 +218,20 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr, pmd = pmd_offset(pud, addr); do { next = pmd_addr_end(addr, end); - if(!pmd_present(*pmd)){ - if(force || pmd_newpage(*pmd)){ - ret = add_munmap(addr, next - addr, ops, - op_index, last_op, mmu, - flush, do_ops); + if (!pmd_present(*pmd)) { + if (hvc->force || pmd_newpage(*pmd)) { + ret = add_munmap(addr, next - addr, hvc); pmd_mkuptodate(*pmd); } } - else ret = update_pte_range(pmd, addr, next, ops, last_op, - op_index, force, mmu, flush, - do_ops); + else ret = update_pte_range(pmd, addr, next, hvc); } while (pmd++, addr = next, ((addr != end) && !ret)); return ret; } static inline int update_pud_range(pgd_t *pgd, unsigned long addr, - unsigned long end, struct host_vm_op *ops, - int last_op, int *op_index, int force, - union mm_context *mmu, void **flush, - int (*do_ops)(union mm_context *, - struct host_vm_op *, int, int, - void **)) + unsigned long end, + struct host_vm_change *hvc) { pud_t *pud; unsigned long next; @@ -203,56 +240,45 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr, pud = pud_offset(pgd, addr); do { next = pud_addr_end(addr, end); - if(!pud_present(*pud)){ - if(force || pud_newpage(*pud)){ - ret = add_munmap(addr, next - addr, ops, - op_index, last_op, mmu, - flush, do_ops); + if (!pud_present(*pud)) { + if (hvc->force || pud_newpage(*pud)) { + ret = add_munmap(addr, next - addr, hvc); pud_mkuptodate(*pud); } } - else ret = update_pmd_range(pud, addr, next, ops, last_op, - op_index, force, mmu, flush, - do_ops); + else ret = update_pmd_range(pud, addr, next, hvc); } while (pud++, addr = next, ((addr != end) && !ret)); return ret; } void fix_range_common(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force, - int (*do_ops)(union mm_context *, struct host_vm_op *, - int, int, void **)) + unsigned long end_addr, int force) { pgd_t *pgd; - union mm_context *mmu = &mm->context; - struct host_vm_op ops[1]; + struct host_vm_change hvc; unsigned long addr = start_addr, next; - int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1; - void *flush = NULL; + int ret = 0; - ops[0].type = NONE; + hvc = INIT_HVC(mm, force); pgd = pgd_offset(mm, addr); do { next = pgd_addr_end(addr, end_addr); - if(!pgd_present(*pgd)){ - if (force || pgd_newpage(*pgd)){ - ret = add_munmap(addr, next - addr, ops, - &op_index, last_op, mmu, - &flush, do_ops); + if (!pgd_present(*pgd)) { + if (force || pgd_newpage(*pgd)) { + ret = add_munmap(addr, next - addr, &hvc); pgd_mkuptodate(*pgd); } } - else ret = update_pud_range(pgd, addr, next, ops, last_op, - &op_index, force, mmu, &flush, - do_ops); + else ret = update_pud_range(pgd, addr, next, &hvc); } while (pgd++, addr = next, ((addr != end_addr) && !ret)); - if(!ret) - ret = (*do_ops)(mmu, ops, op_index, 1, &flush); + if (!ret) + ret = do_ops(&hvc, hvc.index, 1); /* This is not an else because ret is modified above */ - if(ret) { - printk("fix_range_common: failed, killing current process\n"); + if (ret) { + printk(KERN_ERR "fix_range_common: failed, killing current " + "process\n"); force_sig(SIGKILL, current); } } @@ -268,17 +294,17 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) int updated = 0, err; mm = &init_mm; - for(addr = start; addr < end;){ + for (addr = start; addr < end;) { pgd = pgd_offset(mm, addr); - if(!pgd_present(*pgd)){ + if (!pgd_present(*pgd)) { last = ADD_ROUND(addr, PGDIR_SIZE); - if(last > end) + if (last > end) last = end; - if(pgd_newpage(*pgd)){ + if (pgd_newpage(*pgd)) { updated = 1; err = os_unmap_memory((void *) addr, last - addr); - if(err < 0) + if (err < 0) panic("munmap failed, errno = %d\n", -err); } @@ -287,15 +313,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } pud = pud_offset(pgd, addr); - if(!pud_present(*pud)){ + if (!pud_present(*pud)) { last = ADD_ROUND(addr, PUD_SIZE); - if(last > end) + if (last > end) last = end; - if(pud_newpage(*pud)){ + if (pud_newpage(*pud)) { updated = 1; err = os_unmap_memory((void *) addr, last - addr); - if(err < 0) + if (err < 0) panic("munmap failed, errno = %d\n", -err); } @@ -304,15 +330,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } pmd = pmd_offset(pud, addr); - if(!pmd_present(*pmd)){ + if (!pmd_present(*pmd)) { last = ADD_ROUND(addr, PMD_SIZE); - if(last > end) + if (last > end) last = end; - if(pmd_newpage(*pmd)){ + if (pmd_newpage(*pmd)) { updated = 1; err = os_unmap_memory((void *) addr, last - addr); - if(err < 0) + if (err < 0) panic("munmap failed, errno = %d\n", -err); } @@ -321,45 +347,110 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } pte = pte_offset_kernel(pmd, addr); - if(!pte_present(*pte) || pte_newpage(*pte)){ + if (!pte_present(*pte) || pte_newpage(*pte)) { updated = 1; err = os_unmap_memory((void *) addr, PAGE_SIZE); - if(err < 0) + if (err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*pte)) + if (pte_present(*pte)) map_memory(addr, pte_val(*pte) & PAGE_MASK, PAGE_SIZE, 1, 1, 1); } - else if(pte_newprot(*pte)){ + else if (pte_newprot(*pte)) { updated = 1; os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); } addr += PAGE_SIZE; } - return(updated); + return updated; +} + +void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + struct mm_struct *mm = vma->vm_mm; + void *flush = NULL; + int r, w, x, prot, err = 0; + struct mm_id *mm_id; + + address &= PAGE_MASK; + pgd = pgd_offset(mm, address); + if (!pgd_present(*pgd)) + goto kill; + + pud = pud_offset(pgd, address); + if (!pud_present(*pud)) + goto kill; + + pmd = pmd_offset(pud, address); + if (!pmd_present(*pmd)) + goto kill; + + pte = pte_offset_kernel(pmd, address); + + r = pte_read(*pte); + w = pte_write(*pte); + x = pte_exec(*pte); + if (!pte_young(*pte)) { + r = 0; + w = 0; + } else if (!pte_dirty(*pte)) { + w = 0; + } + + mm_id = &mm->context.id; + prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | + (x ? UM_PROT_EXEC : 0)); + if (pte_newpage(*pte)) { + if (pte_present(*pte)) { + unsigned long long offset; + int fd; + + fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); + err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, + 1, &flush); + } + else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); + } + else if (pte_newprot(*pte)) + err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); + + if (err) + goto kill; + + *pte = pte_mkuptodate(*pte); + + return; + +kill: + printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address); + force_sig(SIGKILL, current); } pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) { - return(pgd_offset(mm, address)); + return pgd_offset(mm, address); } pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) { - return(pud_offset(pgd, address)); + return pud_offset(pgd, address); } pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) { - return(pmd_offset(pud, address)); + return pmd_offset(pud, address); } pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) { - return(pte_offset_kernel(pmd, address)); + return pte_offset_kernel(pmd, address); } pte_t *addr_pte(struct task_struct *task, unsigned long addr) @@ -368,7 +459,7 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr) pud_t *pud = pud_offset(pgd, addr); pmd_t *pmd = pmd_offset(pud, addr); - return(pte_offset_map(pmd, addr)); + return pte_offset_map(pmd, addr); } void flush_tlb_all(void) @@ -378,35 +469,58 @@ void flush_tlb_all(void) void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, - flush_tlb_kernel_range_common, start, end); + flush_tlb_kernel_range_common(start, end); } void flush_tlb_kernel_vm(void) { - CHOOSE_MODE(flush_tlb_kernel_vm_tt(), - flush_tlb_kernel_range_common(start_vm, end_vm)); + flush_tlb_kernel_range_common(start_vm, end_vm); } void __flush_tlb_one(unsigned long addr) { - CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); + flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); +} + +static void fix_range(struct mm_struct *mm, unsigned long start_addr, + unsigned long end_addr, int force) +{ + if (!proc_mm && (end_addr > STUB_START)) + end_addr = STUB_START; + + fix_range_common(mm, start_addr, end_addr, force); } void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, - end); + if (vma->vm_mm == NULL) + flush_tlb_kernel_range_common(start, end); + else fix_range(vma->vm_mm, start, end, 0); } void flush_tlb_mm(struct mm_struct *mm) { - CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); + unsigned long end; + + /* + * Don't bother flushing if this address space is about to be + * destroyed. + */ + if (atomic_read(&mm->mm_users) == 0) + return; + + end = proc_mm ? task_size : STUB_START; + fix_range(mm, 0, end, 0); } void force_flush_all(void) { - CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); -} + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma = mm->mmap; + while (vma != NULL) { + fix_range(mm, vma->vm_start, vma->vm_end, 1); + vma = vma->vm_next; + } +} diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 3850d53f79f..bd060551e61 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -1,40 +1,24 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "asm/errno.h" -#include "linux/sched.h" -#include "linux/mm.h" -#include "linux/spinlock.h" -#include "linux/init.h" -#include "linux/ptrace.h" -#include "asm/semaphore.h" -#include "asm/pgtable.h" -#include "asm/pgalloc.h" -#include "asm/tlbflush.h" -#include "asm/a.out.h" -#include "asm/current.h" -#include "asm/irq.h" -#include "sysdep/sigcontext.h" -#include "kern_util.h" -#include "as-layout.h" +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/hardirq.h> +#include <asm/current.h> +#include <asm/pgtable.h> +#include <asm/tlbflush.h> #include "arch.h" -#include "kern.h" -#include "chan_kern.h" -#include "mconsole_kern.h" -#include "mem.h" -#include "mem_kern.h" -#include "sysdep/sigcontext.h" -#include "sysdep/ptrace.h" -#include "os.h" -#ifdef CONFIG_MODE_SKAS -#include "skas.h" -#endif +#include "as-layout.h" +#include "kern_util.h" #include "os.h" +#include "sysdep/sigcontext.h" -/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ +/* + * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by + * segv(). + */ int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out) { @@ -48,31 +32,33 @@ int handle_page_fault(unsigned long address, unsigned long ip, *code_out = SEGV_MAPERR; - /* If the fault was during atomic operation, don't take the fault, just - * fail. */ + /* + * If the fault was during atomic operation, don't take the fault, just + * fail. + */ if (in_atomic()) goto out_nosemaphore; down_read(&mm->mmap_sem); vma = find_vma(mm, address); - if(!vma) + if (!vma) goto out; - else if(vma->vm_start <= address) + else if (vma->vm_start <= address) goto good_area; - else if(!(vma->vm_flags & VM_GROWSDOWN)) + else if (!(vma->vm_flags & VM_GROWSDOWN)) goto out; - else if(is_user && !ARCH_IS_STACKGROW(address)) + else if (is_user && !ARCH_IS_STACKGROW(address)) goto out; - else if(expand_stack(vma, address)) + else if (expand_stack(vma, address)) goto out; good_area: *code_out = SEGV_ACCERR; - if(is_write && !(vma->vm_flags & VM_WRITE)) + if (is_write && !(vma->vm_flags & VM_WRITE)) goto out; /* Don't require VM_READ|VM_EXEC for write faults! */ - if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) + if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) goto out; do { @@ -98,9 +84,10 @@ survive: pud = pud_offset(pgd, address); pmd = pmd_offset(pud, address); pte = pte_offset_kernel(pmd, address); - } while(!pte_present(*pte)); + } while (!pte_present(*pte)); err = 0; - /* The below warning was added in place of + /* + * The below warning was added in place of * pte_mkyoung(); if (is_write) pte_mkdirty(); * If it's triggered, we'd see normally a hang here (a clean pte is * marked read-only to emulate the dirty bit). @@ -114,7 +101,7 @@ survive: out: up_read(&mm->mmap_sem); out_nosemaphore: - return(err); + return err; /* * We ran out of memory, or some other thing happened to us that made @@ -141,11 +128,11 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) force_sig_info(SIGSEGV, &si, current); } -static void segv_handler(int sig, union uml_pt_regs *regs) +static void segv_handler(int sig, struct uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); - if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ + if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { bad_segv(*fi, UPT_IP(regs)); return; } @@ -159,45 +146,49 @@ static void segv_handler(int sig, union uml_pt_regs *regs) * give us bad data! */ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, - union uml_pt_regs *regs) + struct uml_pt_regs *regs) { struct siginfo si; - void *catcher; + jmp_buf *catcher; int err; int is_write = FAULT_WRITE(fi); unsigned long address = FAULT_ADDRESS(fi); - if(!is_user && (address >= start_vm) && (address < end_vm)){ + if (!is_user && (address >= start_vm) && (address < end_vm)) { flush_tlb_kernel_vm(); return 0; } - else if(current->mm == NULL) { + else if (current->mm == NULL) { show_regs(container_of(regs, struct pt_regs, regs)); - panic("Segfault with no mm"); + panic("Segfault with no mm"); } if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) - err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); + err = handle_page_fault(address, ip, is_write, is_user, + &si.si_code); else { err = -EFAULT; - /* A thread accessed NULL, we get a fault, but CR2 is invalid. - * This code is used in __do_copy_from_user() of TT mode. */ + /* + * A thread accessed NULL, we get a fault, but CR2 is invalid. + * This code is used in __do_copy_from_user() of TT mode. + * XXX tt mode is gone, so maybe this isn't needed any more + */ address = 0; } catcher = current->thread.fault_catcher; - if(!err) + if (!err) return 0; - else if(catcher != NULL){ + else if (catcher != NULL) { current->thread.fault_addr = (void *) address; - do_longjmp(catcher, 1); + UML_LONGJMP(catcher, 1); } - else if(current->thread.fault_addr != NULL) + else if (current->thread.fault_addr != NULL) panic("fault_addr set but no fault catcher"); - else if(!is_user && arch_fixup(ip, regs)) + else if (!is_user && arch_fixup(ip, regs)) return 0; - if(!is_user) { + if (!is_user) { show_regs(container_of(regs, struct pt_regs, regs)); panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", address, ip); @@ -211,7 +202,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, current->thread.arch.faultinfo = fi; force_sig_info(SIGBUS, &si, current); } else if (err == -ENOMEM) { - printk("VM: killing process %s\n", current->comm); + printk(KERN_INFO "VM: killing process %s\n", current->comm); do_exit(SIGKILL); } else { BUG_ON(err != -EFAULT); @@ -223,15 +214,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, return 0; } -void relay_signal(int sig, union uml_pt_regs *regs) +void relay_signal(int sig, struct uml_pt_regs *regs) { - if(arch_handle_signal(sig, regs)) + if (arch_handle_signal(sig, regs)) return; - if(!UPT_IS_USER(regs)){ - if(sig == SIGBUS) - printk("Bus error - the host /dev/shm or /tmp mount " - "likely just ran out of space\n"); + if (!UPT_IS_USER(regs)) { + if (sig == SIGBUS) + printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " + "mount likely just ran out of space\n"); panic("Kernel mode signal %d", sig); } @@ -239,14 +230,14 @@ void relay_signal(int sig, union uml_pt_regs *regs) force_sig(sig, current); } -static void bus_handler(int sig, union uml_pt_regs *regs) +static void bus_handler(int sig, struct uml_pt_regs *regs) { - if(current->thread.fault_catcher != NULL) - do_longjmp(current->thread.fault_catcher, 1); + if (current->thread.fault_catcher != NULL) + UML_LONGJMP(current->thread.fault_catcher, 1); else relay_signal(sig, regs); } -static void winch(int sig, union uml_pt_regs *regs) +static void winch(int sig, struct uml_pt_regs *regs) { do_IRQ(WINCH_IRQ, regs); } diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile deleted file mode 100644 index 6939e5af847..00000000000 --- a/arch/um/kernel/tt/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -# Licensed under the GPL -# - -obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ - syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \ - uaccess.o uaccess_user.o - -obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ - -USER_OBJS := gdb.o tracer.o - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c deleted file mode 100644 index 40126cb5180..00000000000 --- a/arch/um/kernel/tt/exec_kern.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/kernel.h" -#include "linux/mm.h" -#include "asm/signal.h" -#include "asm/ptrace.h" -#include "asm/uaccess.h" -#include "asm/pgalloc.h" -#include "asm/tlbflush.h" -#include "kern_util.h" -#include "irq_user.h" -#include "mem_user.h" -#include "os.h" -#include "tlb.h" -#include "mode.h" - -static int exec_tramp(void *sig_stack) -{ - init_new_thread_stack(sig_stack, NULL); - init_new_thread_signals(); - os_stop_process(os_getpid()); - return(0); -} - -void flush_thread_tt(void) -{ - unsigned long stack; - int new_pid; - - stack = alloc_stack(0, 0); - if(stack == 0){ - printk(KERN_ERR - "flush_thread : failed to allocate temporary stack\n"); - do_exit(SIGKILL); - } - - new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); - if(new_pid < 0){ - printk(KERN_ERR - "flush_thread : new thread failed, errno = %d\n", - -new_pid); - do_exit(SIGKILL); - } - - if(current_thread->cpu == 0) - forward_interrupts(new_pid); - current->thread.request.op = OP_EXEC; - current->thread.request.u.exec.pid = new_pid; - unprotect_stack((unsigned long) current_thread); - os_usr1_process(os_getpid()); - change_sig(SIGUSR1, 1); - - change_sig(SIGUSR1, 0); - enable_timer(); - free_page(stack); - protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - stack_protections((unsigned long) current_thread); - force_flush_all(); - unblock_signals(); -} - -void start_thread_tt(struct pt_regs *regs, unsigned long eip, - unsigned long esp) -{ - set_fs(USER_DS); - flush_tlb_mm(current->mm); - PT_REGS_IP(regs) = eip; - PT_REGS_SP(regs) = esp; - PT_FIX_EXEC_STACK(esp); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c deleted file mode 100644 index 7b5f2181cf5..00000000000 --- a/arch/um/kernel/tt/exec_user.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <sched.h> -#include <errno.h> -#include <sys/wait.h> -#include <signal.h> -#include "kern_util.h" -#include "user.h" -#include "ptrace_user.h" -#include "os.h" - -void do_exec(int old_pid, int new_pid) -{ - unsigned long regs[FRAME_SIZE]; - int err; - - if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || - (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) - tracer_panic("do_exec failed to attach proc - errno = %d", - errno); - - CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); - if (err < 0) - tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", - errno); - - if(ptrace_getregs(old_pid, regs) < 0) - tracer_panic("do_exec failed to get registers - errno = %d", - errno); - - os_kill_ptraced_process(old_pid, 0); - - if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) - tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno); - - if(ptrace_setregs(new_pid, regs) < 0) - tracer_panic("do_exec failed to start new proc - errno = %d", - errno); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c deleted file mode 100644 index 030e4658f36..00000000000 --- a/arch/um/kernel/tt/gdb.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include <sys/types.h> -#include "ptrace_user.h" -#include "uml-config.h" -#include "kern_constants.h" -#include "chan_user.h" -#include "init.h" -#include "user.h" -#include "debug.h" -#include "kern_util.h" -#include "tt.h" -#include "sysdep/thread.h" -#include "os.h" - -extern int debugger_pid; -extern int debugger_fd; -extern int debugger_parent; - -int detach(int pid, int sig) -{ - return(ptrace(PTRACE_DETACH, pid, 0, sig)); -} - -int attach(int pid) -{ - int err; - - err = ptrace(PTRACE_ATTACH, pid, 0, 0); - if(err < 0) return(-errno); - else return(err); -} - -int cont(int pid) -{ - return(ptrace(PTRACE_CONT, pid, 0, 0)); -} - -#ifdef UML_CONFIG_PT_PROXY - -int debugger_signal(int status, pid_t pid) -{ - return(debugger_proxy(status, pid)); -} - -void child_signal(pid_t pid, int status) -{ - child_proxy(pid, status); -} - -static void gdb_announce(char *dev_name, int dev) -{ - printf("gdb assigned device '%s'\n", dev_name); -} - -static struct chan_opts opts = { - .announce = gdb_announce, - .xterm_title = "UML kernel debugger", - .raw = 0, - .tramp_stack = 0, - .in_kernel = 0, -}; - -/* Accessed by the tracing thread, which automatically serializes access */ -static void *xterm_data; -static int xterm_fd; - -extern void *xterm_init(char *, int, struct chan_opts *); -extern int xterm_open(int, int, int, void *, char **); -extern void xterm_close(int, void *); - -int open_gdb_chan(void) -{ - char stack[UM_KERN_PAGE_SIZE], *dummy; - - opts.tramp_stack = (unsigned long) stack; - xterm_data = xterm_init("", 0, &opts); - xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); - return(xterm_fd); -} - -static void exit_debugger_cb(void *unused) -{ - if(debugger_pid != -1){ - if(gdb_pid != -1){ - fake_child_exit(); - gdb_pid = -1; - } - else kill_child_dead(debugger_pid); - debugger_pid = -1; - if(debugger_parent != -1) - detach(debugger_parent, SIGINT); - } - if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); -} - -static void exit_debugger(void) -{ - initial_thread_cb(exit_debugger_cb, NULL); -} - -__uml_exitcall(exit_debugger); - -struct gdb_data { - char *str; - int err; -}; - -extern char *linux_prog; - -static void config_gdb_cb(void *arg) -{ - struct gdb_data *data = arg; - void *task; - int pid; - - data->err = -1; - if(debugger_pid != -1) exit_debugger_cb(NULL); - if(!strncmp(data->str, "pid,", strlen("pid,"))){ - data->str += strlen("pid,"); - pid = strtoul(data->str, NULL, 0); - task = cpu_tasks[0].task; - debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); - if(debugger_pid != -1){ - data->err = 0; - gdb_pid = pid; - } - return; - } - data->err = 0; - debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); - init_proxy(debugger_pid, 0, 0); -} - -int gdb_config(char *str, char **error_out) -{ - struct gdb_data data; - - if(*str++ != '=') return(-1); - data.str = str; - initial_thread_cb(config_gdb_cb, &data); - return(data.err); -} - -void remove_gdb_cb(void *unused) -{ - exit_debugger_cb(NULL); -} - -int gdb_remove(int unused, char **error_out) -{ - initial_thread_cb(remove_gdb_cb, NULL); - return 0; -} - -void signal_usr1(int sig) -{ - if(debugger_pid != -1){ - printf("The debugger is already running\n"); - return; - } - debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); - init_proxy(debugger_pid, 0, 0); -} - -int init_ptrace_proxy(int idle_pid, int startup, int stop) -{ - int pid, status; - - pid = start_debugger(linux_prog, startup, stop, &debugger_fd); - status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); - if(pid < 0){ - cont(idle_pid); - return(-1); - } - init_proxy(pid, 1, status); - return(pid); -} - -int attach_debugger(int idle_pid, int pid, int stop) -{ - int status = 0, err; - - err = attach(pid); - if(err < 0){ - printf("Failed to attach pid %d, errno = %d\n", pid, -err); - return(-1); - } - if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); - init_proxy(pid, 1, status); - return(pid); -} - -#ifdef notdef /* Put this back in when it does something useful */ -static int __init uml_gdb_init_setup(char *line, int *add) -{ - gdb_init = uml_strdup(line); - return 0; -} - -__uml_setup("gdb=", uml_gdb_init_setup, -"gdb=<channel description>\n\n" -); -#endif - -static int __init uml_gdb_pid_setup(char *line, int *add) -{ - gdb_pid = strtoul(line, NULL, 0); - *add = 0; - return 0; -} - -__uml_setup("gdb-pid=", uml_gdb_pid_setup, -"gdb-pid=<pid>\n" -" gdb-pid is used to attach an external debugger to UML. This may be\n" -" an already-running gdb or a debugger-like process like strace.\n\n" -); - -#else - -int debugger_signal(int status, pid_t pid){ return(0); } -void child_signal(pid_t pid, int status){ } -int init_ptrace_proxy(int idle_pid, int startup, int stop) -{ - printf("debug requested when CONFIG_PT_PROXY is off\n"); - kill_child_dead(idle_pid); - exit(1); -} - -void signal_usr1(int sig) -{ - printf("debug requested when CONFIG_PT_PROXY is off\n"); -} - -int attach_debugger(int idle_pid, int pid, int stop) -{ - printf("attach_debugger called when CONFIG_PT_PROXY " - "is off\n"); - return(-1); -} - -int config_gdb(char *str) -{ - return(-1); -} - -int remove_gdb(void) -{ - return(-1); -} - -int init_parent_proxy(int pid) -{ - return(-1); -} - -void debugger_parent_signal(int status, int pid) -{ -} - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c deleted file mode 100644 index 03b06bc0077..00000000000 --- a/arch/um/kernel/tt/gdb_kern.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/init.h" -#include "mconsole_kern.h" - -#ifdef CONFIG_MCONSOLE - -extern int gdb_config(char *str, char **error_out); -extern int gdb_remove(int n, char **error_out); - -static struct mc_device gdb_mc = { - .list = INIT_LIST_HEAD(gdb_mc.list), - .name = "gdb", - .config = gdb_config, - .remove = gdb_remove, -}; - -int gdb_mc_init(void) -{ - mconsole_register_dev(&gdb_mc); - return(0); -} - -__initcall(gdb_mc_init); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h deleted file mode 100644 index e171e15fead..00000000000 --- a/arch/um/kernel/tt/include/mode-tt.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_TT_H__ -#define __MODE_TT_H__ - -#include "sysdep/ptrace.h" - -enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; - -extern int tracing_pid; - -extern int tracer(int (*init_proc)(void *), void *sp); -extern void sig_handler_common_tt(int sig, void *sc); -extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); -extern void reboot_tt(void); -extern void halt_tt(void); -extern int is_tracer_winch(int pid, int fd, void *data); -extern void kill_off_processes_tt(void); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c deleted file mode 100644 index 84a9385a8fe..00000000000 --- a/arch/um/kernel/tt/ksyms.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/module.h" -#include "asm/uaccess.h" -#include "mode.h" - -EXPORT_SYMBOL(__do_copy_from_user); -EXPORT_SYMBOL(__do_copy_to_user); -EXPORT_SYMBOL(__do_strncpy_from_user); -EXPORT_SYMBOL(__do_strnlen_user); -EXPORT_SYMBOL(__do_clear_user); -EXPORT_SYMBOL(clear_user_tt); - -EXPORT_SYMBOL(tracing_pid); -EXPORT_SYMBOL(honeypot); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c deleted file mode 100644 index d0c3c4975f2..00000000000 --- a/arch/um/kernel/tt/mem.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/stddef.h" -#include "linux/mm.h" -#include "asm/uaccess.h" -#include "mem_user.h" -#include "kern_util.h" -#include "kern.h" -#include "tt.h" - -void before_mem_tt(unsigned long brk_start) -{ - if(debug) - remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); - remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); - remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); -} - -#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) -#define START (CONFIG_TOP_ADDR - SIZE) - -unsigned long set_task_sizes_tt(unsigned long *task_size_out) -{ - unsigned long host_task_size; - - /* Round up to the nearest 4M */ - host_task_size = ROUND_4M((unsigned long) &host_task_size); - *task_size_out = START; - - return host_task_size; -} diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c deleted file mode 100644 index 9774f6360c3..00000000000 --- a/arch/um/kernel/tt/mem_user.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <sys/mman.h> -#include "tt.h" -#include "mem_user.h" -#include "os.h" - -void remap_data(void *segment_start, void *segment_end, int w) -{ - void *addr; - unsigned long size; - int data, prot; - - if(w) prot = PROT_WRITE; - else prot = 0; - prot |= PROT_READ | PROT_EXEC; - size = (unsigned long) segment_end - - (unsigned long) segment_start; - data = create_mem_file(size); - addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); - if(addr == MAP_FAILED){ - perror("mapping new data segment"); - exit(1); - } - memcpy(addr, segment_start, size); - if(switcheroo(data, prot, addr, segment_start, size) < 0){ - printf("switcheroo failed\n"); - exit(1); - } -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c deleted file mode 100644 index 74347adf81b..00000000000 --- a/arch/um/kernel/tt/process_kern.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/sched.h" -#include "linux/signal.h" -#include "linux/kernel.h" -#include "linux/interrupt.h" -#include "linux/ptrace.h" -#include "asm/system.h" -#include "asm/pgalloc.h" -#include "asm/ptrace.h" -#include "asm/tlbflush.h" -#include "irq_user.h" -#include "kern_util.h" -#include "os.h" -#include "kern.h" -#include "sigcontext.h" -#include "mem_user.h" -#include "tlb.h" -#include "mode.h" -#include "mode_kern.h" -#include "init.h" -#include "tt.h" - -void switch_to_tt(void *prev, void *next) -{ - struct task_struct *from, *to, *prev_sched; - unsigned long flags; - int err, vtalrm, alrm, prof, cpu; - char c; - - from = prev; - to = next; - - cpu = task_thread_info(from)->cpu; - if(cpu == 0) - forward_interrupts(to->thread.mode.tt.extern_pid); -#ifdef CONFIG_SMP - forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); -#endif - local_irq_save(flags); - - vtalrm = change_sig(SIGVTALRM, 0); - alrm = change_sig(SIGALRM, 0); - prof = change_sig(SIGPROF, 0); - - forward_pending_sigio(to->thread.mode.tt.extern_pid); - - c = 0; - - /* Notice that here we "up" the semaphore on which "to" is waiting, and - * below (the read) we wait on this semaphore (which is implemented by - * switch_pipe) and go sleeping. Thus, after that, we have resumed in - * "to", and can't use any more the value of "from" (which is outdated), - * nor the value in "to" (since it was the task which stole us the CPU, - * which we don't care about). */ - - err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); - if(err != sizeof(c)) - panic("write of switch_pipe failed, err = %d", -err); - - if(from->thread.mode.tt.switch_pipe[0] == -1) - os_kill_process(os_getpid(), 0); - - err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, - sizeof(c)); - if(err != sizeof(c)) - panic("read of switch_pipe failed, errno = %d", -err); - - /* If the process that we have just scheduled away from has exited, - * then it needs to be killed here. The reason is that, even though - * it will kill itself when it next runs, that may be too late. Its - * stack will be freed, possibly before then, and if that happens, - * we have a use-after-free situation. So, it gets killed here - * in case it has not already killed itself. - */ - prev_sched = current->thread.prev_sched; - if(prev_sched->thread.mode.tt.switch_pipe[0] == -1) - os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); - - change_sig(SIGVTALRM, vtalrm); - change_sig(SIGALRM, alrm); - change_sig(SIGPROF, prof); - - arch_switch_to_tt(prev_sched, current); - - flush_tlb_all(); - local_irq_restore(flags); -} - -void release_thread_tt(struct task_struct *task) -{ - int pid = task->thread.mode.tt.extern_pid; - - /* - * We first have to kill the other process, before - * closing its switch_pipe. Else it might wake up - * and receive "EOF" before we could kill it. - */ - if(os_getpid() != pid) - os_kill_process(pid, 0); - - os_close_file(task->thread.mode.tt.switch_pipe[0]); - os_close_file(task->thread.mode.tt.switch_pipe[1]); - /* use switch_pipe as flag: thread is released */ - task->thread.mode.tt.switch_pipe[0] = -1; -} - -void suspend_new_thread(int fd) -{ - int err; - char c; - - os_stop_process(os_getpid()); - err = os_read_file(fd, &c, sizeof(c)); - if(err != sizeof(c)) - panic("read failed in suspend_new_thread, err = %d", -err); -} - -void schedule_tail(struct task_struct *prev); - -static void new_thread_handler(int sig) -{ - unsigned long disable; - int (*fn)(void *); - void *arg; - - fn = current->thread.request.u.thread.proc; - arg = current->thread.request.u.thread.arg; - - UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); - disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | - (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); - SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; - - suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); - - force_flush_all(); - if(current->thread.prev_sched != NULL) - schedule_tail(current->thread.prev_sched); - current->thread.prev_sched = NULL; - - init_new_thread_signals(); - enable_timer(); - free_page(current->thread.temp_stack); - set_cmdline("(kernel thread)"); - - change_sig(SIGUSR1, 1); - change_sig(SIGPROF, 1); - local_irq_enable(); - if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) - do_exit(0); - - /* XXX No set_user_mode here because a newly execed process will - * immediately segfault on its non-existent IP, coming straight back - * to the signal handler, which will call set_user_mode on its way - * out. This should probably change since it's confusing. - */ -} - -static int new_thread_proc(void *stack) -{ - /* local_irq_disable is needed to block out signals until this thread is - * properly scheduled. Otherwise, the tracing thread will get mighty - * upset about any signals that arrive before that. - * This has the complication that it sets the saved signal mask in - * the sigcontext to block signals. This gets restored when this - * thread (or a descendant, since they get a copy of this sigcontext) - * returns to userspace. - * So, this is compensated for elsewhere. - * XXX There is still a small window until local_irq_disable() actually - * finishes where signals are possible - shouldn't be a problem in - * practice since SIGIO hasn't been forwarded here yet, and the - * local_irq_disable should finish before a SIGVTALRM has time to be - * delivered. - */ - - local_irq_disable(); - init_new_thread_stack(stack, new_thread_handler); - os_usr1_process(os_getpid()); - change_sig(SIGUSR1, 1); - return(0); -} - -/* Signal masking - signals are blocked at the start of fork_tramp. They - * are re-enabled when finish_fork_handler is entered by fork_tramp hitting - * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, - * so it is blocked before it's called. They are re-enabled on sigreturn - * despite the fact that they were blocked when the SIGUSR1 was issued because - * copy_thread copies the parent's sigcontext, including the signal mask - * onto the signal frame. - */ - -void finish_fork_handler(int sig) -{ - UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); - suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); - - force_flush_all(); - if(current->thread.prev_sched != NULL) - schedule_tail(current->thread.prev_sched); - current->thread.prev_sched = NULL; - - enable_timer(); - change_sig(SIGVTALRM, 1); - local_irq_enable(); - if(current->mm != current->parent->mm) - protect_memory(uml_reserved, high_physmem - uml_reserved, 1, - 1, 0, 1); - stack_protections((unsigned long) current_thread); - - free_page(current->thread.temp_stack); - local_irq_disable(); - change_sig(SIGUSR1, 0); - set_user_mode(current); -} - -int fork_tramp(void *stack) -{ - local_irq_disable(); - arch_init_thread(); - init_new_thread_stack(stack, finish_fork_handler); - - os_usr1_process(os_getpid()); - change_sig(SIGUSR1, 1); - return(0); -} - -int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, - struct pt_regs *regs) -{ - int (*tramp)(void *); - int new_pid, err; - unsigned long stack; - - if(current->thread.forking) - tramp = fork_tramp; - else { - tramp = new_thread_proc; - p->thread.request.u.thread = current->thread.request.u.thread; - } - - err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); - if(err < 0){ - printk("copy_thread : pipe failed, err = %d\n", -err); - return(err); - } - - stack = alloc_stack(0, 0); - if(stack == 0){ - printk(KERN_ERR "copy_thread : failed to allocate " - "temporary stack\n"); - return(-ENOMEM); - } - - clone_flags &= CLONE_VM; - p->thread.temp_stack = stack; - new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); - if(new_pid < 0){ - printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", - -new_pid); - return(new_pid); - } - - if(current->thread.forking){ - sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs)); - SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); - if(sp != 0) - SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; - } - p->thread.mode.tt.extern_pid = new_pid; - - current->thread.request.op = OP_FORK; - current->thread.request.u.fork.pid = new_pid; - os_usr1_process(os_getpid()); - - /* Enable the signal and then disable it to ensure that it is handled - * here, and nowhere else. - */ - change_sig(SIGUSR1, 1); - - change_sig(SIGUSR1, 0); - err = 0; - return(err); -} - -void reboot_tt(void) -{ - current->thread.request.op = OP_REBOOT; - os_usr1_process(os_getpid()); - change_sig(SIGUSR1, 1); -} - -void halt_tt(void) -{ - current->thread.request.op = OP_HALT; - os_usr1_process(os_getpid()); - change_sig(SIGUSR1, 1); -} - -void kill_off_processes_tt(void) -{ - struct task_struct *p; - int me; - - me = os_getpid(); - for_each_process(p){ - if(p->thread.mode.tt.extern_pid != me) - os_kill_process(p->thread.mode.tt.extern_pid, 0); - } - if(init_task.thread.mode.tt.extern_pid != me) - os_kill_process(init_task.thread.mode.tt.extern_pid, 0); -} - -void initial_thread_cb_tt(void (*proc)(void *), void *arg) -{ - if(os_getpid() == tracing_pid){ - (*proc)(arg); - } - else { - current->thread.request.op = OP_CB; - current->thread.request.u.cb.proc = proc; - current->thread.request.u.cb.arg = arg; - os_usr1_process(os_getpid()); - change_sig(SIGUSR1, 1); - - change_sig(SIGUSR1, 0); - } -} - -int do_proc_op(void *t, int proc_id) -{ - struct task_struct *task; - struct thread_struct *thread; - int op, pid; - - task = t; - thread = &task->thread; - op = thread->request.op; - switch(op){ - case OP_NONE: - case OP_TRACE_ON: - break; - case OP_EXEC: - pid = thread->request.u.exec.pid; - do_exec(thread->mode.tt.extern_pid, pid); - thread->mode.tt.extern_pid = pid; - cpu_tasks[task_thread_info(task)->cpu].pid = pid; - break; - case OP_FORK: - attach_process(thread->request.u.fork.pid); - break; - case OP_CB: - (*thread->request.u.cb.proc)(thread->request.u.cb.arg); - break; - case OP_REBOOT: - case OP_HALT: - break; - default: - tracer_panic("Bad op in do_proc_op"); - break; - } - thread->request.op = OP_NONE; - return(op); -} - -void init_idle_tt(void) -{ - default_idle(); -} - -extern void start_kernel(void); - -static int start_kernel_proc(void *unused) -{ - int pid; - - block_signals(); - pid = os_getpid(); - - cpu_tasks[0].pid = pid; - cpu_tasks[0].task = current; -#ifdef CONFIG_SMP - cpu_online_map = cpumask_of_cpu(0); -#endif - if(debug) os_stop_process(pid); - start_kernel(); - return(0); -} - -void set_tracing(void *task, int tracing) -{ - ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; -} - -int is_tracing(void *t) -{ - return (((struct task_struct *) t)->thread.mode.tt.tracing); -} - -int set_user_mode(void *t) -{ - struct task_struct *task; - - task = t ? t : current; - if(task->thread.mode.tt.tracing) - return(1); - task->thread.request.op = OP_TRACE_ON; - os_usr1_process(os_getpid()); - return(0); -} - -void set_init_pid(int pid) -{ - int err; - - init_task.thread.mode.tt.extern_pid = pid; - err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); - if(err) - panic("Can't create switch pipe for init_task, errno = %d", - -err); -} - -int start_uml_tt(void) -{ - void *sp; - int pages; - - pages = (1 << CONFIG_KERNEL_STACK_ORDER); - sp = task_stack_page(&init_task) + - pages * PAGE_SIZE - sizeof(unsigned long); - return(tracer(start_kernel_proc, sp)); -} - -int external_pid_tt(struct task_struct *task) -{ - return(task->thread.mode.tt.extern_pid); -} - -int thread_pid_tt(struct task_struct *task) -{ - return(task->thread.mode.tt.extern_pid); -} - -int is_valid_pid(int pid) -{ - struct task_struct *task; - - read_lock(&tasklist_lock); - for_each_process(task){ - if(task->thread.mode.tt.extern_pid == pid){ - read_unlock(&tasklist_lock); - return(1); - } - } - read_unlock(&tasklist_lock); - return(0); -} diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile deleted file mode 100644 index 3ad5b774de5..00000000000 --- a/arch/um/kernel/tt/ptproxy/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -# Licensed under the GPL -# - -obj-y = proxy.o ptrace.o sysdep.o wait.o - -USER_OBJS := $(obj-y) - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c deleted file mode 100644 index 420c23f311f..00000000000 --- a/arch/um/kernel/tt/ptproxy/proxy.c +++ /dev/null @@ -1,377 +0,0 @@ -/********************************************************************** -proxy.c - -Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -terms and conditions. - -Jeff Dike (jdike@karaya.com) : Modified for integration into uml -**********************************************************************/ - -/* XXX This file shouldn't refer to CONFIG_* */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <termios.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <asm/unistd.h> -#include "ptrace_user.h" - -#include "ptproxy.h" -#include "sysdep.h" -#include "wait.h" - -#include "user.h" -#include "os.h" -#include "tempfile.h" - -static int debugger_wait(debugger_state *debugger, int *status, int options, - int (*syscall)(debugger_state *debugger, pid_t child), - int (*normal_return)(debugger_state *debugger, - pid_t unused), - int (*wait_return)(debugger_state *debugger, - pid_t unused)) -{ - if(debugger->real_wait){ - debugger->handle_trace = normal_return; - syscall_continue(debugger->pid); - debugger->real_wait = 0; - return(1); - } - debugger->wait_status_ptr = status; - debugger->wait_options = options; - if((debugger->debugee != NULL) && debugger->debugee->event){ - syscall_continue(debugger->pid); - wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, - NULL); - (*wait_return)(debugger, -1); - return(0); - } - else if(debugger->wait_options & WNOHANG){ - syscall_cancel(debugger->pid, 0); - debugger->handle_trace = syscall; - return(0); - } - else { - syscall_pause(debugger->pid); - debugger->handle_trace = wait_return; - debugger->waiting = 1; - } - return(1); -} - -/* - * Handle debugger trap, i.e. syscall. - */ - -int debugger_syscall(debugger_state *debugger, pid_t child) -{ - long arg1, arg2, arg3, arg4, arg5, result; - int syscall, ret = 0; - - syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, - &arg5); - - switch(syscall){ - case __NR_execve: - /* execve never returns */ - debugger->handle_trace = debugger_syscall; - break; - - case __NR_ptrace: - if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; - if(!debugger->debugee->in_context) - child = debugger->debugee->pid; - result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, - &ret); - syscall_cancel(debugger->pid, result); - debugger->handle_trace = debugger_syscall; - return(ret); - -#ifdef __NR_waitpid - case __NR_waitpid: -#endif - case __NR_wait4: - if(!debugger_wait(debugger, (int *) arg2, arg3, - debugger_syscall, debugger_normal_return, - proxy_wait_return)) - return(0); - break; - - case __NR_kill: - if(!debugger->debugee->in_context) - child = debugger->debugee->pid; - if(arg1 == debugger->debugee->pid){ - result = kill(child, arg2); - syscall_cancel(debugger->pid, result); - debugger->handle_trace = debugger_syscall; - return(0); - } - else debugger->handle_trace = debugger_normal_return; - break; - - default: - debugger->handle_trace = debugger_normal_return; - } - - syscall_continue(debugger->pid); - return(0); -} - -/* Used by the tracing thread */ -static debugger_state parent; -static int parent_syscall(debugger_state *debugger, int pid); - -int init_parent_proxy(int pid) -{ - parent = ((debugger_state) { .pid = pid, - .wait_options = 0, - .wait_status_ptr = NULL, - .waiting = 0, - .real_wait = 0, - .expecting_child = 0, - .handle_trace = parent_syscall, - .debugee = NULL } ); - return(0); -} - -int parent_normal_return(debugger_state *debugger, pid_t unused) -{ - debugger->handle_trace = parent_syscall; - syscall_continue(debugger->pid); - return(0); -} - -static int parent_syscall(debugger_state *debugger, int pid) -{ - long arg1, arg2, arg3, arg4, arg5; - int syscall; - - syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); - - if((syscall == __NR_wait4) -#ifdef __NR_waitpid - || (syscall == __NR_waitpid) -#endif - ){ - debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, - parent_normal_return, parent_wait_return); - } - else ptrace(PTRACE_SYSCALL, pid, 0, 0); - return(0); -} - -int debugger_normal_return(debugger_state *debugger, pid_t unused) -{ - debugger->handle_trace = debugger_syscall; - syscall_continue(debugger->pid); - return(0); -} - -void debugger_cancelled_return(debugger_state *debugger, int result) -{ - debugger->handle_trace = debugger_syscall; - syscall_set_result(debugger->pid, result); - syscall_continue(debugger->pid); -} - -/* Used by the tracing thread */ -static debugger_state debugger; -static debugee_state debugee; - -void init_proxy (pid_t debugger_pid, int stopped, int status) -{ - debugger.pid = debugger_pid; - debugger.handle_trace = debugger_syscall; - debugger.debugee = &debugee; - debugger.waiting = 0; - debugger.real_wait = 0; - debugger.expecting_child = 0; - - debugee.pid = 0; - debugee.traced = 0; - debugee.stopped = stopped; - debugee.event = 0; - debugee.zombie = 0; - debugee.died = 0; - debugee.wait_status = status; - debugee.in_context = 1; -} - -int debugger_proxy(int status, int pid) -{ - int ret = 0, sig; - - if(WIFSTOPPED(status)){ - sig = WSTOPSIG(status); - if (sig == SIGTRAP) - ret = (*debugger.handle_trace)(&debugger, pid); - - else if(sig == SIGCHLD){ - if(debugger.expecting_child){ - ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); - debugger.expecting_child = 0; - } - else if(debugger.waiting) - real_wait_return(&debugger); - else { - ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); - debugger.real_wait = 1; - } - } - else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); - } - else if(WIFEXITED(status)){ - tracer_panic("debugger (pid %d) exited with status %d", - debugger.pid, WEXITSTATUS(status)); - } - else if(WIFSIGNALED(status)){ - tracer_panic("debugger (pid %d) exited with signal %d", - debugger.pid, WTERMSIG(status)); - } - else { - tracer_panic("proxy got unknown status (0x%x) on debugger " - "(pid %d)", status, debugger.pid); - } - return(ret); -} - -void child_proxy(pid_t pid, int status) -{ - debugee.event = 1; - debugee.wait_status = status; - - if(WIFSTOPPED(status)){ - debugee.stopped = 1; - debugger.expecting_child = 1; - kill(debugger.pid, SIGCHLD); - } - else if(WIFEXITED(status) || WIFSIGNALED(status)){ - debugee.zombie = 1; - debugger.expecting_child = 1; - kill(debugger.pid, SIGCHLD); - } - else panic("proxy got unknown status (0x%x) on child (pid %d)", - status, pid); -} - -void debugger_parent_signal(int status, int pid) -{ - int sig; - - if(WIFSTOPPED(status)){ - sig = WSTOPSIG(status); - if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); - else ptrace(PTRACE_SYSCALL, pid, 0, sig); - } -} - -void fake_child_exit(void) -{ - int status, pid; - - child_proxy(1, W_EXITCODE(0, 0)); - while(debugger.waiting == 1){ - CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); - if(pid != debugger.pid){ - printk("fake_child_exit - waitpid failed, " - "errno = %d\n", errno); - return; - } - debugger_proxy(status, debugger.pid); - } - CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); - if(pid != debugger.pid){ - printk("fake_child_exit - waitpid failed, " - "errno = %d\n", errno); - return; - } - if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) - printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", - errno); -} - -char gdb_init_string[] = -"att 1 \n\ -b panic \n\ -b stop \n\ -handle SIGWINCH nostop noprint pass \n\ -"; - -int start_debugger(char *prog, int startup, int stop, int *fd_out) -{ - int slave, child; - - slave = open_gdb_chan(); - child = fork(); - if(child == 0){ - char *tempname = NULL; - int fd; - - if(setsid() < 0) perror("setsid"); - if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || - (dup2(slave, 2) < 0)){ - printk("start_debugger : dup2 failed, errno = %d\n", - errno); - exit(1); - } - if(ioctl(0, TIOCSCTTY, 0) < 0){ - printk("start_debugger : TIOCSCTTY failed, " - "errno = %d\n", errno); - exit(1); - } - if(tcsetpgrp (1, os_getpid()) < 0){ - printk("start_debugger : tcsetpgrp failed, " - "errno = %d\n", errno); -#ifdef notdef - exit(1); -#endif - } - fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); - if(fd < 0){ - printk("start_debugger : make_tempfile failed," - "err = %d\n", -fd); - exit(1); - } - os_write_file(fd, gdb_init_string, - sizeof(gdb_init_string) - 1); - if(startup){ - if(stop){ - os_write_file(fd, "b start_kernel\n", - strlen("b start_kernel\n")); - } - os_write_file(fd, "c\n", strlen("c\n")); - } - if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ - printk("start_debugger : PTRACE_TRACEME failed, " - "errno = %d\n", errno); - exit(1); - } - execlp("gdb", "gdb", "--command", tempname, prog, NULL); - printk("start_debugger : exec of gdb failed, errno = %d\n", - errno); - } - if(child < 0){ - printk("start_debugger : fork for gdb failed, errno = %d\n", - errno); - return(-1); - } - *fd_out = slave; - return(child); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h deleted file mode 100644 index 5eb0285b196..00000000000 --- a/arch/um/kernel/tt/ptproxy/ptproxy.h +++ /dev/null @@ -1,61 +0,0 @@ -/********************************************************************** -ptproxy.h - -Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -terms and conditions. -**********************************************************************/ - -#ifndef __PTPROXY_H -#define __PTPROXY_H - -#include <sys/types.h> - -typedef struct debugger debugger_state; -typedef struct debugee debugee_state; - -struct debugger -{ - pid_t pid; - int wait_options; - int *wait_status_ptr; - unsigned int waiting : 1; - unsigned int real_wait : 1; - unsigned int expecting_child : 1; - int (*handle_trace) (debugger_state *, pid_t); - - debugee_state *debugee; -}; - -struct debugee -{ - pid_t pid; - int wait_status; - unsigned int died : 1; - unsigned int event : 1; - unsigned int stopped : 1; - unsigned int trace_singlestep : 1; - unsigned int trace_syscall : 1; - unsigned int traced : 1; - unsigned int zombie : 1; - unsigned int in_context : 1; -}; - -extern int debugger_syscall(debugger_state *debugger, pid_t pid); -extern int debugger_normal_return (debugger_state *debugger, pid_t unused); - -extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, - int *strace_out); -extern void debugger_cancelled_return(debugger_state *debugger, int result); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c deleted file mode 100644 index 4b4f6179b21..00000000000 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ /dev/null @@ -1,237 +0,0 @@ -/********************************************************************** -ptrace.c - -Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -terms and conditions. - -Jeff Dike (jdike@karaya.com) : Modified for integration into uml -**********************************************************************/ - -#include <errno.h> -#include <unistd.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/wait.h> - -#include "ptproxy.h" -#include "debug.h" -#include "kern_util.h" -#include "ptrace_user.h" -#include "tt.h" -#include "os.h" - -long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, - long arg3, long arg4, pid_t child, int *ret) -{ - sigset_t relay; - long result; - int status; - - *ret = 0; - if(debugger->debugee->died) return(-ESRCH); - - switch(arg1){ - case PTRACE_ATTACH: - if(debugger->debugee->traced) return(-EPERM); - - debugger->debugee->pid = arg2; - debugger->debugee->traced = 1; - - if(is_valid_pid(arg2) && (arg2 != child)){ - debugger->debugee->in_context = 0; - kill(arg2, SIGSTOP); - debugger->debugee->event = 1; - debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); - } - else { - debugger->debugee->in_context = 1; - if(debugger->debugee->stopped) - child_proxy(child, W_STOPCODE(SIGSTOP)); - else kill(child, SIGSTOP); - } - - return(0); - - case PTRACE_DETACH: - if(!debugger->debugee->traced) return(-EPERM); - - debugger->debugee->traced = 0; - debugger->debugee->pid = 0; - if(!debugger->debugee->in_context) - kill(child, SIGCONT); - - return(0); - - case PTRACE_CONT: - if(!debugger->debugee->in_context) return(-EPERM); - *ret = PTRACE_CONT; - return(ptrace(PTRACE_CONT, child, arg3, arg4)); - -#ifdef UM_HAVE_GETFPREGS - case PTRACE_GETFPREGS: - { - long regs[FP_FRAME_SIZE]; - int i, result; - - result = ptrace(PTRACE_GETFPREGS, child, 0, regs); - if(result == -1) return(-errno); - - for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) - ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, - regs[i]); - return(result); - } -#endif - -#ifdef UM_HAVE_GETFPXREGS - case PTRACE_GETFPXREGS: - { - long regs[FPX_FRAME_SIZE]; - int i, result; - - result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); - if(result == -1) return(-errno); - - for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) - ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, - regs[i]); - return(result); - } -#endif - -#ifdef UM_HAVE_GETREGS - case PTRACE_GETREGS: - { - long regs[FRAME_SIZE]; - int i, result; - - result = ptrace(PTRACE_GETREGS, child, 0, regs); - if(result == -1) return(-errno); - - for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) - ptrace (PTRACE_POKEDATA, debugger->pid, - arg4 + 4 * i, regs[i]); - return(result); - } - break; -#endif - - case PTRACE_KILL: - result = ptrace(PTRACE_KILL, child, arg3, arg4); - if(result == -1) return(-errno); - - return(result); - - case PTRACE_PEEKDATA: - case PTRACE_PEEKTEXT: - case PTRACE_PEEKUSR: - /* The value being read out could be -1, so we have to - * check errno to see if there's an error, and zero it - * beforehand so we're not faked out by an old error - */ - - errno = 0; - result = ptrace(arg1, child, arg3, 0); - if((result == -1) && (errno != 0)) return(-errno); - - result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); - if(result == -1) return(-errno); - - return(result); - - case PTRACE_POKEDATA: - case PTRACE_POKETEXT: - case PTRACE_POKEUSR: - result = ptrace(arg1, child, arg3, arg4); - if(result == -1) return(-errno); - - if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4); - return(result); - -#ifdef UM_HAVE_SETFPREGS - case PTRACE_SETFPREGS: - { - long regs[FP_FRAME_SIZE]; - int i; - - for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) - regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, - arg4 + 4 * i, 0); - result = ptrace(PTRACE_SETFPREGS, child, 0, regs); - if(result == -1) return(-errno); - - return(result); - } -#endif - -#ifdef UM_HAVE_SETFPXREGS - case PTRACE_SETFPXREGS: - { - long regs[FPX_FRAME_SIZE]; - int i; - - for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) - regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, - arg4 + 4 * i, 0); - result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); - if(result == -1) return(-errno); - - return(result); - } -#endif - -#ifdef UM_HAVE_SETREGS - case PTRACE_SETREGS: - { - long regs[FRAME_SIZE]; - int i; - - for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) - regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, - arg4 + 4 * i, 0); - result = ptrace(PTRACE_SETREGS, child, 0, regs); - if(result == -1) return(-errno); - - return(result); - } -#endif - - case PTRACE_SINGLESTEP: - if(!debugger->debugee->in_context) return(-EPERM); - sigemptyset(&relay); - sigaddset(&relay, SIGSEGV); - sigaddset(&relay, SIGILL); - sigaddset(&relay, SIGBUS); - result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); - if(result == -1) return(-errno); - - status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, - &relay); - child_proxy(child, status); - return(result); - - case PTRACE_SYSCALL: - if(!debugger->debugee->in_context) return(-EPERM); - result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); - if(result == -1) return(-errno); - - *ret = PTRACE_SYSCALL; - return(result); - - case PTRACE_TRACEME: - default: - return(-EINVAL); - } -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c deleted file mode 100644 index e0e1ab0588a..00000000000 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ /dev/null @@ -1,70 +0,0 @@ -/********************************************************************** -sysdep.c - -Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -terms and conditions. -**********************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <signal.h> -#include <errno.h> -#include <sys/types.h> -#include <linux/unistd.h> -#include "ptrace_user.h" -#include "user.h" -#include "os.h" - -int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, - long *arg5) -{ - *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0); - *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0); - *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0); - *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0); - *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0); - return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0)); -} - -void syscall_cancel(pid_t pid, int result) -{ - if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, - __NR_getpid) < 0) || - (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || - (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || - (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || - (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) - printk("ptproxy: couldn't cancel syscall: errno = %d\n", - errno); -} - -void syscall_set_result(pid_t pid, long result) -{ - ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result); -} - -void syscall_continue(pid_t pid) -{ - ptrace(PTRACE_SYSCALL, pid, 0, 0); -} - -int syscall_pause(pid_t pid) -{ - if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ - printk("syscall_change - ptrace failed, errno = %d\n", errno); - return(-1); - } - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h deleted file mode 100644 index 735f488049a..00000000000 --- a/arch/um/kernel/tt/ptproxy/sysdep.h +++ /dev/null @@ -1,25 +0,0 @@ -/********************************************************************** -sysdep.h - -Copyright (C) 1999 Lars Brinkhoff. -Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -See the file COPYING for licensing terms and conditions. -**********************************************************************/ - -extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, - long *arg4, long *arg5); -extern void syscall_cancel (pid_t pid, long result); -extern void syscall_set_result (pid_t pid, long result); -extern void syscall_continue (pid_t pid); -extern int syscall_pause(pid_t pid); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c deleted file mode 100644 index bdd4af4b65f..00000000000 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ /dev/null @@ -1,85 +0,0 @@ -/********************************************************************** -wait.c - -Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -terms and conditions. - -**********************************************************************/ - -#include <errno.h> -#include <signal.h> -#include <sys/wait.h> - -#include "ptproxy.h" -#include "sysdep.h" -#include "wait.h" -#include "ptrace_user.h" -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" - -int proxy_wait_return(struct debugger *debugger, pid_t unused) -{ - debugger->waiting = 0; - - if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ - debugger_cancelled_return(debugger, -ECHILD); - return(0); - } - - if(debugger->debugee->zombie && debugger->debugee->event) - debugger->debugee->died = 1; - - if(debugger->debugee->event){ - debugger->debugee->event = 0; - ptrace(PTRACE_POKEDATA, debugger->pid, - debugger->wait_status_ptr, - debugger->debugee->wait_status); - /* if (wait4) - ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ - debugger_cancelled_return(debugger, debugger->debugee->pid); - return(0); - } - - /* pause will return -EINTR, which happens to be right for wait */ - debugger_normal_return(debugger, -1); - return(0); -} - -int parent_wait_return(struct debugger *debugger, pid_t unused) -{ - return(debugger_normal_return(debugger, -1)); -} - -int real_wait_return(struct debugger *debugger) -{ - unsigned long ip; - int pid; - - pid = debugger->pid; - - ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0); - IP_RESTART_SYSCALL(ip); - - if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0) - tracer_panic("real_wait_return : Failed to restart system " - "call, errno = %d\n", errno); - - if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || - (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || - (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || - debugger_normal_return(debugger, -1)) - tracer_panic("real_wait_return : gdb failed to wait, " - "errno = %d\n", errno); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h deleted file mode 100644 index 542e73ee2ce..00000000000 --- a/arch/um/kernel/tt/ptproxy/wait.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** -wait.h - -Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -terms and conditions. -**********************************************************************/ - -#ifndef __PTPROXY_WAIT_H -#define __PTPROXY_WAIT_H - -extern int proxy_wait_return(struct debugger *debugger, pid_t unused); -extern int real_wait_return(struct debugger *debugger); -extern int parent_wait_return(struct debugger *debugger, pid_t unused); - -#endif diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c deleted file mode 100644 index 293caa6d0c2..00000000000 --- a/arch/um/kernel/tt/syscall_kern.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/types.h" -#include "linux/utime.h" -#include "linux/sys.h" -#include "linux/ptrace.h" -#include "asm/unistd.h" -#include "asm/ptrace.h" -#include "asm/uaccess.h" -#include "asm/stat.h" -#include "sysdep/syscalls.h" -#include "sysdep/sigcontext.h" -#include "kern_util.h" -#include "syscall.h" - -void syscall_handler_tt(int sig, struct pt_regs *regs) -{ - void *sc; - long result; - int syscall; - - sc = UPT_SC(®s->regs); - SC_START_SYSCALL(sc); - - syscall = UPT_SYSCALL_NR(®s->regs); - syscall_trace(®s->regs, 0); - - current->thread.nsyscalls++; - nsyscalls++; - - if((syscall >= NR_syscalls) || (syscall < 0)) - result = -ENOSYS; - else result = EXECUTE_SYSCALL(syscall, regs); - - /* regs->sc may have changed while the system call ran (there may - * have been an interrupt or segfault), so it needs to be refreshed. - */ - UPT_SC(®s->regs) = sc; - - SC_SET_SYSCALL_RETURN(sc, result); - - syscall_trace(®s->regs, 1); -} diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c deleted file mode 100644 index f52b47aff1d..00000000000 --- a/arch/um/kernel/tt/syscall_user.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <unistd.h> -#include <signal.h> -#include <errno.h> -#include <asm/unistd.h> -#include "sysdep/ptrace.h" -#include "sigcontext.h" -#include "ptrace_user.h" -#include "task.h" -#include "kern_util.h" -#include "syscall.h" -#include "tt.h" - -void do_sigtrap(void *task) -{ - UPT_SYSCALL_NR(TASK_REGS(task)) = -1; -} - -void do_syscall(void *task, int pid, int local_using_sysemu) -{ - unsigned long proc_regs[FRAME_SIZE]; - - if(ptrace_getregs(pid, proc_regs) < 0) - tracer_panic("Couldn't read registers"); - - UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs); - -#ifdef UPT_ORIGGPR2 - UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs); -#endif - - if(((unsigned long *) PT_IP(proc_regs) >= &_stext) && - ((unsigned long *) PT_IP(proc_regs) <= &_etext)) - tracer_panic("I'm tracing myself and I can't get out"); - - /* advanced sysemu mode set syscall number to -1 automatically */ - if (local_using_sysemu==2) - return; - - /* syscall number -1 in sysemu skips syscall restarting in host */ - if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, - local_using_sysemu ? -1 : __NR_getpid) < 0) - tracer_panic("do_syscall : Nullifying syscall failed, " - "errno = %d", errno); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c deleted file mode 100644 index 7caa24fe05d..00000000000 --- a/arch/um/kernel/tt/tlb.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Copyright 2003 PathScale, Inc. - * Licensed under the GPL - */ - -#include "linux/stddef.h" -#include "linux/kernel.h" -#include "linux/sched.h" -#include "linux/mm.h" -#include "asm/page.h" -#include "asm/pgtable.h" -#include "asm/uaccess.h" -#include "asm/tlbflush.h" -#include "mem_user.h" -#include "os.h" -#include "tlb.h" - -static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, - int finished, void **flush) -{ - struct host_vm_op *op; - int i, ret=0; - - for(i = 0; i <= last && !ret; i++){ - op = &ops[i]; - switch(op->type){ - case MMAP: - ret = os_map_memory((void *) op->u.mmap.addr, - op->u.mmap.fd, op->u.mmap.offset, - op->u.mmap.len, op->u.mmap.r, - op->u.mmap.w, op->u.mmap.x); - break; - case MUNMAP: - ret = os_unmap_memory((void *) op->u.munmap.addr, - op->u.munmap.len); - break; - case MPROTECT: - ret = protect_memory(op->u.mprotect.addr, - op->u.munmap.len, - op->u.mprotect.r, - op->u.mprotect.w, - op->u.mprotect.x, 1); - protect_memory(op->u.mprotect.addr, op->u.munmap.len, - op->u.mprotect.r, op->u.mprotect.w, - op->u.mprotect.x, 1); - break; - default: - printk("Unknown op type %d in do_ops\n", op->type); - break; - } - } - - return ret; -} - -static void fix_range(struct mm_struct *mm, unsigned long start_addr, - unsigned long end_addr, int force) -{ - if((current->thread.mode.tt.extern_pid != -1) && - (current->thread.mode.tt.extern_pid != os_getpid())) - panic("fix_range fixing wrong address space, current = 0x%p", - current); - - fix_range_common(mm, start_addr, end_addr, force, do_ops); -} - -atomic_t vmchange_seq = ATOMIC_INIT(1); - -void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end) -{ - if(flush_tlb_kernel_range_common(start, end)) - atomic_inc(&vmchange_seq); -} - -void flush_tlb_kernel_vm_tt(void) -{ - flush_tlb_kernel_range(start_vm, end_vm); -} - -void __flush_tlb_one_tt(unsigned long addr) -{ - flush_tlb_kernel_range(addr, addr + PAGE_SIZE); -} - -void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - if(vma->vm_mm != current->mm) return; - - /* Assumes that the range start ... end is entirely within - * either process memory or kernel vm - */ - if((start >= start_vm) && (start < end_vm)){ - if(flush_tlb_kernel_range_common(start, end)) - atomic_inc(&vmchange_seq); - } - else fix_range(vma->vm_mm, start, end, 0); -} - -void flush_tlb_mm_tt(struct mm_struct *mm) -{ - unsigned long seq; - - if(mm != current->mm) return; - - fix_range(mm, 0, STACK_TOP, 0); - - seq = atomic_read(&vmchange_seq); - if(current->thread.mode.tt.vm_seq == seq) - return; - current->thread.mode.tt.vm_seq = seq; - flush_tlb_kernel_range_common(start_vm, end_vm); -} - -void force_flush_all_tt(void) -{ - fix_range(current->mm, 0, STACK_TOP, 1); - flush_tlb_kernel_range_common(start_vm, end_vm); -} diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c deleted file mode 100644 index c23588393f6..00000000000 --- a/arch/um/kernel/tt/tracer.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <signal.h> -#include <errno.h> -#include <sched.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/time.h> -#include <sys/wait.h> -#include "user.h" -#include "sysdep/ptrace.h" -#include "sigcontext.h" -#include "sysdep/sigcontext.h" -#include "os.h" -#include "mem_user.h" -#include "process.h" -#include "kern_util.h" -#include "chan_user.h" -#include "ptrace_user.h" -#include "irq_user.h" -#include "mode.h" -#include "tt.h" - -static int tracer_winch[2]; - -int is_tracer_winch(int pid, int fd, void *data) -{ - if(pid != os_getpgrp()) - return(0); - - register_winch_irq(tracer_winch[0], fd, -1, data); - return(1); -} - -static void tracer_winch_handler(int sig) -{ - int n; - char c = 1; - - n = os_write_file(tracer_winch[1], &c, sizeof(c)); - if(n != sizeof(c)) - printk("tracer_winch_handler - write failed, err = %d\n", -n); -} - -/* Called only by the tracing thread during initialization */ - -static void setup_tracer_winch(void) -{ - int err; - - err = os_pipe(tracer_winch, 1, 1); - if(err < 0){ - printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); - return; - } - signal(SIGWINCH, tracer_winch_handler); -} - -void attach_process(int pid) -{ - if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || - (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) - tracer_panic("OP_FORK failed to attach pid"); - wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); - if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) - tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno); - if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) - tracer_panic("OP_FORK failed to continue process"); -} - -void tracer_panic(char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - printf("\n"); - while(1) pause(); -} - -static void tracer_segv(int sig, struct sigcontext sc) -{ - struct faultinfo fi; - GET_FAULTINFO_FROM_SC(fi, &sc); - printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", - FAULT_ADDRESS(fi), SC_IP(&sc)); - while(1) - pause(); -} - -/* Changed early in boot, and then only read */ -int debug = 0; -int debug_stop = 1; -int debug_parent = 0; -int honeypot = 0; - -static int signal_tramp(void *arg) -{ - int (*proc)(void *); - - if(honeypot && munmap((void *) (host_task_size - 0x10000000), - 0x10000000)) - panic("Unmapping stack failed"); - if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) - panic("ptrace PTRACE_TRACEME failed"); - os_stop_process(os_getpid()); - change_sig(SIGWINCH, 0); - signal(SIGUSR1, SIG_IGN); - change_sig(SIGCHLD, 0); - signal(SIGSEGV, (__sighandler_t) sig_handler); - set_cmdline("(idle thread)"); - set_init_pid(os_getpid()); - init_irq_signals(0); - proc = arg; - return((*proc)(NULL)); -} - -static void sleeping_process_signal(int pid, int sig) -{ - switch(sig){ - /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is - * right because the process must be in the kernel already. - */ - case SIGCONT: - case SIGTSTP: - if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) - tracer_panic("sleeping_process_signal : Failed to " - "continue pid %d, signal = %d, " - "errno = %d\n", pid, sig, errno); - break; - - /* This happens when the debugger (e.g. strace) is doing system call - * tracing on the kernel. During a context switch, the current task - * will be set to the incoming process and the outgoing process will - * hop into write and then read. Since it's not the current process - * any more, the trace of those will land here. So, we need to just - * PTRACE_SYSCALL it. - */ - case (SIGTRAP + 0x80): - if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) - tracer_panic("sleeping_process_signal : Failed to " - "PTRACE_SYSCALL pid %d, errno = %d\n", - pid, errno); - break; - case SIGSTOP: - break; - default: - tracer_panic("sleeping process %d got unexpected " - "signal : %d\n", pid, sig); - break; - } -} - -/* Accessed only by the tracing thread */ -int debugger_pid = -1; -int debugger_parent = -1; -int debugger_fd = -1; -int gdb_pid = -1; - -struct { - int pid; - int signal; - unsigned long addr; - struct timeval time; -} signal_record[1024][32]; - -int signal_index[32]; -int nsignals = 0; -int debug_trace = 0; - -extern void signal_usr1(int sig); - -int tracing_pid = -1; - -int tracer(int (*init_proc)(void *), void *sp) -{ - void *task = NULL; - int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; - int proc_id = 0, n, err, old_tracing = 0, strace = 0; - int local_using_sysemu = 0; - - signal(SIGPIPE, SIG_IGN); - setup_tracer_winch(); - tracing_pid = os_getpid(); - printf("tracing thread pid = %d\n", tracing_pid); - - pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); - CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0){ - printf("waitpid on idle thread failed, errno = %d\n", errno); - exit(1); - } - if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) { - printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno); - exit(1); - } - if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ - printf("Failed to continue idle thread, errno = %d\n", errno); - exit(1); - } - - signal(SIGSEGV, (sighandler_t) tracer_segv); - signal(SIGUSR1, signal_usr1); - if(debug_trace){ - printf("Tracing thread pausing to be attached\n"); - stop(); - } - if(debug){ - if(gdb_pid != -1) - debugger_pid = attach_debugger(pid, gdb_pid, 1); - else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); - if(debug_parent){ - debugger_parent = os_process_parent(debugger_pid); - init_parent_proxy(debugger_parent); - err = attach(debugger_parent); - if(err){ - printf("Failed to attach debugger parent %d, " - "errno = %d\n", debugger_parent, -err); - debugger_parent = -1; - } - else { - if(ptrace(PTRACE_SYSCALL, debugger_parent, - 0, 0) < 0){ - printf("Failed to continue debugger " - "parent, errno = %d\n", errno); - debugger_parent = -1; - } - } - } - } - set_cmdline("(tracing thread)"); - while(1){ - CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); - if(pid <= 0){ - if(errno != ECHILD){ - printf("wait failed - errno = %d\n", errno); - } - continue; - } - if(pid == debugger_pid){ - int cont = 0; - - if(WIFEXITED(status) || WIFSIGNALED(status)) - debugger_pid = -1; - /* XXX Figure out how to deal with gdb and SMP */ - else cont = debugger_signal(status, cpu_tasks[0].pid); - if(cont == PTRACE_SYSCALL) strace = 1; - continue; - } - else if(pid == debugger_parent){ - debugger_parent_signal(status, pid); - continue; - } - nsignals++; - if(WIFEXITED(status)) ; -#ifdef notdef - { - printf("Child %d exited with status %d\n", pid, - WEXITSTATUS(status)); - } -#endif - else if(WIFSIGNALED(status)){ - sig = WTERMSIG(status); - if(sig != 9){ - printf("Child %d exited with signal %d\n", pid, - sig); - } - } - else if(WIFSTOPPED(status)){ - proc_id = pid_to_processor_id(pid); - sig = WSTOPSIG(status); - if(proc_id == -1){ - sleeping_process_signal(pid, sig); - continue; - } - - task = cpu_tasks[proc_id].task; - tracing = is_tracing(task); - old_tracing = tracing; - - /* Assume: no syscall, when coming from user */ - if ( tracing ) - do_sigtrap(task); - - switch(sig){ - case SIGUSR1: - sig = 0; - op = do_proc_op(task, proc_id); - switch(op){ - /* - * This is called when entering user mode; after - * this, we start intercepting syscalls. - * - * In fact, a process is started in kernel mode, - * so with is_tracing() == 0 (and that is reset - * when executing syscalls, since UML kernel has - * the right to do syscalls); - */ - case OP_TRACE_ON: - arch_leave_kernel(task, pid); - tracing = 1; - break; - case OP_REBOOT: - case OP_HALT: - unmap_physmem(); - kmalloc_ok = 0; - os_kill_ptraced_process(pid, 0); - /* Now let's reap remaining zombies */ - errno = 0; - do { - waitpid(-1, &status, - WUNTRACED); - } while (errno != ECHILD); - return(op == OP_REBOOT); - case OP_NONE: - printf("Detaching pid %d\n", pid); - detach(pid, SIGSTOP); - continue; - default: - break; - } - /* OP_EXEC switches host processes on us, - * we want to continue the new one. - */ - pid = cpu_tasks[proc_id].pid; - break; - case (SIGTRAP + 0x80): - if(!tracing && (debugger_pid != -1)){ - child_signal(pid, status & 0x7fff); - continue; - } - tracing = 0; - /* local_using_sysemu has been already set - * below, since if we are here, is_tracing() on - * the traced task was 1, i.e. the process had - * already run through one iteration of the - * loop which executed a OP_TRACE_ON request.*/ - do_syscall(task, pid, local_using_sysemu); - sig = SIGUSR2; - break; - case SIGTRAP: - if(!tracing && (debugger_pid != -1)){ - child_signal(pid, status); - continue; - } - tracing = 0; - break; - case SIGPROF: - if(tracing) sig = 0; - break; - case SIGCHLD: - case SIGHUP: - sig = 0; - break; - case SIGSEGV: - case SIGIO: - case SIGALRM: - case SIGVTALRM: - case SIGFPE: - case SIGBUS: - case SIGILL: - case SIGWINCH: - - default: - tracing = 0; - break; - } - set_tracing(task, tracing); - - if(!tracing && old_tracing) - arch_enter_kernel(task, pid); - - if(!tracing && (debugger_pid != -1) && (sig != 0) && - (sig != SIGALRM) && (sig != SIGVTALRM) && - (sig != SIGSEGV) && (sig != SIGTRAP) && - (sig != SIGUSR2) && (sig != SIGIO) && - (sig != SIGFPE)){ - child_signal(pid, status); - continue; - } - - local_using_sysemu = get_using_sysemu(); - - if(tracing) - cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu, - singlestepping(task)); - else if((debugger_pid != -1) && strace) - cont_type = PTRACE_SYSCALL; - else - cont_type = PTRACE_CONT; - - if(ptrace(cont_type, pid, 0, sig) != 0){ - tracer_panic("ptrace failed to continue " - "process - errno = %d\n", - errno); - } - } - } - return(0); -} - -static int __init uml_debug_setup(char *line, int *add) -{ - char *next; - - debug = 1; - *add = 0; - if(*line != '=') return(0); - line++; - - while(line != NULL){ - next = strchr(line, ','); - if(next) *next++ = '\0'; - - if(!strcmp(line, "go")) debug_stop = 0; - else if(!strcmp(line, "parent")) debug_parent = 1; - else printf("Unknown debug option : '%s'\n", line); - - line = next; - } - return(0); -} - -__uml_setup("debug", uml_debug_setup, -"debug\n" -" Starts up the kernel under the control of gdb. See the \n" -" kernel debugging tutorial and the debugging session pages\n" -" at http://user-mode-linux.sourceforge.net/ for more information.\n\n" -); - -static int __init uml_debugtrace_setup(char *line, int *add) -{ - debug_trace = 1; - return 0; -} -__uml_setup("debugtrace", uml_debugtrace_setup, -"debugtrace\n" -" Causes the tracing thread to pause until it is attached by a\n" -" debugger and continued. This is mostly for debugging crashes\n" -" early during boot, and should be pretty much obsoleted by\n" -" the debug switch.\n\n" -); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c deleted file mode 100644 index 3032eb5e246..00000000000 --- a/arch/um/kernel/tt/trap_user.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdlib.h> -#include <errno.h> -#include <signal.h> -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" -#include "kern_util.h" -#include "task.h" -#include "tt.h" -#include "os.h" - -void sig_handler_common_tt(int sig, void *sc_ptr) -{ - struct sigcontext *sc = sc_ptr; - struct tt_regs save_regs, *r; - int save_errno = errno, is_user = 0; - void (*handler)(int, union uml_pt_regs *); - - /* This is done because to allow SIGSEGV to be delivered inside a SEGV - * handler. This can happen in copy_user, and if SEGV is disabled, - * the process will die. - */ - if(sig == SIGSEGV) - change_sig(SIGSEGV, 1); - - r = &TASK_REGS(get_current())->tt; - if ( sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGILL || - sig == SIGTRAP ) { - GET_FAULTINFO_FROM_SC(r->faultinfo, sc); - } - save_regs = *r; - if (sc) - is_user = user_context(SC_SP(sc)); - r->sc = sc; - if(sig != SIGUSR2) - r->syscall = -1; - - handler = sig_info[sig]; - - /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if (sig != SIGIO && sig != SIGWINCH && - sig != SIGVTALRM && sig != SIGALRM) - unblock_signals(); - - handler(sig, (union uml_pt_regs *) r); - - if(is_user){ - interrupt_end(); - block_signals(); - set_user_mode(NULL); - } - *r = save_regs; - errno = save_errno; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c deleted file mode 100644 index 1cb60726567..00000000000 --- a/arch/um/kernel/tt/uaccess.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/sched.h" -#include "asm/uaccess.h" - -int copy_from_user_tt(void *to, const void __user *from, int n) -{ - if(!access_ok(VERIFY_READ, from, n)) - return(n); - - return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int copy_to_user_tt(void __user *to, const void *from, int n) -{ - if(!access_ok(VERIFY_WRITE, to, n)) - return(n); - - return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int strncpy_from_user_tt(char *dst, const char __user *src, int count) -{ - int n; - - if(!access_ok(VERIFY_READ, src, 1)) - return(-EFAULT); - - n = __do_strncpy_from_user(dst, src, count, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher); - if(n < 0) return(-EFAULT); - return(n); -} - -int __clear_user_tt(void __user *mem, int len) -{ - return(__do_clear_user(mem, len, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int clear_user_tt(void __user *mem, int len) -{ - if(!access_ok(VERIFY_WRITE, mem, len)) - return(len); - - return(__do_clear_user(mem, len, ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int strnlen_user_tt(const void __user *str, int len) -{ - return(__do_strnlen_user(str, len, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c deleted file mode 100644 index 0e5c82c5e5b..00000000000 --- a/arch/um/kernel/tt/uaccess_user.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <string.h> -#include "uml_uaccess.h" -#include "task.h" -#include "kern_util.h" -#include "os.h" -#include "longjmp.h" - -int __do_copy_from_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher) -{ - struct tt_regs save = TASK_REGS(get_current())->tt; - unsigned long fault; - int faulted; - - fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, - __do_copy, &faulted); - TASK_REGS(get_current())->tt = save; - - if(!faulted) - return 0; - else if (fault) - return n - (fault - (unsigned long) from); - else - /* In case of a general protection fault, we don't have the - * fault address, so NULL is used instead. Pretend we didn't - * copy anything. */ - return n; -} - -static void __do_strncpy(void *dst, const void *src, int count) -{ - strncpy(dst, src, count); -} - -int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, - void **fault_addr, void **fault_catcher) -{ - struct tt_regs save = TASK_REGS(get_current())->tt; - unsigned long fault; - int faulted; - - fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, - __do_strncpy, &faulted); - TASK_REGS(get_current())->tt = save; - - if(!faulted) return(strlen(dst)); - else return(-1); -} - -static void __do_clear(void *to, const void *from, int n) -{ - memset(to, 0, n); -} - -int __do_clear_user(void *mem, unsigned long len, - void **fault_addr, void **fault_catcher) -{ - struct tt_regs save = TASK_REGS(get_current())->tt; - unsigned long fault; - int faulted; - - fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, - __do_clear, &faulted); - TASK_REGS(get_current())->tt = save; - - if(!faulted) return(0); - else return(len - (fault - (unsigned long) mem)); -} - -int __do_strnlen_user(const char *str, unsigned long n, - void **fault_addr, void **fault_catcher) -{ - struct tt_regs save = TASK_REGS(get_current())->tt; - int ret; - unsigned long *faddrp = (unsigned long *)fault_addr; - jmp_buf jbuf; - - *fault_catcher = &jbuf; - if(UML_SETJMP(&jbuf) == 0) - ret = strlen(str) + 1; - else ret = *faddrp - (unsigned long) str; - - *fault_addr = NULL; - *fault_catcher = NULL; - - TASK_REGS(get_current())->tt = save; - return ret; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c index 054e3de0784..d7436aacd26 100644 --- a/arch/um/kernel/uaccess.c +++ b/arch/um/kernel/uaccess.c @@ -18,7 +18,7 @@ void __do_copy(void *to, const void *from, int n) int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher) + void **fault_addr, jmp_buf **fault_catcher) { unsigned long fault; int faulted; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index ecc458fe51b..f1c71393f57 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -1,46 +1,24 @@ /* - * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/sched.h" -#include "linux/notifier.h" -#include "linux/mm.h" -#include "linux/types.h" -#include "linux/tty.h" -#include "linux/init.h" -#include "linux/bootmem.h" -#include "linux/spinlock.h" -#include "linux/utsname.h" -#include "linux/sysrq.h" -#include "linux/seq_file.h" #include "linux/delay.h" +#include "linux/mm.h" #include "linux/module.h" +#include "linux/seq_file.h" +#include "linux/string.h" #include "linux/utsname.h" -#include "asm/page.h" #include "asm/pgtable.h" -#include "asm/ptrace.h" -#include "asm/elf.h" -#include "asm/user.h" +#include "asm/processor.h" #include "asm/setup.h" -#include "ubd_user.h" -#include "asm/current.h" -#include "kern_util.h" -#include "as-layout.h" #include "arch.h" +#include "as-layout.h" +#include "init.h" #include "kern.h" #include "mem_user.h" -#include "mem.h" -#include "initrd.h" -#include "init.h" #include "os.h" -#include "choose-mode.h" -#include "mode_kern.h" -#include "mode.h" -#ifdef UML_CONFIG_MODE_SKAS #include "skas.h" -#endif #define DEFAULT_COMMAND_LINE "root=98:0" @@ -53,7 +31,7 @@ static void __init add_arg(char *arg) printf("add_arg: Too many command line arguments!\n"); exit(1); } - if(strlen(command_line) > 0) + if (strlen(command_line) > 0) strcat(command_line, " "); strcat(command_line, arg); } @@ -70,8 +48,8 @@ struct cpuinfo_um boot_cpu_data = { unsigned long thread_saved_pc(struct task_struct *task) { - return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, - task)); + /* FIXME: Need to look up userspace_pid by cpu */ + return os_process_pc(userspace_pid[0]); } /* Changed in setup_arch, which is called in early boot */ @@ -90,7 +68,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "processor\t: %d\n", index); seq_printf(m, "vendor_id\t: User Mode Linux\n"); seq_printf(m, "model name\t: UML\n"); - seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); + seq_printf(m, "mode\t\t: skas\n"); seq_printf(m, "host\t\t: %s\n", host_info); seq_printf(m, "bogomips\t: %lu.%02lu\n\n", loops_per_jiffy/(500000/HZ), @@ -132,44 +110,13 @@ unsigned long end_vm; /* Set in uml_ncpus_setup */ int ncpus = 1; -#ifdef CONFIG_CMDLINE_ON_HOST -/* Pointer set in linux_main, the array itself is private to each thread, - * and changed at address space creation time so this poses no concurrency - * problems. - */ -static char *argv1_begin = NULL; -static char *argv1_end = NULL; -#endif - /* Set in early boot */ static int have_root __initdata = 0; /* Set in uml_mem_setup and modified in linux_main */ long long physmem_size = 32 * 1024 * 1024; -void set_cmdline(char *cmd) -{ -#ifdef CONFIG_CMDLINE_ON_HOST - char *umid, *ptr; - - if(CHOOSE_MODE(honeypot, 0)) return; - - umid = get_umid(); - if(*umid != '\0'){ - snprintf(argv1_begin, - (argv1_end - argv1_begin) * sizeof(*ptr), - "(%s) ", umid); - ptr = &argv1_begin[strlen(argv1_begin)]; - } - else ptr = argv1_begin; - - snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); - memset(argv1_begin + strlen(argv1_begin), '\0', - argv1_end - argv1_begin - strlen(argv1_begin)); -#endif -} - -static char *usage_string = +static char *usage_string = "User Mode Linux v%s\n" " available at http://user-mode-linux.sourceforge.net/\n\n"; @@ -201,13 +148,10 @@ __uml_setup("root=", uml_root_setup, " root=/dev/ubd5\n\n" ); -#ifndef CONFIG_MODE_TT - static int __init no_skas_debug_setup(char *line, int *add) { printf("'debug' is not necessary to gdb UML in skas mode - run \n"); - printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); - printf("doesn't work as expected\n"); + printf("'gdb linux'"); return 0; } @@ -217,8 +161,6 @@ __uml_setup("debug", no_skas_debug_setup, " this flag is not needed to run gdb on UML in skas mode\n\n" ); -#endif - #ifdef CONFIG_SMP static int __init uml_ncpus_setup(char *line, int *add) { @@ -232,56 +174,10 @@ static int __init uml_ncpus_setup(char *line, int *add) __uml_setup("ncpus=", uml_ncpus_setup, "ncpus=<# of desired CPUs>\n" -" This tells an SMP kernel how many virtual processors to start.\n\n" +" This tells an SMP kernel how many virtual processors to start.\n\n" ); #endif -static int force_tt = 0; - -#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) -#define DEFAULT_TT 0 - -static int __init mode_tt_setup(char *line, int *add) -{ - force_tt = 1; - return 0; -} - -#else -#ifdef CONFIG_MODE_SKAS - -#define DEFAULT_TT 0 - -static int __init mode_tt_setup(char *line, int *add) -{ - printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); - return 0; -} - -#else -#ifdef CONFIG_MODE_TT - -#define DEFAULT_TT 1 - -static int __init mode_tt_setup(char *line, int *add) -{ - printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); - return 0; -} - -#endif -#endif -#endif - -__uml_setup("mode=tt", mode_tt_setup, -"mode=tt\n" -" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" -" forces UML to run in tt (tracing thread) mode. It is not the default\n" -" because it's slower and less secure than skas mode.\n\n" -); - -int mode_tt = DEFAULT_TT; - static int __init Usage(char *line, int *add) { const char **p; @@ -310,9 +206,8 @@ static int __init uml_checksetup(char *line, int *add) int n; n = strlen(p->str); - if(!strncmp(line, p->str, n)){ - if (p->setup_func(line + n, add)) return 1; - } + if (!strncmp(line, p->str, n) && p->setup_func(line + n, add)) + return 1; p++; } return 0; @@ -323,7 +218,7 @@ static void __init uml_postsetup(void) initcall_t *p; p = &__uml_postsetup_start; - while(p < &__uml_postsetup_end){ + while(p < &__uml_postsetup_end) { (*p)(); p++; } @@ -339,6 +234,20 @@ EXPORT_SYMBOL(end_iomem); extern char __binary_start; +static unsigned long set_task_sizes_skas(unsigned long *task_size_out) +{ + /* Round up to the nearest 4M */ + unsigned long host_task_size = ROUND_4M((unsigned long) + &host_task_size); + + if (!skas_needs_stub) + *task_size_out = host_task_size; + else + *task_size_out = STUB_START & PGDIR_MASK; + + return host_task_size; +} + int __init linux_main(int argc, char **argv) { unsigned long avail, diff; @@ -346,45 +255,30 @@ int __init linux_main(int argc, char **argv) unsigned int i, add; char * mode; - for (i = 1; i < argc; i++){ - if((i == 1) && (argv[i][0] == ' ')) continue; + for (i = 1; i < argc; i++) { + if ((i == 1) && (argv[i][0] == ' ')) + continue; add = 1; uml_checksetup(argv[i], &add); if (add) add_arg(argv[i]); } - if(have_root == 0) + if (have_root == 0) add_arg(DEFAULT_COMMAND_LINE); + /* OS sanity checks that need to happen before the kernel runs */ os_early_checks(); - if (force_tt) - clear_can_do_skas(); - mode_tt = force_tt ? 1 : !can_do_skas(); -#ifndef CONFIG_MODE_TT - if (mode_tt) { - /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, - * can_do_skas() returned 0, and the message is correct. */ - printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); - exit(1); - } -#endif -#ifndef CONFIG_MODE_SKAS - mode = "TT"; -#else - /* Show to the user the result of selection */ - if (mode_tt) - mode = "TT"; - else if (proc_mm && ptrace_faultinfo) + can_do_skas(); + + if (proc_mm && ptrace_faultinfo) mode = "SKAS3"; else mode = "SKAS0"; -#endif printf("UML running in %s mode\n", mode); - host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, - set_task_sizes_skas, &task_size); + host_task_size = set_task_sizes_skas(&task_size); /* * Setting up handlers to 'sig_info' struct @@ -392,13 +286,15 @@ int __init linux_main(int argc, char **argv) os_fill_handlinfo(handlinfo_kern); brk_start = (unsigned long) sbrk(0); - CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); - /* Increase physical memory size for exec-shield users - so they actually get what they asked for. This should - add zero for non-exec shield users */ + + /* + * Increase physical memory size for exec-shield users + * so they actually get what they asked for. This should + * add zero for non-exec shield users + */ diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); - if(diff > 1024 * 1024){ + if (diff > 1024 * 1024) { printf("Adding %ld bytes to physical memory to account for " "exec-shield gap\n", diff); physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); @@ -411,20 +307,16 @@ int __init linux_main(int argc, char **argv) setup_machinename(init_utsname()->machine); -#ifdef CONFIG_CMDLINE_ON_HOST - argv1_begin = argv[1]; - argv1_end = &argv[1][strlen(argv[1])]; -#endif - highmem = 0; iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; - /* Zones have to begin on a 1 << MAX_ORDER page boundary, + /* + * Zones have to begin on a 1 << MAX_ORDER page boundary, * so this makes sure that's true for highmem */ max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); - if(physmem_size + iomem_size > max_physmem){ + if (physmem_size + iomem_size > max_physmem) { highmem = physmem_size + iomem_size - max_physmem; physmem_size -= highmem; #ifndef CONFIG_HIGHMEM @@ -441,7 +333,7 @@ int __init linux_main(int argc, char **argv) start_vm = VMALLOC_START; setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); - if(init_maps(physmem_size, iomem_size, highmem)){ + if (init_maps(physmem_size, iomem_size, highmem)) { printf("Failed to allocate mem_map for %Lu bytes of physical " "memory and %Lu bytes of highmem\n", physmem_size, highmem); @@ -450,10 +342,11 @@ int __init linux_main(int argc, char **argv) virtmem_size = physmem_size; avail = get_kmem_end() - start_vm; - if(physmem_size > avail) virtmem_size = avail; + if (physmem_size > avail) + virtmem_size = avail; end_vm = start_vm + virtmem_size; - if(virtmem_size < physmem_size) + if (virtmem_size < physmem_size) printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); @@ -462,7 +355,7 @@ int __init linux_main(int argc, char **argv) stack_protections((unsigned long) &init_thread_info); os_flush_stdout(); - return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); + return start_uml(); } extern int uml_exitcode; diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 81acdc24348..13df191e2b4 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -18,13 +18,6 @@ SECTIONS . = START + SIZEOF_HEADERS; -#ifdef MODE_TT - .remap_data : { UNMAP_PATH (.data .bss) } - .remap : { UNMAP_PATH (.text) } - - . = ALIGN(4096); /* Init code and data */ -#endif - _text = .; _stext = .; __init_begin = .; diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 2f8c7946401..8e129af8170 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -1,23 +1,18 @@ # -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ - sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ - user_syms.o util.o drivers/ sys-$(SUBARCH)/ - -obj-$(CONFIG_MODE_SKAS) += skas/ - -obj-$(CONFIG_MODE_TT) += tt.o -user-objs-$(CONFIG_MODE_TT) += tt.o + registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \ + umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ obj-$(CONFIG_TTY_LOG) += tty_log.o user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ - main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \ - tls.o uaccess.o umid.o util.o + main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ + trap.o tty.o tls.o uaccess.o umid.o util.o CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 59348359f9a..4158118c4a5 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -1,20 +1,19 @@ /* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdlib.h> #include <unistd.h> +#include <sched.h> #include <signal.h> #include <errno.h> -#include <sched.h> -#include <sys/syscall.h> -#include "os.h" +#include <sys/time.h> +#include <asm/unistd.h> #include "aio.h" #include "init.h" -#include "user.h" -#include "mode.h" #include "kern_constants.h" +#include "os.h" +#include "user.h" struct aio_thread_req { enum aio_type type; @@ -28,7 +27,8 @@ struct aio_thread_req { #if defined(HAVE_AIO_ABI) #include <linux/aio_abi.h> -/* If we have the headers, we are going to build with AIO enabled. +/* + * If we have the headers, we are going to build with AIO enabled. * If we don't have aio in libc, we define the necessary stubs here. */ @@ -52,7 +52,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, #endif -/* The AIO_MMAP cases force the mmapped page into memory here +/* + * The AIO_MMAP cases force the mmapped page into memory here * rather than in whatever place first touches the data. I used * to do this by touching the page, but that's delicate because * gcc is prone to optimizing that away. So, what's done here @@ -106,12 +107,12 @@ static int aio_thread(void *arg) signal(SIGWINCH, SIG_IGN); - while(1){ + while (1) { n = io_getevents(ctx, 1, 1, &event, NULL); - if(n < 0){ - if(errno == EINTR) + if (n < 0) { + if (errno == EINTR) continue; - printk("aio_thread - io_getevents failed, " + printk(UM_KERN_ERR "aio_thread - io_getevents failed, " "errno = %d\n", errno); } else { @@ -120,9 +121,9 @@ static int aio_thread(void *arg) .err = event.res }); reply_fd = ((struct aio_context *) reply.data)->reply_fd; err = write(reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("aio_thread - write failed, fd = %d, " - "err = %d\n", reply_fd, errno); + if (err != sizeof(reply)) + printk(UM_KERN_ERR "aio_thread - write failed, " + "fd = %d, err = %d\n", reply_fd, errno); } } return 0; @@ -137,10 +138,10 @@ static int do_not_aio(struct aio_thread_req *req) int n; actual = lseek64(req->io_fd, req->offset, SEEK_SET); - if(actual != req->offset) + if (actual != req->offset) return -errno; - switch(req->type){ + switch(req->type) { case AIO_READ: n = read(req->io_fd, req->buf, req->len); break; @@ -151,11 +152,12 @@ static int do_not_aio(struct aio_thread_req *req) n = read(req->io_fd, &c, sizeof(c)); break; default: - printk("do_not_aio - bad request type : %d\n", req->type); + printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n", + req->type); return -EINVAL; } - if(n < 0) + if (n < 0) return -errno; return 0; } @@ -173,16 +175,18 @@ static int not_aio_thread(void *arg) int err; signal(SIGWINCH, SIG_IGN); - while(1){ + while (1) { err = read(aio_req_fd_r, &req, sizeof(req)); - if(err != sizeof(req)){ - if(err < 0) - printk("not_aio_thread - read failed, " - "fd = %d, err = %d\n", aio_req_fd_r, + if (err != sizeof(req)) { + if (err < 0) + printk(UM_KERN_ERR "not_aio_thread - " + "read failed, fd = %d, err = %d\n", + aio_req_fd_r, errno); else { - printk("not_aio_thread - short read, fd = %d, " - "length = %d\n", aio_req_fd_r, err); + printk(UM_KERN_ERR "not_aio_thread - short " + "read, fd = %d, length = %d\n", + aio_req_fd_r, err); } continue; } @@ -190,9 +194,9 @@ static int not_aio_thread(void *arg) reply = ((struct aio_thread_reply) { .data = req.aio, .err = err }); err = write(req.aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("not_aio_thread - write failed, fd = %d, " - "err = %d\n", req.aio->reply_fd, errno); + if (err != sizeof(reply)) + printk(UM_KERN_ERR "not_aio_thread - write failed, " + "fd = %d, err = %d\n", req.aio->reply_fd, errno); } return 0; @@ -203,35 +207,36 @@ static int init_aio_24(void) int fds[2], err; err = os_pipe(fds, 1, 1); - if(err) + if (err) goto out; aio_req_fd_w = fds[0]; aio_req_fd_r = fds[1]; err = os_set_fd_block(aio_req_fd_w, 0); - if(err) + if (err) goto out_close_pipe; err = run_helper_thread(not_aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); - if(err < 0) + if (err < 0) goto out_close_pipe; aio_pid = err; goto out; out_close_pipe: - os_close_file(fds[0]); - os_close_file(fds[1]); + close(fds[0]); + close(fds[1]); aio_req_fd_w = -1; aio_req_fd_r = -1; out: #ifndef HAVE_AIO_ABI - printk("/usr/include/linux/aio_abi.h not present during build\n"); + printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during " + "build\n"); #endif - printk("2.6 host AIO support not used - falling back to I/O " - "thread\n"); + printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to " + "I/O thread\n"); return 0; } @@ -241,21 +246,21 @@ static int init_aio_26(void) { int err; - if(io_setup(256, &ctx)){ + if (io_setup(256, &ctx)) { err = -errno; - printk("aio_thread failed to initialize context, err = %d\n", - errno); + printk(UM_KERN_ERR "aio_thread failed to initialize context, " + "err = %d\n", errno); return err; } err = run_helper_thread(aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); - if(err < 0) + if (err < 0) return err; aio_pid = err; - printk("Using 2.6 host AIO\n"); + printk(UM_KERN_INFO "Using 2.6 host AIO\n"); return 0; } @@ -266,13 +271,13 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, int err; err = do_aio(ctx, type, io_fd, buf, len, offset, aio); - if(err){ + if (err) { reply = ((struct aio_thread_reply) { .data = aio, .err = err }); err = write(aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)){ + if (err != sizeof(reply)) { err = -errno; - printk("submit_aio_26 - write failed, " + printk(UM_KERN_ERR "submit_aio_26 - write failed, " "fd = %d, err = %d\n", aio->reply_fd, -err); } else err = 0; @@ -320,28 +325,24 @@ static int init_aio(void) { int err; - CHOOSE_MODE(({ if(!aio_24){ - printk("Disabling 2.6 AIO in tt mode\n"); - aio_24 = 1; - } }), (void) 0); - - if(!aio_24){ + if (!aio_24) { err = init_aio_26(); - if(err && (errno == ENOSYS)){ - printk("2.6 AIO not supported on the host - " - "reverting to 2.4 AIO\n"); + if (err && (errno == ENOSYS)) { + printk(UM_KERN_INFO "2.6 AIO not supported on the " + "host - reverting to 2.4 AIO\n"); aio_24 = 1; } else return err; } - if(aio_24) + if (aio_24) return init_aio_24(); return 0; } -/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio +/* + * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio * needs to be called when the kernel is running because it calls run_helper, * which needs get_free_page. exit_aio is a __uml_exitcall because the generic * kernel does not run __exitcalls on shutdown, and can't because many of them @@ -372,7 +373,7 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, int err; err = write(aio_req_fd_w, &req, sizeof(req)); - if(err == sizeof(req)) + if (err == sizeof(req)) err = 0; else err = -errno; @@ -384,9 +385,8 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len, struct aio_context *aio) { aio->reply_fd = reply_fd; - if(aio_24) + if (aio_24) return submit_aio_24(type, io_fd, buf, len, offset, aio); - else { + else return submit_aio_26(type, io_fd, buf, len, offset, aio); - } } diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h index 57ecdaf2f67..ddffd41c3f3 100644 --- a/arch/um/os-Linux/drivers/etap.h +++ b/arch/um/os-Linux/drivers/etap.h @@ -1,8 +1,11 @@ /* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ +#ifndef __DRIVERS_ETAP_H +#define __DRIVERS_ETAP_H + #include "net_user.h" struct ethertap_data { @@ -15,13 +18,4 @@ struct ethertap_data { extern const struct net_user_info ethertap_user_info; -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +#endif diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 12689141414..04f11b9f1ac 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -1,16 +1,15 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ #include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" -#include "net_kern.h" -#include "net_user.h" +#include <linux/netdevice.h> #include "etap.h" +#include "net_kern.h" struct ethertap_init { char *dev_name; @@ -37,32 +36,24 @@ static void etap_init(struct net_device *dev, void *data) printk("\n"); } -static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) +static int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { int len; - *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); - if(*skb == NULL) return(-ENOMEM); - len = net_recvfrom(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); - if(len <= 0) return(len); - skb_pull(*skb, 2); + len = net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + 2 + ETH_HEADER_ETHERTAP); + if (len <= 0) + return(len); + + skb_pull(skb, 2); len -= 2; - return(len); + return len; } -static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) +static int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - if(skb_headroom(*skb) < 2){ - struct sk_buff *skb2; - - skb2 = skb_realloc_headroom(*skb, 2); - dev_kfree_skb(*skb); - if (skb2 == NULL) return(-ENOMEM); - *skb = skb2; - } - skb_push(*skb, 2); - return(net_send(fd, (*skb)->data, (*skb)->len)); + skb_push(skb, 2); + return net_send(fd, skb->data, skb->len); } const struct net_kern_info ethertap_kern_info = { @@ -79,15 +70,15 @@ int ethertap_setup(char *str, char **mac_out, void *data) *init = ((struct ethertap_init) { .dev_name = NULL, .gate_addr = NULL }); - if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, + if (tap_setup_common(str, "ethertap", &init->dev_name, mac_out, &init->gate_addr)) - return(0); - if(init->dev_name == NULL){ - printk("ethertap_setup : Missing tap device name\n"); - return(0); + return 0; + if (init->dev_name == NULL) { + printk(KERN_ERR "ethertap_setup : Missing tap device name\n"); + return 0; } - return(1); + return 1; } static struct transport ethertap_transport = { @@ -97,6 +88,7 @@ static struct transport ethertap_transport = { .user = ðertap_user_info, .kern = ðertap_kern_info, .private_size = sizeof(struct ethertap_data), + .setup_size = sizeof(struct ethertap_init), }; static int register_ethertap(void) diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 61d3953c7ac..4ff55360344 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. @@ -7,20 +8,16 @@ #include <stdio.h> #include <unistd.h> -#include <stddef.h> -#include <stdlib.h> -#include <sys/errno.h> +#include <errno.h> +#include <string.h> #include <sys/socket.h> #include <sys/wait.h> -#include <sys/un.h> -#include <net/if.h> -#include "user.h" -#include "kern_util.h" -#include "net_user.h" #include "etap.h" +#include "kern_constants.h" #include "os.h" +#include "net_user.h" #include "um_malloc.h" -#include "kern_constants.h" +#include "user.h" #define MAX_PACKET ETH_MAX_PACKET @@ -49,16 +46,18 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, memcpy(change.addr, addr, sizeof(change.addr)); memcpy(change.netmask, netmask, sizeof(change.netmask)); CATCH_EINTR(n = write(fd, &change, sizeof(change))); - if(n != sizeof(change)){ - printk("etap_change - request failed, err = %d\n", errno); + if (n != sizeof(change)) { + printk(UM_KERN_ERR "etap_change - request failed, err = %d\n", + errno); return; } output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); - if(output == NULL) - printk("etap_change : Failed to allocate output buffer\n"); + if (output == NULL) + printk(UM_KERN_ERR "etap_change : Failed to allocate output " + "buffer\n"); read_output(fd, output, UM_KERN_PAGE_SIZE); - if(output != NULL){ + if (output != NULL) { printk("%s", output); kfree(output); } @@ -87,11 +86,11 @@ static void etap_pre_exec(void *arg) struct etap_pre_exec_data *data = arg; dup2(data->control_remote, 1); - os_close_file(data->data_me); - os_close_file(data->control_me); + close(data->data_me); + close(data->control_me); } -static int etap_tramp(char *dev, char *gate, int control_me, +static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; @@ -101,13 +100,13 @@ static int etap_tramp(char *dev, char *gate, int control_me, char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, gate_buf, NULL }; - char *nosetup_args[] = { "uml_net", version_buf, "ethertap", + char *nosetup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, NULL }; char **args, c; sprintf(data_fd_buf, "%d", data_remote); sprintf(version_buf, "%d", UML_NET_VERSION); - if(gate != NULL){ + if (gate != NULL) { strcpy(gate_buf, gate); args = setup_args; } @@ -119,24 +118,26 @@ static int etap_tramp(char *dev, char *gate, int control_me, pe_data.data_me = data_me; pid = run_helper(etap_pre_exec, &pe_data, args); - if(pid < 0) + if (pid < 0) err = pid; - os_close_file(data_remote); - os_close_file(control_remote); + close(data_remote); + close(control_remote); CATCH_EINTR(n = read(control_me, &c, sizeof(c))); - if(n != sizeof(c)){ + if (n != sizeof(c)) { err = -errno; - printk("etap_tramp : read of status failed, err = %d\n", -err); + printk(UM_KERN_ERR "etap_tramp : read of status failed, " + "err = %d\n", -err); return err; } - if(c != 1){ - printk("etap_tramp : uml_net failed\n"); + if (c != 1) { + printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); err = -EINVAL; CATCH_EINTR(n = waitpid(pid, &status, 0)); - if(n < 0) + if (n < 0) err = -errno; - else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) - printk("uml_net didn't exit with status 1\n"); + else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) + printk(UM_KERN_ERR "uml_net didn't exit with " + "status 1\n"); } return err; } @@ -148,43 +149,56 @@ static int etap_open(void *data) int data_fds[2], control_fds[2], err, output_len; err = tap_open_common(pri->dev, pri->gate_addr); - if(err) + if (err) return err; - err = os_pipe(data_fds, 0, 0); - if(err < 0){ - printk("data os_pipe failed - err = %d\n", -err); + err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "etap_open - data socketpair failed - " + "err = %d\n", errno); return err; } - err = os_pipe(control_fds, 1, 0); - if(err < 0){ - printk("control os_pipe failed - err = %d\n", -err); - return err; + err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "etap_open - control socketpair failed - " + "err = %d\n", errno); + goto out_close_data; } - err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], + err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], control_fds[1], data_fds[0], data_fds[1]); output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); read_output(control_fds[0], output, output_len); - if(output == NULL) - printk("etap_open : failed to allocate output buffer\n"); + if (output == NULL) + printk(UM_KERN_ERR "etap_open : failed to allocate output " + "buffer\n"); else { printk("%s", output); kfree(output); } - if(err < 0){ - printk("etap_tramp failed - err = %d\n", -err); - return err; + if (err < 0) { + printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err); + goto out_close_control; } pri->data_fd = data_fds[0]; pri->control_fd = control_fds[0]; iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); return data_fds[0]; + +out_close_control: + close(control_fds[0]); + close(control_fds[1]); +out_close_data: + close(data_fds[0]); + close(data_fds[1]); + return err; } static void etap_close(int fd, void *data) @@ -192,37 +206,41 @@ static void etap_close(int fd, void *data) struct ethertap_data *pri = data; iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); - os_close_file(fd); - os_shutdown_socket(pri->data_fd, 1, 1); - os_close_file(pri->data_fd); + close(fd); + + if (shutdown(pri->data_fd, SHUT_RDWR) < 0) + printk(UM_KERN_ERR "etap_close - shutdown data socket failed, " + "errno = %d\n", errno); + + if (shutdown(pri->control_fd, SHUT_RDWR) < 0) + printk(UM_KERN_ERR "etap_close - shutdown control socket " + "failed, errno = %d\n", errno); + + close(pri->data_fd); pri->data_fd = -1; - os_close_file(pri->control_fd); + close(pri->control_fd); pri->control_fd = -1; } -static int etap_set_mtu(int mtu, void *data) -{ - return mtu; -} - static void etap_add_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if(pri->control_fd == -1) + if (pri->control_fd == -1) return; etap_open_addr(addr, netmask, &pri->control_fd); } -static void etap_del_addr(unsigned char *addr, unsigned char *netmask, +static void etap_del_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; - if(pri->control_fd == -1) + if (pri->control_fd == -1) return; + etap_close_addr(addr, netmask, &pri->control_fd); } @@ -231,8 +249,8 @@ const struct net_user_info ethertap_user_info = { .open = etap_open, .close = etap_close, .remove = NULL, - .set_mtu = etap_set_mtu, .add_address = etap_add_addr, .delete_address = etap_del_addr, - .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_ETHERTAP, }; diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h index d3e8d3af624..f17c31586c8 100644 --- a/arch/um/os-Linux/drivers/tuntap.h +++ b/arch/um/os-Linux/drivers/tuntap.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -19,14 +19,3 @@ struct tuntap_data { extern const struct net_user_info tuntap_user_info; #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index f1714e7fb1d..9d384807b07 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -1,16 +1,13 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" -#include "linux/skbuff.h" -#include "linux/init.h" -#include "asm/errno.h" +#include <linux/netdevice.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <asm/errno.h> #include "net_kern.h" -#include "net_user.h" #include "tuntap.h" struct tuntap_init { @@ -38,19 +35,15 @@ static void tuntap_init(struct net_device *dev, void *data) printk("\n"); } -static int tuntap_read(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if(*skb == NULL) return(-ENOMEM); - return(net_read(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + ETH_HEADER_OTHER)); + return net_read(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); } -static int tuntap_write(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int tuntap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(net_write(fd, (*skb)->data, (*skb)->len)); + return net_write(fd, skb->data, skb->len); } const struct net_kern_info tuntap_kern_info = { @@ -67,11 +60,11 @@ int tuntap_setup(char *str, char **mac_out, void *data) *init = ((struct tuntap_init) { .dev_name = NULL, .gate_addr = NULL }); - if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, + if (tap_setup_common(str, "tuntap", &init->dev_name, mac_out, &init->gate_addr)) - return(0); + return 0; - return(1); + return 1; } static struct transport tuntap_transport = { diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index f848b4ea934..6c55d3c8ead 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -1,27 +1,22 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <stdio.h> -#include <stddef.h> -#include <stdlib.h> #include <unistd.h> #include <errno.h> -#include <sys/wait.h> +#include <string.h> +#include <linux/if_tun.h> +#include <net/if.h> +#include <sys/ioctl.h> #include <sys/socket.h> -#include <sys/un.h> +#include <sys/wait.h> #include <sys/uio.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <linux/if_tun.h> -#include "net_user.h" +#include "kern_constants.h" +#include "os.h" #include "tuntap.h" -#include "kern_util.h" #include "user.h" -#include "os.h" - -#define MAX_PACKET ETH_MAX_PACKET static int tuntap_user_init(void *data, void *dev) { @@ -37,7 +32,7 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, struct tuntap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if((pri->fd == -1) || pri->fixed_config) + if ((pri->fd == -1) || pri->fixed_config) return; open_addr(addr, netmask, pri->dev_name); } @@ -47,7 +42,7 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, { struct tuntap_data *pri = data; - if((pri->fd == -1) || pri->fixed_config) + if ((pri->fd == -1) || pri->fixed_config) return; close_addr(addr, netmask, pri->dev_name); } @@ -62,7 +57,7 @@ static void tuntap_pre_exec(void *arg) struct tuntap_pre_exec_data *data = arg; dup2(data->stdout, 1); - os_close_file(data->close_me); + close(data->close_me); } static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, @@ -85,14 +80,14 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, pid = run_helper(tuntap_pre_exec, &data, argv); - if(pid < 0) + if (pid < 0) return -pid; - os_close_file(remote); + close(remote); msg.msg_name = NULL; msg.msg_namelen = 0; - if(buffer != NULL){ + if (buffer != NULL) { iov = ((struct iovec) { buffer, buffer_len }); msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -106,26 +101,28 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, msg.msg_flags = 0; n = recvmsg(me, &msg, 0); *used_out = n; - if(n < 0){ + if (n < 0) { err = -errno; - printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", - errno); + printk(UM_KERN_ERR "tuntap_open_tramp : recvmsg failed - " + "errno = %d\n", errno); return err; } CATCH_EINTR(waitpid(pid, NULL, 0)); cmsg = CMSG_FIRSTHDR(&msg); - if(cmsg == NULL){ - printk("tuntap_open_tramp : didn't receive a message\n"); + if (cmsg == NULL) { + printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " + "message\n"); return -EINVAL; } - if((cmsg->cmsg_level != SOL_SOCKET) || - (cmsg->cmsg_type != SCM_RIGHTS)){ - printk("tuntap_open_tramp : didn't receive a descriptor\n"); + if ((cmsg->cmsg_level != SOL_SOCKET) || + (cmsg->cmsg_type != SCM_RIGHTS)) { + printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " + "descriptor\n"); return -EINVAL; } *fd_out = ((int *) CMSG_DATA(cmsg))[0]; - os_set_exec_close(*fd_out, 1); + os_set_exec_close(*fd_out); return 0; } @@ -137,47 +134,51 @@ static int tuntap_open(void *data) int err, fds[2], len, used; err = tap_open_common(pri->dev, pri->gate_addr); - if(err < 0) + if (err < 0) return err; - if(pri->fixed_config){ + if (pri->fixed_config) { pri->fd = os_open_file("/dev/net/tun", of_cloexec(of_rdwr(OPENFLAGS())), 0); - if(pri->fd < 0){ - printk("Failed to open /dev/net/tun, err = %d\n", - -pri->fd); + if (pri->fd < 0) { + printk(UM_KERN_ERR "Failed to open /dev/net/tun, " + "err = %d\n", -pri->fd); return pri->fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); - if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ + if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) { err = -errno; - printk("TUNSETIFF failed, errno = %d\n", errno); - os_close_file(pri->fd); + printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", + errno); + close(pri->fd); return err; } } else { - err = os_pipe(fds, 0, 0); - if(err < 0){ - printk("tuntap_open : os_pipe failed - err = %d\n", - -err); + err = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "tuntap_open : socketpair failed - " + "errno = %d\n", errno); return err; } buffer = get_output_buffer(&len); - if(buffer != NULL) len--; + if (buffer != NULL) + len--; used = 0; err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], fds[1], buffer, len, &used); output = buffer; - if(err < 0) { + if (err < 0) { printk("%s", output); free_output_buffer(buffer); - printk("tuntap_open_tramp failed - err = %d\n", -err); + printk(UM_KERN_ERR "tuntap_open_tramp failed - " + "err = %d\n", -err); return err; } @@ -186,7 +187,7 @@ static int tuntap_open(void *data) printk("%s", output); free_output_buffer(buffer); - os_close_file(fds[0]); + close(fds[0]); iter_addresses(pri->dev, open_addr, pri->dev_name); } @@ -197,24 +198,19 @@ static void tuntap_close(int fd, void *data) { struct tuntap_data *pri = data; - if(!pri->fixed_config) + if (!pri->fixed_config) iter_addresses(pri->dev, close_addr, pri->dev_name); - os_close_file(fd); + close(fd); pri->fd = -1; } -static int tuntap_set_mtu(int mtu, void *data) -{ - return mtu; -} - const struct net_user_info tuntap_user_info = { .init = tuntap_user_init, .open = tuntap_open, .close = tuntap_close, .remove = NULL, - .set_mtu = tuntap_set_mtu, .add_address = tuntap_add_addr, .delete_address = tuntap_del_addr, - .max_packet = MAX_PACKET + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, }; diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index c3ecc2a84e0..b542a3a021b 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -82,13 +82,6 @@ int os_access(const char* file, int mode) return 0; } -void os_print_error(int error, const char* str) -{ - errno = error < 0 ? -error : error; - - perror(str); -} - /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) { @@ -101,30 +94,6 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) return err; } -int os_window_size(int fd, int *rows, int *cols) -{ - struct winsize size; - - if(ioctl(fd, TIOCGWINSZ, &size) < 0) - return -errno; - - *rows = size.ws_row; - *cols = size.ws_col; - - return 0; -} - -int os_new_tty_pgrp(int fd, int pid) -{ - if(ioctl(fd, TIOCSCTTY, 0) < 0) - return -errno; - - if(tcsetpgrp(fd, pid) < 0) - return -errno; - - return 0; -} - /* FIXME: ensure namebuf in os_get_if_name is big enough */ int os_get_ifname(int fd, char* namebuf) { @@ -205,19 +174,19 @@ int os_file_mode(char *file, struct openflags *mode_out) *mode_out = OPENFLAGS(); - err = os_access(file, OS_ACC_W_OK); - if((err < 0) && (err != -EACCES)) - return(err); - - *mode_out = of_write(*mode_out); - - err = os_access(file, OS_ACC_R_OK); - if((err < 0) && (err != -EACCES)) - return(err); + err = access(file, W_OK); + if(err && (errno != EACCES)) + return -errno; + else if(!err) + *mode_out = of_write(*mode_out); - *mode_out = of_read(*mode_out); + err = access(file, R_OK); + if(err && (errno != EACCES)) + return -errno; + else if(!err) + *mode_out = of_read(*mode_out); - return(0); + return err; } int os_open_file(char *file, struct openflags flags, int mode) @@ -236,15 +205,15 @@ int os_open_file(char *file, struct openflags flags, int mode) fd = open64(file, f, mode); if(fd < 0) - return(-errno); + return -errno; if(flags.cl && fcntl(fd, F_SETFD, 1)){ err = -errno; - os_close_file(fd); + close(fd); return err; } - return(fd); + return fd; } int os_connect_socket(char *name) @@ -280,9 +249,9 @@ void os_close_file(int fd) close(fd); } -int os_seek_file(int fd, __u64 offset) +int os_seek_file(int fd, unsigned long long offset) { - __u64 actual; + unsigned long long actual; actual = lseek64(fd, offset, SEEK_SET); if(actual != offset) @@ -316,31 +285,33 @@ int os_file_size(char *file, unsigned long long *size_out) err = os_stat_file(file, &buf); if(err < 0){ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); - return(err); + return err; } if(S_ISBLK(buf.ust_mode)){ int fd; long blocks; - fd = os_open_file(file, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Couldn't open \"%s\", errno = %d\n", file, -fd); - return(fd); + fd = open(file, O_RDONLY, 0); + if(fd < 0) { + err = -errno; + printk("Couldn't open \"%s\", errno = %d\n", file, + errno); + return err; } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ err = -errno; printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - os_close_file(fd); - return(err); + close(fd); + return err; } *size_out = ((long long) blocks) * 512; - os_close_file(fd); - return(0); + close(fd); } - *size_out = buf.ust_size; - return(0); + else *size_out = buf.ust_size; + + return 0; } int os_file_modtime(char *file, unsigned long *modtime) @@ -358,35 +329,28 @@ int os_file_modtime(char *file, unsigned long *modtime) return 0; } -int os_get_exec_close(int fd, int* close_on_exec) +int os_get_exec_close(int fd, int *close_on_exec) { int ret; - do { - ret = fcntl(fd, F_GETFD); - } while((ret < 0) && (errno == EINTR)) ; + CATCH_EINTR(ret = fcntl(fd, F_GETFD)); if(ret < 0) - return(-errno); + return -errno; - *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; - return(ret); + *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0; + return ret; } -int os_set_exec_close(int fd, int close_on_exec) +int os_set_exec_close(int fd) { - int flag, err; - - if(close_on_exec) flag = FD_CLOEXEC; - else flag = 0; + int err; - do { - err = fcntl(fd, F_SETFD, flag); - } while((err < 0) && (errno == EINTR)) ; + CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC)); if(err < 0) - return(-errno); - return(err); + return -errno; + return err; } int os_pipe(int *fds, int stream, int close_on_exec) @@ -395,16 +359,16 @@ int os_pipe(int *fds, int stream, int close_on_exec) err = socketpair(AF_UNIX, type, 0, fds); if(err < 0) - return(-errno); + return -errno; if(!close_on_exec) - return(0); + return 0; - err = os_set_exec_close(fds[0], 1); + err = os_set_exec_close(fds[0]); if(err < 0) goto error; - err = os_set_exec_close(fds[1], 1); + err = os_set_exec_close(fds[1]); if(err < 0) goto error; @@ -412,9 +376,9 @@ int os_pipe(int *fds, int stream, int close_on_exec) error: printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); - os_close_file(fds[1]); - os_close_file(fds[0]); - return(err); + close(fds[1]); + close(fds[0]); + return err; } int os_set_fd_async(int fd, int owner) @@ -561,7 +525,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) return -errno; if(close_on_exec) { - err = os_set_exec_close(sock, 1); + err = os_set_exec_close(sock); if(err < 0) printk("create_unix_socket : close_on_exec failed, " "err = %d", -err); diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index d81af7b8587..7a72dbb61b0 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -11,6 +11,7 @@ #include <limits.h> #include <sys/signal.h> #include <sys/wait.h> +#include <sys/socket.h> #include "user.h" #include "kern_util.h" #include "os.h" @@ -54,13 +55,14 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) if (stack == 0) return -ENOMEM; - ret = os_pipe(fds, 1, 0); + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); if (ret < 0) { - printk("run_helper : pipe failed, ret = %d\n", -ret); + ret = -errno; + printk("run_helper : pipe failed, errno = %d\n", errno); goto out_free; } - ret = os_set_exec_close(fds[1], 1); + ret = os_set_exec_close(fds[1]); if (ret < 0) { printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", -ret); diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index a633fa8e0a9..6aa6f95d652 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -145,11 +145,7 @@ void init_irq_signals(int on_sigstack) flags = on_sigstack ? SA_ONSTACK : 0; - set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, - flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); - set_handler(SIGALRM, (__sighandler_t) alarm_handler, - flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); signal(SIGWINCH, SIG_IGN); } diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index e85f4995a01..82c3778627b 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -1,33 +1,21 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <unistd.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <signal.h> +#include <unistd.h> #include <errno.h> +#include <signal.h> +#include <string.h> #include <sys/resource.h> -#include <sys/mman.h> -#include <sys/user.h> -#include <asm/page.h> -#include "kern_util.h" #include "as-layout.h" -#include "mem_user.h" -#include "irq_user.h" -#include "user.h" #include "init.h" -#include "mode.h" -#include "choose-mode.h" -#include "uml-config.h" +#include "kern_constants.h" +#include "kern_util.h" #include "os.h" #include "um_malloc.h" -#include "kern_constants.h" - -/* Set in main, unchanged thereafter */ -char *linux_prog; #define PGD_BOUND (4 * 1024 * 1024) #define STACKSIZE (8 * 1024 * 1024) @@ -37,13 +25,13 @@ static void set_stklim(void) { struct rlimit lim; - if(getrlimit(RLIMIT_STACK, &lim) < 0){ + if (getrlimit(RLIMIT_STACK, &lim) < 0) { perror("getrlimit"); exit(1); } - if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ + if ((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)) { lim.rlim_cur = STACKSIZE; - if(setrlimit(RLIMIT_STACK, &lim) < 0){ + if (setrlimit(RLIMIT_STACK, &lim) < 0) { perror("setrlimit"); exit(1); } @@ -55,7 +43,7 @@ static __init void do_uml_initcalls(void) initcall_t *call; call = &__uml_initcall_start; - while (call < &__uml_initcall_end){ + while (call < &__uml_initcall_end) { (*call)(); call++; } @@ -74,7 +62,8 @@ static void install_fatal_handler(int sig) /* All signals are enabled in this handler ... */ sigemptyset(&action.sa_mask); - /* ... including the signal being handled, plus we want the + /* + * ... including the signal being handled, plus we want the * handler reset to the default behavior, so that if an exit * handler is hanging for some reason, the UML will just die * after this signal is sent a second time. @@ -82,7 +71,7 @@ static void install_fatal_handler(int sig) action.sa_flags = SA_RESETHAND | SA_NODEFER; action.sa_restorer = NULL; action.sa_handler = last_ditch_exit; - if(sigaction(sig, &action, NULL) < 0){ + if (sigaction(sig, &action, NULL) < 0) { printf("failed to install handler for signal %d - errno = %d\n", errno); exit(1); @@ -98,7 +87,8 @@ static void setup_env_path(void) int path_len = 0; old_path = getenv("PATH"); - /* if no PATH variable is set or it has an empty value + /* + * if no PATH variable is set or it has an empty value * just use the default + /usr/lib/uml */ if (!old_path || (path_len = strlen(old_path)) == 0) { @@ -126,93 +116,68 @@ int __init main(int argc, char **argv, char **envp) char **new_argv; int ret, i, err; -#ifdef UML_CONFIG_CMDLINE_ON_HOST - /* Allocate memory for thread command lines */ - if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ - - char padding[THREAD_NAME_LEN] = { - [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' - }; - - new_argv = malloc((argc + 2) * sizeof(char*)); - if(!new_argv) { - perror("Allocating extended argv"); - exit(1); - } - - new_argv[0] = argv[0]; - new_argv[1] = padding; - - for(i = 2; i <= argc; i++) - new_argv[i] = argv[i - 1]; - new_argv[argc + 1] = NULL; - - execvp(new_argv[0], new_argv); - perror("execing with extended args"); - exit(1); - } -#endif - - linux_prog = argv[0]; - set_stklim(); setup_env_path(); new_argv = malloc((argc + 1) * sizeof(char *)); - if(new_argv == NULL){ + if (new_argv == NULL) { perror("Mallocing argv"); exit(1); } - for(i=0;i<argc;i++){ + for (i = 0; i < argc; i++) { new_argv[i] = strdup(argv[i]); - if(new_argv[i] == NULL){ + if (new_argv[i] == NULL) { perror("Mallocing an arg"); exit(1); } } new_argv[argc] = NULL; - /* Allow these signals to bring down a UML if all other + /* + * Allow these signals to bring down a UML if all other * methods of control fail. */ install_fatal_handler(SIGINT); install_fatal_handler(SIGTERM); install_fatal_handler(SIGHUP); - scan_elf_aux( envp); + scan_elf_aux(envp); do_uml_initcalls(); ret = linux_main(argc, argv); - /* Disable SIGPROF - I have no idea why libc doesn't do this or turn + /* + * Disable SIGPROF - I have no idea why libc doesn't do this or turn * off the profiling time, but UML dies with a SIGPROF just before * exiting when profiling is active. */ change_sig(SIGPROF, 0); - /* This signal stuff used to be in the reboot case. However, + /* + * This signal stuff used to be in the reboot case. However, * sometimes a SIGVTALRM can come in when we're halting (reproducably * when writing out gcov information, presumably because that takes * some time) and cause a segfault. */ - /* stop timers and set SIG*ALRM to be ignored */ + /* stop timers and set SIGVTALRM to be ignored */ disable_timer(); /* disable SIGIO for the fds and set SIGIO to be ignored */ err = deactivate_all_fds(); - if(err) + if (err) printf("deactivate_all_fds failed, errno = %d\n", -err); - /* Let any pending signals fire now. This ensures + /* + * Let any pending signals fire now. This ensures * that they won't be delivered after the exec, when * they are definitely not expected. */ unblock_signals(); /* Reboot */ - if(ret){ + if (ret) { printf("\n"); execvp(new_argv[0], new_argv); perror("Failed to exec kernel"); @@ -222,26 +187,24 @@ int __init main(int argc, char **argv, char **envp) return uml_exitcode; } -#define CAN_KMALLOC() \ - (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1)) - extern void *__real_malloc(int); void *__wrap_malloc(int size) { void *ret; - if(!CAN_KMALLOC()) + if (!kmalloc_ok) return __real_malloc(size); - else if(size <= UM_KERN_PAGE_SIZE) + else if (size <= UM_KERN_PAGE_SIZE) /* finding contiguous pages can be hard*/ ret = kmalloc(size, UM_GFP_KERNEL); else ret = vmalloc(size); - /* glibc people insist that if malloc fails, errno should be + /* + * glibc people insist that if malloc fails, errno should be * set by malloc as well. So we do. */ - if(ret == NULL) + if (ret == NULL) errno = ENOMEM; return ret; @@ -251,7 +214,7 @@ void *__wrap_calloc(int n, int size) { void *ptr = __wrap_malloc(n * size); - if(ptr == NULL) + if (ptr == NULL) return NULL; memset(ptr, 0, n * size); return ptr; @@ -265,7 +228,8 @@ void __wrap_free(void *ptr) { unsigned long addr = (unsigned long) ptr; - /* We need to know how the allocation happened, so it can be correctly + /* + * We need to know how the allocation happened, so it can be correctly * freed. This is done by seeing what region of memory the pointer is * in - * physical memory - kmalloc/kfree @@ -283,12 +247,12 @@ void __wrap_free(void *ptr) * there is a possibility for memory leaks. */ - if((addr >= uml_physmem) && (addr < high_physmem)){ - if(CAN_KMALLOC()) + if ((addr >= uml_physmem) && (addr < high_physmem)) { + if (kmalloc_ok) kfree(ptr); } - else if((addr >= start_vm) && (addr < end_vm)){ - if(CAN_KMALLOC()) + else if ((addr >= start_vm) && (addr < end_vm)) { + if (kmalloc_ok) vfree(ptr); } else __real_free(ptr); diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index c6378c6d10d..436f8d20b20 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -218,7 +218,7 @@ int __init create_tmp_file(unsigned long long len) err = fchmod(fd, 0777); if(err < 0){ - perror("os_mode_fd"); + perror("fchmod"); exit(1); } @@ -226,7 +226,7 @@ int __init create_tmp_file(unsigned long long len) * increase the file size by one byte, to the desired length. */ if (lseek64(fd, len - 1, SEEK_SET) < 0) { - perror("os_seek_file"); + perror("lseek64"); exit(1); } @@ -247,7 +247,7 @@ int __init create_mem_file(unsigned long long len) fd = create_tmp_file(len); - err = os_set_exec_close(fd, 1); + err = os_set_exec_close(fd); if(err < 0){ errno = -err; perror("exec_close"); diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index e9c14329751..37781db4cec 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -1,27 +1,24 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <unistd.h> #include <stdio.h> +#include <unistd.h> #include <errno.h> #include <signal.h> +#include <fcntl.h> #include <sys/mman.h> +#include <sys/ptrace.h> #include <sys/wait.h> -#include <sys/mman.h> -#include <sys/syscall.h> -#include "ptrace_user.h" +#include <asm/unistd.h> +#include "init.h" +#include "kern_constants.h" +#include "longjmp.h" #include "os.h" -#include "user.h" #include "process.h" -#include "irq_user.h" -#include "kern_util.h" -#include "longjmp.h" #include "skas_ptrace.h" -#include "kern_constants.h" -#include "uml-config.h" -#include "init.h" +#include "user.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -32,30 +29,32 @@ unsigned long os_process_pc(int pid) { char proc_stat[STAT_PATH_LEN], buf[256]; - unsigned long pc; + unsigned long pc = ARBITRARY_ADDR; int fd, err; sprintf(proc_stat, "/proc/%d/stat", pid); - fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("os_process_pc - couldn't open '%s', err = %d\n", - proc_stat, -fd); - return ARBITRARY_ADDR; + fd = open(proc_stat, O_RDONLY, 0); + if (fd < 0) { + printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', " + "errno = %d\n", proc_stat, errno); + goto out; } CATCH_EINTR(err = read(fd, buf, sizeof(buf))); - if(err < 0){ - printk("os_process_pc - couldn't read '%s', err = %d\n", - proc_stat, errno); - os_close_file(fd); - return ARBITRARY_ADDR; + if (err < 0) { + printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', " + "err = %d\n", proc_stat, errno); + goto out_close; } os_close_file(fd); pc = ARBITRARY_ADDR; - if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %*d %lu", &pc) != 1){ - printk("os_process_pc - couldn't find pc in '%s'\n", buf); - } + if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " + "%*d %*d %*d %*d %*d %lu", &pc) != 1) + printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n", + buf); + out_close: + close(fd); + out: return pc; } @@ -63,30 +62,32 @@ int os_process_parent(int pid) { char stat[STAT_PATH_LEN]; char data[256]; - int parent, n, fd; + int parent = FAILURE_PID, n, fd; - if(pid == -1) - return -1; + if (pid == -1) + return parent; snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); - fd = os_open_file(stat, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Couldn't open '%s', err = %d\n", stat, -fd); - return FAILURE_PID; + fd = open(stat, O_RDONLY, 0); + if (fd < 0) { + printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat, + errno); + return parent; } CATCH_EINTR(n = read(fd, data, sizeof(data))); - os_close_file(fd); + close(fd); - if(n < 0){ - printk("Couldn't read '%s', err = %d\n", stat, errno); - return FAILURE_PID; + if (n < 0) { + printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat, + errno); + return parent; } parent = FAILURE_PID; n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); - if(n != 1) - printk("Failed to scan '%s'\n", data); + if (n != 1) + printk(UM_KERN_ERR "Failed to scan '%s'\n", data); return parent; } @@ -99,9 +100,8 @@ void os_stop_process(int pid) void os_kill_process(int pid, int reap_child) { kill(pid, SIGKILL); - if(reap_child) + if (reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); - } /* This is here uniquely to have access to the userspace errno, i.e. the one @@ -129,17 +129,10 @@ void os_kill_ptraced_process(int pid, int reap_child) kill(pid, SIGKILL); ptrace(PTRACE_KILL, pid); ptrace(PTRACE_CONT, pid); - if(reap_child) + if (reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); } -#ifdef UML_CONFIG_MODE_TT -void os_usr1_process(int pid) -{ - kill(pid, SIGUSR1); -} -#endif - /* Don't use the glibc version, which caches the result in TLS. It misses some * syscalls, and also breaks with clone(), which does not unshare the TLS. */ @@ -160,34 +153,35 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, void *loc; int prot; - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, fd, off); - if(loc == MAP_FAILED) + if (loc == MAP_FAILED) return -errno; return 0; } int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) { - int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0)); - if(mprotect(addr, len, prot) < 0) + if (mprotect(addr, len, prot) < 0) return -errno; - return 0; + + return 0; } int os_unmap_memory(void *addr, int len) { - int err; + int err; - err = munmap(addr, len); - if(err < 0) + err = munmap(addr, len); + if (err < 0) return -errno; - return 0; + return 0; } #ifndef MADV_REMOVE @@ -199,7 +193,7 @@ int os_drop_memory(void *addr, int length) int err; err = madvise(addr, length, MADV_REMOVE); - if(err < 0) + if (err < 0) err = -errno; return err; } @@ -209,22 +203,24 @@ int __init can_drop_memory(void) void *addr; int fd, ok = 0; - printk("Checking host MADV_REMOVE support..."); + printk(UM_KERN_INFO "Checking host MADV_REMOVE support..."); fd = create_mem_file(UM_KERN_PAGE_SIZE); - if(fd < 0){ - printk("Creating test memory file failed, err = %d\n", -fd); + if (fd < 0) { + printk(UM_KERN_ERR "Creating test memory file failed, " + "err = %d\n", -fd); goto out; } addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if(addr == MAP_FAILED){ - printk("Mapping test memory file failed, err = %d\n", -errno); + if (addr == MAP_FAILED) { + printk(UM_KERN_ERR "Mapping test memory file failed, " + "err = %d\n", -errno); goto out_close; } - if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){ - printk("MADV_REMOVE failed, err = %d\n", -errno); + if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) { + printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno); goto out_unmap; } @@ -239,58 +235,31 @@ out: return ok; } -#ifdef UML_CONFIG_MODE_TT -void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) -{ - int flags = 0, pages; - - if(sig_stack != NULL){ - pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); - set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE); - flags = SA_ONSTACK; - } - if(usr1_handler){ - struct sigaction sa; - - sa.sa_handler = usr1_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = flags; - sa.sa_restorer = NULL; - if(sigaction(SIGUSR1, &sa, NULL) < 0) - panic("init_new_thread_stack - sigaction failed - " - "errno = %d\n", errno); - } -} -#endif - void init_new_thread_signals(void) { set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); - set_handler(SIGUSR2, (__sighandler_t) sig_handler, - SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, - -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); signal(SIGHUP, SIG_IGN); init_irq_signals(1); } -int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) +int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) { jmp_buf buf; int n; *jmp_ptr = &buf; n = UML_SETJMP(&buf); - if(n != 0) + if (n != 0) return n; (*fn)(arg); return 0; diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c new file mode 100644 index 00000000000..a32ba6ab121 --- /dev/null +++ b/arch/um/os-Linux/registers.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + +#include <errno.h> +#include <string.h> +#include <sys/ptrace.h> +#include "sysdep/ptrace.h" +#include "user.h" + +/* This is set once at boot time and not changed thereafter */ + +static unsigned long exec_regs[MAX_REG_NR]; + +void init_thread_registers(struct uml_pt_regs *to) +{ + memcpy(to->gp, exec_regs, sizeof(to->gp)); +} + +void save_registers(int pid, struct uml_pt_regs *regs) +{ + int err; + + err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); + if (err < 0) + panic("save_registers - saving registers failed, errno = %d\n", + errno); +} + +void restore_registers(int pid, struct uml_pt_regs *regs) +{ + int err; + + err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp); + if (err < 0) + panic("restore_registers - saving registers failed, " + "errno = %d\n", errno); +} + +void init_registers(int pid) +{ + int err; + + err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); + if (err) + panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", + errno); + + arch_init_registers(pid); +} + +void get_safe_registers(unsigned long *regs) +{ + memcpy(regs, exec_regs, sizeof(exec_regs)); +} diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index b98f7ea2d2f..e9800b0b568 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -1,26 +1,21 @@ /* * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> -#include <stdio.h> -#include <unistd.h> #include <stdlib.h> -#include <errno.h> #include <stdarg.h> -#include <string.h> -#include <sys/mman.h> -#include "user.h" -#include "signal_kern.h" -#include "sysdep/sigcontext.h" -#include "sysdep/barrier.h" -#include "sigcontext.h" -#include "mode.h" +#include <errno.h> +#include <signal.h> +#include <strings.h> #include "os.h" +#include "sysdep/barrier.h" +#include "sysdep/sigcontext.h" +#include "user.h" -/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled - * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to +/* + * These are the asynchronous signals. SIGPROF is excluded because we want to * be able to profile all of UML, not just the non-critical sections. If * profiling is not thread-safe, then that is not my problem. We can disable * profiling when SMP is enabled in that case. @@ -31,10 +26,8 @@ #define SIGVTALRM_BIT 1 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) -#define SIGALRM_BIT 2 -#define SIGALRM_MASK (1 << SIGALRM_BIT) - -/* These are used by both the signal handlers and +/* + * These are used by both the signal handlers and * block/unblock_signals. I don't want modifications cached in a * register - they must go straight to memory. */ @@ -46,34 +39,27 @@ void sig_handler(int sig, struct sigcontext *sc) int enabled; enabled = signals_enabled; - if(!enabled && (sig == SIGIO)){ + if (!enabled && (sig == SIGIO)) { pending |= SIGIO_MASK; return; } block_signals(); - CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, - sig, sc); + sig_handler_common_skas(sig, sc); set_signals(enabled); } -static void real_alarm_handler(int sig, struct sigcontext *sc) +static void real_alarm_handler(struct sigcontext *sc) { - union uml_pt_regs regs; + struct uml_pt_regs regs; - if(sig == SIGALRM) - switch_timers(0); - - if(sc != NULL) + if (sc != NULL) copy_sc(®s, sc); - regs.skas.is_user = 0; + regs.is_user = 0; unblock_signals(); - timer_handler(sig, ®s); - - if(sig == SIGALRM) - switch_timers(1); + timer_handler(SIGVTALRM, ®s); } void alarm_handler(int sig, struct sigcontext *sc) @@ -81,27 +67,30 @@ void alarm_handler(int sig, struct sigcontext *sc) int enabled; enabled = signals_enabled; - if(!signals_enabled){ - if(sig == SIGVTALRM) - pending |= SIGVTALRM_MASK; - else pending |= SIGALRM_MASK; - + if (!signals_enabled) { + pending |= SIGVTALRM_MASK; return; } block_signals(); - real_alarm_handler(sig, sc); + real_alarm_handler(sc); set_signals(enabled); } +void timer_init(void) +{ + set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); +} + void set_sigstack(void *sig_stack, int size) { stack_t stack = ((stack_t) { .ss_flags = 0, .ss_sp = (__ptr_t) sig_stack, .ss_size = size - sizeof(void *) }); - if(sigaltstack(&stack, NULL) != 0) + if (sigaltstack(&stack, NULL) != 0) panic("enabling signal stack failed, errno = %d\n", errno); } @@ -111,7 +100,7 @@ void remove_sigstack(void) .ss_sp = NULL, .ss_size = 0 }); - if(sigaltstack(&stack, NULL) != 0) + if (sigaltstack(&stack, NULL) != 0) panic("disabling signal stack failed, errno = %d\n", errno); } @@ -135,26 +124,27 @@ void handle_signal(int sig, struct sigcontext *sc) * with this interrupt. */ bail = to_irq_stack(&pending); - if(bail) + if (bail) return; nested = pending & 1; pending &= ~1; - while((sig = ffs(pending)) != 0){ + while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); (*handlers[sig])(sig, sc); } - /* Again, pending comes back with a mask of signals + /* + * Again, pending comes back with a mask of signals * that arrived while tearing down the stack. If this * is non-zero, we just go back, set up the stack * again, and handle the new interrupts. */ - if(!nested) + if (!nested) pending = from_irq_stack(nested); - } while(pending); + } while (pending); } extern void hard_handler(int sig); @@ -172,18 +162,18 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) sigemptyset(&action.sa_mask); va_start(ap, flags); - while((mask = va_arg(ap, int)) != -1) + while ((mask = va_arg(ap, int)) != -1) sigaddset(&action.sa_mask, mask); va_end(ap); action.sa_flags = flags; action.sa_restorer = NULL; - if(sigaction(sig, &action, NULL) < 0) + if (sigaction(sig, &action, NULL) < 0) panic("sigaction failed - errno = %d\n", errno); sigemptyset(&sig_mask); sigaddset(&sig_mask, sig); - if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) + if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) panic("sigprocmask failed - errno = %d\n", errno); } @@ -194,13 +184,14 @@ int change_sig(int signal, int on) sigemptyset(&sigset); sigaddset(&sigset, signal); sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return(!sigismember(&old, signal)); + return !sigismember(&old, signal); } void block_signals(void) { signals_enabled = 0; - /* This must return with signals disabled, so this barrier + /* + * This must return with signals disabled, so this barrier * ensures that writes are flushed out before the return. * This might matter if gcc figures out how to inline this and * decides to shuffle this code into the caller. @@ -212,27 +203,31 @@ void unblock_signals(void) { int save_pending; - if(signals_enabled == 1) + if (signals_enabled == 1) return; - /* We loop because the IRQ handler returns with interrupts off. So, + /* + * We loop because the IRQ handler returns with interrupts off. So, * interrupts may have arrived and we need to re-enable them and * recheck pending. */ - while(1){ - /* Save and reset save_pending after enabling signals. This + while(1) { + /* + * Save and reset save_pending after enabling signals. This * way, pending won't be changed while we're reading it. */ signals_enabled = 1; - /* Setting signals_enabled and reading pending must + /* + * Setting signals_enabled and reading pending must * happen in this order. */ mb(); save_pending = pending; - if(save_pending == 0){ - /* This must return with signals enabled, so + if (save_pending == 0) { + /* + * This must return with signals enabled, so * this barrier ensures that writes are * flushed out before the return. This might * matter if gcc figures out how to inline @@ -245,26 +240,24 @@ void unblock_signals(void) pending = 0; - /* We have pending interrupts, so disable signals, as the + /* + * We have pending interrupts, so disable signals, as the * handlers expect them off when they are called. They will * be enabled again above. */ signals_enabled = 0; - /* Deal with SIGIO first because the alarm handler might + /* + * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. */ - if(save_pending & SIGIO_MASK) - CHOOSE_MODE_PROC(sig_handler_common_tt, - sig_handler_common_skas, SIGIO, NULL); - - if(save_pending & SIGALRM_MASK) - real_alarm_handler(SIGALRM, NULL); + if (save_pending & SIGIO_MASK) + sig_handler_common_skas(SIGIO, NULL); - if(save_pending & SIGVTALRM_MASK) - real_alarm_handler(SIGVTALRM, NULL); + if (save_pending & SIGVTALRM_MASK) + real_alarm_handler(NULL); } } @@ -276,11 +269,11 @@ int get_signals(void) int set_signals(int enable) { int ret; - if(signals_enabled == enable) + if (signals_enabled == enable) return enable; ret = signals_enabled; - if(enable) + if (enable) unblock_signals(); else block_signals(); diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 0f7df4eb903..484e68f9f7a 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -1,31 +1,26 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> +#include <stddef.h> +#include <unistd.h> #include <errno.h> #include <string.h> -#include <unistd.h> #include <sys/mman.h> -#include <sys/wait.h> -#include <asm/page.h> -#include <asm/unistd.h> -#include "mem_user.h" -#include "mem.h" -#include "skas.h" -#include "user.h" +#include "init.h" +#include "kern_constants.h" +#include "as-layout.h" +#include "mm_id.h" #include "os.h" #include "proc_mm.h" #include "ptrace_user.h" -#include "kern_util.h" -#include "task.h" #include "registers.h" -#include "uml-config.h" +#include "skas.h" +#include "user.h" #include "sysdep/ptrace.h" #include "sysdep/stub.h" -#include "init.h" -#include "kern_constants.h" +#include "uml-config.h" extern unsigned long batch_syscall_stub, __syscall_stub_start; @@ -34,7 +29,7 @@ extern void wait_stub_done(int pid); static inline unsigned long *check_init_stack(struct mm_id * mm_idp, unsigned long *stack) { - if(stack == NULL) { + if (stack == NULL) { stack = (unsigned long *) mm_idp->stack + 2; *stack = 0; } @@ -45,8 +40,8 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { - get_safe_registers(syscall_regs, NULL); - syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + get_safe_registers(syscall_regs); + syscall_regs[REGS_IP_INDEX] = STUB_CODE + ((unsigned long) &batch_syscall_stub - (unsigned long) &__syscall_stub_start); return 0; @@ -68,29 +63,30 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) unsigned long * syscall; int err, pid = mm_idp->u.pid; - if(proc_mm) + if (proc_mm) /* FIXME: Need to look up userspace_pid by cpu */ pid = userspace_pid[0]; multi_count++; n = ptrace_setregs(pid, syscall_regs); - if(n < 0){ - printk("Registers - \n"); - for(i = 0; i < MAX_REG_NR; i++) - printk("\t%d\t0x%lx\n", i, syscall_regs[i]); + if (n < 0) { + printk(UM_KERN_ERR "Registers - \n"); + for (i = 0; i < MAX_REG_NR; i++) + printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]); panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", -n); } err = ptrace(PTRACE_CONT, pid, 0, 0); - if(err) + if (err) panic("Failed to continue stub, pid = %d, errno = %d\n", pid, errno); wait_stub_done(pid); - /* When the stub stops, we find the following values on the + /* + * When the stub stops, we find the following values on the * beginning of the stack: * (long )return_value * (long )offset to failed sycall-data (0, if no error) @@ -98,26 +94,26 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) ret = *((unsigned long *) mm_idp->stack); offset = *((unsigned long *) mm_idp->stack + 1); if (offset) { - data = (unsigned long *)(mm_idp->stack + - offset - UML_CONFIG_STUB_DATA); - printk("do_syscall_stub : ret = %ld, offset = %ld, " + data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA); + printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, " "data = %p\n", ret, offset, data); syscall = (unsigned long *)((unsigned long)data + data[0]); - printk("do_syscall_stub: syscall %ld failed, return value = " - "0x%lx, expected return value = 0x%lx\n", + printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, " + "return value = 0x%lx, expected return value = 0x%lx\n", syscall[0], ret, syscall[7]); - printk(" syscall parameters: " + printk(UM_KERN_ERR " syscall parameters: " "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", syscall[1], syscall[2], syscall[3], syscall[4], syscall[5], syscall[6]); - for(n = 1; n < data[0]/sizeof(long); n++) { - if(n == 1) - printk(" additional syscall data:"); - if(n % 4 == 1) - printk("\n "); + for (n = 1; n < data[0]/sizeof(long); n++) { + if (n == 1) + printk(UM_KERN_ERR " additional syscall " + "data:"); + if (n % 4 == 1) + printk("\n" UM_KERN_ERR " "); printk(" 0x%lx", data[n]); } - if(n > 1) + if (n > 1) printk("\n"); } else ret = 0; @@ -133,7 +129,7 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, { unsigned long *stack = check_init_stack(mm_idp, *addr); - if(done && *addr == NULL) + if (done && *addr == NULL) single_count++; *stack += sizeof(long); @@ -150,8 +146,8 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, *stack = 0; multi_op_count++; - if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < - UM_KERN_PAGE_SIZE - 10 * sizeof(long))){ + if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < + UM_KERN_PAGE_SIZE - 10 * sizeof(long))) { *addr = stack; return 0; } @@ -166,14 +162,15 @@ long syscall_stub_data(struct mm_id * mm_idp, unsigned long *stack; int ret = 0; - /* If *addr still is uninitialized, it *must* contain NULL. + /* + * If *addr still is uninitialized, it *must* contain NULL. * Thus in this case do_syscall_stub correctly won't be called. */ - if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= + if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) { ret = do_syscall_stub(mm_idp, addr); /* in case of error, don't overwrite data on stack */ - if(ret) + if (ret) return ret; } @@ -185,7 +182,7 @@ long syscall_stub_data(struct mm_id * mm_idp, memcpy(stack + 1, data, data_count * sizeof(long)); *stub_addr = (void *)(((unsigned long)(stack + 1) & - ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA); + ~UM_KERN_PAGE_MASK) + STUB_DATA); return 0; } @@ -195,7 +192,7 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, { int ret; - if(proc_mm){ + if (proc_mm) { struct proc_mm_op map; int fd = mm_idp->u.mm_fd; @@ -211,9 +208,10 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, .offset= offset } } } ); CATCH_EINTR(ret = write(fd, &map, sizeof(map))); - if(ret != sizeof(map)){ + if (ret != sizeof(map)) { ret = -errno; - printk("map : /proc/mm map failed, err = %d\n", -ret); + printk(UM_KERN_ERR "map : /proc/mm map failed, " + "err = %d\n", -ret); } else ret = 0; } @@ -234,7 +232,7 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, { int ret; - if(proc_mm){ + if (proc_mm) { struct proc_mm_op unmap; int fd = mm_idp->u.mm_fd; @@ -245,9 +243,10 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, (unsigned long) addr, .len = len } } } ); CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); - if(ret != sizeof(unmap)){ + if (ret != sizeof(unmap)) { ret = -errno; - printk("unmap - proc_mm write returned %d\n", ret); + printk(UM_KERN_ERR "unmap - proc_mm write returned " + "%d\n", ret); } else ret = 0; } @@ -268,7 +267,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, struct proc_mm_op protect; int ret; - if(proc_mm){ + if (proc_mm) { int fd = mm_idp->u.mm_fd; protect = ((struct proc_mm_op) { .op = MM_MPROTECT, @@ -280,9 +279,9 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, .prot = prot } } } ); CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); - if(ret != sizeof(protect)){ + if (ret != sizeof(protect)) { ret = -errno; - printk("protect failed, err = %d", -ret); + printk(UM_KERN_ERR "protect failed, err = %d", -ret); } else ret = 0; } @@ -295,7 +294,3 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, return ret; } - -void before_mem_skas(unsigned long unused) -{ -} diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index ba9af8d6205..d77c81d7068 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -1,48 +1,38 @@ /* - * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <stdlib.h> -#include <string.h> #include <unistd.h> -#include <errno.h> -#include <signal.h> #include <sched.h> -#include "ptrace_user.h" -#include <sys/wait.h> +#include <errno.h> +#include <string.h> #include <sys/mman.h> -#include <sys/user.h> -#include <sys/time.h> -#include <sys/syscall.h> -#include <asm/types.h> -#include "user.h" -#include "sysdep/ptrace.h" -#include "kern_util.h" -#include "skas.h" -#include "stub-data.h" -#include "mm_id.h" -#include "sysdep/sigcontext.h" -#include "sysdep/stub.h" -#include "os.h" -#include "proc_mm.h" -#include "skas_ptrace.h" +#include <sys/ptrace.h> +#include <sys/wait.h> +#include <asm/unistd.h> +#include "as-layout.h" #include "chan_user.h" -#include "registers.h" +#include "kern_constants.h" #include "mem.h" -#include "uml-config.h" +#include "os.h" #include "process.h" -#include "longjmp.h" -#include "kern_constants.h" -#include "as-layout.h" +#include "proc_mm.h" +#include "ptrace_user.h" +#include "registers.h" +#include "skas.h" +#include "skas_ptrace.h" +#include "user.h" +#include "sysdep/stub.h" int is_skas_winch(int pid, int fd, void *data) { - if(pid != os_getpgrp()) - return(0); + if (pid != getpgrp()) + return 0; register_winch_irq(-1, fd, -1, data, 0); - return(1); + return 1; } static int ptrace_dump_regs(int pid) @@ -50,13 +40,12 @@ static int ptrace_dump_regs(int pid) unsigned long regs[MAX_REG_NR]; int i; - if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) return -errno; - else { - printk("Stub registers -\n"); - for(i = 0; i < ARRAY_SIZE(regs); i++) - printk("\t%d - %lx\n", i, regs[i]); - } + + printk(UM_KERN_ERR "Stub registers -\n"); + for (i = 0; i < ARRAY_SIZE(regs); i++) + printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]); return 0; } @@ -74,27 +63,28 @@ void wait_stub_done(int pid) { int n, status, err; - while(1){ + while (1) { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if((n < 0) || !WIFSTOPPED(status)) + if ((n < 0) || !WIFSTOPPED(status)) goto bad_wait; - if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) + if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) break; err = ptrace(PTRACE_CONT, pid, 0, 0); - if(err) + if (err) panic("wait_stub_done : continue failed, errno = %d\n", errno); } - if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) + if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) return; bad_wait: err = ptrace_dump_regs(pid); - if(err) - printk("Failed to get registers from stub, errno = %d\n", -err); + if (err) + printk(UM_KERN_ERR "Failed to get registers from stub, " + "errno = %d\n", -err); panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); } @@ -105,9 +95,9 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) { int err; - if(ptrace_faultinfo){ + if (ptrace_faultinfo) { err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); - if(err) + if (err) panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " "errno = %d\n", errno); @@ -119,52 +109,57 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) } else { err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); - if(err) + if (err) panic("Failed to continue stub, pid = %d, errno = %d\n", pid, errno); wait_stub_done(pid); - /* faultinfo is prepared by the stub-segv-handler at start of + /* + * faultinfo is prepared by the stub-segv-handler at start of * the stub stack page. We just have to copy it. */ memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); } } -static void handle_segv(int pid, union uml_pt_regs * regs) +static void handle_segv(int pid, struct uml_pt_regs * regs) { - get_skas_faultinfo(pid, ®s->skas.faultinfo); - segv(regs->skas.faultinfo, 0, 1, NULL); + get_skas_faultinfo(pid, ®s->faultinfo); + segv(regs->faultinfo, 0, 1, NULL); } -/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ -static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) +/* + * To use the same value of using_sysemu as the caller, ask it that value + * (in local_using_sysemu + */ +static void handle_trap(int pid, struct uml_pt_regs *regs, + int local_using_sysemu) { int err, status; /* Mark this as a syscall */ - UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); + UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); if (!local_using_sysemu) { err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); - if(err < 0) - panic("handle_trap - nullifying syscall failed errno = %d\n", - errno); + if (err < 0) + panic("handle_trap - nullifying syscall failed, " + "errno = %d\n", errno); err = ptrace(PTRACE_SYSCALL, pid, 0, 0); - if(err < 0) - panic("handle_trap - continuing to end of syscall failed, " - "errno = %d\n", errno); + if (err < 0) + panic("handle_trap - continuing to end of syscall " + "failed, errno = %d\n", errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if((err < 0) || !WIFSTOPPED(status) || - (WSTOPSIG(status) != SIGTRAP + 0x80)){ + if ((err < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGTRAP + 0x80)) { err = ptrace_dump_regs(pid); - if(err) - printk("Failed to get registers from process, " - "errno = %d\n", -err); + if (err) + printk(UM_KERN_ERR "Failed to get registers " + "from process, errno = %d\n", -err); panic("handle_trap - failed to wait at end of syscall, " "errno = %d, status = %d\n", errno, status); } @@ -182,63 +177,64 @@ static int userspace_tramp(void *stack) ptrace(PTRACE_TRACEME, 0, 0, 0); - init_new_thread_signals(); - err = set_interval(1); - if(err) + signal(SIGTERM, SIG_DFL); + err = set_interval(); + if (err) panic("userspace_tramp - setting timer failed, errno = %d\n", err); - if(!proc_mm){ - /* This has a pte, but it can't be mapped in with the usual + if (!proc_mm) { + /* + * This has a pte, but it can't be mapped in with the usual * tlb_flush mechanism because this is part of that mechanism */ int fd; - __u64 offset; + unsigned long long offset; fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); - addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE, + addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); - if(addr == MAP_FAILED){ - printk("mapping mmap stub failed, errno = %d\n", - errno); + if (addr == MAP_FAILED) { + printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " + "errno = %d\n", STUB_CODE, errno); exit(1); } - if(stack != NULL){ + if (stack != NULL) { fd = phys_mapping(to_phys(stack), &offset); - addr = mmap((void *) UML_CONFIG_STUB_DATA, + addr = mmap((void *) STUB_DATA, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset); - if(addr == MAP_FAILED){ - printk("mapping segfault stack failed, " - "errno = %d\n", errno); + if (addr == MAP_FAILED) { + printk(UM_KERN_ERR "mapping segfault stack " + "at 0x%lx failed, errno = %d\n", + STUB_DATA, errno); exit(1); } } } - if(!ptrace_faultinfo && (stack != NULL)){ + if (!ptrace_faultinfo && (stack != NULL)) { struct sigaction sa; - unsigned long v = UML_CONFIG_STUB_CODE + + unsigned long v = STUB_CODE + (unsigned long) stub_segv_handler - (unsigned long) &__syscall_stub_start; - set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE); + set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGIO); sigaddset(&sa.sa_mask, SIGWINCH); - sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGVTALRM); sigaddset(&sa.sa_mask, SIGUSR1); sa.sa_flags = SA_ONSTACK; sa.sa_handler = (void *) v; sa.sa_restorer = NULL; - if(sigaction(SIGSEGV, &sa, NULL) < 0) + if (sigaction(SIGSEGV, &sa, NULL) < 0) panic("userspace_tramp - setting SIGSEGV handler " "failed - errno = %d\n", errno); } - os_stop_process(os_getpid()); - return(0); + kill(os_getpid(), SIGSTOP); + return 0; } /* Each element set once, and only accessed by a single processor anyway */ @@ -255,44 +251,55 @@ int start_userspace(unsigned long stub_stack) stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if(stack == MAP_FAILED) + if (stack == MAP_FAILED) panic("start_userspace : mmap failed, errno = %d", errno); sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); flags = CLONE_FILES | SIGCHLD; - if(proc_mm) flags |= CLONE_VM; + if (proc_mm) + flags |= CLONE_VM; + pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); - if(pid < 0) + if (pid < 0) panic("start_userspace : clone failed, errno = %d", errno); do { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) + if (n < 0) panic("start_userspace : wait failed, errno = %d", errno); - } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); + } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) panic("start_userspace : expected SIGSTOP, got status = %d", status); - if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) - panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", - errno); + if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, + (void *) PTRACE_O_TRACESYSGOOD) < 0) + panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " + "errno = %d\n", errno); - if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) + if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) panic("start_userspace : munmap failed, errno = %d\n", errno); - return(pid); + return pid; } -void userspace(union uml_pt_regs *regs) +void userspace(struct uml_pt_regs *regs) { + struct itimerval timer; + unsigned long long nsecs, now; int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; - while(1){ + if (getitimer(ITIMER_VIRTUAL, &timer)) + printk("Failed to get itimer, errno = %d\n", errno); + nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + + timer.it_value.tv_usec * UM_NSEC_PER_USEC; + nsecs += os_nsecs(); + + while (1) { restore_registers(pid, regs); /* Now we set local_using_sysemu to be used for one loop */ @@ -302,26 +309,28 @@ void userspace(union uml_pt_regs *regs) singlestepping(NULL)); err = ptrace(op, pid, 0, 0); - if(err) + if (err) panic("userspace - could not resume userspace process, " "pid=%d, ptrace operation = %d, errno = %d\n", pid, op, errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if(err < 0) + if (err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); - regs->skas.is_user = 1; + regs->is_user = 1; save_registers(pid, regs); UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ - if(WIFSTOPPED(status)){ + if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); - switch(sig){ + switch(sig) { case SIGSEGV: - if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){ - get_skas_faultinfo(pid, ®s->skas.faultinfo); + if (PTRACE_FULL_FAULTINFO || + !ptrace_faultinfo) { + get_skas_faultinfo(pid, + ®s->faultinfo); (*sig_info[SIGSEGV])(SIGSEGV, regs); } else handle_segv(pid, regs); @@ -332,8 +341,20 @@ void userspace(union uml_pt_regs *regs) case SIGTRAP: relay_signal(SIGTRAP, regs); break; - case SIGIO: case SIGVTALRM: + now = os_nsecs(); + if(now < nsecs) + break; + block_signals(); + (*sig_info[sig])(sig, regs); + unblock_signals(); + nsecs = timer.it_value.tv_sec * + UM_NSEC_PER_SEC + + timer.it_value.tv_usec * + UM_NSEC_PER_USEC; + nsecs += os_nsecs(); + break; + case SIGIO: case SIGILL: case SIGBUS: case SIGFPE: @@ -343,30 +364,29 @@ void userspace(union uml_pt_regs *regs) unblock_signals(); break; default: - printk("userspace - child stopped with signal " - "%d\n", sig); + printk(UM_KERN_ERR "userspace - child stopped " + "with signal %d\n", sig); } pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ - if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) - PT_SYSCALL_NR(regs->skas.regs) = -1; + if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) + PT_SYSCALL_NR(regs->gp) = -1; } } } static unsigned long thread_regs[MAX_REG_NR]; -static unsigned long thread_fp_regs[HOST_FP_SIZE]; static int __init init_thread_regs(void) { - get_safe_registers(thread_regs, thread_fp_regs); + get_safe_registers(thread_regs); /* Set parent's instruction pointer to start of clone-stub */ - thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) &__syscall_stub_start; - thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE - + thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; @@ -378,53 +398,53 @@ __initcall(init_thread_regs); int copy_context_skas0(unsigned long new_stack, int pid) { + struct timeval tv = { .tv_sec = 0, .tv_usec = UM_USEC_PER_SEC / UM_HZ }; int err; unsigned long current_stack = current_stub_stack(); struct stub_data *data = (struct stub_data *) current_stack; struct stub_data *child_data = (struct stub_data *) new_stack; - __u64 new_offset; + unsigned long long new_offset; int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); - /* prepare offset and fd of child's stack as argument for parent's + /* + * prepare offset and fd of child's stack as argument for parent's * and child's mmap2 calls */ *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), .fd = new_fd, .timer = ((struct itimerval) - { { 0, 1000000 / hz() }, - { 0, 1000000 / hz() }})}); + { .it_value = tv, + .it_interval = tv }) }); + err = ptrace_setregs(pid, thread_regs); - if(err < 0) + if (err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " "pid = %d, errno = %d\n", pid, -err); - err = ptrace_setfpregs(pid, thread_fp_regs); - if(err < 0) - panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " - "pid = %d, errno = %d\n", pid, -err); - /* set a well known return code for detection of child write failure */ child_data->err = 12345678; - /* Wait, until parent has finished its work: read child's pid from + /* + * Wait, until parent has finished its work: read child's pid from * parent's stack, and check, if bad result. */ err = ptrace(PTRACE_CONT, pid, 0, 0); - if(err) + if (err) panic("Failed to continue new process, pid = %d, " "errno = %d\n", pid, errno); wait_stub_done(pid); pid = data->err; - if(pid < 0) + if (pid < 0) panic("copy_context_skas0 - stub-parent reports error %d\n", -pid); - /* Wait, until child has finished too: read child's result from + /* + * Wait, until child has finished too: read child's result from * child's stack and check it. */ wait_stub_done(pid); - if (child_data->err != UML_CONFIG_STUB_DATA) + if (child_data->err != STUB_DATA) panic("copy_context_skas0 - stub-child reports error %ld\n", child_data->err); @@ -446,7 +466,7 @@ void map_stub_pages(int fd, unsigned long code, { struct proc_mm_op mmop; int n; - __u64 code_offset; + unsigned long long code_offset; int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), &code_offset); @@ -461,16 +481,17 @@ void map_stub_pages(int fd, unsigned long code, .offset = code_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if(n != sizeof(mmop)){ + if (n != sizeof(mmop)) { n = errno; - printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", - code, code_fd, (unsigned long long) code_offset); + printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " + "offset = %llx\n", code, code_fd, + (unsigned long long) code_offset); panic("map_stub_pages : /proc/mm map for code failed, " "err = %d\n", n); } - if ( stack ) { - __u64 map_offset; + if (stack) { + unsigned long long map_offset; int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); mmop = ((struct proc_mm_op) { .op = MM_MMAP, @@ -484,7 +505,7 @@ void map_stub_pages(int fd, unsigned long code, .offset = map_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if(n != sizeof(mmop)) + if (n != sizeof(mmop)) panic("map_stub_pages : /proc/mm map for data failed, " "err = %d\n", errno); } @@ -504,7 +525,7 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) void switch_threads(jmp_buf *me, jmp_buf *you) { - if(UML_SETJMP(me) == 0) + if (UML_SETJMP(me) == 0) UML_LONGJMP(you, 1); } @@ -520,8 +541,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, - SIGVTALRM, -1); + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); /* * Can't use UML_SETJMP or UML_LONGJMP here because they save @@ -532,7 +552,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) * after returning to the jumper. */ n = setjmp(initial_jmpbuf); - switch(n){ + switch(n) { case INIT_JMP_NEW_THREAD: (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; (*switch_buf)[0].JB_SP = (unsigned long) stack + @@ -544,10 +564,10 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) break; case INIT_JMP_HALT: kmalloc_ok = 0; - return(0); + return 0; case INIT_JMP_REBOOT: kmalloc_ok = 0; - return(1); + return 1; default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } @@ -563,7 +583,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) cb_back = &here; block_signals(); - if(UML_SETJMP(&here) == 0) + if (UML_SETJMP(&here) == 0) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); @@ -584,16 +604,16 @@ void reboot_skas(void) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); } -void switch_mm_skas(struct mm_id *mm_idp) +void __switch_mm(struct mm_id *mm_idp) { int err; - /* FIXME: need cpu pid in switch_mm_skas */ - if(proc_mm){ + /* FIXME: need cpu pid in __switch_mm */ + if (proc_mm) { err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); - if(err) - panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " + if (err) + panic("__switch_mm - PTRACE_SWITCH_MM failed, " "errno = %d\n", errno); } else userspace_pid[0] = mm_idp->u.pid; diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c index 3b600c2e63b..3b1b9244f46 100644 --- a/arch/um/os-Linux/skas/trap.c +++ b/arch/um/os-Linux/skas/trap.c @@ -1,37 +1,43 @@ /* - * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> -#include <errno.h> +#if 0 #include "kern_util.h" -#include "as-layout.h" -#include "task.h" -#include "sigcontext.h" #include "skas.h" #include "ptrace_user.h" -#include "sysdep/ptrace.h" #include "sysdep/ptrace_user.h" +#endif + +#include <errno.h> +#include <signal.h> +#include "sysdep/ptrace.h" +#include "kern_constants.h" +#include "as-layout.h" #include "os.h" +#include "sigcontext.h" +#include "task.h" -static union uml_pt_regs ksig_regs[UM_NR_CPUS]; +static struct uml_pt_regs ksig_regs[UM_NR_CPUS]; void sig_handler_common_skas(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; - union uml_pt_regs *r; - void (*handler)(int, union uml_pt_regs *); + struct uml_pt_regs *r; + void (*handler)(int, struct uml_pt_regs *); int save_user, save_errno = errno; - /* This is done because to allow SIGSEGV to be delivered inside a SEGV + /* + * This is done because to allow SIGSEGV to be delivered inside a SEGV * handler. This can happen in copy_user, and if SEGV is disabled, * the process will die. * XXX Figure out why this is better than SA_NODEFER */ - if(sig == SIGSEGV) { + if (sig == SIGSEGV) { change_sig(SIGSEGV, 1); - /* For segfaults, we want the data from the + /* + * For segfaults, we want the data from the * sigcontext. In this case, we don't want to mangle * the process registers, so use a static set of * registers. For other signals, the process @@ -42,25 +48,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr) } else r = TASK_REGS(get_current()); - save_user = r->skas.is_user; - r->skas.is_user = 0; - if ( sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGILL || - sig == SIGTRAP ) { - GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc); - } + save_user = r->is_user; + r->is_user = 0; + if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || + (sig == SIGILL) || (sig == SIGTRAP)) + GET_FAULTINFO_FROM_SC(r->faultinfo, sc); change_sig(SIGUSR1, 1); handler = sig_info[sig]; - /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if (sig != SIGIO && sig != SIGWINCH && - sig != SIGVTALRM && sig != SIGALRM) + /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */ + if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) unblock_signals(); handler(sig, r); errno = save_errno; - r->skas.is_user = save_user; + r->is_user = save_user; } diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 46f613975c1..7b81f6c08a5 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -1,75 +1,65 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <pty.h> #include <stdio.h> -#include <stddef.h> -#include <stdarg.h> #include <stdlib.h> -#include <string.h> +#include <stdarg.h> #include <unistd.h> -#include <signal.h> -#include <sched.h> -#include <fcntl.h> #include <errno.h> -#include <sys/time.h> -#include <sys/wait.h> +#include <fcntl.h> +#include <sched.h> +#include <signal.h> +#include <string.h> #include <sys/mman.h> -#include <sys/resource.h> +#include <sys/ptrace.h> +#include <sys/stat.h> +#include <sys/wait.h> #include <asm/unistd.h> -#include <asm/page.h> -#include <sys/types.h> -#include "kern_util.h" -#include "user.h" -#include "signal_kern.h" -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" -#include "irq_user.h" -#include "ptrace_user.h" -#include "mem_user.h" #include "init.h" -#include "os.h" -#include "uml-config.h" -#include "choose-mode.h" -#include "mode.h" -#include "tempfile.h" #include "kern_constants.h" - -#ifdef UML_CONFIG_MODE_SKAS -#include "skas.h" -#include "skas_ptrace.h" +#include "os.h" +#include "mem_user.h" +#include "ptrace_user.h" #include "registers.h" -#endif +#include "skas_ptrace.h" -static int ptrace_child(void *arg) +static int ptrace_child(void) { int ret; + /* Calling os_getpid because some libcs cached getpid incorrectly */ int pid = os_getpid(), ppid = getppid(); int sc_result; change_sig(SIGWINCH, 0); - if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ + if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { perror("ptrace"); - os_kill_process(pid, 0); + kill(pid, SIGKILL); } kill(pid, SIGSTOP); - /*This syscall will be intercepted by the parent. Don't call more than - * once, please.*/ + /* + * This syscall will be intercepted by the parent. Don't call more than + * once, please. + */ sc_result = os_getpid(); if (sc_result == pid) - ret = 1; /*Nothing modified by the parent, we are running - normally.*/ + /* Nothing modified by the parent, we are running normally. */ + ret = 1; else if (sc_result == ppid) - ret = 0; /*Expected in check_ptrace and check_sysemu when they - succeed in modifying the stack frame*/ + /* + * Expected in check_ptrace and check_sysemu when they succeed + * in modifying the stack frame + */ + ret = 0; else - ret = 2; /*Serious trouble! This could be caused by a bug in - host 2.6 SKAS3/2.6 patch before release -V6, together - with a bug in the UML code itself.*/ + /* Serious trouble! This could be caused by a bug in host 2.6 + * SKAS3/2.6 patch before release -V6, together with a bug in + * the UML code itself. + */ + ret = 2; _exit(ret); } @@ -101,29 +91,23 @@ static void non_fatal(char *fmt, ...) fflush(stdout); } -static int start_ptraced_child(void **stack_out) +static int start_ptraced_child(void) { - void *stack; - unsigned long sp; int pid, n, status; - stack = mmap(NULL, UM_KERN_PAGE_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if(stack == MAP_FAILED) - fatal_perror("check_ptrace : mmap failed"); - sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); - pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); - if(pid < 0) - fatal_perror("start_ptraced_child : clone failed"); + pid = fork(); + if (pid == 0) + ptrace_child(); + else if (pid < 0) + fatal_perror("start_ptraced_child : fork failed"); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) - fatal_perror("check_ptrace : clone failed"); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) + if (n < 0) + fatal_perror("check_ptrace : waitpid failed"); + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) fatal("check_ptrace : expected SIGSTOP, got status = %d", status); - *stack_out = stack; return pid; } @@ -133,15 +117,14 @@ static int start_ptraced_child(void **stack_out) * So only for SYSEMU features we test mustpanic, while normal host features * must work anyway! */ -static int stop_ptraced_child(int pid, void *stack, int exitcode, - int mustexit) +static int stop_ptraced_child(int pid, int exitcode, int mustexit) { int status, n, ret = 0; - if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) + if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) fatal_perror("stop_ptraced_child : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, 0)); - if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { + if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); if (exit_with == 2) non_fatal("check_ptrace : child exited with status 2. " @@ -154,8 +137,6 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, ret = -1; } - if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) - fatal_perror("check_ptrace : munmap failed"); return ret; } @@ -207,40 +188,39 @@ __uml_setup("nosysemu", nosysemu_cmd_param, static void __init check_sysemu(void) { - void *stack; unsigned long regs[MAX_REG_NR]; int pid, n, status, count=0; non_fatal("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); - if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) + if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if (n < 0) fatal_perror("check_sysemu : wait failed"); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) fatal("check_sysemu : expected SIGTRAP, got status = %d", status); - if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) fatal_perror("check_sysemu : PTRACE_GETREGS failed"); - if(PT_SYSCALL_NR(regs) != __NR_getpid){ + if (PT_SYSCALL_NR(regs) != __NR_getpid) { non_fatal("check_sysemu got system call number %d, " "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); goto fail; } n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); - if(n < 0){ + if (n < 0) { non_fatal("check_sysemu : failed to modify system call " "return"); goto fail; } - if (stop_ptraced_child(pid, stack, 0, 0) < 0) + if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; sysemu_supported = 1; @@ -248,90 +228,90 @@ static void __init check_sysemu(void) set_using_sysemu(!force_sysemu_disabled); non_fatal("Checking advanced syscall emulation patch for ptrace..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); - if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *) PTRACE_O_TRACESYSGOOD) < 0)) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); - while(1){ + while (1) { count++; - if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) + if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) + if (n < 0) fatal_perror("check_ptrace : wait failed"); - if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ + if (WIFSTOPPED(status) && + (WSTOPSIG(status) == (SIGTRAP|0x80))) { if (!count) fatal("check_ptrace : SYSEMU_SINGLESTEP " "doesn't singlestep"); n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); - if(n < 0) + if (n < 0) fatal_perror("check_sysemu : failed to modify " "system call return"); break; } - else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) + else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; else fatal("check_ptrace : expected SIGTRAP or " "(SIGTRAP | 0x80), got status = %d", status); } - if (stop_ptraced_child(pid, stack, 0, 0) < 0) + if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; sysemu_supported = 2; non_fatal("OK\n"); - if ( !force_sysemu_disabled ) + if (!force_sysemu_disabled) set_using_sysemu(sysemu_supported); return; fail: - stop_ptraced_child(pid, stack, 1, 0); + stop_ptraced_child(pid, 1, 0); fail_stopped: non_fatal("missing\n"); } static void __init check_ptrace(void) { - void *stack; int pid, syscall, n, status; non_fatal("Checking that ptrace can change system call numbers..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); - if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *) PTRACE_O_TRACESYSGOOD) < 0)) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); - while(1){ - if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) + while (1) { + if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) fatal_perror("check_ptrace : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) + if (n < 0) fatal_perror("check_ptrace : wait failed"); - if(!WIFSTOPPED(status) || + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP | 0x80))) fatal("check_ptrace : expected (SIGTRAP|0x80), " "got status = %d", status); syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0); - if(syscall == __NR_getpid){ + if (syscall == __NR_getpid) { n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getppid); - if(n < 0) + if (n < 0) fatal_perror("check_ptrace : failed to modify " "system call"); break; } } - stop_ptraced_child(pid, stack, 0, 1); + stop_ptraced_child(pid, 0, 1); non_fatal("OK\n"); check_sysemu(); } @@ -343,18 +323,18 @@ static void __init check_coredump_limit(void) struct rlimit lim; int err = getrlimit(RLIMIT_CORE, &lim); - if(err){ + if (err) { perror("Getting core dump limit"); return; } printf("Core dump limits :\n\tsoft - "); - if(lim.rlim_cur == RLIM_INFINITY) + if (lim.rlim_cur == RLIM_INFINITY) printf("NONE\n"); else printf("%lu\n", lim.rlim_cur); printf("\thard - "); - if(lim.rlim_max == RLIM_INFINITY) + if (lim.rlim_max == RLIM_INFINITY) printf("NONE\n"); else printf("%lu\n", lim.rlim_max); } @@ -408,20 +388,18 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param, " To support PTRACE_LDT, the host needs to be patched using\n" " the current skas3 patch.\n\n"); -#ifdef UML_CONFIG_MODE_SKAS static inline void check_skas3_ptrace_faultinfo(void) { struct ptrace_faultinfo fi; - void *stack; int pid, n; non_fatal(" - PTRACE_FAULTINFO..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { ptrace_faultinfo = 0; - if(errno == EIO) + if (errno == EIO) non_fatal("not found\n"); else perror("not found"); @@ -434,13 +412,12 @@ static inline void check_skas3_ptrace_faultinfo(void) } init_registers(pid); - stop_ptraced_child(pid, stack, 1, 1); + stop_ptraced_child(pid, 1, 1); } static inline void check_skas3_ptrace_ldt(void) { #ifdef PTRACE_LDT - void *stack; int pid, n; unsigned char ldtbuf[40]; struct ptrace_ldt ldt_op = (struct ptrace_ldt) { @@ -449,11 +426,11 @@ static inline void check_skas3_ptrace_ldt(void) .bytecount = sizeof(ldtbuf)}; non_fatal(" - PTRACE_LDT..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); if (n < 0) { - if(errno == EIO) + if (errno == EIO) non_fatal("not found\n"); else { perror("not found"); @@ -461,13 +438,13 @@ static inline void check_skas3_ptrace_ldt(void) ptrace_ldt = 0; } else { - if(ptrace_ldt) + if (ptrace_ldt) non_fatal("found\n"); else non_fatal("found, but use is disabled\n"); } - stop_ptraced_child(pid, stack, 1, 1); + stop_ptraced_child(pid, 1, 1); #else /* PTRACE_LDT might be disabled via cmdline option. * We want to override this, else we might use the stub @@ -484,12 +461,9 @@ static inline void check_skas3_proc_mm(void) proc_mm = 0; perror("not found"); } - else { - if (!proc_mm) - non_fatal("found but disabled on command line\n"); - else - non_fatal("found\n"); - } + else if (!proc_mm) + non_fatal("found but disabled on command line\n"); + else non_fatal("found\n"); } int can_do_skas(void) @@ -500,17 +474,11 @@ int can_do_skas(void) check_skas3_ptrace_faultinfo(); check_skas3_ptrace_ldt(); - if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt) + if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) skas_needs_stub = 1; return 1; } -#else -int can_do_skas(void) -{ - return 0; -} -#endif int __init parse_iomem(char *str, int *add) { @@ -521,25 +489,25 @@ int __init parse_iomem(char *str, int *add) driver = str; file = strchr(str,','); - if(file == NULL){ + if (file == NULL) { printf("parse_iomem : failed to parse iomem\n"); goto out; } *file = '\0'; file++; fd = open(file, O_RDWR, 0); - if(fd < 0){ - os_print_error(fd, "parse_iomem - Couldn't open io file"); + if (fd < 0) { + perror("parse_iomem - Couldn't open io file"); goto out; } - if(fstat64(fd, &buf) < 0){ + if (fstat64(fd, &buf) < 0) { perror("parse_iomem - cannot stat_fd file"); goto out_close; } new = malloc(sizeof(*new)); - if(new == NULL){ + if (new == NULL) { perror("Couldn't allocate iomem_region struct"); goto out_close; } diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile index 37806621b25..a841262c594 100644 --- a/arch/um/os-Linux/sys-i386/Makefile +++ b/arch/um/os-Linux/sys-i386/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # -obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o +obj-y = registers.o signal.o tls.o USER_OBJS := $(obj-y) diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 84b44f9cd42..d1997ca76e5 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -1,144 +1,73 @@ /* * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <errno.h> -#include <string.h> -#include "sysdep/ptrace_user.h" -#include "sysdep/ptrace.h" -#include "uml-config.h" -#include "skas_ptregs.h" -#include "registers.h" +#include "kern_constants.h" #include "longjmp.h" #include "user.h" +#include "sysdep/ptrace_user.h" -/* These are set once at boot time and not changed thereafter */ - -static unsigned long exec_regs[MAX_REG_NR]; -static unsigned long exec_fp_regs[HOST_FP_SIZE]; -static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; -static int have_fpx_regs = 1; - -void init_thread_registers(union uml_pt_regs *to) -{ - memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); - memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); - if(have_fpx_regs) - memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); -} - -/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs - * to pass in a sufficiently large buffer - */ int save_fp_registers(int pid, unsigned long *fp_regs) { - if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) + if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) return -errno; return 0; } int restore_fp_registers(int pid, unsigned long *fp_regs) { - if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) + if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) return -errno; return 0; } -static int move_registers(int pid, int int_op, union uml_pt_regs *regs, - int fp_op, unsigned long *fp_regs) +int save_fpx_registers(int pid, unsigned long *fp_regs) { - if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return -errno; - - if(ptrace(fp_op, pid, 0, fp_regs) < 0) + if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) return -errno; - return 0; } -void save_registers(int pid, union uml_pt_regs *regs) +int restore_fpx_registers(int pid, unsigned long *fp_regs) { - unsigned long *fp_regs; - int err, fp_op; - - if(have_fpx_regs){ - fp_op = PTRACE_GETFPXREGS; - fp_regs = regs->skas.xfp; - } - else { - fp_op = PTRACE_GETFPREGS; - fp_regs = regs->skas.fp; - } - - err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); - if(err) - panic("save_registers - saving registers failed, errno = %d\n", - -err); + if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) + return -errno; + return 0; } -void restore_registers(int pid, union uml_pt_regs *regs) +unsigned long get_thread_reg(int reg, jmp_buf *buf) { - unsigned long *fp_regs; - int err, fp_op; - - if(have_fpx_regs){ - fp_op = PTRACE_SETFPXREGS; - fp_regs = regs->skas.xfp; - } - else { - fp_op = PTRACE_SETFPREGS; - fp_regs = regs->skas.fp; + switch (reg) { + case EIP: + return buf[0]->__eip; + case UESP: + return buf[0]->__esp; + case EBP: + return buf[0]->__ebp; + default: + printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", + reg); + return 0; } - - err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); - if(err) - panic("restore_registers - saving registers failed, " - "errno = %d\n", -err); } -void init_registers(int pid) +int have_fpx_regs = 1; + +void arch_init_registers(int pid) { + unsigned long fpx_regs[HOST_XFP_SIZE]; int err; - memset(exec_regs, 0, sizeof(exec_regs)); - err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); - if(err) - panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", - errno); - - errno = 0; - err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); + err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); if(!err) return; + if(errno != EIO) panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", errno); have_fpx_regs = 0; - - err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); - if(err) - panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", - errno); -} - -void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) -{ - memcpy(regs, exec_regs, sizeof(exec_regs)); - if(fp_regs != NULL) - memcpy(fp_regs, exec_fp_regs, - HOST_FP_SIZE * sizeof(unsigned long)); -} - -unsigned long get_thread_reg(int reg, jmp_buf *buf) -{ - switch(reg){ - case EIP: return buf[0]->__eip; - case UESP: return buf[0]->__esp; - case EBP: return buf[0]->__ebp; - default: - printk("get_thread_regs - unknown register %d\n", reg); - return 0; - } } diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile index 7955e061a67..a42a4ef02e1 100644 --- a/arch/um/os-Linux/sys-x86_64/Makefile +++ b/arch/um/os-Linux/sys-x86_64/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # -obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o +obj-y = registers.o prctl.o signal.o USER_OBJS := $(obj-y) diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 9467315b805..9bfa789992d 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -1,23 +1,15 @@ /* - * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2006-2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <errno.h> #include <sys/ptrace.h> -#include <string.h> -#include "ptrace_user.h" -#include "uml-config.h" -#include "skas_ptregs.h" -#include "registers.h" +#define __FRAME_OFFSETS +#include <asm/ptrace.h> #include "longjmp.h" #include "user.h" -/* These are set once at boot time and not changed thereafter */ - -static unsigned long exec_regs[MAX_REG_NR]; -static unsigned long exec_fp_regs[HOST_FP_SIZE]; - int save_fp_registers(int pid, unsigned long *fp_regs) { if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) @@ -32,67 +24,6 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) return 0; } -void init_thread_registers(union uml_pt_regs *to) -{ - memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); - memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); -} - -static int move_registers(int pid, int int_op, int fp_op, - union uml_pt_regs *regs) -{ - if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return -errno; - - if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) - return -errno; - - return 0; -} - -void save_registers(int pid, union uml_pt_regs *regs) -{ - int err; - - err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); - if(err) - panic("save_registers - saving registers failed, errno = %d\n", - -err); -} - -void restore_registers(int pid, union uml_pt_regs *regs) -{ - int err; - - err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); - if(err) - panic("restore_registers - saving registers failed, " - "errno = %d\n", -err); -} - -void init_registers(int pid) -{ - int err; - - err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); - if(err) - panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", - errno); - - err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); - if(err) - panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", - errno); -} - -void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) -{ - memcpy(regs, exec_regs, sizeof(exec_regs)); - if(fp_regs != NULL) - memcpy(fp_regs, exec_fp_regs, - HOST_FP_SIZE * sizeof(unsigned long)); -} - unsigned long get_thread_reg(int reg, jmp_buf *buf) { switch(reg){ diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 5de169b168f..e34e1effe0f 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -1,101 +1,86 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> +#include <stddef.h> +#include <errno.h> +#include <signal.h> #include <time.h> #include <sys/time.h> -#include <signal.h> -#include <errno.h> -#include "kern_util.h" -#include "user.h" -#include "process.h" #include "kern_constants.h" #include "os.h" -#include "uml-config.h" +#include "user.h" -int set_interval(int is_virtual) +int set_interval(void) { - int usec = 1000000/hz(); - int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL; + int usec = UM_USEC_PER_SEC / UM_HZ; struct itimerval interval = ((struct itimerval) { { 0, usec }, { 0, usec } }); - if(setitimer(timer_type, &interval, NULL) == -1) + if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) return -errno; return 0; } -#ifdef UML_CONFIG_MODE_TT -void enable_timer(void) +int timer_one_shot(int ticks) { - set_interval(1); -} -#endif + unsigned long usec = ticks * UM_USEC_PER_SEC / UM_HZ; + unsigned long sec = usec / UM_USEC_PER_SEC; + struct itimerval interval; -void disable_timer(void) -{ - struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); - if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || - (setitimer(ITIMER_REAL, &disable, NULL) < 0)) - printk("disnable_timer - setitimer failed, errno = %d\n", - errno); - /* If there are signals already queued, after unblocking ignore them */ - signal(SIGALRM, SIG_IGN); - signal(SIGVTALRM, SIG_IGN); + usec %= UM_USEC_PER_SEC; + interval = ((struct itimerval) { { 0, 0 }, { sec, usec } }); + + if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) + return -errno; + + return 0; } -void switch_timers(int to_real) +/** + * timeval_to_ns - Convert timeval to nanoseconds + * @ts: pointer to the timeval variable to be converted + * + * Returns the scalar nanosecond representation of the timeval + * parameter. + * + * Ripped from linux/time.h because it's a kernel header, and thus + * unusable from here. + */ +static inline long long timeval_to_ns(const struct timeval *tv) { - struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); - struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, - { 0, 1000000/hz() }}); - int old, new; - - if(to_real){ - old = ITIMER_VIRTUAL; - new = ITIMER_REAL; - } - else { - old = ITIMER_REAL; - new = ITIMER_VIRTUAL; - } - - if((setitimer(old, &disable, NULL) < 0) || - (setitimer(new, &enable, NULL))) - printk("switch_timers - setitimer failed, errno = %d\n", - errno); + return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + + tv->tv_usec * UM_NSEC_PER_USEC; } -#ifdef UML_CONFIG_MODE_TT -void uml_idle_timer(void) +long long disable_timer(void) { - if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) - panic("Couldn't unset SIGVTALRM handler"); + struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); + + if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0) + printk(UM_KERN_ERR "disable_timer - setitimer failed, " + "errno = %d\n", errno); - set_handler(SIGALRM, (__sighandler_t) alarm_handler, - SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - set_interval(0); + return timeval_to_ns(&time.it_value); } -#endif -unsigned long long os_nsecs(void) +long long os_nsecs(void) { struct timeval tv; gettimeofday(&tv, NULL); - return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); + return timeval_to_ns(&tv); } -void idle_sleep(int secs) +extern void alarm_handler(int sig, struct sigcontext *sc); + +void idle_sleep(unsigned long long nsecs) { - struct timespec ts; + struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC, + .tv_nsec = nsecs % UM_NSEC_PER_SEC }; - ts.tv_sec = secs; - ts.tv_nsec = 0; - nanosleep(&ts, NULL); + if (nanosleep(&ts, &ts) == 0) + alarm_handler(SIGVTALRM, NULL); } diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index 16215b99080..73277801ef1 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c @@ -1,18 +1,9 @@ #include <errno.h> -#include <unistd.h> #include <sys/ptrace.h> -#include <sys/syscall.h> -#include <asm/ldt.h> #include "sysdep/tls.h" -#include "uml-config.h" /* TLS support - we basically rely on the host's one.*/ -/* In TT mode, this should be called only by the tracing thread, and makes sense - * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. - * - */ - #ifndef PTRACE_GET_THREAD_AREA #define PTRACE_GET_THREAD_AREA 25 #endif @@ -32,8 +23,6 @@ int os_set_thread_area(user_desc_t *info, int pid) return ret; } -#ifdef UML_CONFIG_MODE_SKAS - int os_get_thread_area(user_desc_t *info, int pid) { int ret; @@ -44,32 +33,3 @@ int os_get_thread_area(user_desc_t *info, int pid) ret = -errno; return ret; } - -#endif - -#ifdef UML_CONFIG_MODE_TT -#include "linux/unistd.h" - -int do_set_thread_area_tt(user_desc_t *info) -{ - int ret; - - ret = syscall(__NR_set_thread_area,info); - if (ret < 0) { - ret = -errno; - } - return ret; -} - -int do_get_thread_area_tt(user_desc_t *info) -{ - int ret; - - ret = syscall(__NR_get_thread_area,info); - if (ret < 0) { - ret = -errno; - } - return ret; -} - -#endif /* UML_CONFIG_MODE_TT */ diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 295da657931..2a1c9843e32 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c @@ -1,22 +1,14 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdlib.h> #include <signal.h> -#include "kern_util.h" #include "os.h" -#include "mode.h" -#include "longjmp.h" - -void usr2_handler(int sig, union uml_pt_regs *regs) -{ - CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -} +#include "sysdep/ptrace.h" /* Initialized from linux_main() */ -void (*sig_info[NSIG])(int, union uml_pt_regs *); +void (*sig_info[NSIG])(int, struct uml_pt_regs *); void os_fill_handlinfo(struct kern_handlers h) { @@ -28,13 +20,4 @@ void os_fill_handlinfo(struct kern_handlers h) sig_info[SIGSEGV] = h.page_fault; sig_info[SIGIO] = h.sigio_handler; sig_info[SIGVTALRM] = h.timer_handler; - sig_info[SIGALRM] = h.timer_handler; - sig_info[SIGUSR2] = usr2_handler; -} - -void do_longjmp(void *b, int val) -{ - jmp_buf *buf = b; - - UML_LONGJMP(buf, val); } diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c deleted file mode 100644 index bcf9359c4e9..00000000000 --- a/arch/um/os-Linux/tt.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <unistd.h> -#include <signal.h> -#include <sched.h> -#include <errno.h> -#include <stdarg.h> -#include <stdlib.h> -#include <sys/time.h> -#include <sys/ptrace.h> -#include <linux/ptrace.h> -#include <sys/wait.h> -#include <sys/mman.h> -#include <asm/ptrace.h> -#include <asm/unistd.h> -#include <asm/page.h> -#include "kern_util.h" -#include "user.h" -#include "signal_kern.h" -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" -#include "irq_user.h" -#include "ptrace_user.h" -#include "init.h" -#include "os.h" -#include "uml-config.h" -#include "choose-mode.h" -#include "mode.h" -#include "tempfile.h" -#include "kern_constants.h" - -int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, - int must_succeed) -{ - int err; - - err = os_protect_memory((void *) addr, len, r, w, x); - if(err < 0){ - if(must_succeed) - panic("protect failed, err = %d", -err); - else return(err); - } - return(0); -} - -void kill_child_dead(int pid) -{ - kill(pid, SIGKILL); - kill(pid, SIGCONT); - do { - int n; - CATCH_EINTR(n = waitpid(pid, NULL, 0)); - if (n > 0) - kill(pid, SIGCONT); - else - break; - } while(1); -} - -void stop(void) -{ - while(1) sleep(1000000); -} - -int wait_for_stop(int pid, int sig, int cont_type, void *relay) -{ - sigset_t *relay_signals = relay; - int status, ret; - - while(1){ - CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); - if((ret < 0) || - !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ - if(ret < 0){ - printk("wait failed, errno = %d\n", - errno); - } - else if(WIFEXITED(status)) - printk("process %d exited with status %d\n", - pid, WEXITSTATUS(status)); - else if(WIFSIGNALED(status)) - printk("process %d exited with signal %d\n", - pid, WTERMSIG(status)); - else if((WSTOPSIG(status) == SIGVTALRM) || - (WSTOPSIG(status) == SIGALRM) || - (WSTOPSIG(status) == SIGIO) || - (WSTOPSIG(status) == SIGPROF) || - (WSTOPSIG(status) == SIGCHLD) || - (WSTOPSIG(status) == SIGWINCH) || - (WSTOPSIG(status) == SIGINT)){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else if((relay_signals != NULL) && - sigismember(relay_signals, WSTOPSIG(status))){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else printk("process %d stopped with signal %d\n", - pid, WSTOPSIG(status)); - panic("wait_for_stop failed to wait for %d to stop " - "with %d\n", pid, sig); - } - return(status); - } -} - -void forward_ipi(int fd, int pid) -{ - int err; - - err = os_set_owner(fd, pid); - if(err < 0) - printk("forward_ipi: set_owner failed, fd = %d, me = %d, " - "target = %d, err = %d\n", fd, os_getpid(), pid, -err); -} - -/* - *------------------------- - * only for tt mode (will be deleted in future...) - *------------------------- - */ - -struct tramp { - int (*tramp)(void *); - void *tramp_data; - unsigned long temp_stack; - int flags; - int pid; -}; - -/* See above for why sigkill is here */ - -int sigkill = SIGKILL; - -int outer_tramp(void *arg) -{ - struct tramp *t; - int sig = sigkill; - - t = arg; - t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2, - t->flags, t->tramp_data); - if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); - kill(os_getpid(), sig); - _exit(0); -} - -int start_fork_tramp(void *thread_arg, unsigned long temp_stack, - int clone_flags, int (*tramp)(void *)) -{ - struct tramp arg; - unsigned long sp; - int new_pid, status, err; - - /* The trampoline will run on the temporary stack */ - sp = stack_sp(temp_stack); - - clone_flags |= CLONE_FILES | SIGCHLD; - - arg.tramp = tramp; - arg.tramp_data = thread_arg; - arg.temp_stack = temp_stack; - arg.flags = clone_flags; - - /* Start the process and wait for it to kill itself */ - new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); - if(new_pid < 0) - return(new_pid); - - CATCH_EINTR(err = waitpid(new_pid, &status, 0)); - if(err < 0) - panic("Waiting for outer trampoline failed - errno = %d", - errno); - - if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) - panic("outer trampoline didn't exit with SIGKILL, " - "status = %d", status); - - return(arg.pid); -} - -void forward_pending_sigio(int target) -{ - sigset_t sigs; - - if(sigpending(&sigs)) - panic("forward_pending_sigio : sigpending failed"); - if(sigismember(&sigs, SIGIO)) - kill(target, SIGIO); -} - diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index bbb73a65037..8d27b6d1df9 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c @@ -8,7 +8,7 @@ #include "longjmp.h" unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher, + void **fault_addr, jmp_buf **fault_catcher, void (*op)(void *to, const void *from, int n), int *faulted_out) { diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index b462863f717..106fa864155 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -1,17 +1,21 @@ +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + #include <stdio.h> -#include <unistd.h> #include <stdlib.h> -#include <string.h> +#include <dirent.h> #include <errno.h> +#include <fcntl.h> #include <signal.h> -#include <dirent.h> -#include <sys/fcntl.h> +#include <string.h> +#include <unistd.h> #include <sys/stat.h> -#include <sys/param.h> #include "init.h" +#include "kern_constants.h" #include "os.h" #include "user.h" -#include "mode.h" #define UML_DIR "~/.uml/" @@ -28,13 +32,13 @@ static int __init make_uml_dir(void) char dir[512] = { '\0' }; int len, err; - if(*uml_dir == '~'){ + if (*uml_dir == '~') { char *home = getenv("HOME"); err = -ENOENT; - if(home == NULL){ - printk("make_uml_dir : no value in environment for " - "$HOME\n"); + if (home == NULL) { + printk(UM_KERN_ERR "make_uml_dir : no value in " + "environment for $HOME\n"); goto err; } strlcpy(dir, home, sizeof(dir)); @@ -53,7 +57,7 @@ static int __init make_uml_dir(void) } strcpy(uml_dir, dir); - if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ + if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) { printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); err = -errno; goto err_free; @@ -70,8 +74,8 @@ err: /* * Unlinks the files contained in @dir and then removes @dir. * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We - * ignore ENOENT errors for anything (they happen, strangely enough - possibly due - * to races between multiple dying UML threads). + * ignore ENOENT errors for anything (they happen, strangely enough - possibly + * due to races between multiple dying UML threads). */ static int remove_files_and_dir(char *dir) { @@ -116,7 +120,8 @@ out: return ret; } -/* This says that there isn't already a user of the specified directory even if +/* + * This says that there isn't already a user of the specified directory even if * there are errors during the checking. This is because if these errors * happen, the directory is unusable by the pre-existing UML, so we might as * well take it over. This could happen either by @@ -134,44 +139,45 @@ static inline int is_umdir_used(char *dir) int dead, fd, p, n, err; n = snprintf(file, sizeof(file), "%s/pid", dir); - if(n >= sizeof(file)){ - printk("is_umdir_used - pid filename too long\n"); + if (n >= sizeof(file)) { + printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n"); err = -E2BIG; goto out; } dead = 0; fd = open(file, O_RDONLY); - if(fd < 0) { + if (fd < 0) { fd = -errno; - if(fd != -ENOENT){ - printk("is_umdir_used : couldn't open pid file '%s', " - "err = %d\n", file, -fd); + if (fd != -ENOENT) { + printk(UM_KERN_ERR "is_umdir_used : couldn't open pid " + "file '%s', err = %d\n", file, -fd); } goto out; } err = 0; n = read(fd, pid, sizeof(pid)); - if(n < 0){ - printk("is_umdir_used : couldn't read pid file '%s', " - "err = %d\n", file, errno); + if (n < 0) { + printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " + "'%s', err = %d\n", file, errno); goto out_close; - } else if(n == 0){ - printk("is_umdir_used : couldn't read pid file '%s', " - "0-byte read\n", file); + } else if (n == 0) { + printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " + "'%s', 0-byte read\n", file); goto out_close; } p = strtoul(pid, &end, 0); - if(end == pid){ - printk("is_umdir_used : couldn't parse pid file '%s', " - "errno = %d\n", file, errno); + if (end == pid) { + printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file " + "'%s', errno = %d\n", file, errno); goto out_close; } - if((kill(p, 0) == 0) || (errno != ESRCH)){ - printk("umid \"%s\" is already in use by pid %d\n", umid, p); + if ((kill(p, 0) == 0) || (errno != ESRCH)) { + printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n", + umid, p); return 1; } @@ -195,8 +201,8 @@ static int umdir_take_if_dead(char *dir) ret = remove_files_and_dir(dir); if (ret) { - printk("is_umdir_used - remove_files_and_dir failed with " - "err = %d\n", ret); + printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir " + "failed with err = %d\n", ret); } return ret; } @@ -207,27 +213,28 @@ static void __init create_pid_file(void) char pid[sizeof("nnnnn\0")]; int fd, n; - if(umid_file_name("pid", file, sizeof(file))) + if (umid_file_name("pid", file, sizeof(file))) return; fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); - if(fd < 0){ - printk("Open of machine pid file \"%s\" failed: %s\n", - file, strerror(errno)); + if (fd < 0) { + printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: " + "%s\n", file, strerror(errno)); return; } snprintf(pid, sizeof(pid), "%d\n", getpid()); n = write(fd, pid, strlen(pid)); - if(n != strlen(pid)) - printk("Write of pid file failed - err = %d\n", errno); + if (n != strlen(pid)) + printk(UM_KERN_ERR "Write of pid file failed - err = %d\n", + errno); close(fd); } int __init set_umid(char *name) { - if(strlen(name) > UMID_LEN - 1) + if (strlen(name) > UMID_LEN - 1) return -E2BIG; strlcpy(umid, name, sizeof(umid)); @@ -243,18 +250,18 @@ int __init make_umid(void) int fd, err; char tmp[256]; - if(umid_setup) + if (umid_setup) return 0; make_uml_dir(); - if(*umid == '\0'){ + if (*umid == '\0') { strlcpy(tmp, uml_dir, sizeof(tmp)); strlcat(tmp, "XXXXXX", sizeof(tmp)); fd = mkstemp(tmp); - if(fd < 0){ - printk("make_umid - mkstemp(%s) failed: %s\n", - tmp, strerror(errno)); + if (fd < 0) { + printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: " + "%s\n", tmp, strerror(errno)); err = -errno; goto err; } @@ -263,11 +270,12 @@ int __init make_umid(void) set_umid(&tmp[strlen(uml_dir)]); - /* There's a nice tiny little race between this unlink and + /* + * There's a nice tiny little race between this unlink and * the mkdir below. It'd be nice if there were a mkstemp * for directories. */ - if(unlink(tmp)){ + if (unlink(tmp)) { err = -errno; goto err; } @@ -275,9 +283,9 @@ int __init make_umid(void) snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); err = mkdir(tmp, 0777); - if(err < 0){ + if (err < 0) { err = -errno; - if(err != -EEXIST) + if (err != -EEXIST) goto err; if (umdir_take_if_dead(tmp) < 0) @@ -285,9 +293,10 @@ int __init make_umid(void) err = mkdir(tmp, 0777); } - if(err){ + if (err) { err = -errno; - printk("Failed to create '%s' - err = %d\n", umid, -errno); + printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid, + errno); goto err; } @@ -302,14 +311,15 @@ int __init make_umid(void) static int __init make_umid_init(void) { - if(!make_umid()) + if (!make_umid()) return 0; - /* If initializing with the given umid failed, then try again with + /* + * If initializing with the given umid failed, then try again with * a random one. */ - printk("Failed to initialize umid \"%s\", trying with a random umid\n", - umid); + printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a " + "random umid\n", umid); *umid = '\0'; make_umid(); @@ -323,12 +333,12 @@ int __init umid_file_name(char *name, char *buf, int len) int n, err; err = make_umid(); - if(err) + if (err) return err; n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); - if(n >= len){ - printk("umid_file_name : buffer too short\n"); + if (n >= len) { + printk(UM_KERN_ERR "umid_file_name : buffer too short\n"); return -E2BIG; } @@ -342,21 +352,22 @@ char *get_umid(void) static int __init set_uml_dir(char *name, int *add) { - if(*name == '\0'){ + if (*name == '\0') { printf("uml_dir can't be an empty string\n"); return 0; } - if(name[strlen(name) - 1] == '/'){ + if (name[strlen(name) - 1] == '/') { uml_dir = name; return 0; } uml_dir = malloc(strlen(name) + 2); - if(uml_dir == NULL){ + if (uml_dir == NULL) { printf("Failed to malloc uml_dir - error = %d\n", errno); - /* Return 0 here because do_initcalls doesn't look at + /* + * Return 0 here because do_initcalls doesn't look at * the return value. */ return 0; @@ -377,7 +388,7 @@ static void remove_umid_dir(void) sprintf(dir, "%s%s", uml_dir, umid); err = remove_files_and_dir(dir); - if(err) + if (err) printf("remove_umid_dir - remove_files_and_dir failed with " "err = %d\n", err); } diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 7cbcf484e13..ef095436a78 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -105,6 +105,44 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) void os_dump_core(void) { + int pid; + signal(SIGSEGV, SIG_DFL); + + /* + * We are about to SIGTERM this entire process group to ensure that + * nothing is around to run after the kernel exits. The + * kernel wants to abort, not die through SIGTERM, so we + * ignore it here. + */ + + signal(SIGTERM, SIG_IGN); + kill(0, SIGTERM); + /* + * Most of the other processes associated with this UML are + * likely sTopped, so give them a SIGCONT so they see the + * SIGTERM. + */ + kill(0, SIGCONT); + + /* + * Now, having sent signals to everyone but us, make sure they + * die by ptrace. Processes can survive what's been done to + * them so far - the mechanism I understand is receiving a + * SIGSEGV and segfaulting immediately upon return. There is + * always a SIGSEGV pending, and (I'm guessing) signals are + * processed in numeric order so the SIGTERM (signal 15 vs + * SIGSEGV being signal 11) is never handled. + * + * Run a waitpid loop until we get some kind of error. + * Hopefully, it's ECHILD, but there's not a lot we can do if + * it's something else. Tell os_kill_ptraced_process not to + * wait for the child to report its death because there's + * nothing reasonable to do if that fails. + */ + + while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) + os_kill_ptraced_process(pid, 0); + abort(); } diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index bf23dd3e24d..61107b68e05 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -21,7 +21,7 @@ $(UNPROFILE_OBJS:.o=.%): \ $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ -Dunix -D__unix__ -D__$(SUBARCH)__ $(CF) -# The stubs and unmap.o can't try to call mcount or update basic block data +# The stubs can't try to call mcount or update basic block data define unprofile $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) endef diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index a4618b6b85b..964dc1a04c3 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,23 +1,21 @@ +# +# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# + obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ - ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ + ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ sys_call_table.o tls.o -obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o - subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o -USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o +USER_OBJS := bugs.o ptrace_user.o fault.o USER_OBJS += user-offsets.s extra-y += user-offsets.s -extra-$(CONFIG_MODE_TT) += unmap.o - UNPROFILE_OBJS := stub_segv.o CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) include arch/um/scripts/Makefile.rules - -$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS)) diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index 0393e44813e..806895d73bc 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c @@ -1,18 +1,15 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <unistd.h> #include <errno.h> +#include <signal.h> #include <string.h> -#include <sys/signal.h> -#include <asm/ldt.h> -#include "kern_util.h" -#include "user.h" -#include "sysdep/ptrace.h" -#include "task.h" +#include "kern_constants.h" #include "os.h" +#include "task.h" +#include "user.h" #define MAXTOKEN 64 @@ -30,18 +27,20 @@ static char token(int fd, char *buf, int len, char stop) do { n = os_read_file(fd, ptr, sizeof(*ptr)); c = *ptr++; - if(n != sizeof(*ptr)){ - if(n == 0) + if (n != sizeof(*ptr)) { + if (n == 0) return 0; - printk("Reading /proc/cpuinfo failed, err = %d\n", -n); - if(n < 0) + printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, " + "err = %d\n", -n); + if (n < 0) return n; else return -EIO; } - } while((c != '\n') && (c != stop) && (ptr < end)); + } while ((c != '\n') && (c != stop) && (ptr < end)); - if(ptr == end){ - printk("Failed to find '%c' in /proc/cpuinfo\n", stop); + if (ptr == end) { + printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n", + stop); return -1; } *(ptr - 1) = '\0'; @@ -54,26 +53,27 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) char c; scratch[len - 1] = '\0'; - while(1){ + while (1) { c = token(fd, scratch, len - 1, ':'); - if(c <= 0) + if (c <= 0) return 0; - else if(c != ':'){ - printk("Failed to find ':' in /proc/cpuinfo\n"); + else if (c != ':') { + printk(UM_KERN_ERR "Failed to find ':' in " + "/proc/cpuinfo\n"); return 0; } - if(!strncmp(scratch, key, strlen(key))) + if (!strncmp(scratch, key, strlen(key))) return 1; do { n = os_read_file(fd, &c, sizeof(c)); - if(n != sizeof(c)){ - printk("Failed to find newline in " + if (n != sizeof(c)) { + printk(UM_KERN_ERR "Failed to find newline in " "/proc/cpuinfo, err = %d\n", -n); return 0; } - } while(c != '\n'); + } while (c != '\n'); } return 0; } @@ -83,46 +83,50 @@ static int check_cpu_flag(char *feature, int *have_it) char buf[MAXTOKEN], c; int fd, len = ARRAY_SIZE(buf); - printk("Checking for host processor %s support...", feature); + printk(UM_KERN_INFO "Checking for host processor %s support...", + feature); fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + if (fd < 0) { + printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n", + -fd); return 0; } *have_it = 0; - if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) + if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) goto out; c = token(fd, buf, len - 1, ' '); - if(c < 0) + if (c < 0) goto out; - else if(c != ' '){ - printk("Failed to find ' ' in /proc/cpuinfo\n"); + else if (c != ' ') { + printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n"); goto out; } - while(1){ + while (1) { c = token(fd, buf, len - 1, ' '); - if(c < 0) + if (c < 0) goto out; - else if(c == '\n') break; + else if (c == '\n') + break; - if(!strcmp(buf, feature)){ + if (!strcmp(buf, feature)) { *have_it = 1; goto out; } } out: - if(*have_it == 0) + if (*have_it == 0) printk("No\n"); - else if(*have_it == 1) + else if (*have_it == 1) printk("Yes\n"); os_close_file(fd); return 1; } -#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems +#if 0 /* + * This doesn't work in tt mode, plus it's causing compilation problems * for some people. */ static void disable_lcall(void) @@ -135,8 +139,9 @@ static void disable_lcall(void) ldt.base_addr = 0; ldt.limit = 0; err = modify_ldt(1, &ldt, sizeof(ldt)); - if(err) - printk("Failed to disable lcall7 - errno = %d\n", errno); + if (err) + printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n", + errno); } #endif @@ -151,40 +156,41 @@ void arch_check_bugs(void) { int have_it; - if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ - printk("/proc/cpuinfo not available - skipping CPU capability " - "checks\n"); + if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) { + printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU " + "capability checks\n"); return; } - if(check_cpu_flag("cmov", &have_it)) + if (check_cpu_flag("cmov", &have_it)) host_has_cmov = have_it; - if(check_cpu_flag("xmm", &have_it)) + if (check_cpu_flag("xmm", &have_it)) host_has_xmm = have_it; } -int arch_handle_signal(int sig, union uml_pt_regs *regs) +int arch_handle_signal(int sig, struct uml_pt_regs *regs) { unsigned char tmp[2]; - /* This is testing for a cmov (0x0f 0x4x) instruction causing a + /* + * This is testing for a cmov (0x0f 0x4x) instruction causing a * SIGILL in init. */ - if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) + if ((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return 0; if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) panic("SIGILL in init, could not read instructions!\n"); - if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) + if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) return 0; - if(host_has_cmov == 0) + if (host_has_cmov == 0) panic("SIGILL caused by cmov, which this processor doesn't " "implement, boot a filesystem compiled for older " "processors"); - else if(host_has_cmov == 1) + else if (host_has_cmov == 1) panic("SIGILL caused by cmov, which this processor claims to " "implement"); - else if(host_has_cmov == -1) + else if (host_has_cmov == -1) panic("SIGILL caused by cmov, couldn't tell if this processor " "implements it, boot a filesystem compiled for older " "processors"); diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c index 745b4fd49e9..d670f68532f 100644 --- a/arch/um/sys-i386/fault.c +++ b/arch/um/sys-i386/fault.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -15,14 +15,14 @@ struct exception_table_entry const struct exception_table_entry *search_exception_tables(unsigned long add); /* Compare this to arch/i386/mm/extable.c:fixup_exception() */ -int arch_fixup(unsigned long address, union uml_pt_regs *regs) +int arch_fixup(unsigned long address, struct uml_pt_regs *regs) { const struct exception_table_entry *fixup; fixup = search_exception_tables(address); - if(fixup != 0){ + if (fixup != 0) { UPT_IP(regs) = fixup->fixup; - return(1); + return 1; } - return(0); + return 0; } diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index a939a7ef022..67c0958eb98 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -1,106 +1,30 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/slab.h" -#include "linux/types.h" -#include "linux/errno.h" -#include "linux/spinlock.h" -#include "asm/uaccess.h" -#include "asm/smp.h" -#include "asm/ldt.h" +#include "linux/mm.h" #include "asm/unistd.h" -#include "choose-mode.h" -#include "kern.h" -#include "mode_kern.h" #include "os.h" - -extern int modify_ldt(int func, void *ptr, unsigned long bytecount); - -#ifdef CONFIG_MODE_TT - -static long do_modify_ldt_tt(int func, void __user *ptr, - unsigned long bytecount) -{ - struct user_desc info; - int res = 0; - void *buf = NULL; - void *p = NULL; /* What we pass to host. */ - - switch(func){ - case 1: - case 0x11: /* write_ldt */ - /* Do this check now to avoid overflows. */ - if (bytecount != sizeof(struct user_desc)) { - res = -EINVAL; - goto out; - } - - if(copy_from_user(&info, ptr, sizeof(info))) { - res = -EFAULT; - goto out; - } - - p = &info; - break; - case 0: - case 2: /* read_ldt */ - - /* The use of info avoids kmalloc on the write case, not on the - * read one. */ - buf = kmalloc(bytecount, GFP_KERNEL); - if (!buf) { - res = -ENOMEM; - goto out; - } - p = buf; - break; - default: - res = -ENOSYS; - goto out; - } - - res = modify_ldt(func, p, bytecount); - if(res < 0) - goto out; - - switch(func){ - case 0: - case 2: - /* Modify_ldt was for reading and returned the number of read - * bytes.*/ - if(copy_to_user(ptr, p, res)) - res = -EFAULT; - break; - } - -out: - kfree(buf); - return res; -} - -#endif - -#ifdef CONFIG_MODE_SKAS - +#include "proc_mm.h" #include "skas.h" #include "skas_ptrace.h" -#include "asm/mmu_context.h" -#include "proc_mm.h" +#include "sysdep/tls.h" + +extern int modify_ldt(int func, void *ptr, unsigned long bytecount); long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, void **addr, int done) { long res; - if(proc_mm){ - /* This is a special handling for the case, that the mm to + if (proc_mm) { + /* + * This is a special handling for the case, that the mm to * modify isn't current->active_mm. * If this is called directly by modify_ldt, * (current->active_mm->context.skas.u == mm_idp) - * will be true. So no call to switch_mm_skas(mm_idp) is done. + * will be true. So no call to __switch_mm(mm_idp) is done. * If this is called in case of init_new_ldt or PTRACE_LDT, * mm_idp won't belong to current->active_mm, but child->mm. * So we need to switch child's mm into our userspace, then @@ -108,12 +32,12 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, * * Note: I'm unsure: should interrupts be disabled here? */ - if(!current->active_mm || current->active_mm == &init_mm || - mm_idp != ¤t->active_mm->context.skas.id) - switch_mm_skas(mm_idp); + if (!current->active_mm || current->active_mm == &init_mm || + mm_idp != ¤t->active_mm->context.id) + __switch_mm(mm_idp); } - if(ptrace_ldt) { + if (ptrace_ldt) { struct ptrace_ldt ldt_op = (struct ptrace_ldt) { .func = func, .ptr = desc, @@ -121,7 +45,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, u32 cpu; int pid; - if(!proc_mm) + if (!proc_mm) pid = mm_idp->u.pid; else { cpu = get_cpu(); @@ -130,7 +54,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); - if(proc_mm) + if (proc_mm) put_cpu(); } else { @@ -139,7 +63,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, (sizeof(*desc) + sizeof(long) - 1) & ~(sizeof(long) - 1), addr, &stub_addr); - if(!res){ + if (!res) { unsigned long args[] = { func, (unsigned long)stub_addr, sizeof(*desc), @@ -149,13 +73,14 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, } } - if(proc_mm){ - /* This is the second part of special handling, that makes + if (proc_mm) { + /* + * This is the second part of special handling, that makes * PTRACE_LDT possible to implement. */ - if(current->active_mm && current->active_mm != &init_mm && - mm_idp != ¤t->active_mm->context.skas.id) - switch_mm_skas(¤t->active_mm->context.skas.id); + if (current->active_mm && current->active_mm != &init_mm && + mm_idp != ¤t->active_mm->context.id) + __switch_mm(¤t->active_mm->context.id); } return res; @@ -170,21 +95,22 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) .ptr = kmalloc(bytecount, GFP_KERNEL)}; u32 cpu; - if(ptrace_ldt.ptr == NULL) + if (ptrace_ldt.ptr == NULL) return -ENOMEM; - /* This is called from sys_modify_ldt only, so userspace_pid gives + /* + * This is called from sys_modify_ldt only, so userspace_pid gives * us the right number */ cpu = get_cpu(); res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); put_cpu(); - if(res < 0) + if (res < 0) goto out; n = copy_to_user(ptr, ptrace_ldt.ptr, res); - if(n != 0) + if (n != 0) res = -EFAULT; out: @@ -209,35 +135,34 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) { int i, err = 0; unsigned long size; - uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; + uml_ldt_t * ldt = ¤t->mm->context.ldt; - if(!ldt->entry_count) + if (!ldt->entry_count) goto out; - if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) + if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; err = bytecount; - if(ptrace_ldt){ + if (ptrace_ldt) return read_ldt_from_host(ptr, bytecount); - } down(&ldt->semaphore); - if(ldt->entry_count <= LDT_DIRECT_ENTRIES){ + if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; - if(size > bytecount) + if (size > bytecount) size = bytecount; - if(copy_to_user(ptr, ldt->u.entries, size)) + if (copy_to_user(ptr, ldt->u.entries, size)) err = -EFAULT; bytecount -= size; ptr += size; } else { - for(i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount; - i++){ + for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount; + i++) { size = PAGE_SIZE; - if(size > bytecount) + if (size > bytecount) size = bytecount; - if(copy_to_user(ptr, ldt->u.pages[i], size)){ + if (copy_to_user(ptr, ldt->u.pages[i], size)) { err = -EFAULT; break; } @@ -247,10 +172,10 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) } up(&ldt->semaphore); - if(bytecount == 0 || err == -EFAULT) + if (bytecount == 0 || err == -EFAULT) goto out; - if(clear_user(ptr, bytecount)) + if (clear_user(ptr, bytecount)) err = -EFAULT; out: @@ -261,15 +186,16 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) { int err; - if(bytecount > 5*LDT_ENTRY_SIZE) + if (bytecount > 5*LDT_ENTRY_SIZE) bytecount = 5*LDT_ENTRY_SIZE; err = bytecount; - /* UML doesn't support lcall7 and lcall27. + /* + * UML doesn't support lcall7 and lcall27. * So, we don't really have a default ldt, but emulate * an empty ldt of common host default ldt size. */ - if(clear_user(ptr, bytecount)) + if (clear_user(ptr, bytecount)) err = -EFAULT; return err; @@ -277,60 +203,60 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) static int write_ldt(void __user * ptr, unsigned long bytecount, int func) { - uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; - struct mm_id * mm_idp = ¤t->mm->context.skas.id; + uml_ldt_t * ldt = ¤t->mm->context.ldt; + struct mm_id * mm_idp = ¤t->mm->context.id; int i, err; struct user_desc ldt_info; struct ldt_entry entry0, *ldt_p; void *addr = NULL; err = -EINVAL; - if(bytecount != sizeof(ldt_info)) + if (bytecount != sizeof(ldt_info)) goto out; err = -EFAULT; - if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) + if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) goto out; err = -EINVAL; - if(ldt_info.entry_number >= LDT_ENTRIES) + if (ldt_info.entry_number >= LDT_ENTRIES) goto out; - if(ldt_info.contents == 3){ + if (ldt_info.contents == 3) { if (func == 1) goto out; if (ldt_info.seg_not_present == 0) goto out; } - if(!ptrace_ldt) - down(&ldt->semaphore); + if (!ptrace_ldt) + down(&ldt->semaphore); err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); - if(err) + if (err) goto out_unlock; - else if(ptrace_ldt) { - /* With PTRACE_LDT available, this is used as a flag only */ - ldt->entry_count = 1; - goto out; - } - - if(ldt_info.entry_number >= ldt->entry_count && - ldt_info.entry_number >= LDT_DIRECT_ENTRIES){ - for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; - i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; - i++){ - if(i == 0) + else if (ptrace_ldt) { + /* With PTRACE_LDT available, this is used as a flag only */ + ldt->entry_count = 1; + goto out; + } + + if (ldt_info.entry_number >= ldt->entry_count && + ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { + for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; + i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; + i++) { + if (i == 0) memcpy(&entry0, ldt->u.entries, sizeof(entry0)); ldt->u.pages[i] = (struct ldt_entry *) __get_free_page(GFP_KERNEL|__GFP_ZERO); - if(!ldt->u.pages[i]){ + if (!ldt->u.pages[i]) { err = -ENOMEM; /* Undo the change in host */ memset(&ldt_info, 0, sizeof(ldt_info)); write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); goto out_unlock; } - if(i == 0) { + if (i == 0) { memcpy(ldt->u.pages[0], &entry0, sizeof(entry0)); memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, @@ -339,17 +265,17 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; } } - if(ldt->entry_count <= ldt_info.entry_number) + if (ldt->entry_count <= ldt_info.entry_number) ldt->entry_count = ldt_info.entry_number + 1; - if(ldt->entry_count <= LDT_DIRECT_ENTRIES) + if (ldt->entry_count <= LDT_DIRECT_ENTRIES) ldt_p = ldt->u.entries + ldt_info.entry_number; else ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; - if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && - (func == 1 || LDT_empty(&ldt_info))){ + if (ldt_info.base_addr == 0 && ldt_info.limit == 0 && + (func == 1 || LDT_empty(&ldt_info))) { ldt_p->a = 0; ldt_p->b = 0; } @@ -400,7 +326,7 @@ static void ldt_get_host_info(void) spin_lock(&host_ldt_lock); - if(host_ldt_entries != NULL){ + if (host_ldt_entries != NULL) { spin_unlock(&host_ldt_lock); return; } @@ -408,49 +334,49 @@ static void ldt_get_host_info(void) spin_unlock(&host_ldt_lock); - for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); + for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++) + ; ldt = (struct ldt_entry *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); - if(ldt == NULL) { - printk("ldt_get_host_info: couldn't allocate buffer for host " - "ldt\n"); + if (ldt == NULL) { + printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer " + "for host ldt\n"); return; } ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE); - if(ret < 0) { - printk("ldt_get_host_info: couldn't read host ldt\n"); + if (ret < 0) { + printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n"); goto out_free; } - if(ret == 0) { + if (ret == 0) { /* default_ldt is active, simply write an empty entry 0 */ host_ldt_entries = dummy_list; goto out_free; } - for(i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++){ - if(ldt[i].a != 0 || ldt[i].b != 0) + for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) { + if (ldt[i].a != 0 || ldt[i].b != 0) size++; } - if(size < ARRAY_SIZE(dummy_list)) + if (size < ARRAY_SIZE(dummy_list)) host_ldt_entries = dummy_list; else { size = (size + 1) * sizeof(dummy_list[0]); tmp = kmalloc(size, GFP_KERNEL); - if(tmp == NULL) { - printk("ldt_get_host_info: couldn't allocate host ldt " - "list\n"); + if (tmp == NULL) { + printk(KERN_ERR "ldt_get_host_info: couldn't allocate " + "host ldt list\n"); goto out_free; } host_ldt_entries = tmp; } - for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){ - if(ldt[i].a != 0 || ldt[i].b != 0) { + for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) { + if (ldt[i].a != 0 || ldt[i].b != 0) host_ldt_entries[k++] = i; - } } host_ldt_entries[k] = -1; @@ -458,8 +384,7 @@ out_free: free_pages((unsigned long)ldt, order); } -long init_new_ldt(struct mmu_context_skas * new_mm, - struct mmu_context_skas * from_mm) +long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) { struct user_desc desc; short * num_p; @@ -469,15 +394,15 @@ long init_new_ldt(struct mmu_context_skas * new_mm, struct proc_mm_op copy; - if(!ptrace_ldt) + if (!ptrace_ldt) init_MUTEX(&new_mm->ldt.semaphore); - if(!from_mm){ + if (!from_mm) { memset(&desc, 0, sizeof(desc)); /* * We have to initialize a clean ldt. */ - if(proc_mm) { + if (proc_mm) { /* * If the new mm was created using proc_mm, host's * default-ldt currently is assigned, which normally @@ -485,8 +410,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm, * To remove these gates, we simply write an empty * entry as number 0 to the host. */ - err = write_ldt_entry(&new_mm->id, 1, &desc, - &addr, 1); + err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); } else{ /* @@ -495,11 +419,11 @@ long init_new_ldt(struct mmu_context_skas * new_mm, * will be reset in the following loop */ ldt_get_host_info(); - for(num_p=host_ldt_entries; *num_p != -1; num_p++){ + for (num_p=host_ldt_entries; *num_p != -1; num_p++) { desc.entry_number = *num_p; err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, *(num_p + 1) == -1); - if(err) + if (err) break; } } @@ -508,8 +432,9 @@ long init_new_ldt(struct mmu_context_skas * new_mm, goto out; } - if(proc_mm){ - /* We have a valid from_mm, so we now have to copy the LDT of + if (proc_mm) { + /* + * We have a valid from_mm, so we now have to copy the LDT of * from_mm to new_mm, because using proc_mm an new mm with * an empty/default LDT was created in new_mm() */ @@ -518,27 +443,27 @@ long init_new_ldt(struct mmu_context_skas * new_mm, { .copy_segments = from_mm->id.u.mm_fd } } ); i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); - if(i != sizeof(copy)) - printk("new_mm : /proc/mm copy_segments failed, " - "err = %d\n", -i); + if (i != sizeof(copy)) + printk(KERN_ERR "new_mm : /proc/mm copy_segments " + "failed, err = %d\n", -i); } - if(!ptrace_ldt) { - /* Our local LDT is used to supply the data for + if (!ptrace_ldt) { + /* + * Our local LDT is used to supply the data for * modify_ldt(READLDT), if PTRACE_LDT isn't available, * i.e., we have to use the stub for modify_ldt, which * can't handle the big read buffer of up to 64kB. */ down(&from_mm->ldt.semaphore); - if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ + if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, sizeof(new_mm->ldt.u.entries)); - } - else{ + else { i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; - while(i-->0){ + while (i-->0) { page = __get_free_page(GFP_KERNEL|__GFP_ZERO); - if (!page){ + if (!page) { err = -ENOMEM; break; } @@ -557,22 +482,19 @@ long init_new_ldt(struct mmu_context_skas * new_mm, } -void free_ldt(struct mmu_context_skas * mm) +void free_ldt(struct mm_context *mm) { int i; - if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ + if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) { i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; - while(i-- > 0){ - free_page((long )mm->ldt.u.pages[i]); - } + while (i-- > 0) + free_page((long) mm->ldt.u.pages[i]); } mm->ldt.entry_count = 0; } -#endif int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { - return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, - ptr, bytecount); + return do_modify_ldt_skas(func, ptr, bytecount); } diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 28bf0115032..9657c89fdf3 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -1,35 +1,26 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <linux/compiler.h> -#include "linux/sched.h" #include "linux/mm.h" -#include "asm/elf.h" -#include "asm/ptrace.h" +#include "linux/sched.h" #include "asm/uaccess.h" -#include "asm/unistd.h" -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" -#include "sysdep/sc.h" +#include "skas.h" -void arch_switch_to_tt(struct task_struct *from, struct task_struct *to) -{ - update_debugregs(to->thread.arch.debugregs_seq); - arch_switch_tls_tt(from, to); -} +extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); -void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) +void arch_switch_to(struct task_struct *from, struct task_struct *to) { - int err = arch_switch_tls_skas(from, to); + int err = arch_switch_tls(from, to); if (!err) return; if (err != -EINVAL) - printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err); + printk(KERN_WARNING "arch_switch_tls failed, errno %d, " + "not EINVAL\n", -err); else - printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n"); + printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); } int is_syscall(unsigned long addr) @@ -38,21 +29,21 @@ int is_syscall(unsigned long addr) int n; n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if(n){ + if (n) { /* access_process_vm() grants access to vsyscall and stub, * while copy_from_user doesn't. Maybe access_process_vm is * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. */ n = access_process_vm(current, addr, &instr, sizeof(instr), 0); - if(n != sizeof(instr)) { - printk("is_syscall : failed to read instruction from " - "0x%lx\n", addr); - return(1); + if (n != sizeof(instr)) { + printk(KERN_ERR "is_syscall : failed to read " + "instruction from 0x%lx\n", addr); + return 1; } } /* int 0x80 or sysenter */ - return((instr == 0x80cd) || (instr == 0x340f)); + return (instr == 0x80cd) || (instr == 0x340f); } /* determines which flags the user has access to. */ @@ -96,21 +87,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value) int poke_user(struct task_struct *child, long addr, long data) { - if ((addr & 3) || addr < 0) - return -EIO; - - if (addr < MAX_REG_OFFSET) - return putreg(child, addr, data); + if ((addr & 3) || addr < 0) + return -EIO; - else if((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if((addr == 4) || (addr == 5)) return -EIO; - child->thread.arch.debugregs[addr] = data; - return 0; - } - return -EIO; + if (addr < MAX_REG_OFFSET) + return putreg(child, addr, data); + else if ((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))) { + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + if ((addr == 4) || (addr == 5)) + return -EIO; + child->thread.arch.debugregs[addr] = data; + return 0; + } + return -EIO; } unsigned long getreg(struct task_struct *child, int regno) @@ -133,20 +124,20 @@ unsigned long getreg(struct task_struct *child, int regno) return retval; } +/* read the word at location addr in the USER area. */ int peek_user(struct task_struct *child, long addr, long data) { -/* read the word at location addr in the USER area. */ unsigned long tmp; if ((addr & 3) || addr < 0) return -EIO; tmp = 0; /* Default return condition */ - if(addr < MAX_REG_OFFSET){ + if (addr < MAX_REG_OFFSET) { tmp = getreg(child, addr); } - else if((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ + else if ((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))) { addr -= offsetof(struct user, u_debugreg[0]); addr = addr >> 2; tmp = child->thread.arch.debugregs[addr]; @@ -154,277 +145,68 @@ int peek_user(struct task_struct *child, long addr, long data) return put_user(tmp, (unsigned long __user *) data); } -struct i387_fxsave_struct { - unsigned short cwd; - unsigned short swd; - unsigned short twd; - unsigned short fop; - long fip; - long fcs; - long foo; - long fos; - long mxcsr; - long reserved; - long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ - long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ - long padding[56]; -}; - -/* - * FPU tag word conversions. - */ - -static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) +int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { - unsigned int tmp; /* to avoid 16 bit prefixes in the code */ - - /* Transform each pair of bits into 01 (valid) or 00 (empty) */ - tmp = ~twd; - tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ - /* and move the valid bits to the lower byte. */ - tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ - tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ - tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ - return tmp; -} + int err, n, cpu = ((struct thread_info *) child->stack)->cpu; + long fpregs[HOST_FP_SIZE]; -static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) -{ - struct _fpxreg *st = NULL; - unsigned long twd = (unsigned long) fxsave->twd; - unsigned long tag; - unsigned long ret = 0xffff0000; - int i; + BUG_ON(sizeof(*buf) != sizeof(fpregs)); + err = save_fp_registers(userspace_pid[cpu], fpregs); + if (err) + return err; -#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); + n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); + if(n > 0) + return -EFAULT; - for ( i = 0 ; i < 8 ; i++ ) { - if ( twd & 0x1 ) { - st = (struct _fpxreg *) FPREG_ADDR( fxsave, i ); - - switch ( st->exponent & 0x7fff ) { - case 0x7fff: - tag = 2; /* Special */ - break; - case 0x0000: - if ( !st->significand[0] && - !st->significand[1] && - !st->significand[2] && - !st->significand[3] ) { - tag = 1; /* Zero */ - } else { - tag = 2; /* Special */ - } - break; - default: - if ( st->significand[3] & 0x8000 ) { - tag = 0; /* Valid */ - } else { - tag = 2; /* Special */ - } - break; - } - } else { - tag = 3; /* Empty */ - } - ret |= (tag << (2 * i)); - twd = twd >> 1; - } - return ret; + return n; } -/* - * FXSR floating point environment conversions. - */ - -#ifdef CONFIG_MODE_TT -static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf, - struct pt_regs *regs) +int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { - struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); - unsigned long env[7]; - struct _fpreg __user *to; - struct _fpxreg *from; - int i; + int n, cpu = ((struct thread_info *) child->stack)->cpu; + long fpregs[HOST_FP_SIZE]; - env[0] = (unsigned long)fxsave->cwd | 0xffff0000; - env[1] = (unsigned long)fxsave->swd | 0xffff0000; - env[2] = twd_fxsr_to_i387(fxsave); - env[3] = fxsave->fip; - env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); - env[5] = fxsave->foo; - env[6] = fxsave->fos; + BUG_ON(sizeof(*buf) != sizeof(fpregs)); + n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); + if (n > 0) + return -EFAULT; - if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) ) - return 1; - - to = &buf->_st[0]; - from = (struct _fpxreg *) &fxsave->st_space[0]; - for ( i = 0 ; i < 8 ; i++, to++, from++ ) { - if ( __copy_to_user( to, from, sizeof(*to) ) ) - return 1; - } - return 0; + return restore_fp_registers(userspace_pid[cpu], fpregs); } -#endif -static inline int convert_fxsr_to_user(struct _fpstate __user *buf, - struct pt_regs *regs) +int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { - return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); -} + int err, n, cpu = ((struct thread_info *) child->stack)->cpu; + long fpregs[HOST_XFP_SIZE]; -#ifdef CONFIG_MODE_TT -static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, - struct _fpstate __user *buf) -{ - struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); - unsigned long env[7]; - struct _fpxreg *to; - struct _fpreg __user *from; - int i; - - if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) - return 1; + BUG_ON(sizeof(*buf) != sizeof(fpregs)); + err = save_fpx_registers(userspace_pid[cpu], fpregs); + if (err) + return err; - fxsave->cwd = (unsigned short)(env[0] & 0xffff); - fxsave->swd = (unsigned short)(env[1] & 0xffff); - fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); - fxsave->fip = env[3]; - fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16); - fxsave->fcs = (env[4] & 0xffff); - fxsave->foo = env[5]; - fxsave->fos = env[6]; + n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); + if(n > 0) + return -EFAULT; - to = (struct _fpxreg *) &fxsave->st_space[0]; - from = &buf->_st[0]; - for ( i = 0 ; i < 8 ; i++, to++, from++ ) { - if ( __copy_from_user( to, from, sizeof(*from) ) ) - return 1; - } - return 0; -} -#endif - -static inline int convert_fxsr_from_user(struct pt_regs *regs, - struct _fpstate __user *buf) -{ - return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); -} - -int get_fpregs(unsigned long buf, struct task_struct *child) -{ - int err; - - err = convert_fxsr_to_user((struct _fpstate __user *) buf, - &child->thread.regs); - if(err) return(-EFAULT); - else return(0); -} - -int set_fpregs(unsigned long buf, struct task_struct *child) -{ - int err; - - err = convert_fxsr_from_user(&child->thread.regs, - (struct _fpstate __user *) buf); - if(err) return(-EFAULT); - else return(0); -} - -#ifdef CONFIG_MODE_TT -int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -{ - struct pt_regs *regs = &tsk->thread.regs; - struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); - int err; - - err = __copy_to_user((void __user *) buf, fxsave, - sizeof(struct user_fxsr_struct)); - if(err) return -EFAULT; - else return 0; -} -#endif - -int get_fpxregs(unsigned long buf, struct task_struct *tsk) -{ - return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0)); -} - -#ifdef CONFIG_MODE_TT -int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -{ - struct pt_regs *regs = &tsk->thread.regs; - struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); - int err; - - err = __copy_from_user(fxsave, (void __user *) buf, - sizeof(struct user_fxsr_struct) ); - if(err) return -EFAULT; - else return 0; -} -#endif - -int set_fpxregs(unsigned long buf, struct task_struct *tsk) -{ - return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0)); -} - -#ifdef notdef -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -{ - fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) | - (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff)); - fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; - fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs)); - fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; - fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs)); - fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs)); - fpu->fos = 0; - memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), - sizeof(fpu->st_space)); - return(1); + return n; } -#endif -#ifdef CONFIG_MODE_TT -static inline void copy_fpu_fxsave_tt(struct pt_regs *regs, - struct user_i387_struct *buf) +int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { - struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs)); - unsigned short *to; - unsigned short *from; - int i; + int n, cpu = ((struct thread_info *) child->stack)->cpu; + long fpregs[HOST_XFP_SIZE]; - memcpy( buf, fpu, 7 * sizeof(long) ); + BUG_ON(sizeof(*buf) != sizeof(fpregs)); + n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); + if (n > 0) + return -EFAULT; - to = (unsigned short *) &buf->st_space[0]; - from = (unsigned short *) &fpu->st_space[0]; - for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) { - memcpy( to, from, 5 * sizeof(unsigned short) ); - } + return restore_fpx_registers(userspace_pid[cpu], fpregs); } -#endif -static inline void copy_fpu_fxsave(struct pt_regs *regs, - struct user_i387_struct *buf) +long subarch_ptrace(struct task_struct *child, long request, long addr, + long data) { - (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0); + return -EIO; } - -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) -{ - copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu); - return(1); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 40ff0c831bd..5cf97bc229b 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c @@ -1,20 +1,10 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdio.h> -#include <stddef.h> #include <errno.h> -#include <unistd.h> -#include "ptrace_user.h" -/* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */ -#include <asm/user.h> -#include "kern_util.h" -#include "sysdep/thread.h" -#include "user.h" -#include "os.h" -#include "uml-config.h" +#include <sys/ptrace.h> int ptrace_getregs(long pid, unsigned long *regs_out) { @@ -43,89 +33,3 @@ int ptrace_setfpregs(long pid, unsigned long *regs) return -errno; return 0; } - -#ifdef UML_CONFIG_MODE_TT - -static void write_debugregs(int pid, unsigned long *regs) -{ - struct user *dummy; - int nregs, i; - - dummy = NULL; - nregs = ARRAY_SIZE(dummy->u_debugreg); - for(i = 0; i < nregs; i++){ - if((i == 4) || (i == 5)) continue; - if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], - regs[i]) < 0) - printk("write_debugregs - ptrace failed on " - "register %d, value = 0x%lx, errno = %d\n", i, - regs[i], errno); - } -} - -static void read_debugregs(int pid, unsigned long *regs) -{ - struct user *dummy; - int nregs, i; - - dummy = NULL; - nregs = ARRAY_SIZE(dummy->u_debugreg); - for(i = 0; i < nregs; i++){ - regs[i] = ptrace(PTRACE_PEEKUSR, pid, - &dummy->u_debugreg[i], 0); - } -} - -/* Accessed only by the tracing thread */ -static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; - -void arch_enter_kernel(void *task, int pid) -{ - read_debugregs(pid, TASK_DEBUGREGS(task)); - write_debugregs(pid, kernel_debugregs); -} - -void arch_leave_kernel(void *task, int pid) -{ - read_debugregs(pid, kernel_debugregs); - write_debugregs(pid, TASK_DEBUGREGS(task)); -} - -#ifdef UML_CONFIG_PT_PROXY -/* Accessed only by the tracing thread */ -static int debugregs_seq; - -/* Only called by the ptrace proxy */ -void ptrace_pokeuser(unsigned long addr, unsigned long data) -{ - if((addr < offsetof(struct user, u_debugreg[0])) || - (addr > offsetof(struct user, u_debugreg[7]))) - return; - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if(kernel_debugregs[addr] == data) return; - - kernel_debugregs[addr] = data; - debugregs_seq++; -} - -static void update_debugregs_cb(void *arg) -{ - int pid = *((int *) arg); - - write_debugregs(pid, kernel_debugregs); -} - -/* Optimized out in its header when not defined */ -void update_debugregs(int seq) -{ - int me; - - if(seq == debugregs_seq) return; - - me = os_getpid(); - initial_thread_cb(update_debugregs_cb, &me); -} -#endif - -#endif diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c deleted file mode 100644 index 467d489c31c..00000000000 --- a/arch/um/sys-i386/sigcontext.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stddef.h> -#include <string.h> -#include <asm/ptrace.h> -#include <asm/sigcontext.h> -#include "sysdep/ptrace.h" -#include "kern_util.h" - -void sc_to_sc(void *to_ptr, void *from_ptr) -{ - struct sigcontext *to = to_ptr, *from = from_ptr; - - memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate)); - if(from->fpstate != NULL) - to->fpstate = (struct _fpstate *) (to + 1); -} - -unsigned long *sc_sigmask(void *sc_ptr) -{ - struct sigcontext *sc = sc_ptr; - return &sc->oldmask; -} - -int sc_get_fpregs(unsigned long buf, void *sc_ptr) -{ - struct sigcontext *sc = sc_ptr; - struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf; - int err = 0; - - if(from == NULL){ - err |= clear_user_proc(&to->cw, sizeof(to->cw)); - err |= clear_user_proc(&to->sw, sizeof(to->sw)); - err |= clear_user_proc(&to->tag, sizeof(to->tag)); - err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff)); - err |= clear_user_proc(&to->cssel, sizeof(to->cssel)); - err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff)); - err |= clear_user_proc(&to->datasel, sizeof(to->datasel)); - err |= clear_user_proc(&to->_st, sizeof(to->_st)); - } - else { - err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw)); - err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw)); - err |= copy_to_user_proc(&to->tag, &from->tag, - sizeof(to->tag)); - err |= copy_to_user_proc(&to->ipoff, &from->ipoff, - sizeof(to->ipoff)); - err |= copy_to_user_proc(&to->cssel,& from->cssel, - sizeof(to->cssel)); - err |= copy_to_user_proc(&to->dataoff, &from->dataoff, - sizeof(to->dataoff)); - err |= copy_to_user_proc(&to->datasel, &from->datasel, - sizeof(to->datasel)); - err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st)); - } - return(err); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 1cbf95f6858..0147227ce18 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c @@ -1,189 +1,293 @@ /* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/signal.h" #include "linux/ptrace.h" -#include "asm/current.h" -#include "asm/ucontext.h" -#include "asm/uaccess.h" #include "asm/unistd.h" +#include "asm/uaccess.h" +#include "asm/ucontext.h" #include "frame_kern.h" -#include "sigcontext.h" -#include "registers.h" -#include "mode.h" - -#ifdef CONFIG_MODE_SKAS - #include "skas.h" -void copy_sc(union uml_pt_regs *regs, void *from) +void copy_sc(struct uml_pt_regs *regs, void *from) { struct sigcontext *sc = from; - REGS_GS(regs->skas.regs) = sc->gs; - REGS_FS(regs->skas.regs) = sc->fs; - REGS_ES(regs->skas.regs) = sc->es; - REGS_DS(regs->skas.regs) = sc->ds; - REGS_EDI(regs->skas.regs) = sc->edi; - REGS_ESI(regs->skas.regs) = sc->esi; - REGS_EBP(regs->skas.regs) = sc->ebp; - REGS_SP(regs->skas.regs) = sc->esp; - REGS_EBX(regs->skas.regs) = sc->ebx; - REGS_EDX(regs->skas.regs) = sc->edx; - REGS_ECX(regs->skas.regs) = sc->ecx; - REGS_EAX(regs->skas.regs) = sc->eax; - REGS_IP(regs->skas.regs) = sc->eip; - REGS_CS(regs->skas.regs) = sc->cs; - REGS_EFLAGS(regs->skas.regs) = sc->eflags; - REGS_SS(regs->skas.regs) = sc->ss; + REGS_GS(regs->gp) = sc->gs; + REGS_FS(regs->gp) = sc->fs; + REGS_ES(regs->gp) = sc->es; + REGS_DS(regs->gp) = sc->ds; + REGS_EDI(regs->gp) = sc->edi; + REGS_ESI(regs->gp) = sc->esi; + REGS_EBP(regs->gp) = sc->ebp; + REGS_SP(regs->gp) = sc->esp; + REGS_EBX(regs->gp) = sc->ebx; + REGS_EDX(regs->gp) = sc->edx; + REGS_ECX(regs->gp) = sc->ecx; + REGS_EAX(regs->gp) = sc->eax; + REGS_IP(regs->gp) = sc->eip; + REGS_CS(regs->gp) = sc->cs; + REGS_EFLAGS(regs->gp) = sc->eflags; + REGS_SS(regs->gp) = sc->ss; } -static int copy_sc_from_user_skas(struct pt_regs *regs, - struct sigcontext __user *from) +/* + * FPU tag word conversions. + */ + +static inline unsigned short twd_i387_to_fxsr(unsigned short twd) { - struct sigcontext sc; - unsigned long fpregs[HOST_FP_SIZE]; - int err; + unsigned int tmp; /* to avoid 16 bit prefixes in the code */ + + /* Transform each pair of bits into 01 (valid) or 00 (empty) */ + tmp = ~twd; + tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ + /* and move the valid bits to the lower byte. */ + tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ + tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ + tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ + return tmp; +} - err = copy_from_user(&sc, from, sizeof(sc)); - err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); - if(err) - return err; +static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) +{ + struct _fpxreg *st = NULL; + unsigned long twd = (unsigned long) fxsave->twd; + unsigned long tag; + unsigned long ret = 0xffff0000; + int i; + +#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); + + for (i = 0; i < 8; i++) { + if (twd & 0x1) { + st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); + + switch (st->exponent & 0x7fff) { + case 0x7fff: + tag = 2; /* Special */ + break; + case 0x0000: + if ( !st->significand[0] && + !st->significand[1] && + !st->significand[2] && + !st->significand[3] ) { + tag = 1; /* Zero */ + } else { + tag = 2; /* Special */ + } + break; + default: + if (st->significand[3] & 0x8000) { + tag = 0; /* Valid */ + } else { + tag = 2; /* Special */ + } + break; + } + } else { + tag = 3; /* Empty */ + } + ret |= (tag << (2 * i)); + twd = twd >> 1; + } + return ret; +} - copy_sc(®s->regs, &sc); +static int convert_fxsr_to_user(struct _fpstate __user *buf, + struct user_fxsr_struct *fxsave) +{ + unsigned long env[7]; + struct _fpreg __user *to; + struct _fpxreg *from; + int i; + + env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; + env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; + env[2] = twd_fxsr_to_i387(fxsave); + env[3] = fxsave->fip; + env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); + env[5] = fxsave->foo; + env[6] = fxsave->fos; + + if (__copy_to_user(buf, env, 7 * sizeof(unsigned long))) + return 1; - err = restore_fp_registers(userspace_pid[0], fpregs); - if(err < 0) { - printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " - "errno = %d\n", -err); - return err; - } + to = &buf->_st[0]; + from = (struct _fpxreg *) &fxsave->st_space[0]; + for (i = 0; i < 8; i++, to++, from++) { + unsigned long __user *t = (unsigned long __user *)to; + unsigned long *f = (unsigned long *)from; + if (__put_user(*f, t) || + __put_user(*(f + 1), t + 1) || + __put_user(from->exponent, &to->exponent)) + return 1; + } return 0; } -int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, - struct pt_regs *regs, unsigned long sp) +static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, + struct _fpstate __user *buf) { - struct sigcontext sc; - unsigned long fpregs[HOST_FP_SIZE]; - struct faultinfo * fi = ¤t->thread.arch.faultinfo; - int err; + unsigned long env[7]; + struct _fpxreg *to; + struct _fpreg __user *from; + int i; - sc.gs = REGS_GS(regs->regs.skas.regs); - sc.fs = REGS_FS(regs->regs.skas.regs); - sc.es = REGS_ES(regs->regs.skas.regs); - sc.ds = REGS_DS(regs->regs.skas.regs); - sc.edi = REGS_EDI(regs->regs.skas.regs); - sc.esi = REGS_ESI(regs->regs.skas.regs); - sc.ebp = REGS_EBP(regs->regs.skas.regs); - sc.esp = sp; - sc.ebx = REGS_EBX(regs->regs.skas.regs); - sc.edx = REGS_EDX(regs->regs.skas.regs); - sc.ecx = REGS_ECX(regs->regs.skas.regs); - sc.eax = REGS_EAX(regs->regs.skas.regs); - sc.eip = REGS_IP(regs->regs.skas.regs); - sc.cs = REGS_CS(regs->regs.skas.regs); - sc.eflags = REGS_EFLAGS(regs->regs.skas.regs); - sc.esp_at_signal = regs->regs.skas.regs[UESP]; - sc.ss = regs->regs.skas.regs[SS]; - sc.cr2 = fi->cr2; - sc.err = fi->error_code; - sc.trapno = fi->trap_no; - - err = save_fp_registers(userspace_pid[0], fpregs); - if(err < 0){ - printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " - "errno = %d\n", err); + if (copy_from_user( env, buf, 7 * sizeof(long))) return 1; - } - to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); - sc.fpstate = to_fp; - if(err) - return err; - - return copy_to_user(to, &sc, sizeof(sc)) || - copy_to_user(to_fp, fpregs, sizeof(fpregs)); + fxsave->cwd = (unsigned short)(env[0] & 0xffff); + fxsave->swd = (unsigned short)(env[1] & 0xffff); + fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); + fxsave->fip = env[3]; + fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); + fxsave->fcs = (env[4] & 0xffff); + fxsave->foo = env[5]; + fxsave->fos = env[6]; + + to = (struct _fpxreg *) &fxsave->st_space[0]; + from = &buf->_st[0]; + for (i = 0; i < 8; i++, to++, from++) { + unsigned long *t = (unsigned long *)to; + unsigned long __user *f = (unsigned long __user *)from; + + if (__get_user(*t, f) || + __get_user(*(t + 1), f + 1) || + __get_user(to->exponent, &from->exponent)) + return 1; + } + return 0; } -#endif -#ifdef CONFIG_MODE_TT +extern int have_fpx_regs; -/* These copy a sigcontext to/from userspace. They copy the fpstate pointer, - * blowing away the old, good one. So, that value is saved, and then restored - * after the sigcontext copy. In copy_from, the variable holding the saved - * fpstate pointer, and the sigcontext that it should be restored to are both - * in the kernel, so we can just restore using an assignment. In copy_to, the - * saved pointer is in the kernel, but the sigcontext is in userspace, so we - * copy_to_user it. - */ -int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, - int fpsize) +static int copy_sc_from_user(struct pt_regs *regs, + struct sigcontext __user *from) { - struct _fpstate *to_fp; - struct _fpstate __user *from_fp; - unsigned long sigs; + struct sigcontext sc; int err; - to_fp = to->fpstate; - sigs = to->oldmask; - err = copy_from_user(to, from, sizeof(*to)); - from_fp = to->fpstate; - to->oldmask = sigs; - to->fpstate = to_fp; - if(to_fp != NULL) - err |= copy_from_user(to_fp, from_fp, fpsize); - return err; + err = copy_from_user(&sc, from, sizeof(sc)); + if (err) + return err; + + copy_sc(®s->regs, &sc); + if (have_fpx_regs) { + struct user_fxsr_struct fpx; + + err = copy_from_user(&fpx, &sc.fpstate->_fxsr_env[0], + sizeof(struct user_fxsr_struct)); + if (err) + return 1; + + err = convert_fxsr_from_user(&fpx, sc.fpstate); + if (err) + return 1; + + err = restore_fpx_registers(userspace_pid[current_thread->cpu], + (unsigned long *) &fpx); + if (err < 0) { + printk(KERN_ERR "copy_sc_from_user - " + "restore_fpx_registers failed, errno = %d\n", + -err); + return 1; + } + } + else { + struct user_i387_struct fp; + + err = copy_from_user(&fp, sc.fpstate, + sizeof(struct user_i387_struct)); + if (err) + return 1; + + err = restore_fp_registers(userspace_pid[current_thread->cpu], + (unsigned long *) &fp); + if (err < 0) { + printk(KERN_ERR "copy_sc_from_user - " + "restore_fp_registers failed, errno = %d\n", + -err); + return 1; + } + } + + return 0; } -int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, - struct sigcontext *from, int fpsize, unsigned long sp) +static int copy_sc_to_user(struct sigcontext __user *to, + struct _fpstate __user *to_fp, struct pt_regs *regs, + unsigned long sp) { - struct _fpstate __user *to_fp; - struct _fpstate *from_fp; + struct sigcontext sc; + struct faultinfo * fi = ¤t->thread.arch.faultinfo; int err; - to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); - from_fp = from->fpstate; - err = copy_to_user(to, from, sizeof(*to)); + sc.gs = REGS_GS(regs->regs.gp); + sc.fs = REGS_FS(regs->regs.gp); + sc.es = REGS_ES(regs->regs.gp); + sc.ds = REGS_DS(regs->regs.gp); + sc.edi = REGS_EDI(regs->regs.gp); + sc.esi = REGS_ESI(regs->regs.gp); + sc.ebp = REGS_EBP(regs->regs.gp); + sc.esp = sp; + sc.ebx = REGS_EBX(regs->regs.gp); + sc.edx = REGS_EDX(regs->regs.gp); + sc.ecx = REGS_ECX(regs->regs.gp); + sc.eax = REGS_EAX(regs->regs.gp); + sc.eip = REGS_IP(regs->regs.gp); + sc.cs = REGS_CS(regs->regs.gp); + sc.eflags = REGS_EFLAGS(regs->regs.gp); + sc.esp_at_signal = regs->regs.gp[UESP]; + sc.ss = regs->regs.gp[SS]; + sc.cr2 = fi->cr2; + sc.err = fi->error_code; + sc.trapno = fi->trap_no; - /* The SP in the sigcontext is the updated one for the signal - * delivery. The sp passed in is the original, and this needs - * to be restored, so we stick it in separately. - */ - err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); + to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); + sc.fpstate = to_fp; - if(from_fp != NULL){ - err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); - err |= copy_to_user(to_fp, from_fp, fpsize); + if (have_fpx_regs) { + struct user_fxsr_struct fpx; + + err = save_fpx_registers(userspace_pid[current_thread->cpu], + (unsigned long *) &fpx); + if (err < 0){ + printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " + "failed, errno = %d\n", err); + return 1; + } + + err = convert_fxsr_to_user(to_fp, &fpx); + if (err) + return 1; + + err |= __put_user(fpx.swd, &to_fp->status); + err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); + if (err) + return 1; + + if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, + sizeof(struct user_fxsr_struct))) + return 1; } - return err; -} -#endif - -static int copy_sc_from_user(struct pt_regs *to, void __user *from) -{ - int ret; + else { + struct user_i387_struct fp; - ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, - sizeof(struct _fpstate)), - copy_sc_from_user_skas(to, from)); - return ret; -} + err = save_fp_registers(userspace_pid[current_thread->cpu], + (unsigned long *) &fp); + if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) + return 1; + } -static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, - struct pt_regs *from, unsigned long sp) -{ - return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), - sizeof(*fp), sp), - copy_sc_to_user_skas(to, fp, from, sp)); + return copy_to_user(to, &sc, sizeof(sc)); } -static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, - sigset_t *set, unsigned long sp) +static int copy_ucontext_to_user(struct ucontext __user *uc, + struct _fpstate __user *fp, sigset_t *set, + unsigned long sp) { int err = 0; @@ -233,7 +337,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, return 1; restorer = frame->retcode; - if(ka->sa.sa_flags & SA_RESTORER) + if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; /* Update SP now because the page fault handler refuses to extend @@ -265,7 +369,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); - if(err) + if (err) goto err; PT_REGS_SP(regs) = (unsigned long) frame; @@ -298,7 +402,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, return 1; restorer = frame->retcode; - if(ka->sa.sa_flags & SA_RESTORER) + if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; /* See comment above about why this is here */ @@ -323,7 +427,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); - if(err) + if (err) goto err; PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; @@ -350,8 +454,8 @@ long sys_sigreturn(struct pt_regs regs) unsigned long __user *extramask = frame->extramask; int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); - if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || - copy_from_user(&set.sig[1], extramask, sig_size)) + if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || + copy_from_user(&set.sig[1], extramask, sig_size)) goto segfault; sigdelsetmask(&set, ~_BLOCKABLE); @@ -361,7 +465,7 @@ long sys_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if(copy_sc_from_user(¤t->thread.regs, sc)) + if (copy_sc_from_user(¤t->thread.regs, sc)) goto segfault; /* Avoid ERESTART handling */ @@ -376,12 +480,13 @@ long sys_sigreturn(struct pt_regs regs) long sys_rt_sigreturn(struct pt_regs regs) { unsigned long sp = PT_REGS_SP(¤t->thread.regs); - struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4); + struct rt_sigframe __user *frame = + (struct rt_sigframe __user *) (sp - 4); sigset_t set; struct ucontext __user *uc = &frame->uc; int sig_size = _NSIG_WORDS * sizeof(unsigned long); - if(copy_from_user(&set, &uc->uc_sigmask, sig_size)) + if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) goto segfault; sigdelsetmask(&set, ~_BLOCKABLE); @@ -391,7 +496,7 @@ long sys_rt_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) + if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) goto segfault; /* Avoid ERESTART handling */ diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S index 6a70d9ab5c2..e730772c401 100644 --- a/arch/um/sys-i386/stub.S +++ b/arch/um/sys-i386/stub.S @@ -1,4 +1,5 @@ #include "uml-config.h" +#include "as-layout.h" .globl syscall_stub .section .__syscall_stub, "x" @@ -6,7 +7,7 @@ .globl batch_syscall_stub batch_syscall_stub: /* load pointer to first operation */ - mov $(UML_CONFIG_STUB_DATA+8), %esp + mov $(ASM_STUB_DATA+8), %esp again: /* load length of additional data */ @@ -14,12 +15,12 @@ again: /* if(length == 0) : end of list */ /* write possible 0 to header */ - mov %eax, UML_CONFIG_STUB_DATA+4 + mov %eax, ASM_STUB_DATA+4 cmpl $0, %eax jz done /* save current pointer */ - mov %esp, UML_CONFIG_STUB_DATA+4 + mov %esp, ASM_STUB_DATA+4 /* skip additional data */ add %eax, %esp @@ -45,7 +46,7 @@ again: done: /* save return value */ - mov %eax, UML_CONFIG_STUB_DATA + mov %eax, ASM_STUB_DATA /* stop */ int3 diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index 2355dc19c46..b3999cb76bf 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c @@ -6,6 +6,7 @@ #include <signal.h> #include <sys/select.h> /* The only way I can see to get sigset_t */ #include <asm/unistd.h> +#include "as-layout.h" #include "uml-config.h" #include "sysdep/stub.h" #include "sysdep/sigcontext.h" @@ -17,8 +18,7 @@ stub_segv_handler(int sig) struct sigcontext *sc = (struct sigcontext *) (&sig + 1); int pid; - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), - sc); + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc); pid = stub_syscall0(__NR_getpid); stub_syscall2(__NR_kill, pid, SIGUSR1); diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c index fea8e5e15cc..b02266ab5c5 100644 --- a/arch/um/sys-i386/tls.c +++ b/arch/um/sys-i386/tls.c @@ -3,25 +3,12 @@ * Licensed under the GPL */ -#include "linux/kernel.h" +#include "linux/percpu.h" #include "linux/sched.h" -#include "linux/slab.h" -#include "linux/types.h" #include "asm/uaccess.h" -#include "asm/ptrace.h" -#include "asm/segment.h" -#include "asm/smp.h" -#include "asm/desc.h" -#include "choose-mode.h" -#include "kern.h" -#include "kern_util.h" -#include "mode_kern.h" #include "os.h" -#include "mode.h" - -#ifdef CONFIG_MODE_SKAS #include "skas.h" -#endif +#include "sysdep/tls.h" /* * If needed we can detect when it's uninitialized. @@ -31,8 +18,7 @@ static int host_supports_tls = -1; int host_gdt_entry_tls_min; -#ifdef CONFIG_MODE_SKAS -int do_set_thread_area_skas(struct user_desc *info) +int do_set_thread_area(struct user_desc *info) { int ret; u32 cpu; @@ -43,7 +29,7 @@ int do_set_thread_area_skas(struct user_desc *info) return ret; } -int do_get_thread_area_skas(struct user_desc *info) +int do_get_thread_area(struct user_desc *info) { int ret; u32 cpu; @@ -53,7 +39,6 @@ int do_get_thread_area_skas(struct user_desc *info) put_cpu(); return ret; } -#endif /* * sys_get_thread_area: get a yet unused TLS descriptor index. @@ -82,7 +67,8 @@ static inline void clear_user_desc(struct user_desc* info) /* Postcondition: LDT_empty(info) returns true. */ memset(info, 0, sizeof(*info)); - /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain + /* + * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain * indeed an empty user_desc. */ info->read_exec_only = 1; @@ -97,10 +83,13 @@ static int load_TLS(int flags, struct task_struct *to) int idx; for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) { - struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; + struct uml_tls_struct* curr = + &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; - /* Actually, now if it wasn't flushed it gets cleared and - * flushed to the host, which will clear it.*/ + /* + * Actually, now if it wasn't flushed it gets cleared and + * flushed to the host, which will clear it. + */ if (!curr->present) { if (!curr->flushed) { clear_user_desc(&curr->tls); @@ -124,7 +113,8 @@ out: return ret; } -/* Verify if we need to do a flush for the new process, i.e. if there are any +/* + * Verify if we need to do a flush for the new process, i.e. if there are any * present desc's, only if they haven't been flushed. */ static inline int needs_TLS_update(struct task_struct *task) @@ -133,10 +123,13 @@ static inline int needs_TLS_update(struct task_struct *task) int ret = 0; for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { - struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; + struct uml_tls_struct* curr = + &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; - /* Can't test curr->present, we may need to clear a descriptor - * which had a value. */ + /* + * Can't test curr->present, we may need to clear a descriptor + * which had a value. + */ if (curr->flushed) continue; ret = 1; @@ -145,7 +138,8 @@ static inline int needs_TLS_update(struct task_struct *task) return ret; } -/* On a newly forked process, the TLS descriptors haven't yet been flushed. So +/* + * On a newly forked process, the TLS descriptors haven't yet been flushed. So * we mark them as such and the first switch_to will do the job. */ void clear_flushed_tls(struct task_struct *task) @@ -153,10 +147,13 @@ void clear_flushed_tls(struct task_struct *task) int i; for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { - struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; + struct uml_tls_struct* curr = + &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; - /* Still correct to do this, if it wasn't present on the host it - * will remain as flushed as it was. */ + /* + * Still correct to do this, if it wasn't present on the host it + * will remain as flushed as it was. + */ if (!curr->present) continue; @@ -164,40 +161,33 @@ void clear_flushed_tls(struct task_struct *task) } } -/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a +/* + * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a * common host process. So this is needed in SKAS0 too. * * However, if each thread had a different host process (and this was discussed * for SMP support) this won't be needed. * * And this will not need be used when (and if) we'll add support to the host - * SKAS patch. */ + * SKAS patch. + */ -int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) +int arch_switch_tls(struct task_struct *from, struct task_struct *to) { if (!host_supports_tls) return 0; - /* We have no need whatsoever to switch TLS for kernel threads; beyond + /* + * We have no need whatsoever to switch TLS for kernel threads; beyond * that, that would also result in us calling os_set_thread_area with - * userspace_pid[cpu] == 0, which gives an error. */ + * userspace_pid[cpu] == 0, which gives an error. + */ if (likely(to->mm)) return load_TLS(O_FORCE, to); return 0; } -int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to) -{ - if (!host_supports_tls) - return 0; - - if (needs_TLS_update(to)) - return load_TLS(0, to); - - return 0; -} - static int set_tls_entry(struct task_struct* task, struct user_desc *info, int idx, int flushed) { @@ -251,17 +241,20 @@ static int get_tls_entry(struct task_struct* task, struct user_desc *info, int i *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls; out: - /* Temporary debugging check, to make sure that things have been + /* + * Temporary debugging check, to make sure that things have been * flushed. This could be triggered if load_TLS() failed. */ - if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { + if (unlikely(task == current && + !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { printk(KERN_ERR "get_tls_entry: task with pid %d got here " "without flushed TLS.", current->pid); } return 0; clear: - /* When the TLS entry has not been set, the values read to user in the + /* + * When the TLS entry has not been set, the values read to user in the * tls_array are 0 (because it's cleared at boot, see * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that. */ @@ -293,7 +286,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) return -EFAULT; } - ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info); + ret = do_set_thread_area(&info); if (ret) return ret; return set_tls_entry(current, &info, idx, 1); @@ -363,8 +356,10 @@ out: } -/* XXX: This part is probably common to i386 and x86-64. Don't create a common - * file for now, do that when implementing x86-64 support.*/ +/* + * XXX: This part is probably common to i386 and x86-64. Don't create a common + * file for now, do that when implementing x86-64 support. + */ static int __init __setup_host_supports_tls(void) { check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c deleted file mode 100644 index 1b0ad0e4adc..00000000000 --- a/arch/um/sys-i386/unmap.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <linux/mman.h> -#include <asm/unistd.h> - -static int errno; - -static inline _syscall2(int,munmap,void *,start,size_t,len) -static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) -int switcheroo(int fd, int prot, void *from, void *to, int size) -{ - if(munmap(to, size) < 0){ - return(-1); - } - if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ - return(-1); - } - if(munmap(from, size) < 0){ - return(-1); - } - return(0); -} diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 29118cf5ff2..514241526a1 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c @@ -2,9 +2,9 @@ #include <stddef.h> #include <signal.h> #include <sys/poll.h> +#include <sys/user.h> #include <sys/mman.h> #include <asm/ptrace.h> -#include <asm/user.h> #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -48,8 +48,8 @@ void foo(void) OFFSET(HOST_SC_FP_ST, _fpstate, _st); OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); - DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); - DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); + DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); + DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct)); DEFINE(HOST_IP, EIP); DEFINE(HOST_SP, UESP); diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index ea8185d8540..3c22de53208 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -5,10 +5,9 @@ # obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ - setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ - ksyms.o tls.o + setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ + sysrq.o ksyms.o tls.o -obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o obj-$(CONFIG_MODULES) += um_module.o subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o @@ -16,16 +15,12 @@ subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o ldt-y = ../sys-i386/ldt.o -USER_OBJS := ptrace_user.o sigcontext.o +USER_OBJS := ptrace_user.o USER_OBJS += user-offsets.s extra-y += user-offsets.s -extra-$(CONFIG_MODE_TT) += unmap.o - UNPROFILE_OBJS := stub_segv.o CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) include arch/um/scripts/Makefile.rules - -$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS)) diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c index 09547889037..506b6765bbc 100644 --- a/arch/um/sys-x86_64/bugs.c +++ b/arch/um/sys-x86_64/bugs.c @@ -14,7 +14,7 @@ void arch_check_bugs(void) { } -int arch_handle_signal(int sig, union uml_pt_regs *regs) +int arch_handle_signal(int sig, struct uml_pt_regs *regs) { return 0; } diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c index 4636b1465b6..ce85117fc64 100644 --- a/arch/um/sys-x86_64/fault.c +++ b/arch/um/sys-x86_64/fault.c @@ -14,14 +14,15 @@ struct exception_table_entry }; const struct exception_table_entry *search_exception_tables(unsigned long add); -int arch_fixup(unsigned long address, union uml_pt_regs *regs) + +int arch_fixup(unsigned long address, struct uml_pt_regs *regs) { const struct exception_table_entry *fixup; fixup = search_exception_tables(address); - if(fixup != 0){ + if (fixup != 0) { UPT_IP(regs) = fixup->fixup; - return(1); + return 1; } - return(0); + return 0; } diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index 1970d78aa52..a3cfeed17af 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c @@ -1,5 +1,6 @@ /* * Copyright 2003 PathScale, Inc. + * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * * Licensed under the GPL */ @@ -12,17 +13,10 @@ #include <asm/uaccess.h> #include <asm/elf.h> -/* XXX x86_64 */ -unsigned long not_ss; -unsigned long not_ds; -unsigned long not_es; - -#define SC_SS(r) (not_ss) -#define SC_DS(r) (not_ds) -#define SC_ES(r) (not_es) - -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ +/* + * determines which flags the user has access to. + * 1 = access 0 = no access + */ #define FLAG_MASK 0x44dd5UL int putreg(struct task_struct *child, int regno, unsigned long value) @@ -66,20 +60,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value) int poke_user(struct task_struct *child, long addr, long data) { - if ((addr & 3) || addr < 0) - return -EIO; - - if (addr < MAX_REG_OFFSET) - return putreg(child, addr, data); - else if((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if((addr == 4) || (addr == 5)) return -EIO; - child->thread.arch.debugregs[addr] = data; - return 0; - } - return -EIO; + if ((addr & 3) || addr < 0) + return -EIO; + + if (addr < MAX_REG_OFFSET) + return putreg(child, addr, data); + else if ((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + if ((addr == 4) || (addr == 5)) + return -EIO; + child->thread.arch.debugregs[addr] = data; + return 0; + } + return -EIO; } unsigned long getreg(struct task_struct *child, int regno) @@ -107,29 +102,22 @@ unsigned long getreg(struct task_struct *child, int regno) int peek_user(struct task_struct *child, long addr, long data) { /* read the word at location addr in the USER area. */ - unsigned long tmp; - - if ((addr & 3) || addr < 0) - return -EIO; - - tmp = 0; /* Default return condition */ - if(addr < MAX_REG_OFFSET){ - tmp = getreg(child, addr); - } - else if((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - tmp = child->thread.arch.debugregs[addr]; - } - return put_user(tmp, (unsigned long *) data); -} + unsigned long tmp; -void arch_switch(void) -{ -/* XXX - printk("arch_switch\n"); -*/ + if ((addr & 3) || addr < 0) + return -EIO; + + tmp = 0; /* Default return condition */ + if (addr < MAX_REG_OFFSET){ + tmp = getreg(child, addr); + } + else if ((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + tmp = child->thread.arch.debugregs[addr]; + } + return put_user(tmp, (unsigned long *) data); } /* XXX Mostly copied from sys-i386 */ @@ -139,54 +127,68 @@ int is_syscall(unsigned long addr) int n; n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if(n){ + if (n){ /* access_process_vm() grants access to vsyscall and stub, * while copy_from_user doesn't. Maybe access_process_vm is * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. */ n = access_process_vm(current, addr, &instr, sizeof(instr), 0); - if(n != sizeof(instr)) { + if (n != sizeof(instr)) { printk("is_syscall : failed to read instruction from " "0x%lx\n", addr); - return(1); + return 1; } } /* sysenter */ - return(instr == 0x050f); + return instr == 0x050f; } -int get_fpregs(unsigned long buf, struct task_struct *child) +int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { - panic("get_fpregs"); - return(0); -} + int err, n, cpu = ((struct thread_info *) child->stack)->cpu; + long fpregs[HOST_FP_SIZE]; -int set_fpregs(unsigned long buf, struct task_struct *child) -{ - panic("set_fpregs"); - return(0); + BUG_ON(sizeof(*buf) != sizeof(fpregs)); + err = save_fp_registers(userspace_pid[cpu], fpregs); + if (err) + return err; + + n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); + if(n > 0) + return -EFAULT; + + return n; } -int get_fpxregs(unsigned long buf, struct task_struct *tsk) +int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { - panic("get_fpxregs"); - return(0); + int n, cpu = ((struct thread_info *) child->stack)->cpu; + long fpregs[HOST_FP_SIZE]; + + BUG_ON(sizeof(*buf) != sizeof(fpregs)); + n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); + if (n > 0) + return -EFAULT; + + return restore_fp_registers(userspace_pid[cpu], fpregs); } -int set_fpxregs(unsigned long buf, struct task_struct *tsk) +long subarch_ptrace(struct task_struct *child, long request, long addr, + long data) { - panic("set_fxpregs"); - return(0); -} + int ret = -EIO; -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ + switch (request) { + case PTRACE_GETFPXREGS: /* Get the child FPU state. */ + ret = get_fpregs((struct user_i387_struct __user *) data, + child); + break; + case PTRACE_SETFPXREGS: /* Set the child FPU state. */ + ret = set_fpregs((struct user_i387_struct __user *) data, + child); + break; + } + + return ret; +} diff --git a/arch/um/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c deleted file mode 100644 index c88e64def6f..00000000000 --- a/arch/um/sys-x86_64/sigcontext.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include <stdio.h> -#include <string.h> -#include <signal.h> -#include "user.h" - -void sc_to_sc(void *to_ptr, void *from_ptr) -{ - struct sigcontext *to = to_ptr, *from = from_ptr; - int size = sizeof(*to); /* + sizeof(struct _fpstate); */ - - memcpy(to, from, size); - if(from->fpstate != NULL) - to->fpstate = (struct _fpstate *) (to + 1); - - to->fpstate = NULL; -} - -unsigned long *sc_sigmask(void *sc_ptr) -{ - struct sigcontext *sc = sc_ptr; - - return(&sc->oldmask); -} - -/* Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index fe8ec04d35b..1778d33808f 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c @@ -1,111 +1,121 @@ /* * Copyright (C) 2003 PathScale, Inc. + * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/errno.h" #include "linux/personality.h" #include "linux/ptrace.h" -#include "asm/current.h" +#include "asm/unistd.h" #include "asm/uaccess.h" -#include "asm/sigcontext.h" -#include "asm/ptrace.h" -#include "asm/arch/ucontext.h" -#include "choose-mode.h" -#include "sysdep/ptrace.h" +#include "asm/ucontext.h" #include "frame_kern.h" - -#ifdef CONFIG_MODE_SKAS - #include "skas.h" -void copy_sc(union uml_pt_regs *regs, void *from) +void copy_sc(struct uml_pt_regs *regs, void *from) { struct sigcontext *sc = from; -#define GETREG(regs, regno, sc, regname) \ - (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname - - GETREG(regs, R8, sc, r8); - GETREG(regs, R9, sc, r9); - GETREG(regs, R10, sc, r10); - GETREG(regs, R11, sc, r11); - GETREG(regs, R12, sc, r12); - GETREG(regs, R13, sc, r13); - GETREG(regs, R14, sc, r14); - GETREG(regs, R15, sc, r15); - GETREG(regs, RDI, sc, rdi); - GETREG(regs, RSI, sc, rsi); - GETREG(regs, RBP, sc, rbp); - GETREG(regs, RBX, sc, rbx); - GETREG(regs, RDX, sc, rdx); - GETREG(regs, RAX, sc, rax); - GETREG(regs, RCX, sc, rcx); - GETREG(regs, RSP, sc, rsp); - GETREG(regs, RIP, sc, rip); - GETREG(regs, EFLAGS, sc, eflags); - GETREG(regs, CS, sc, cs); +#define GETREG(regs, regno, sc, regname) \ + (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname + + GETREG(regs, R8, sc, r8); + GETREG(regs, R9, sc, r9); + GETREG(regs, R10, sc, r10); + GETREG(regs, R11, sc, r11); + GETREG(regs, R12, sc, r12); + GETREG(regs, R13, sc, r13); + GETREG(regs, R14, sc, r14); + GETREG(regs, R15, sc, r15); + GETREG(regs, RDI, sc, rdi); + GETREG(regs, RSI, sc, rsi); + GETREG(regs, RBP, sc, rbp); + GETREG(regs, RBX, sc, rbx); + GETREG(regs, RDX, sc, rdx); + GETREG(regs, RAX, sc, rax); + GETREG(regs, RCX, sc, rcx); + GETREG(regs, RSP, sc, rsp); + GETREG(regs, RIP, sc, rip); + GETREG(regs, EFLAGS, sc, eflags); + GETREG(regs, CS, sc, cs); #undef GETREG } -static int copy_sc_from_user_skas(struct pt_regs *regs, - struct sigcontext __user *from) +static int copy_sc_from_user(struct pt_regs *regs, + struct sigcontext __user *from, + struct _fpstate __user *fpp) { - int err = 0; - -#define GETREG(regs, regno, sc, regname) \ - __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ - &(sc)->regname) - - err |= GETREG(regs, R8, from, r8); - err |= GETREG(regs, R9, from, r9); - err |= GETREG(regs, R10, from, r10); - err |= GETREG(regs, R11, from, r11); - err |= GETREG(regs, R12, from, r12); - err |= GETREG(regs, R13, from, r13); - err |= GETREG(regs, R14, from, r14); - err |= GETREG(regs, R15, from, r15); - err |= GETREG(regs, RDI, from, rdi); - err |= GETREG(regs, RSI, from, rsi); - err |= GETREG(regs, RBP, from, rbp); - err |= GETREG(regs, RBX, from, rbx); - err |= GETREG(regs, RDX, from, rdx); - err |= GETREG(regs, RAX, from, rax); - err |= GETREG(regs, RCX, from, rcx); - err |= GETREG(regs, RSP, from, rsp); - err |= GETREG(regs, RIP, from, rip); - err |= GETREG(regs, EFLAGS, from, eflags); - err |= GETREG(regs, CS, from, cs); + struct user_i387_struct fp; + int err = 0; + +#define GETREG(regs, regno, sc, regname) \ + __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) + + err |= GETREG(regs, R8, from, r8); + err |= GETREG(regs, R9, from, r9); + err |= GETREG(regs, R10, from, r10); + err |= GETREG(regs, R11, from, r11); + err |= GETREG(regs, R12, from, r12); + err |= GETREG(regs, R13, from, r13); + err |= GETREG(regs, R14, from, r14); + err |= GETREG(regs, R15, from, r15); + err |= GETREG(regs, RDI, from, rdi); + err |= GETREG(regs, RSI, from, rsi); + err |= GETREG(regs, RBP, from, rbp); + err |= GETREG(regs, RBX, from, rbx); + err |= GETREG(regs, RDX, from, rdx); + err |= GETREG(regs, RAX, from, rax); + err |= GETREG(regs, RCX, from, rcx); + err |= GETREG(regs, RSP, from, rsp); + err |= GETREG(regs, RIP, from, rip); + err |= GETREG(regs, EFLAGS, from, eflags); + err |= GETREG(regs, CS, from, cs); + if (err) + return 1; #undef GETREG - return err; + err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct)); + if (err) + return 1; + + err = restore_fp_registers(userspace_pid[current_thread->cpu], + (unsigned long *) &fp); + if (err < 0) { + printk(KERN_ERR "copy_sc_from_user - " + "restore_fp_registers failed, errno = %d\n", + -err); + return 1; + } + + return 0; } -int copy_sc_to_user_skas(struct sigcontext __user *to, - struct _fpstate __user *to_fp, - struct pt_regs *regs, unsigned long mask, - unsigned long sp) +static int copy_sc_to_user(struct sigcontext __user *to, + struct _fpstate __user *to_fp, struct pt_regs *regs, + unsigned long mask, unsigned long sp) { - struct faultinfo * fi = ¤t->thread.arch.faultinfo; + struct faultinfo * fi = ¤t->thread.arch.faultinfo; + struct user_i387_struct fp; int err = 0; err |= __put_user(0, &to->gs); err |= __put_user(0, &to->fs); -#define PUTREG(regs, regno, sc, regname) \ - __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ - &(sc)->regname) +#define PUTREG(regs, regno, sc, regname) \ + __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) err |= PUTREG(regs, RDI, to, rdi); err |= PUTREG(regs, RSI, to, rsi); err |= PUTREG(regs, RBP, to, rbp); - /* Must use orignal RSP, which is passed in, rather than what's in - * the pt_regs, because that's already been updated to point at the - * signal frame. - */ + /* + * Must use orignal RSP, which is passed in, rather than what's in + * the pt_regs, because that's already been updated to point at the + * signal frame. + */ err |= __put_user(sp, &to->rsp); err |= PUTREG(regs, RBX, to, rbx); err |= PUTREG(regs, RDX, to, rdx); @@ -121,91 +131,38 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, err |= PUTREG(regs, R15, to, r15); err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ - err |= __put_user(fi->cr2, &to->cr2); - err |= __put_user(fi->error_code, &to->err); - err |= __put_user(fi->trap_no, &to->trapno); + err |= __put_user(fi->cr2, &to->cr2); + err |= __put_user(fi->error_code, &to->err); + err |= __put_user(fi->trap_no, &to->trapno); err |= PUTREG(regs, RIP, to, rip); err |= PUTREG(regs, EFLAGS, to, eflags); #undef PUTREG err |= __put_user(mask, &to->oldmask); - - return(err); -} - -#endif - -#ifdef CONFIG_MODE_TT -int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, - int fpsize) -{ - struct _fpstate *to_fp; - struct _fpstate __user *from_fp; - unsigned long sigs; - int err; - - to_fp = to->fpstate; - sigs = to->oldmask; - err = copy_from_user(to, from, sizeof(*to)); - from_fp = to->fpstate; - to->fpstate = to_fp; - to->oldmask = sigs; - if(to_fp != NULL) - err |= copy_from_user(to_fp, from_fp, fpsize); - return(err); -} - -int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, - struct sigcontext *from, int fpsize, unsigned long sp) -{ - struct _fpstate __user *to_fp; - struct _fpstate *from_fp; - int err; - - to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); - from_fp = from->fpstate; - err = copy_to_user(to, from, sizeof(*to)); - /* The SP in the sigcontext is the updated one for the signal - * delivery. The sp passed in is the original, and this needs - * to be restored, so we stick it in separately. - */ - err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); - - if(from_fp != NULL){ - err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); - err |= copy_to_user(to_fp, from_fp, fpsize); + if (err) + return 1; + + err = save_fp_registers(userspace_pid[current_thread->cpu], + (unsigned long *) &fp); + if (err < 0) { + printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " + "failed, errno = %d\n", -err); + return 1; } - return err; -} -#endif - -static int copy_sc_from_user(struct pt_regs *to, void __user *from) -{ - int ret; - - ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, - sizeof(struct _fpstate)), - copy_sc_from_user_skas(to, from)); - return(ret); -} + if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) + return 1; -static int copy_sc_to_user(struct sigcontext __user *to, - struct _fpstate __user *fp, - struct pt_regs *from, unsigned long mask, - unsigned long sp) -{ - return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), - sizeof(*fp), sp), - copy_sc_to_user_skas(to, fp, from, mask, sp))); + return err; } struct rt_sigframe { - char __user *pretcode; - struct ucontext uc; - struct siginfo info; + char __user *pretcode; + struct ucontext uc; + struct siginfo info; + struct _fpstate fpstate; }; #define round_down(m, n) (((m) / (n)) * (n)) @@ -215,7 +172,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, siginfo_t *info, sigset_t *set) { struct rt_sigframe __user *frame; - struct _fpstate __user *fp = NULL; unsigned long save_sp = PT_REGS_RSP(regs); int err = 0; struct task_struct *me = current; @@ -223,15 +179,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, frame = (struct rt_sigframe __user *) round_down(stack_top - sizeof(struct rt_sigframe), 16); /* Subtract 128 for a red zone and 8 for proper alignment */ - frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); - - if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) - goto out; + frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); -#if 0 /* XXX */ - if (save_i387(fp) < 0) - err |= -1; -#endif if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto out; @@ -241,7 +190,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, goto out; } - /* Update SP now because the page fault handler refuses to extend + /* + * Update SP now because the page fault handler refuses to extend * the stack if the faulting address is too far below the current * SP, which frame now certainly is. If there's an error, the original * value is restored on the way out. @@ -258,9 +208,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, err |= __put_user(sas_ss_flags(save_sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0], - save_sp); - err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); + err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, + set->sig[0], save_sp); + err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); if (sizeof(*set) == 16) { __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); @@ -269,8 +219,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ + /* + * Set up to return from userspace. If provided, use a stub + * already in userspace. + */ /* x86-64 should always use SA_RESTORER. */ if (ka->sa.sa_flags & SA_RESTORER) err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); @@ -292,8 +244,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, /* In case the signal handler was declared without prototypes */ PT_REGS_RAX(regs) = 0; - /* This also works for non SA_SIGINFO handlers because they expect the - next argument after the signal number on the stack. */ + /* + * This also works for non SA_SIGINFO handlers because they expect the + * next argument after the signal number on the stack. + */ PT_REGS_RSI(regs) = (unsigned long) &frame->info; PT_REGS_RDX(regs) = (unsigned long) &frame->uc; PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; @@ -313,7 +267,7 @@ long sys_rt_sigreturn(struct pt_regs *regs) struct ucontext __user *uc = &frame->uc; sigset_t set; - if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) goto segfault; sigdelsetmask(&set, ~_BLOCKABLE); @@ -323,24 +277,15 @@ long sys_rt_sigreturn(struct pt_regs *regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) + if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, + &frame->fpstate)) goto segfault; /* Avoid ERESTART handling */ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; - return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); + return PT_REGS_SYSCALL_RET(¤t->thread.regs); segfault: force_sig(SIGSEGV, current); return 0; } -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S index 03c27973578..4afe204a6af 100644 --- a/arch/um/sys-x86_64/stub.S +++ b/arch/um/sys-x86_64/stub.S @@ -1,4 +1,5 @@ #include "uml-config.h" +#include "as-layout.h" .globl syscall_stub .section .__syscall_stub, "x" @@ -7,18 +8,18 @@ syscall_stub: /* We don't have 64-bit constants, so this constructs the address * we need. */ - movq $(UML_CONFIG_STUB_DATA >> 32), %rbx + movq $(ASM_STUB_DATA >> 32), %rbx salq $32, %rbx - movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx + movq $(ASM_STUB_DATA & 0xffffffff), %rcx or %rcx, %rbx movq %rax, (%rbx) int3 .globl batch_syscall_stub batch_syscall_stub: - mov $(UML_CONFIG_STUB_DATA >> 32), %rbx + mov $(ASM_STUB_DATA >> 32), %rbx sal $32, %rbx - mov $(UML_CONFIG_STUB_DATA & 0xffffffff), %rax + mov $(ASM_STUB_DATA & 0xffffffff), %rax or %rax, %rbx /* load pointer to first operation */ mov %rbx, %rsp diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 652fa34c2cd..3afb590f007 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -6,6 +6,7 @@ #include <stddef.h> #include <signal.h> #include <asm/unistd.h> +#include "as-layout.h" #include "uml-config.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" @@ -33,7 +34,7 @@ stub_segv_handler(int sig) int pid; __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), &uc->uc_mcontext); pid = stub_syscall0(__NR_getpid); diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index b3f6350cac4..86f6b18410e 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -1,70 +1,36 @@ /* + * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright 2003 PathScale, Inc. * * Licensed under the GPL */ #include "linux/linkage.h" -#include "linux/slab.h" -#include "linux/shm.h" -#include "linux/utsname.h" #include "linux/personality.h" -#include "asm/uaccess.h" -#define __FRAME_OFFSETS -#include "asm/ptrace.h" -#include "asm/unistd.h" +#include "linux/utsname.h" #include "asm/prctl.h" /* XXX This should get the constants from libc */ -#include "choose-mode.h" -#include "kern.h" +#include "asm/uaccess.h" #include "os.h" asmlinkage long sys_uname64(struct new_utsname __user * name) { int err; + down_read(&uts_sem); err = copy_to_user(name, utsname(), sizeof (*name)); up_read(&uts_sem); + if (personality(current->personality) == PER_LINUX32) err |= copy_to_user(&name->machine, "i686", 5); - return err ? -EFAULT : 0; -} - -#ifdef CONFIG_MODE_TT -extern long arch_prctl(int code, unsigned long addr); - -static long arch_prctl_tt(int code, unsigned long addr) -{ - unsigned long tmp; - long ret; - - switch(code){ - case ARCH_SET_GS: - case ARCH_SET_FS: - ret = arch_prctl(code, addr); - break; - case ARCH_GET_FS: - case ARCH_GET_GS: - ret = arch_prctl(code, (unsigned long) &tmp); - if(!ret) - ret = put_user(tmp, (long __user *)addr); - break; - default: - ret = -EINVAL; - break; - } - return(ret); + return err ? -EFAULT : 0; } -#endif - -#ifdef CONFIG_MODE_SKAS -long arch_prctl_skas(struct task_struct *task, int code, - unsigned long __user *addr) +long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) { - unsigned long *ptr = addr, tmp; + unsigned long *ptr = addr, tmp; long ret; - int pid = task->mm->context.skas.id.u.pid; + int pid = task->mm->context.id.u.pid; /* * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to @@ -79,52 +45,50 @@ long arch_prctl_skas(struct task_struct *task, int code, * arch_prctl is run on the host, then the registers are read * back. */ - switch(code){ + switch (code) { case ARCH_SET_FS: case ARCH_SET_GS: - restore_registers(pid, ¤t->thread.regs.regs); - break; - case ARCH_GET_FS: - case ARCH_GET_GS: - /* - * With these two, we read to a local pointer and - * put_user it to the userspace pointer that we were - * given. If addr isn't valid (because it hasn't been - * faulted in or is just bogus), we want put_user to - * fault it in (or return -EFAULT) instead of having - * the host return -EFAULT. - */ - ptr = &tmp; - } + restore_registers(pid, ¤t->thread.regs.regs); + break; + case ARCH_GET_FS: + case ARCH_GET_GS: + /* + * With these two, we read to a local pointer and + * put_user it to the userspace pointer that we were + * given. If addr isn't valid (because it hasn't been + * faulted in or is just bogus), we want put_user to + * fault it in (or return -EFAULT) instead of having + * the host return -EFAULT. + */ + ptr = &tmp; + } - ret = os_arch_prctl(pid, code, ptr); - if(ret) - return ret; + ret = os_arch_prctl(pid, code, ptr); + if (ret) + return ret; - switch(code){ + switch (code) { case ARCH_SET_FS: current->thread.arch.fs = (unsigned long) ptr; save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_SET_GS: - save_registers(pid, ¤t->thread.regs.regs); + save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: ret = put_user(tmp, addr); - break; + break; case ARCH_GET_GS: ret = put_user(tmp, addr); - break; + break; } return ret; } -#endif long sys_arch_prctl(int code, unsigned long addr) { - return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code, - (unsigned long __user *) addr); + return arch_prctl(current, code, (unsigned long __user *) addr); } long sys_clone(unsigned long clone_flags, unsigned long newsp, @@ -141,10 +105,10 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, return ret; } -void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) +void arch_switch_to(struct task_struct *from, struct task_struct *to) { - if((to->thread.arch.fs == 0) || (to->mm == NULL)) - return; + if ((to->thread.arch.fs == 0) || (to->mm == NULL)) + return; - arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); + arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); } diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c index febbc94be25..f7ba46200ec 100644 --- a/arch/um/sys-x86_64/tls.c +++ b/arch/um/sys-x86_64/tls.c @@ -11,7 +11,7 @@ int arch_copy_tls(struct task_struct *t) * (which is argument 5, child_tid, of clone) so it can be set * during context switches. */ - t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)]; + t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)]; - return 0; + return 0; } diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c deleted file mode 100644 index f4a4bffd8a1..00000000000 --- a/arch/um/sys-x86_64/unmap.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <linux/mman.h> -#include <asm/unistd.h> - -static int errno; - -static inline _syscall2(int,munmap,void *,start,size_t,len) -static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) -int switcheroo(int fd, int prot, void *from, void *to, int size) -{ - if(munmap(to, size) < 0){ - return(-1); - } - if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ - return(-1); - } - if(munmap(from, size) < 0){ - return(-1); - } - return(0); -} diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 0d5fd764c21..f1ef2a8dfbc 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c @@ -3,17 +3,10 @@ #include <signal.h> #include <sys/poll.h> #include <sys/mman.h> +#include <sys/user.h> #define __FRAME_OFFSETS #include <asm/ptrace.h> #include <asm/types.h> -/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I - * refuse to include here, even though they're used throughout the headers. - * These are used in asm/user.h, and that include can't be avoided because of - * the sizeof(struct user_regs_struct) below. - */ -typedef __u64 u64; -typedef __u32 u32; -#include <asm/user.h> #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c index 5c4923558a7..ab9cf16a85c 100644 --- a/arch/v850/kernel/fpga85e2c.c +++ b/arch/v850/kernel/fpga85e2c.c @@ -160,5 +160,8 @@ static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs) static int reg_snap_dev_id; static struct irqaction reg_snap_action = { - make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", ®_snap_dev_id, 0 + .handler = make_reg_snap, + .mask = CPU_MASK_NONE, + .name = "reg_snap", + .dev_id = ®_snap_dev_id, }; diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c index f0905b03523..d810c93fe66 100644 --- a/arch/v850/kernel/time.c +++ b/arch/v850/kernel/time.c @@ -92,12 +92,11 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs) static int timer_dev_id; static struct irqaction timer_irqaction = { - timer_interrupt, - IRQF_DISABLED, - CPU_MASK_NONE, - "timer", - &timer_dev_id, - NULL + .handler = timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "timer", + .dev_id = &timer_dev_id, }; void time_init (void) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index ffd01e5dcb5..2ca43ba32bc 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -595,7 +595,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) dmi_check_system(sw_any_bug_dmi_table); if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) { policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; - policy->cpus = cpu_core_map[cpu]; + policy->cpus = per_cpu(cpu_core_map, cpu); } #endif diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 8eb414b906d..793eae854f4 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -200,7 +200,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) unsigned int i; #ifdef CONFIG_SMP - policy->cpus = cpu_sibling_map[policy->cpu]; + policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); #endif /* Errata workaround */ diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index b273b69cfdd..c06ac680c9c 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -57,7 +57,7 @@ static struct powernow_k8_data *powernow_data[NR_CPUS]; static int cpu_family = CPU_OPTERON; #ifndef CONFIG_SMP -static cpumask_t cpu_core_map[1]; +DEFINE_PER_CPU(cpumask_t, cpu_core_map); #endif /* Return a frequency in MHz, given an input fid */ @@ -667,7 +667,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid); data->powernow_table = powernow_table; - if (first_cpu(cpu_core_map[data->cpu]) == data->cpu) + if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) print_basics(data); for (j = 0; j < data->numps; j++) @@ -821,7 +821,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) /* fill in data */ data->numps = data->acpi_data.state_count; - if (first_cpu(cpu_core_map[data->cpu]) == data->cpu) + if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) print_basics(data); powernow_k8_acpi_pst_values(data, 0); @@ -1214,7 +1214,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) if (cpu_family == CPU_HW_PSTATE) pol->cpus = cpumask_of_cpu(pol->cpu); else - pol->cpus = cpu_core_map[pol->cpu]; + pol->cpus = per_cpu(cpu_core_map, pol->cpu); data->available_cores = &(pol->cpus); /* Take a crude guess here. @@ -1281,7 +1281,7 @@ static unsigned int powernowk8_get (unsigned int cpu) cpumask_t oldmask = current->cpus_allowed; unsigned int khz = 0; - data = powernow_data[first_cpu(cpu_core_map[cpu])]; + data = powernow_data[first_cpu(per_cpu(cpu_core_map, cpu))]; if (!data) return -EINVAL; diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index 36685e8f7be..14d68aa301e 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c @@ -322,7 +322,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* only run on CPU to be set, or on its sibling */ #ifdef CONFIG_SMP - policy->cpus = cpu_sibling_map[policy->cpu]; + policy->cpus = per_cpu(cpu_sibling_map, policy->cpu); #endif cpus_allowed = current->cpus_allowed; diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 1e31b6caffb..879a0f789b1 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -122,7 +122,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef CONFIG_X86_HT if (c->x86_max_cores * smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); - seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n])); + seq_printf(m, "siblings\t: %d\n", + cpus_weight(per_cpu(cpu_core_map, n))); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); } diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index e2f4a1c6854..4ee1e5ee9b5 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -378,7 +378,7 @@ static struct irq_cpu_info { #define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask) -#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) +#define CPU_TO_PACKAGEINDEX(i) (first_cpu(per_cpu(cpu_sibling_map, i))) static cpumask_t balance_irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL @@ -598,7 +598,7 @@ tryanotherirq: * (A+B)/2 vs B */ load = CPU_IRQ(min_loaded) >> 1; - for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) { + for_each_cpu_mask(j, per_cpu(cpu_sibling_map, min_loaded)) { if (load > CPU_IRQ(j)) { /* This won't change cpu_sibling_map[min_loaded] */ load = CPU_IRQ(j); diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c index e7d0d3c2ef6..90f778c04b3 100644 --- a/arch/x86/kernel/kprobes_32.c +++ b/arch/x86/kernel/kprobes_32.c @@ -41,6 +41,13 @@ void jprobe_return_end(void); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); +struct kretprobe_blackpoint kretprobe_blacklist[] = { + {"__switch_to", }, /* This function switches only current task, but + doesn't switch kernel stack.*/ + {NULL, NULL} /* Terminator */ +}; +const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); + /* insert a jmp code */ static __always_inline void set_jmp_op(void *from, void *to) { @@ -584,7 +591,7 @@ out: return 1; } -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -666,7 +673,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_GPF: - case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */ preempt_disable(); if (kprobe_running() && diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 62e28e52d78..681b801c5e2 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c @@ -48,6 +48,13 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); +struct kretprobe_blackpoint kretprobe_blacklist[] = { + {"__switch_to", }, /* This function switches only current task, but + doesn't switch kernel stack.*/ + {NULL, NULL} /* Terminator */ +}; +const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); + /* * returns non-zero if opcode modifies the interrupt flag. */ @@ -657,7 +664,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_GPF: - case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */ preempt_disable(); if (kprobe_running() && diff --git a/arch/x86/kernel/mce_amd_64.c b/arch/x86/kernel/mce_amd_64.c index 2f8a7f18b0f..805b62b1e0d 100644 --- a/arch/x86/kernel/mce_amd_64.c +++ b/arch/x86/kernel/mce_amd_64.c @@ -472,7 +472,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifdef CONFIG_SMP if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) { /* symlink */ - i = first_cpu(cpu_core_map[cpu]); + i = first_cpu(per_cpu(cpu_core_map, cpu)); /* first core not up yet */ if (cpu_data[i].cpu_core_id) @@ -492,7 +492,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) if (err) goto out; - b->cpus = cpu_core_map[cpu]; + b->cpus = per_cpu(cpu_core_map, cpu); per_cpu(threshold_banks, cpu)[bank] = b; goto out; } @@ -509,7 +509,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifndef CONFIG_SMP b->cpus = CPU_MASK_ALL; #else - b->cpus = cpu_core_map[cpu]; + b->cpus = per_cpu(cpu_core_map, cpu); #endif err = kobject_register(&b->kobj); if (err) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 7352d4b377e..6309b275cb9 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -581,7 +581,7 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, * * Kprobes not supported here. Set the probe on schedule instead. */ -__kprobes struct task_struct * +struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, diff --git a/arch/x86/kernel/ptrace_32.c b/arch/x86/kernel/ptrace_32.c index 0cecd7513c9..8622b9cd3e3 100644 --- a/arch/x86/kernel/ptrace_32.c +++ b/arch/x86/kernel/ptrace_32.c @@ -524,11 +524,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; - case PTRACE_DETACH: - /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, datap, FRAME_SIZE*sizeof(long))) { ret = -EIO; diff --git a/arch/x86/kernel/ptrace_64.c b/arch/x86/kernel/ptrace_64.c index c0cac42df3b..86321ee6da9 100644 --- a/arch/x86/kernel/ptrace_64.c +++ b/arch/x86/kernel/ptrace_64.c @@ -500,11 +500,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = 0; break; - case PTRACE_DETACH: - /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, sizeof(struct user_regs_struct))) { diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index b7da90e79c7..85b5b6310ac 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -1070,7 +1070,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (smp_num_siblings * c->x86_max_cores > 1) { int cpu = c - cpu_data; seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); - seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu])); + seq_printf(m, "siblings\t: %d\n", + cpus_weight(per_cpu(cpu_core_map, cpu))); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); } diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c index e4f61d1c624..31fc08bd15e 100644 --- a/arch/x86/kernel/smpboot_32.c +++ b/arch/x86/kernel/smpboot_32.c @@ -70,12 +70,12 @@ EXPORT_SYMBOL(smp_num_siblings); int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; /* representing HT siblings of each logical CPU */ -cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; -EXPORT_SYMBOL(cpu_sibling_map); +DEFINE_PER_CPU(cpumask_t, cpu_sibling_map); +EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -cpumask_t cpu_core_map[NR_CPUS] __read_mostly; -EXPORT_SYMBOL(cpu_core_map); +DEFINE_PER_CPU(cpumask_t, cpu_core_map); +EXPORT_PER_CPU_SYMBOL(cpu_core_map); /* bitmap of online cpus */ cpumask_t cpu_online_map __read_mostly; @@ -300,7 +300,7 @@ cpumask_t cpu_coregroup_map(int cpu) * And for power savings, we return cpu_core_map */ if (sched_mc_power_savings || sched_smt_power_savings) - return cpu_core_map[cpu]; + return per_cpu(cpu_core_map, cpu); else return c->llc_shared_map; } @@ -319,22 +319,22 @@ void __cpuinit set_cpu_sibling_map(int cpu) for_each_cpu_mask(i, cpu_sibling_setup_map) { if (c[cpu].phys_proc_id == c[i].phys_proc_id && c[cpu].cpu_core_id == c[i].cpu_core_id) { - cpu_set(i, cpu_sibling_map[cpu]); - cpu_set(cpu, cpu_sibling_map[i]); - cpu_set(i, cpu_core_map[cpu]); - cpu_set(cpu, cpu_core_map[i]); + cpu_set(i, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, per_cpu(cpu_sibling_map, i)); + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); cpu_set(i, c[cpu].llc_shared_map); cpu_set(cpu, c[i].llc_shared_map); } } } else { - cpu_set(cpu, cpu_sibling_map[cpu]); + cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); } cpu_set(cpu, c[cpu].llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { - cpu_core_map[cpu] = cpu_sibling_map[cpu]; + per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); c[cpu].booted_cores = 1; return; } @@ -346,17 +346,17 @@ void __cpuinit set_cpu_sibling_map(int cpu) cpu_set(cpu, c[i].llc_shared_map); } if (c[cpu].phys_proc_id == c[i].phys_proc_id) { - cpu_set(i, cpu_core_map[cpu]); - cpu_set(cpu, cpu_core_map[i]); + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); /* * Does this new cpu bringup a new core? */ - if (cpus_weight(cpu_sibling_map[cpu]) == 1) { + if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) { /* * for each core in package, increment * the booted_cores for this new cpu */ - if (first_cpu(cpu_sibling_map[i]) == i) + if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) c[cpu].booted_cores++; /* * increment the core count for all @@ -983,8 +983,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n"); map_cpu_to_logical_apicid(); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, per_cpu(cpu_core_map, 0)); return; } @@ -1008,8 +1008,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); smpboot_clear_io_apic_irqs(); phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, per_cpu(cpu_core_map, 0)); return; } @@ -1023,8 +1023,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); smpboot_clear_io_apic_irqs(); phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, per_cpu(cpu_core_map, 0)); return; } @@ -1102,16 +1102,16 @@ static void __init smp_boot_cpus(unsigned int max_cpus) Dprintk("Boot done.\n"); /* - * construct cpu_sibling_map[], so that we can tell sibling CPUs + * construct cpu_sibling_map, so that we can tell sibling CPUs * efficiently. */ for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpus_clear(cpu_sibling_map[cpu]); - cpus_clear(cpu_core_map[cpu]); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + cpus_clear(per_cpu(cpu_core_map, cpu)); } - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, per_cpu(cpu_core_map, 0)); smpboot_setup_io_apic(); @@ -1148,19 +1148,19 @@ void remove_siblinginfo(int cpu) int sibling; struct cpuinfo_x86 *c = cpu_data; - for_each_cpu_mask(sibling, cpu_core_map[cpu]) { - cpu_clear(cpu, cpu_core_map[sibling]); - /* + for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { + cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); + /*/ * last thread sibling in this cpu core going down */ - if (cpus_weight(cpu_sibling_map[cpu]) == 1) + if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) c[sibling].booted_cores--; } - for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) - cpu_clear(cpu, cpu_sibling_map[sibling]); - cpus_clear(cpu_sibling_map[cpu]); - cpus_clear(cpu_core_map[cpu]); + for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) + cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + cpus_clear(per_cpu(cpu_core_map, cpu)); c[cpu].phys_proc_id = 0; c[cpu].cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index 720a7d1f886..0faa0a0af27 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c @@ -91,12 +91,12 @@ EXPORT_SYMBOL(cpu_data); int smp_threads_ready; /* representing HT siblings of each logical CPU */ -cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; -EXPORT_SYMBOL(cpu_sibling_map); +DEFINE_PER_CPU(cpumask_t, cpu_sibling_map); +EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -cpumask_t cpu_core_map[NR_CPUS] __read_mostly; -EXPORT_SYMBOL(cpu_core_map); +DEFINE_PER_CPU(cpumask_t, cpu_core_map); +EXPORT_PER_CPU_SYMBOL(cpu_core_map); /* * Trampoline 80x86 program as an array. @@ -243,7 +243,7 @@ cpumask_t cpu_coregroup_map(int cpu) * And for power savings, we return cpu_core_map */ if (sched_mc_power_savings || sched_smt_power_savings) - return cpu_core_map[cpu]; + return per_cpu(cpu_core_map, cpu); else return c->llc_shared_map; } @@ -262,22 +262,22 @@ static inline void set_cpu_sibling_map(int cpu) for_each_cpu_mask(i, cpu_sibling_setup_map) { if (c[cpu].phys_proc_id == c[i].phys_proc_id && c[cpu].cpu_core_id == c[i].cpu_core_id) { - cpu_set(i, cpu_sibling_map[cpu]); - cpu_set(cpu, cpu_sibling_map[i]); - cpu_set(i, cpu_core_map[cpu]); - cpu_set(cpu, cpu_core_map[i]); + cpu_set(i, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, per_cpu(cpu_sibling_map, i)); + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); cpu_set(i, c[cpu].llc_shared_map); cpu_set(cpu, c[i].llc_shared_map); } } } else { - cpu_set(cpu, cpu_sibling_map[cpu]); + cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); } cpu_set(cpu, c[cpu].llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { - cpu_core_map[cpu] = cpu_sibling_map[cpu]; + per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); c[cpu].booted_cores = 1; return; } @@ -289,17 +289,17 @@ static inline void set_cpu_sibling_map(int cpu) cpu_set(cpu, c[i].llc_shared_map); } if (c[cpu].phys_proc_id == c[i].phys_proc_id) { - cpu_set(i, cpu_core_map[cpu]); - cpu_set(cpu, cpu_core_map[i]); + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); /* * Does this new cpu bringup a new core? */ - if (cpus_weight(cpu_sibling_map[cpu]) == 1) { + if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) { /* * for each core in package, increment * the booted_cores for this new cpu */ - if (first_cpu(cpu_sibling_map[i]) == i) + if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) c[cpu].booted_cores++; /* * increment the core count for all @@ -735,8 +735,8 @@ static __init void disable_smp(void) phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id); else phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, per_cpu(cpu_core_map, 0)); } #ifdef CONFIG_HOTPLUG_CPU @@ -971,19 +971,19 @@ static void remove_siblinginfo(int cpu) int sibling; struct cpuinfo_x86 *c = cpu_data; - for_each_cpu_mask(sibling, cpu_core_map[cpu]) { - cpu_clear(cpu, cpu_core_map[sibling]); + for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { + cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); /* * last thread sibling in this cpu core going down */ - if (cpus_weight(cpu_sibling_map[cpu]) == 1) + if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) c[sibling].booted_cores--; } - for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) - cpu_clear(cpu, cpu_sibling_map[sibling]); - cpus_clear(cpu_sibling_map[cpu]); - cpus_clear(cpu_core_map[cpu]); + for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) + cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + cpus_clear(per_cpu(cpu_core_map, cpu)); c[cpu].phys_proc_id = 0; c[cpu].cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index fcb38e7f354..c686ae20fd6 100644 --- a/arch/x86/mm/fault_32.c +++ b/arch/x86/mm/fault_32.c @@ -25,6 +25,7 @@ #include <linux/kprobes.h> #include <linux/uaccess.h> #include <linux/kdebug.h> +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/desc.h> @@ -32,33 +33,27 @@ extern void die(const char *,struct pt_regs *,long); -static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -int register_page_fault_notifier(struct notifier_block *nb) +#ifdef CONFIG_KPROBES +static inline int notify_page_fault(struct pt_regs *regs) { - vmalloc_sync_all(); - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} -EXPORT_SYMBOL_GPL(register_page_fault_notifier); + int ret = 0; + + /* kprobe_running() needs smp_processor_id() */ + if (!user_mode_vm(regs)) { + preempt_disable(); + if (kprobe_running() && kprobe_fault_handler(regs, 14)) + ret = 1; + preempt_enable(); + } -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); + return ret; } -EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); - -static inline int notify_page_fault(struct pt_regs *regs, long err) +#else +static inline int notify_page_fault(struct pt_regs *regs) { - struct die_args args = { - .regs = regs, - .str = "page fault", - .err = err, - .trapnr = 14, - .signr = SIGSEGV - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, - DIE_PAGE_FAULT, &args); + return 0; } +#endif /* * Return EIP plus the CS segment base. The segment limit is also @@ -331,7 +326,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, if (unlikely(address >= TASK_SIZE)) { if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) return; - if (notify_page_fault(regs, error_code) == NOTIFY_STOP) + if (notify_page_fault(regs)) return; /* * Don't take the mm semaphore here. If we fixup a prefetch @@ -340,7 +335,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area_nosemaphore; } - if (notify_page_fault(regs, error_code) == NOTIFY_STOP) + if (notify_page_fault(regs)) return; /* It's safe to allow irq's after cr2 has been saved and the vmalloc @@ -598,7 +593,7 @@ out_of_memory: } printk("VM: killing process %s\n", tsk->comm); if (error_code & 4) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto no_context; do_sigbus: diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index 54816adb8e9..5e0e54906c4 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c @@ -25,6 +25,7 @@ #include <linux/kprobes.h> #include <linux/uaccess.h> #include <linux/kdebug.h> +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/pgalloc.h> @@ -40,34 +41,27 @@ #define PF_RSVD (1<<3) #define PF_INSTR (1<<4) -static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -/* Hook to register for page fault notifications */ -int register_page_fault_notifier(struct notifier_block *nb) +#ifdef CONFIG_KPROBES +static inline int notify_page_fault(struct pt_regs *regs) { - vmalloc_sync_all(); - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} -EXPORT_SYMBOL_GPL(register_page_fault_notifier); + int ret = 0; + + /* kprobe_running() needs smp_processor_id() */ + if (!user_mode(regs)) { + preempt_disable(); + if (kprobe_running() && kprobe_fault_handler(regs, 14)) + ret = 1; + preempt_enable(); + } -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); + return ret; } -EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); - -static inline int notify_page_fault(struct pt_regs *regs, long err) +#else +static inline int notify_page_fault(struct pt_regs *regs) { - struct die_args args = { - .regs = regs, - .str = "page fault", - .err = err, - .trapnr = 14, - .signr = SIGSEGV - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, - DIE_PAGE_FAULT, &args); + return 0; } +#endif /* Sometimes the CPU reports invalid exceptions on prefetch. Check that here and ignore. @@ -345,7 +339,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, if (vmalloc_fault(address) >= 0) return; } - if (notify_page_fault(regs, error_code) == NOTIFY_STOP) + if (notify_page_fault(regs)) return; /* * Don't take the mm semaphore here. If we fixup a prefetch @@ -354,7 +348,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area_nosemaphore; } - if (notify_page_fault(regs, error_code) == NOTIFY_STOP) + if (notify_page_fault(regs)) return; if (likely(regs->eflags & X86_EFLAGS_IF)) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 730a5b177b1..dda4e83649a 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -735,11 +735,6 @@ int arch_add_memory(int nid, u64 start, u64 size) return __add_pages(zone, start_pfn, nr_pages); } -int remove_memory(u64 start, u64 size) -{ - return -EINVAL; -} -EXPORT_SYMBOL_GPL(remove_memory); #endif struct kmem_cache *pmd_cache; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 458893b376f..1e3862e4106 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -474,12 +474,6 @@ error: } EXPORT_SYMBOL_GPL(arch_add_memory); -int remove_memory(u64 start, u64 size) -{ - return -EINVAL; -} -EXPORT_SYMBOL_GPL(remove_memory); - #if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA) int memory_add_physaddr_to_nid(u64 start) { @@ -748,3 +742,48 @@ const char *arch_vma_name(struct vm_area_struct *vma) return "[vsyscall]"; return NULL; } + +#ifdef CONFIG_SPARSEMEM_VMEMMAP +/* + * Initialise the sparsemem vmemmap using huge-pages at the PMD level. + */ +int __meminit vmemmap_populate(struct page *start_page, + unsigned long size, int node) +{ + unsigned long addr = (unsigned long)start_page; + unsigned long end = (unsigned long)(start_page + size); + unsigned long next; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + for (; addr < end; addr = next) { + next = pmd_addr_end(addr, end); + + pgd = vmemmap_pgd_populate(addr, node); + if (!pgd) + return -ENOMEM; + pud = vmemmap_pud_populate(pgd, addr, node); + if (!pud) + return -ENOMEM; + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) { + pte_t entry; + void *p = vmemmap_alloc_block(PMD_SIZE, node); + if (!p) + return -ENOMEM; + + entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL); + mk_pte_huge(entry); + set_pmd(pmd, __pmd(pte_val(entry))); + + printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n", + addr, addr + PMD_SIZE - 1, p, node); + } else + vmemmap_verify((pte_t *)pmd, node, addr, next); + } + + return 0; +} +#endif diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index 47925927b12..56b4757a1f4 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -379,7 +379,7 @@ static unsigned int get_stagger(void) { #ifdef CONFIG_SMP int cpu = smp_processor_id(); - return (cpu != first_cpu(cpu_sibling_map[cpu])); + return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu))); #endif return 0; } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 557b8e24706..4fa33c27ccb 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -147,8 +147,13 @@ void __init xen_smp_prepare_boot_cpu(void) make_lowmem_page_readwrite(&per_cpu__gdt_page); for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpus_clear(cpu_sibling_map[cpu]); - cpus_clear(cpu_core_map[cpu]); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + /* + * cpu_core_map lives in a per cpu area that is cleared + * when the per cpu array is allocated. + * + * cpus_clear(per_cpu(cpu_core_map, cpu)); + */ } xen_setup_vcpu_info_placement(); @@ -159,8 +164,13 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus) unsigned cpu; for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpus_clear(cpu_sibling_map[cpu]); - cpus_clear(cpu_core_map[cpu]); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + /* + * cpu_core_ map will be zeroed when the per + * cpu area is allocated. + * + * cpus_clear(per_cpu(cpu_core_map, cpu)); + */ } smp_store_cpu_info(0); diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index cf013cb85ea..8c83dbe4c4d 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -409,6 +409,7 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y depends on (NUMA || EXPERIMENTAL) + select SPARSEMEM_VMEMMAP_ENABLE config ARCH_MEMORY_PROBE def_bool y diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 06a13d9b69d..5533c7850d5 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -304,10 +304,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data); break; - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - default: ret = ptrace_request(child, request, addr, data); goto out; diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 45d28f217c0..2f842859948 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c @@ -152,7 +152,7 @@ out_of_memory: } printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); bad_page_fault(regs, address, SIGKILL); return; |