aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/process.c1
-rw-r--r--arch/arm/mach-ux500/board-u5500.c84
-rw-r--r--arch/cris/arch-v32/mach-a3/pinmux.c10
-rw-r--r--arch/cris/include/arch-v10/arch/processor.h1
-rw-r--r--arch/cris/include/arch-v32/arch/processor.h1
-rw-r--r--arch/h8300/include/asm/processor.h2
-rw-r--r--arch/m32r/include/asm/processor.h1
-rw-r--r--arch/m68k/include/asm/processor.h4
-rw-r--r--arch/m68k/kernel/process_mm.c2
-rw-r--r--arch/m68k/kernel/process_no.c2
-rw-r--r--arch/powerpc/kernel/rtas.c1
-rw-r--r--arch/powerpc/kernel/rtas_flash.c1
-rw-r--r--arch/sparc/Kconfig5
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h76
-rw-r--r--arch/sparc/include/asm/pgtable_64.h15
-rw-r--r--arch/sparc/mm/Makefile2
-rw-r--r--arch/sparc/mm/gup.c181
-rw-r--r--arch/sparc/mm/tsb.c11
-rw-r--r--arch/um/Kconfig.x862
-rw-r--r--arch/um/drivers/chan_kern.c3
-rw-r--r--arch/um/drivers/cow_user.c6
-rw-r--r--arch/um/drivers/harddog_user.c2
-rw-r--r--arch/um/drivers/line.c3
-rw-r--r--arch/um/drivers/net_kern.c12
-rw-r--r--arch/um/drivers/net_user.c5
-rw-r--r--arch/um/drivers/slip_user.c3
-rw-r--r--arch/um/include/asm/delay.h10
-rw-r--r--arch/um/kernel/exec.c1
-rw-r--r--arch/um/kernel/reboot.c3
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/elf_aux.c7
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/main.c4
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/user_syms.c5
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/asm/elf.h2
-rw-r--r--arch/um/sys-i386/delay.c59
-rw-r--r--arch/um/sys-i386/mem.c62
-rw-r--r--arch/um/sys-x86_64/Makefile4
-rw-r--r--arch/um/sys-x86_64/asm/elf.h10
-rw-r--r--arch/um/sys-x86_64/delay.c54
-rw-r--r--arch/um/sys-x86_64/mem.c32
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/vm-flags.h26
-rw-r--r--arch/um/sys-x86_64/vdso/Makefile90
-rw-r--r--arch/um/sys-x86_64/vdso/checkundef.sh10
-rw-r--r--arch/um/sys-x86_64/vdso/um_vdso.c71
-rw-r--r--arch/um/sys-x86_64/vdso/vdso-layout.lds.S64
-rw-r--r--arch/um/sys-x86_64/vdso/vdso-note.S12
-rw-r--r--arch/um/sys-x86_64/vdso/vdso.S10
-rw-r--r--arch/um/sys-x86_64/vdso/vdso.lds.S32
-rw-r--r--arch/um/sys-x86_64/vdso/vma.c74
-rw-r--r--arch/xtensa/include/asm/uaccess.h1
-rw-r--r--arch/xtensa/kernel/ptrace.c3
54 files changed, 965 insertions, 133 deletions
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 838eac128409..89bbe5b41145 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -200,7 +200,6 @@ show_regs(struct pt_regs *regs)
200void 200void
201start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) 201start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
202{ 202{
203 set_fs(USER_DS);
204 regs->pc = pc; 203 regs->pc = pc;
205 regs->ps = 8; 204 regs->ps = 8;
206 wrusp(sp); 205 wrusp(sp);
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 44fd3b5c33ec..e58f0f562426 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -10,16 +10,97 @@
10#include <linux/amba/bus.h> 10#include <linux/amba/bus.h>
11#include <linux/gpio.h> 11#include <linux/gpio.h>
12#include <linux/irq.h> 12#include <linux/irq.h>
13#include <linux/i2c.h>
13 14
14#include <asm/mach/arch.h> 15#include <asm/mach/arch.h>
15#include <asm/mach-types.h> 16#include <asm/mach-types.h>
16 17
18#include <plat/pincfg.h>
19#include <plat/i2c.h>
20
17#include <mach/hardware.h> 21#include <mach/hardware.h>
18#include <mach/devices.h> 22#include <mach/devices.h>
19#include <mach/setup.h> 23#include <mach/setup.h>
20 24
25#include "pins-db5500.h"
21#include "devices-db5500.h" 26#include "devices-db5500.h"
27#include <linux/led-lm3530.h>
28
29/*
30 * GPIO
31 */
32
33static pin_cfg_t u5500_pins[] = {
34 /* I2C */
35 GPIO218_I2C2_SCL | PIN_INPUT_PULLUP,
36 GPIO219_I2C2_SDA | PIN_INPUT_PULLUP,
37
38 /* DISPLAY_ENABLE */
39 GPIO226_GPIO | PIN_OUTPUT_LOW,
40
41 /* Backlight Enbale */
42 GPIO224_GPIO | PIN_OUTPUT_HIGH,
43};
44/*
45 * I2C
46 */
47
48#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
49static struct nmk_i2c_controller u5500_i2c##id##_data = { \
50 /* \
51 * slave data setup time, which is \
52 * 250 ns,100ns,10ns which is 14,6,2 \
53 * respectively for a 48 Mhz \
54 * i2c clock \
55 */ \
56 .slsu = _slsu, \
57 /* Tx FIFO threshold */ \
58 .tft = _tft, \
59 /* Rx FIFO threshold */ \
60 .rft = _rft, \
61 /* std. mode operation */ \
62 .clk_freq = clk, \
63 .sm = _sm, \
64}
65/*
66 * The board uses TODO <3> i2c controllers, initialize all of
67 * them with slave data setup time of 250 ns,
68 * Tx & Rx FIFO threshold values as 1 and standard
69 * mode of operation
70 */
71
72U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST);
73
74static struct lm3530_platform_data u5500_als_platform_data = {
75 .mode = LM3530_BL_MODE_MANUAL,
76 .als_input_mode = LM3530_INPUT_ALS1,
77 .max_current = LM3530_FS_CURR_26mA,
78 .pwm_pol_hi = true,
79 .als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
80 .brt_ramp_law = 1, /* Linear */
81 .brt_ramp_fall = LM3530_RAMP_TIME_8s,
82 .brt_ramp_rise = LM3530_RAMP_TIME_8s,
83 .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm,
84 .als2_resistor_sel = LM3530_ALS_IMPD_Z,
85 .als_vmin = 730, /* mV */
86 .als_vmax = 1020, /* mV */
87 .brt_val = 0x7F, /* Max brightness */
88};
22 89
90
91static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
92 {
93 /* Backlight */
94 I2C_BOARD_INFO("lm3530-led", 0x36),
95 .platform_data = &u5500_als_platform_data,
96 },
97};
98
99static void __init u5500_i2c_init(void)
100{
101 db5500_add_i2c2(&u5500_i2c2_data);
102 i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
103}
23static void __init u5500_uart_init(void) 104static void __init u5500_uart_init(void)
24{ 105{
25 db5500_add_uart0(NULL); 106 db5500_add_uart0(NULL);
@@ -30,7 +111,8 @@ static void __init u5500_uart_init(void)
30static void __init u5500_init_machine(void) 111static void __init u5500_init_machine(void)
31{ 112{
32 u5500_init_devices(); 113 u5500_init_devices();
33 114 nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins));
115 u5500_i2c_init();
34 u5500_sdi_init(); 116 u5500_sdi_init();
35 u5500_uart_init(); 117 u5500_uart_init();
36} 118}
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c
index 18648ef2d874..591f77526746 100644
--- a/arch/cris/arch-v32/mach-a3/pinmux.c
+++ b/arch/cris/arch-v32/mach-a3/pinmux.c
@@ -85,6 +85,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
85 int ret = -EINVAL; 85 int ret = -EINVAL;
86 char saved[sizeof pins]; 86 char saved[sizeof pins];
87 unsigned long flags; 87 unsigned long flags;
88 reg_pinmux_rw_hwprot hwprot;
89 reg_clkgen_rw_clk_ctrl clk_ctrl;
88 90
89 spin_lock_irqsave(&pinmux_lock, flags); 91 spin_lock_irqsave(&pinmux_lock, flags);
90 92
@@ -93,9 +95,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
93 95
94 crisv32_pinmux_init(); /* must be done before we read rw_hwprot */ 96 crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
95 97
96 reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); 98 hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
97 reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen, 99 clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
98 rw_clk_ctrl);
99 100
100 switch (function) { 101 switch (function) {
101 case pinmux_eth: 102 case pinmux_eth:
@@ -262,6 +263,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
262 int ret = -EINVAL; 263 int ret = -EINVAL;
263 char saved[sizeof pins]; 264 char saved[sizeof pins];
264 unsigned long flags; 265 unsigned long flags;
266 reg_pinmux_rw_hwprot hwprot;
265 267
266 spin_lock_irqsave(&pinmux_lock, flags); 268 spin_lock_irqsave(&pinmux_lock, flags);
267 269
@@ -270,7 +272,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
270 272
271 crisv32_pinmux_init(); /* must be done before we read rw_hwprot */ 273 crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
272 274
273 reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); 275 hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
274 276
275 switch (function) { 277 switch (function) {
276 case pinmux_eth: 278 case pinmux_eth:
diff --git a/arch/cris/include/arch-v10/arch/processor.h b/arch/cris/include/arch-v10/arch/processor.h
index cc692c7a0660..93feb2a487d8 100644
--- a/arch/cris/include/arch-v10/arch/processor.h
+++ b/arch/cris/include/arch-v10/arch/processor.h
@@ -53,7 +53,6 @@ struct thread_struct {
53 */ 53 */
54 54
55#define start_thread(regs, ip, usp) do { \ 55#define start_thread(regs, ip, usp) do { \
56 set_fs(USER_DS); \
57 regs->irp = ip; \ 56 regs->irp = ip; \
58 regs->dccr |= 1 << U_DCCR_BITNR; \ 57 regs->dccr |= 1 << U_DCCR_BITNR; \
59 wrusp(usp); \ 58 wrusp(usp); \
diff --git a/arch/cris/include/arch-v32/arch/processor.h b/arch/cris/include/arch-v32/arch/processor.h
index f80b47790ca6..9603c907fbc4 100644
--- a/arch/cris/include/arch-v32/arch/processor.h
+++ b/arch/cris/include/arch-v32/arch/processor.h
@@ -47,7 +47,6 @@ struct thread_struct {
47 */ 47 */
48#define start_thread(regs, ip, usp) \ 48#define start_thread(regs, ip, usp) \
49do { \ 49do { \
50 set_fs(USER_DS); \
51 regs->erp = ip; \ 50 regs->erp = ip; \
52 regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \ 51 regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \
53 wrusp(usp); \ 52 wrusp(usp); \
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 69e8a34eb6d5..e834b6018897 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -81,7 +81,6 @@ struct thread_struct {
81#if defined(__H8300H__) 81#if defined(__H8300H__)
82#define start_thread(_regs, _pc, _usp) \ 82#define start_thread(_regs, _pc, _usp) \
83do { \ 83do { \
84 set_fs(USER_DS); /* reads from user space */ \
85 (_regs)->pc = (_pc); \ 84 (_regs)->pc = (_pc); \
86 (_regs)->ccr = 0x00; /* clear all flags */ \ 85 (_regs)->ccr = 0x00; /* clear all flags */ \
87 (_regs)->er5 = current->mm->start_data; /* GOT base */ \ 86 (_regs)->er5 = current->mm->start_data; /* GOT base */ \
@@ -91,7 +90,6 @@ do { \
91#if defined(__H8300S__) 90#if defined(__H8300S__)
92#define start_thread(_regs, _pc, _usp) \ 91#define start_thread(_regs, _pc, _usp) \
93do { \ 92do { \
94 set_fs(USER_DS); /* reads from user space */ \
95 (_regs)->pc = (_pc); \ 93 (_regs)->pc = (_pc); \
96 (_regs)->ccr = 0x00; /* clear kernel flag */ \ 94 (_regs)->ccr = 0x00; /* clear kernel flag */ \
97 (_regs)->exr = 0x78; /* enable all interrupts */ \ 95 (_regs)->exr = 0x78; /* enable all interrupts */ \
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index 8397c249989b..e1f46d757460 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -106,7 +106,6 @@ struct thread_struct {
106 106
107#define start_thread(regs, new_pc, new_spu) \ 107#define start_thread(regs, new_pc, new_spu) \
108 do { \ 108 do { \
109 set_fs(USER_DS); \
110 regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL; \ 109 regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL; \
111 regs->bpc = new_pc; \ 110 regs->bpc = new_pc; \
112 regs->spu = new_spu; \ 111 regs->spu = new_spu; \
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index f111b02b704f..d8ef53ac03f9 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -105,9 +105,6 @@ struct thread_struct {
105static inline void start_thread(struct pt_regs * regs, unsigned long pc, 105static inline void start_thread(struct pt_regs * regs, unsigned long pc,
106 unsigned long usp) 106 unsigned long usp)
107{ 107{
108 /* reads from user space */
109 set_fs(USER_DS);
110
111 regs->pc = pc; 108 regs->pc = pc;
112 regs->sr &= ~0x2000; 109 regs->sr &= ~0x2000;
113 wrusp(usp); 110 wrusp(usp);
@@ -129,7 +126,6 @@ extern int handle_kernel_fault(struct pt_regs *regs);
129 126
130#define start_thread(_regs, _pc, _usp) \ 127#define start_thread(_regs, _pc, _usp) \
131do { \ 128do { \
132 set_fs(USER_DS); /* reads from user space */ \
133 (_regs)->pc = (_pc); \ 129 (_regs)->pc = (_pc); \
134 ((struct switch_stack *)(_regs))[-1].a6 = 0; \ 130 ((struct switch_stack *)(_regs))[-1].a6 = 0; \
135 reformat(_regs); \ 131 reformat(_regs); \
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c
index c2a1fc23dd75..1bc223aa07ec 100644
--- a/arch/m68k/kernel/process_mm.c
+++ b/arch/m68k/kernel/process_mm.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(kernel_thread);
185void flush_thread(void) 185void flush_thread(void)
186{ 186{
187 unsigned long zero = 0; 187 unsigned long zero = 0;
188 set_fs(USER_DS); 188
189 current->thread.fs = __USER_DS; 189 current->thread.fs = __USER_DS;
190 if (!FPU_IS_EMU) 190 if (!FPU_IS_EMU)
191 asm volatile (".chip 68k/68881\n\t" 191 asm volatile (".chip 68k/68881\n\t"
diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c
index 9b86ad11c68e..69c1803fcf1b 100644
--- a/arch/m68k/kernel/process_no.c
+++ b/arch/m68k/kernel/process_no.c
@@ -158,7 +158,7 @@ void flush_thread(void)
158#ifdef CONFIG_FPU 158#ifdef CONFIG_FPU
159 unsigned long zero = 0; 159 unsigned long zero = 0;
160#endif 160#endif
161 set_fs(USER_DS); 161
162 current->thread.fs = __USER_DS; 162 current->thread.fs = __USER_DS;
163#ifdef CONFIG_FPU 163#ifdef CONFIG_FPU
164 if (!FPU_IS_EMU) 164 if (!FPU_IS_EMU)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 271ff6318eda..0e0ea941156f 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -24,6 +24,7 @@
24#include <linux/cpumask.h> 24#include <linux/cpumask.h>
25#include <linux/memblock.h> 25#include <linux/memblock.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/reboot.h>
27 28
28#include <asm/prom.h> 29#include <asm/prom.h>
29#include <asm/rtas.h> 30#include <asm/rtas.h>
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index bf5f5ce3a7bd..e037c7494fd8 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
20#include <linux/reboot.h>
20#include <asm/delay.h> 21#include <asm/delay.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
22#include <asm/rtas.h> 23#include <asm/rtas.h>
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 253986bd6bb6..1074dddcb104 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -41,6 +41,7 @@ config SPARC64
41 select HAVE_FUNCTION_TRACE_MCOUNT_TEST 41 select HAVE_FUNCTION_TRACE_MCOUNT_TEST
42 select HAVE_KRETPROBES 42 select HAVE_KRETPROBES
43 select HAVE_KPROBES 43 select HAVE_KPROBES
44 select HAVE_RCU_TABLE_FREE if SMP
44 select HAVE_MEMBLOCK 45 select HAVE_MEMBLOCK
45 select HAVE_SYSCALL_WRAPPERS 46 select HAVE_SYSCALL_WRAPPERS
46 select HAVE_DYNAMIC_FTRACE 47 select HAVE_DYNAMIC_FTRACE
@@ -81,10 +82,6 @@ config IOMMU_HELPER
81 bool 82 bool
82 default y if SPARC64 83 default y if SPARC64
83 84
84config QUICKLIST
85 bool
86 default y if SPARC64
87
88config STACKTRACE_SUPPORT 85config STACKTRACE_SUPPORT
89 bool 86 bool
90 default y if SPARC64 87 default y if SPARC64
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
index 4e5e0878144f..40b2d7a7023d 100644
--- a/arch/sparc/include/asm/pgalloc_64.h
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -5,7 +5,6 @@
5#include <linux/sched.h> 5#include <linux/sched.h>
6#include <linux/mm.h> 6#include <linux/mm.h>
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/quicklist.h>
9 8
10#include <asm/spitfire.h> 9#include <asm/spitfire.h>
11#include <asm/cpudata.h> 10#include <asm/cpudata.h>
@@ -14,71 +13,114 @@
14 13
15/* Page table allocation/freeing. */ 14/* Page table allocation/freeing. */
16 15
16extern struct kmem_cache *pgtable_cache;
17
17static inline pgd_t *pgd_alloc(struct mm_struct *mm) 18static inline pgd_t *pgd_alloc(struct mm_struct *mm)
18{ 19{
19 return quicklist_alloc(0, GFP_KERNEL, NULL); 20 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
20} 21}
21 22
22static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 23static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
23{ 24{
24 quicklist_free(0, NULL, pgd); 25 kmem_cache_free(pgtable_cache, pgd);
25} 26}
26 27
27#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) 28#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
28 29
29static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 30static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
30{ 31{
31 return quicklist_alloc(0, GFP_KERNEL, NULL); 32 return kmem_cache_alloc(pgtable_cache,
33 GFP_KERNEL|__GFP_REPEAT);
32} 34}
33 35
34static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) 36static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
35{ 37{
36 quicklist_free(0, NULL, pmd); 38 kmem_cache_free(pgtable_cache, pmd);
37} 39}
38 40
39static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 41static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
40 unsigned long address) 42 unsigned long address)
41{ 43{
42 return quicklist_alloc(0, GFP_KERNEL, NULL); 44 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
43} 45}
44 46
45static inline pgtable_t pte_alloc_one(struct mm_struct *mm, 47static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
46 unsigned long address) 48 unsigned long address)
47{ 49{
48 struct page *page; 50 struct page *page;
49 void *pg; 51 pte_t *pte;
50 52
51 pg = quicklist_alloc(0, GFP_KERNEL, NULL); 53 pte = pte_alloc_one_kernel(mm, address);
52 if (!pg) 54 if (!pte)
53 return NULL; 55 return NULL;
54 page = virt_to_page(pg); 56 page = virt_to_page(pte);
55 pgtable_page_ctor(page); 57 pgtable_page_ctor(page);
56 return page; 58 return page;
57} 59}
58 60
59static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 61static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
60{ 62{
61 quicklist_free(0, NULL, pte); 63 free_page((unsigned long)pte);
62} 64}
63 65
64static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) 66static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
65{ 67{
66 pgtable_page_dtor(ptepage); 68 pgtable_page_dtor(ptepage);
67 quicklist_free_page(0, NULL, ptepage); 69 __free_page(ptepage);
68} 70}
69 71
70
71#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE) 72#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
72#define pmd_populate(MM,PMD,PTE_PAGE) \ 73#define pmd_populate(MM,PMD,PTE_PAGE) \
73 pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE)) 74 pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
74#define pmd_pgtable(pmd) pmd_page(pmd) 75#define pmd_pgtable(pmd) pmd_page(pmd)
75 76
76static inline void check_pgt_cache(void) 77#define check_pgt_cache() do { } while (0)
78
79static inline void pgtable_free(void *table, bool is_page)
80{
81 if (is_page)
82 free_page((unsigned long)table);
83 else
84 kmem_cache_free(pgtable_cache, table);
85}
86
87#ifdef CONFIG_SMP
88
89struct mmu_gather;
90extern void tlb_remove_table(struct mmu_gather *, void *);
91
92static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
93{
94 unsigned long pgf = (unsigned long)table;
95 if (is_page)
96 pgf |= 0x1UL;
97 tlb_remove_table(tlb, (void *)pgf);
98}
99
100static inline void __tlb_remove_table(void *_table)
101{
102 void *table = (void *)((unsigned long)_table & ~0x1UL);
103 bool is_page = false;
104
105 if ((unsigned long)_table & 0x1UL)
106 is_page = true;
107 pgtable_free(table, is_page);
108}
109#else /* CONFIG_SMP */
110static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
77{ 111{
78 quicklist_trim(0, NULL, 25, 16); 112 pgtable_free(table, is_page);
113}
114#endif /* !CONFIG_SMP */
115
116static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
117 unsigned long address)
118{
119 pgtable_page_dtor(ptepage);
120 pgtable_free_tlb(tlb, page_address(ptepage), true);
79} 121}
80 122
81#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte) 123#define __pmd_free_tlb(tlb, pmd, addr) \
82#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) 124 pgtable_free_tlb(tlb, pmd, false)
83 125
84#endif /* _SPARC64_PGALLOC_H */ 126#endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1e03c5a6b4f7..adf89329af59 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -95,6 +95,10 @@
95/* PTE bits which are the same in SUN4U and SUN4V format. */ 95/* PTE bits which are the same in SUN4U and SUN4V format. */
96#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */ 96#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
97#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ 97#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
98#define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */
99
100/* Advertise support for _PAGE_SPECIAL */
101#define __HAVE_ARCH_PTE_SPECIAL
98 102
99/* SUN4U pte bits... */ 103/* SUN4U pte bits... */
100#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */ 104#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */
@@ -104,6 +108,7 @@
104#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */ 108#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */
105#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */ 109#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */
106#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ 110#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
111#define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */
107#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */ 112#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */
108#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ 113#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
109#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ 114#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
@@ -133,6 +138,7 @@
133#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */ 138#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */
134#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */ 139#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */
135#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */ 140#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */
141#define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */
136#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */ 142#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */
137#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */ 143#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */
138#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ 144#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */
@@ -302,10 +308,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
302 : "=r" (mask), "=r" (tmp) 308 : "=r" (mask), "=r" (tmp)
303 : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | 309 : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
304 _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U | 310 _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
305 _PAGE_SZBITS_4U), 311 _PAGE_SZBITS_4U | _PAGE_SPECIAL),
306 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | 312 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
307 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V | 313 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
308 _PAGE_SZBITS_4V)); 314 _PAGE_SZBITS_4V | _PAGE_SPECIAL));
309 315
310 return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); 316 return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
311} 317}
@@ -502,6 +508,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
502 508
503static inline pte_t pte_mkspecial(pte_t pte) 509static inline pte_t pte_mkspecial(pte_t pte)
504{ 510{
511 pte_val(pte) |= _PAGE_SPECIAL;
505 return pte; 512 return pte;
506} 513}
507 514
@@ -607,9 +614,9 @@ static inline unsigned long pte_present(pte_t pte)
607 return val; 614 return val;
608} 615}
609 616
610static inline int pte_special(pte_t pte) 617static inline unsigned long pte_special(pte_t pte)
611{ 618{
612 return 0; 619 return pte_val(pte) & _PAGE_SPECIAL;
613} 620}
614 621
615#define pmd_set(pmdp, ptep) \ 622#define pmd_set(pmdp, ptep) \
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 79836a7dd00c..e3cda21b5ee9 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -4,7 +4,7 @@
4asflags-y := -ansi 4asflags-y := -ansi
5ccflags-y := -Werror 5ccflags-y := -Werror
6 6
7obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o 7obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
8obj-y += fault_$(BITS).o 8obj-y += fault_$(BITS).o
9obj-y += init_$(BITS).o 9obj-y += init_$(BITS).o
10obj-$(CONFIG_SPARC32) += loadmmu.o 10obj-$(CONFIG_SPARC32) += loadmmu.o
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
new file mode 100644
index 000000000000..a986b5d05712
--- /dev/null
+++ b/arch/sparc/mm/gup.c
@@ -0,0 +1,181 @@
1/*
2 * Lockless get_user_pages_fast for sparc, cribbed from powerpc
3 *
4 * Copyright (C) 2008 Nick Piggin
5 * Copyright (C) 2008 Novell Inc.
6 */
7
8#include <linux/sched.h>
9#include <linux/mm.h>
10#include <linux/vmstat.h>
11#include <linux/pagemap.h>
12#include <linux/rwsem.h>
13#include <asm/pgtable.h>
14
15/*
16 * The performance critical leaf functions are made noinline otherwise gcc
17 * inlines everything into a single function which results in too much
18 * register pressure.
19 */
20static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
21 unsigned long end, int write, struct page **pages, int *nr)
22{
23 unsigned long mask, result;
24 pte_t *ptep;
25
26 if (tlb_type == hypervisor) {
27 result = _PAGE_PRESENT_4V|_PAGE_P_4V;
28 if (write)
29 result |= _PAGE_WRITE_4V;
30 } else {
31 result = _PAGE_PRESENT_4U|_PAGE_P_4U;
32 if (write)
33 result |= _PAGE_WRITE_4U;
34 }
35 mask = result | _PAGE_SPECIAL;
36
37 ptep = pte_offset_kernel(&pmd, addr);
38 do {
39 struct page *page, *head;
40 pte_t pte = *ptep;
41
42 if ((pte_val(pte) & mask) != result)
43 return 0;
44 VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
45
46 /* The hugepage case is simplified on sparc64 because
47 * we encode the sub-page pfn offsets into the
48 * hugepage PTEs. We could optimize this in the future
49 * use page_cache_add_speculative() for the hugepage case.
50 */
51 page = pte_page(pte);
52 head = compound_head(page);
53 if (!page_cache_get_speculative(head))
54 return 0;
55 if (unlikely(pte_val(pte) != pte_val(*ptep))) {
56 put_page(head);
57 return 0;
58 }
59
60 pages[*nr] = page;
61 (*nr)++;
62 } while (ptep++, addr += PAGE_SIZE, addr != end);
63
64 return 1;
65}
66
67static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
68 int write, struct page **pages, int *nr)
69{
70 unsigned long next;
71 pmd_t *pmdp;
72
73 pmdp = pmd_offset(&pud, addr);
74 do {
75 pmd_t pmd = *pmdp;
76
77 next = pmd_addr_end(addr, end);
78 if (pmd_none(pmd))
79 return 0;
80 if (!gup_pte_range(pmd, addr, next, write, pages, nr))
81 return 0;
82 } while (pmdp++, addr = next, addr != end);
83
84 return 1;
85}
86
87static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
88 int write, struct page **pages, int *nr)
89{
90 unsigned long next;
91 pud_t *pudp;
92
93 pudp = pud_offset(&pgd, addr);
94 do {
95 pud_t pud = *pudp;
96
97 next = pud_addr_end(addr, end);
98 if (pud_none(pud))
99 return 0;
100 if (!gup_pmd_range(pud, addr, next, write, pages, nr))
101 return 0;
102 } while (pudp++, addr = next, addr != end);
103
104 return 1;
105}
106
107int get_user_pages_fast(unsigned long start, int nr_pages, int write,
108 struct page **pages)
109{
110 struct mm_struct *mm = current->mm;
111 unsigned long addr, len, end;
112 unsigned long next;
113 pgd_t *pgdp;
114 int nr = 0;
115
116 start &= PAGE_MASK;
117 addr = start;
118 len = (unsigned long) nr_pages << PAGE_SHIFT;
119 end = start + len;
120
121 /*
122 * XXX: batch / limit 'nr', to avoid large irq off latency
123 * needs some instrumenting to determine the common sizes used by
124 * important workloads (eg. DB2), and whether limiting the batch size
125 * will decrease performance.
126 *
127 * It seems like we're in the clear for the moment. Direct-IO is
128 * the main guy that batches up lots of get_user_pages, and even
129 * they are limited to 64-at-a-time which is not so many.
130 */
131 /*
132 * This doesn't prevent pagetable teardown, but does prevent
133 * the pagetables from being freed on sparc.
134 *
135 * So long as we atomically load page table pointers versus teardown,
136 * we can follow the address down to the the page and take a ref on it.
137 */
138 local_irq_disable();
139
140 pgdp = pgd_offset(mm, addr);
141 do {
142 pgd_t pgd = *pgdp;
143
144 next = pgd_addr_end(addr, end);
145 if (pgd_none(pgd))
146 goto slow;
147 if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
148 goto slow;
149 } while (pgdp++, addr = next, addr != end);
150
151 local_irq_enable();
152
153 VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
154 return nr;
155
156 {
157 int ret;
158
159slow:
160 local_irq_enable();
161
162 /* Try to get the remaining pages with get_user_pages */
163 start += nr << PAGE_SHIFT;
164 pages += nr;
165
166 down_read(&mm->mmap_sem);
167 ret = get_user_pages(current, mm, start,
168 (end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
169 up_read(&mm->mmap_sem);
170
171 /* Have to be a bit careful with return values */
172 if (nr > 0) {
173 if (ret < 0)
174 ret = nr;
175 else
176 ret += nr;
177 }
178
179 return ret;
180 }
181}
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index a5f51b22fcbe..536412d8f416 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -236,6 +236,8 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
236 } 236 }
237} 237}
238 238
239struct kmem_cache *pgtable_cache __read_mostly;
240
239static struct kmem_cache *tsb_caches[8] __read_mostly; 241static struct kmem_cache *tsb_caches[8] __read_mostly;
240 242
241static const char *tsb_cache_names[8] = { 243static const char *tsb_cache_names[8] = {
@@ -253,6 +255,15 @@ void __init pgtable_cache_init(void)
253{ 255{
254 unsigned long i; 256 unsigned long i;
255 257
258 pgtable_cache = kmem_cache_create("pgtable_cache",
259 PAGE_SIZE, PAGE_SIZE,
260 0,
261 _clear_page);
262 if (!pgtable_cache) {
263 prom_printf("pgtable_cache_init(): Could not create!\n");
264 prom_halt();
265 }
266
256 for (i = 0; i < 8; i++) { 267 for (i = 0; i < 8; i++) {
257 unsigned long size = 8192 << i; 268 unsigned long size = 8192 << i;
258 const char *name = tsb_cache_names[i]; 269 const char *name = tsb_cache_names[i];
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
index 8aae429a56e2..d31ecf346b4e 100644
--- a/arch/um/Kconfig.x86
+++ b/arch/um/Kconfig.x86
@@ -1,3 +1,5 @@
1mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
2
1source "arch/um/Kconfig.common" 3source "arch/um/Kconfig.common"
2 4
3menu "UML-specific options" 5menu "UML-specific options"
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 25e1965df7ce..d4191fe1cede 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -543,11 +543,10 @@ int parse_chan_pair(char *str, struct line *line, int device,
543 const struct chan_opts *opts, char **error_out) 543 const struct chan_opts *opts, char **error_out)
544{ 544{
545 struct list_head *chans = &line->chan_list; 545 struct list_head *chans = &line->chan_list;
546 struct chan *new, *chan; 546 struct chan *new;
547 char *in, *out; 547 char *in, *out;
548 548
549 if (!list_empty(chans)) { 549 if (!list_empty(chans)) {
550 chan = list_entry(chans->next, struct chan, list);
551 free_chan(chans, 0); 550 free_chan(chans, 0);
552 INIT_LIST_HEAD(chans); 551 INIT_LIST_HEAD(chans);
553 } 552 }
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 93f227a25ba4..9cbb426c0b91 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -186,7 +186,11 @@ static int absolutize(char *to, int size, char *from)
186 strcat(to, "/"); 186 strcat(to, "/");
187 strcat(to, from); 187 strcat(to, from);
188 } 188 }
189 chdir(save_cwd); 189 if (chdir(save_cwd)) {
190 cow_printf("absolutize : Can't cd to '%s' - "
191 "errno = %d\n", save_cwd, errno);
192 return -1;
193 }
190 return 0; 194 return 0;
191} 195}
192 196
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index b56f8e0196a9..84dce3fc590c 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -32,7 +32,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
32{ 32{
33 struct dog_data data; 33 struct dog_data data;
34 int in_fds[2], out_fds[2], pid, n, err; 34 int in_fds[2], out_fds[2], pid, n, err;
35 char pid_buf[sizeof("nnnnn\0")], c; 35 char pid_buf[sizeof("nnnnnnn\0")], c;
36 char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; 36 char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
37 char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, 37 char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
38 NULL }; 38 NULL };
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 35dd0b86401a..d51c404239a8 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -176,10 +176,9 @@ void line_flush_buffer(struct tty_struct *tty)
176{ 176{
177 struct line *line = tty->driver_data; 177 struct line *line = tty->driver_data;
178 unsigned long flags; 178 unsigned long flags;
179 int err;
180 179
181 spin_lock_irqsave(&line->lock, flags); 180 spin_lock_irqsave(&line->lock, flags);
182 err = flush_buffer(line); 181 flush_buffer(line);
183 spin_unlock_irqrestore(&line->lock, flags); 182 spin_unlock_irqrestore(&line->lock, flags);
184} 183}
185 184
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 47d0c37897d5..22745b47c829 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -262,6 +262,15 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
262 return 0; 262 return 0;
263} 263}
264 264
265#ifdef CONFIG_NET_POLL_CONTROLLER
266static void uml_net_poll_controller(struct net_device *dev)
267{
268 disable_irq(dev->irq);
269 uml_net_interrupt(dev->irq, dev);
270 enable_irq(dev->irq);
271}
272#endif
273
265static void uml_net_get_drvinfo(struct net_device *dev, 274static void uml_net_get_drvinfo(struct net_device *dev,
266 struct ethtool_drvinfo *info) 275 struct ethtool_drvinfo *info)
267{ 276{
@@ -364,6 +373,9 @@ static const struct net_device_ops uml_netdev_ops = {
364 .ndo_set_mac_address = eth_mac_addr, 373 .ndo_set_mac_address = eth_mac_addr,
365 .ndo_change_mtu = uml_net_change_mtu, 374 .ndo_change_mtu = uml_net_change_mtu,
366 .ndo_validate_addr = eth_validate_addr, 375 .ndo_validate_addr = eth_validate_addr,
376#ifdef CONFIG_NET_POLL_CONTROLLER
377 .ndo_poll_controller = uml_net_poll_controller,
378#endif
367}; 379};
368 380
369/* 381/*
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 9415dd9e63ef..520118888f16 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -228,7 +228,10 @@ static void change(char *dev, char *what, unsigned char *addr,
228 "buffer\n"); 228 "buffer\n");
229 229
230 pid = change_tramp(argv, output, output_len); 230 pid = change_tramp(argv, output, output_len);
231 if (pid < 0) return; 231 if (pid < 0) {
232 kfree(output);
233 return;
234 }
232 235
233 if (output != NULL) { 236 if (output != NULL) {
234 printk("%s", output); 237 printk("%s", output);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index a1c2d2c98a94..cbacfc4e63e6 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -102,7 +102,7 @@ static int slip_tramp(char **argv, int fd)
102 "buffer\n"); 102 "buffer\n");
103 os_kill_process(pid, 1); 103 os_kill_process(pid, 1);
104 err = -ENOMEM; 104 err = -ENOMEM;
105 goto out_free; 105 goto out_close;
106 } 106 }
107 107
108 close(fds[1]); 108 close(fds[1]);
@@ -112,7 +112,6 @@ static int slip_tramp(char **argv, int fd)
112 err = helper_wait(pid); 112 err = helper_wait(pid);
113 close(fds[0]); 113 close(fds[0]);
114 114
115out_free:
116 kfree(output); 115 kfree(output);
117 return err; 116 return err;
118 117
diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h
index c71e32b6741e..8a5576d8eda5 100644
--- a/arch/um/include/asm/delay.h
+++ b/arch/um/include/asm/delay.h
@@ -1,20 +1,18 @@
1#ifndef __UM_DELAY_H 1#ifndef __UM_DELAY_H
2#define __UM_DELAY_H 2#define __UM_DELAY_H
3 3
4#define MILLION 1000000
5
6/* Undefined on purpose */ 4/* Undefined on purpose */
7extern void __bad_udelay(void); 5extern void __bad_udelay(void);
6extern void __bad_ndelay(void);
8 7
9extern void __udelay(unsigned long usecs); 8extern void __udelay(unsigned long usecs);
9extern void __ndelay(unsigned long usecs);
10extern void __delay(unsigned long loops); 10extern void __delay(unsigned long loops);
11 11
12#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \ 12#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
13 __bad_udelay() : __udelay(n)) 13 __bad_udelay() : __udelay(n))
14 14
15/* It appears that ndelay is not used at all for UML, and has never been 15#define ndelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
16 * implemented. */ 16 __bad_ndelay() : __ndelay(n))
17extern void __unimplemented_ndelay(void);
18#define ndelay(n) __unimplemented_ndelay()
19 17
20#endif 18#endif
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 09bd7b585726..939a4a67f0fd 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -38,7 +38,6 @@ void flush_thread(void)
38 38
39void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) 39void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
40{ 40{
41 set_fs(USER_DS);
42 PT_REGS_IP(regs) = eip; 41 PT_REGS_IP(regs) = eip;
43 PT_REGS_SP(regs) = esp; 42 PT_REGS_SP(regs) = esp;
44} 43}
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 869bec9f2516..4d93dff6b371 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -20,9 +20,8 @@ static void kill_off_processes(void)
20 os_kill_ptraced_process(userspace_pid[0], 1); 20 os_kill_ptraced_process(userspace_pid[0], 1);
21 else { 21 else {
22 struct task_struct *p; 22 struct task_struct *p;
23 int pid, me; 23 int pid;
24 24
25 me = os_getpid();
26 for_each_process(p) { 25 for_each_process(p) {
27 if (p->mm == NULL) 26 if (p->mm == NULL)
28 continue; 27 continue;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d66f0388f091..b33f4dfe7ae5 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,10 +3,12 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ 6obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
7 registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \ 7 registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
8 umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ 8 umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
9 9
10obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
11
10USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ 12USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
11 main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ 13 main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
12 tty.o tls.o uaccess.o umid.o util.o 14 tty.o tls.o uaccess.o umid.o util.o
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 608784d4ec57..953323799381 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -14,16 +14,11 @@
14#include "mem_user.h" 14#include "mem_user.h"
15#include <kern_constants.h> 15#include <kern_constants.h>
16 16
17/* Use the one from the kernel - the host may miss it, if having old headers. */
18#if UM_ELF_CLASS == UM_ELFCLASS32
19typedef Elf32_auxv_t elf_auxv_t; 17typedef Elf32_auxv_t elf_auxv_t;
20#else
21typedef Elf64_auxv_t elf_auxv_t;
22#endif
23 18
24/* These are initialized very early in boot and never changed */ 19/* These are initialized very early in boot and never changed */
25char * elf_aux_platform; 20char * elf_aux_platform;
26long elf_aux_hwcap; 21extern long elf_aux_hwcap;
27unsigned long vsyscall_ehdr; 22unsigned long vsyscall_ehdr;
28unsigned long vsyscall_end; 23unsigned long vsyscall_end;
29unsigned long __kernel_vsyscall; 24unsigned long __kernel_vsyscall;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index b6b1096152aa..feff22d64672 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -28,14 +28,14 @@ static int helper_child(void *arg)
28{ 28{
29 struct helper_data *data = arg; 29 struct helper_data *data = arg;
30 char **argv = data->argv; 30 char **argv = data->argv;
31 int err; 31 int err, ret;
32 32
33 if (data->pre_exec != NULL) 33 if (data->pre_exec != NULL)
34 (*data->pre_exec)(data->pre_data); 34 (*data->pre_exec)(data->pre_data);
35 err = execvp_noalloc(data->buf, argv[0], argv); 35 err = execvp_noalloc(data->buf, argv[0], argv);
36 36
37 /* If the exec succeeds, we don't get here */ 37 /* If the exec succeeds, we don't get here */
38 write(data->fd, &err, sizeof(err)); 38 CATCH_EINTR(ret = write(data->fd, &err, sizeof(err)));
39 39
40 return 0; 40 return 0;
41} 41}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index fb2a97a75fb1..8471b817d94f 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -21,6 +21,8 @@
21#define STACKSIZE (8 * 1024 * 1024) 21#define STACKSIZE (8 * 1024 * 1024)
22#define THREAD_NAME_LEN (256) 22#define THREAD_NAME_LEN (256)
23 23
24long elf_aux_hwcap;
25
24static void set_stklim(void) 26static void set_stklim(void)
25{ 27{
26 struct rlimit lim; 28 struct rlimit lim;
@@ -143,7 +145,9 @@ int __init main(int argc, char **argv, char **envp)
143 install_fatal_handler(SIGINT); 145 install_fatal_handler(SIGINT);
144 install_fatal_handler(SIGTERM); 146 install_fatal_handler(SIGTERM);
145 147
148#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
146 scan_elf_aux(envp); 149 scan_elf_aux(envp);
150#endif
147 151
148 do_uml_initcalls(); 152 do_uml_initcalls();
149 ret = linux_main(argc, argv); 153 ret = linux_main(argc, argv);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index e696144d2be3..62878cf1d33f 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -176,7 +176,7 @@ static int __init make_tempfile(const char *template, char **out_tempname,
176 176
177 find_tempdir(); 177 find_tempdir();
178 if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN)) 178 if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
179 return -1; 179 goto out;
180 180
181 if (template[0] != '/') 181 if (template[0] != '/')
182 strcpy(tempname, tempdir); 182 strcpy(tempname, tempdir);
@@ -191,13 +191,15 @@ static int __init make_tempfile(const char *template, char **out_tempname,
191 } 191 }
192 if (do_unlink && (unlink(tempname) < 0)) { 192 if (do_unlink && (unlink(tempname) < 0)) {
193 perror("unlink"); 193 perror("unlink");
194 goto out; 194 goto close;
195 } 195 }
196 if (out_tempname) { 196 if (out_tempname) {
197 *out_tempname = tempname; 197 *out_tempname = tempname;
198 } else 198 } else
199 free(tempname); 199 free(tempname);
200 return fd; 200 return fd;
201close:
202 close(fd);
201out: 203out:
202 free(tempname); 204 free(tempname);
203 return -1; 205 return -1;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 05f5ea8e83d2..45ffe46871e0 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -113,3 +113,8 @@ EXPORT_SYMBOL(__stack_smash_handler);
113 113
114extern long __guard __attribute__((weak)); 114extern long __guard __attribute__((weak));
115EXPORT_SYMBOL(__guard); 115EXPORT_SYMBOL(__guard);
116
117#ifdef _FORTIFY_SOURCE
118extern int __sprintf_chk(char *str, int flag, size_t strlen, const char *format);
119EXPORT_SYMBOL(__sprintf_chk);
120#endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 87b659dadf3f..3923cfb87649 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ 5obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
6 ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ 6 ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
7 sys_call_table.o tls.o atomic64_cx8_32.o 7 sys_call_table.o tls.o atomic64_cx8_32.o mem.o
8 8
9obj-$(CONFIG_BINFMT_ELF) += elfcore.o 9obj-$(CONFIG_BINFMT_ELF) += elfcore.o
10 10
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index d964a4111ac6..42305551d204 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -105,6 +105,8 @@ extern unsigned long __kernel_vsyscall;
105#define FIXADDR_USER_START VSYSCALL_BASE 105#define FIXADDR_USER_START VSYSCALL_BASE
106#define FIXADDR_USER_END VSYSCALL_END 106#define FIXADDR_USER_END VSYSCALL_END
107 107
108#define __HAVE_ARCH_GATE_AREA 1
109
108/* 110/*
109 * Architecture-neutral AT_ values in 0-17, leave some room 111 * Architecture-neutral AT_ values in 0-17, leave some room
110 * for more of them, start the x86-specific ones at 32. 112 * for more of them, start the x86-specific ones at 32.
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index d623e074f41d..f3fe1a688f7e 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,29 +1,60 @@
1/*
2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
3 * Mostly copied from arch/x86/lib/delay.c
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
1#include <linux/module.h> 10#include <linux/module.h>
2#include <linux/kernel.h> 11#include <linux/kernel.h>
3#include <linux/delay.h> 12#include <linux/delay.h>
4#include <asm/param.h> 13#include <asm/param.h>
5 14
6void __delay(unsigned long time) 15void __delay(unsigned long loops)
7{ 16{
8 /* Stolen from the i386 __loop_delay */ 17 asm volatile(
9 int d0; 18 "test %0,%0\n"
10 __asm__ __volatile__( 19 "jz 3f\n"
11 "\tjmp 1f\n" 20 "jmp 1f\n"
21
12 ".align 16\n" 22 ".align 16\n"
13 "1:\tjmp 2f\n" 23 "1: jmp 2f\n"
24
14 ".align 16\n" 25 ".align 16\n"
15 "2:\tdecl %0\n\tjns 2b" 26 "2: dec %0\n"
16 :"=&a" (d0) 27 " jnz 2b\n"
17 :"0" (time)); 28 "3: dec %0\n"
29
30 : /* we don't need output */
31 : "a" (loops)
32 );
18} 33}
34EXPORT_SYMBOL(__delay);
19 35
20void __udelay(unsigned long usecs) 36inline void __const_udelay(unsigned long xloops)
21{ 37{
22 int i, n; 38 int d0;
23 39
24 n = (loops_per_jiffy * HZ * usecs) / MILLION; 40 xloops *= 4;
25 for(i=0;i<n;i++) 41 asm("mull %%edx"
26 cpu_relax(); 42 : "=d" (xloops), "=&a" (d0)
43 : "1" (xloops), "0"
44 (loops_per_jiffy * (HZ/4)));
45
46 __delay(++xloops);
27} 47}
48EXPORT_SYMBOL(__const_udelay);
28 49
50void __udelay(unsigned long usecs)
51{
52 __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
53}
29EXPORT_SYMBOL(__udelay); 54EXPORT_SYMBOL(__udelay);
55
56void __ndelay(unsigned long nsecs)
57{
58 __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
59}
60EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-i386/mem.c b/arch/um/sys-i386/mem.c
new file mode 100644
index 000000000000..639900a6fde9
--- /dev/null
+++ b/arch/um/sys-i386/mem.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/mm.h>
10#include <asm/page.h>
11#include <asm/mman.h>
12
13static struct vm_area_struct gate_vma;
14
15static int __init gate_vma_init(void)
16{
17 if (!FIXADDR_USER_START)
18 return 0;
19
20 gate_vma.vm_mm = NULL;
21 gate_vma.vm_start = FIXADDR_USER_START;
22 gate_vma.vm_end = FIXADDR_USER_END;
23 gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
24 gate_vma.vm_page_prot = __P101;
25
26 /*
27 * Make sure the vDSO gets into every core dump.
28 * Dumping its contents makes post-mortem fully interpretable later
29 * without matching up the same kernel and hardware config to see
30 * what PC values meant.
31 */
32 gate_vma.vm_flags |= VM_ALWAYSDUMP;
33
34 return 0;
35}
36__initcall(gate_vma_init);
37
38struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
39{
40 return FIXADDR_USER_START ? &gate_vma : NULL;
41}
42
43int in_gate_area_no_mm(unsigned long addr)
44{
45 if (!FIXADDR_USER_START)
46 return 0;
47
48 if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
49 return 1;
50
51 return 0;
52}
53
54int in_gate_area(struct mm_struct *mm, unsigned long addr)
55{
56 struct vm_area_struct *vma = get_gate_vma(mm);
57
58 if (!vma)
59 return 0;
60
61 return (addr >= vma->vm_start) && (addr < vma->vm_end);
62}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 61fc99a42e10..bd4d1d3ba919 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,10 +4,12 @@
4# Licensed under the GPL 4# Licensed under the GPL
5# 5#
6 6
7obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ 7obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
8 setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ 8 setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
9 sysrq.o ksyms.o tls.o 9 sysrq.o ksyms.o tls.o
10 10
11obj-y += vdso/
12
11subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \ 13subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
12 lib/rwsem.o 14 lib/rwsem.o
13subarch-obj-$(CONFIG_MODULES) += kernel/module.o 15subarch-obj-$(CONFIG_MODULES) += kernel/module.o
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
index d6d5af376251..11a2bfb38859 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/um/sys-x86_64/asm/elf.h
@@ -119,4 +119,14 @@ extern long elf_aux_hwcap;
119 119
120#define SET_PERSONALITY(ex) do ; while(0) 120#define SET_PERSONALITY(ex) do ; while(0)
121 121
122#define __HAVE_ARCH_GATE_AREA 1
123#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
124struct linux_binprm;
125extern int arch_setup_additional_pages(struct linux_binprm *bprm,
126 int uses_interp);
127
128extern unsigned long um_vdso_addr;
129#define AT_SYSINFO_EHDR 33
130#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
131
122#endif 132#endif
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index dee5be66da82..f3fe1a688f7e 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -1,30 +1,60 @@
1/* 1/*
2 * Copyright 2003 PathScale, Inc. 2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
3 * Copied from arch/x86_64 3 * Mostly copied from arch/x86/lib/delay.c
4 * 4 *
5 * Licensed under the GPL 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
6 */ 8 */
7 9
8#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/kernel.h>
9#include <linux/delay.h> 12#include <linux/delay.h>
10#include <asm/processor.h>
11#include <asm/param.h> 13#include <asm/param.h>
12 14
13void __delay(unsigned long loops) 15void __delay(unsigned long loops)
14{ 16{
15 unsigned long i; 17 asm volatile(
18 "test %0,%0\n"
19 "jz 3f\n"
20 "jmp 1f\n"
16 21
17 for(i = 0; i < loops; i++) 22 ".align 16\n"
18 cpu_relax(); 23 "1: jmp 2f\n"
24
25 ".align 16\n"
26 "2: dec %0\n"
27 " jnz 2b\n"
28 "3: dec %0\n"
29
30 : /* we don't need output */
31 : "a" (loops)
32 );
19} 33}
34EXPORT_SYMBOL(__delay);
20 35
21void __udelay(unsigned long usecs) 36inline void __const_udelay(unsigned long xloops)
22{ 37{
23 unsigned long i, n; 38 int d0;
24 39
25 n = (loops_per_jiffy * HZ * usecs) / MILLION; 40 xloops *= 4;
26 for(i=0;i<n;i++) 41 asm("mull %%edx"
27 cpu_relax(); 42 : "=d" (xloops), "=&a" (d0)
43 : "1" (xloops), "0"
44 (loops_per_jiffy * (HZ/4)));
45
46 __delay(++xloops);
28} 47}
48EXPORT_SYMBOL(__const_udelay);
29 49
50void __udelay(unsigned long usecs)
51{
52 __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
53}
30EXPORT_SYMBOL(__udelay); 54EXPORT_SYMBOL(__udelay);
55
56void __ndelay(unsigned long nsecs)
57{
58 __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
59}
60EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c
index 3f8df8abf347..546518727a73 100644
--- a/arch/um/sys-x86_64/mem.c
+++ b/arch/um/sys-x86_64/mem.c
@@ -1,16 +1,26 @@
1/*
2 * Copyright 2003 PathScale, Inc.
3 *
4 * Licensed under the GPL
5 */
6
7#include "linux/mm.h" 1#include "linux/mm.h"
8#include "asm/page.h" 2#include "asm/page.h"
9#include "asm/mman.h" 3#include "asm/mman.h"
10 4
11unsigned long vm_stack_flags = __VM_STACK_FLAGS; 5const char *arch_vma_name(struct vm_area_struct *vma)
12unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; 6{
13unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; 7 if (vma->vm_mm && vma->vm_start == um_vdso_addr)
14unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; 8 return "[vdso]";
15unsigned long vm_force_exec32 = PROT_EXEC; 9
10 return NULL;
11}
12
13struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
14{
15 return NULL;
16}
17
18int in_gate_area(struct mm_struct *mm, unsigned long addr)
19{
20 return 0;
21}
16 22
23int in_gate_area_no_mm(unsigned long addr)
24{
25 return 0;
26}
diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
index 3213edfa7888..3978e55132d2 100644
--- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
+++ b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
@@ -7,27 +7,9 @@
7#ifndef __VM_FLAGS_X86_64_H 7#ifndef __VM_FLAGS_X86_64_H
8#define __VM_FLAGS_X86_64_H 8#define __VM_FLAGS_X86_64_H
9 9
10#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 10#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
11 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 11 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
12#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \ 12#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
13 VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \ 13 VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
14 VM_MAYEXEC)
15
16extern unsigned long vm_stack_flags, vm_stack_flags32;
17extern unsigned long vm_data_default_flags, vm_data_default_flags32;
18extern unsigned long vm_force_exec32;
19
20#ifdef TIF_IA32
21#define VM_DATA_DEFAULT_FLAGS \
22 (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \
23 vm_data_default_flags)
24
25#define VM_STACK_DEFAULT_FLAGS \
26 (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags)
27#endif
28
29#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags
30
31#define VM_STACK_DEFAULT_FLAGS vm_stack_flags
32 14
33#endif 15#endif
diff --git a/arch/um/sys-x86_64/vdso/Makefile b/arch/um/sys-x86_64/vdso/Makefile
new file mode 100644
index 000000000000..5dffe6d46686
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/Makefile
@@ -0,0 +1,90 @@
1#
2# Building vDSO images for x86.
3#
4
5VDSO64-y := y
6
7vdso-install-$(VDSO64-y) += vdso.so
8
9
10# files to link into the vdso
11vobjs-y := vdso-note.o um_vdso.o
12
13# files to link into kernel
14obj-$(VDSO64-y) += vdso.o vma.o
15
16vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
17
18$(obj)/vdso.o: $(obj)/vdso.so
19
20targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
21
22export CPPFLAGS_vdso.lds += -P -C
23
24VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
25 -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
26
27$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
28
29$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
30 $(call if_changed,vdso)
31
32$(obj)/%.so: OBJCOPYFLAGS := -S
33$(obj)/%.so: $(obj)/%.so.dbg FORCE
34 $(call if_changed,objcopy)
35
36#
37# Don't omit frame pointers for ease of userspace debugging, but do
38# optimize sibling calls.
39#
40CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
41 $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
42 -fno-omit-frame-pointer -foptimize-sibling-calls
43
44$(vobjs): KBUILD_CFLAGS += $(CFL)
45
46#
47# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
48#
49CFLAGS_REMOVE_vdso-note.o = -pg
50CFLAGS_REMOVE_um_vdso.o = -pg
51
52targets += vdso-syms.lds
53obj-$(VDSO64-y) += vdso-syms.lds
54
55#
56# Match symbols in the DSO that look like VDSO*; produce a file of constants.
57#
58sed-vdsosym := -e 's/^00*/0/' \
59 -e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
60quiet_cmd_vdsosym = VDSOSYM $@
61define cmd_vdsosym
62 $(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
63endef
64
65$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
66 $(call if_changed,vdsosym)
67
68#
69# The DSO images are built using a special linker script.
70#
71quiet_cmd_vdso = VDSO $@
72 cmd_vdso = $(CC) -nostdlib -o $@ \
73 $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
74 -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
75 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
76
77VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
78GCOV_PROFILE := n
79
80#
81# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
82#
83quiet_cmd_vdso_install = INSTALL $@
84 cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
85$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
86 @mkdir -p $(MODLIB)/vdso
87 $(call cmd,vdso_install)
88
89PHONY += vdso_install $(vdso-install-y)
90vdso_install: $(vdso-install-y)
diff --git a/arch/um/sys-x86_64/vdso/checkundef.sh b/arch/um/sys-x86_64/vdso/checkundef.sh
new file mode 100644
index 000000000000..7ee90a9b549d
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/checkundef.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2nm="$1"
3file="$2"
4$nm "$file" | grep '^ *U' > /dev/null 2>&1
5if [ $? -eq 1 ]; then
6 exit 0
7else
8 echo "$file: undefined symbols found" >&2
9 exit 1
10fi
diff --git a/arch/um/sys-x86_64/vdso/um_vdso.c b/arch/um/sys-x86_64/vdso/um_vdso.c
new file mode 100644
index 000000000000..7c441b59d375
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/um_vdso.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This vDSO turns all calls into a syscall so that UML can trap them.
9 */
10
11
12/* Disable profiling for userspace code */
13#define DISABLE_BRANCH_PROFILING
14
15#include <linux/time.h>
16#include <linux/getcpu.h>
17#include <asm/unistd.h>
18
19int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
20{
21 long ret;
22
23 asm("syscall" : "=a" (ret) :
24 "0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
25
26 return ret;
27}
28int clock_gettime(clockid_t, struct timespec *)
29 __attribute__((weak, alias("__vdso_clock_gettime")));
30
31int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
32{
33 long ret;
34
35 asm("syscall" : "=a" (ret) :
36 "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
37
38 return ret;
39}
40int gettimeofday(struct timeval *, struct timezone *)
41 __attribute__((weak, alias("__vdso_gettimeofday")));
42
43time_t __vdso_time(time_t *t)
44{
45 long secs;
46
47 asm volatile("syscall"
48 : "=a" (secs)
49 : "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
50
51 return secs;
52}
53int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
54
55long
56__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
57{
58 /*
59 * UML does not support SMP, we can cheat here. :)
60 */
61
62 if (cpu)
63 *cpu = 0;
64 if (node)
65 *node = 0;
66
67 return 0;
68}
69
70long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
71 __attribute__((weak, alias("__vdso_getcpu")));
diff --git a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
new file mode 100644
index 000000000000..634a2cf62046
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
@@ -0,0 +1,64 @@
1/*
2 * Linker script for vDSO. This is an ELF shared object prelinked to
3 * its virtual address, and with only one read-only segment.
4 * This script controls its layout.
5 */
6
7SECTIONS
8{
9 . = VDSO_PRELINK + SIZEOF_HEADERS;
10
11 .hash : { *(.hash) } :text
12 .gnu.hash : { *(.gnu.hash) }
13 .dynsym : { *(.dynsym) }
14 .dynstr : { *(.dynstr) }
15 .gnu.version : { *(.gnu.version) }
16 .gnu.version_d : { *(.gnu.version_d) }
17 .gnu.version_r : { *(.gnu.version_r) }
18
19 .note : { *(.note.*) } :text :note
20
21 .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
22 .eh_frame : { KEEP (*(.eh_frame)) } :text
23
24 .dynamic : { *(.dynamic) } :text :dynamic
25
26 .rodata : { *(.rodata*) } :text
27 .data : {
28 *(.data*)
29 *(.sdata*)
30 *(.got.plt) *(.got)
31 *(.gnu.linkonce.d.*)
32 *(.bss*)
33 *(.dynbss*)
34 *(.gnu.linkonce.b.*)
35 }
36
37 .altinstructions : { *(.altinstructions) }
38 .altinstr_replacement : { *(.altinstr_replacement) }
39
40 /*
41 * Align the actual code well away from the non-instruction data.
42 * This is the best thing for the I-cache.
43 */
44 . = ALIGN(0x100);
45
46 .text : { *(.text*) } :text =0x90909090
47}
48
49/*
50 * Very old versions of ld do not recognize this name token; use the constant.
51 */
52#define PT_GNU_EH_FRAME 0x6474e550
53
54/*
55 * We must supply the ELF program headers explicitly to get just one
56 * PT_LOAD segment, and set the flags explicitly to make segments read-only.
57 */
58PHDRS
59{
60 text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
61 dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
62 note PT_NOTE FLAGS(4); /* PF_R */
63 eh_frame_hdr PT_GNU_EH_FRAME;
64}
diff --git a/arch/um/sys-x86_64/vdso/vdso-note.S b/arch/um/sys-x86_64/vdso/vdso-note.S
new file mode 100644
index 000000000000..79a071e4357e
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso-note.S
@@ -0,0 +1,12 @@
1/*
2 * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
3 * Here we can supply some information useful to userland.
4 */
5
6#include <linux/uts.h>
7#include <linux/version.h>
8#include <linux/elfnote.h>
9
10ELFNOTE_START(Linux, 0, "a")
11 .long LINUX_VERSION_CODE
12ELFNOTE_END
diff --git a/arch/um/sys-x86_64/vdso/vdso.S b/arch/um/sys-x86_64/vdso/vdso.S
new file mode 100644
index 000000000000..ec82c1686bd6
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso.S
@@ -0,0 +1,10 @@
1#include <linux/init.h>
2
3__INITDATA
4
5 .globl vdso_start, vdso_end
6vdso_start:
7 .incbin "arch/um/sys-x86_64/vdso/vdso.so"
8vdso_end:
9
10__FINIT
diff --git a/arch/um/sys-x86_64/vdso/vdso.lds.S b/arch/um/sys-x86_64/vdso/vdso.lds.S
new file mode 100644
index 000000000000..b96b2677cad8
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso.lds.S
@@ -0,0 +1,32 @@
1/*
2 * Linker script for 64-bit vDSO.
3 * We #include the file to define the layout details.
4 * Here we only choose the prelinked virtual address.
5 *
6 * This file defines the version script giving the user-exported symbols in
7 * the DSO. We can define local symbols here called VDSO* to make their
8 * values visible using the asm-x86/vdso.h macros from the kernel proper.
9 */
10
11#define VDSO_PRELINK 0xffffffffff700000
12#include "vdso-layout.lds.S"
13
14/*
15 * This controls what userland symbols we export from the vDSO.
16 */
17VERSION {
18 LINUX_2.6 {
19 global:
20 clock_gettime;
21 __vdso_clock_gettime;
22 gettimeofday;
23 __vdso_gettimeofday;
24 getcpu;
25 __vdso_getcpu;
26 time;
27 __vdso_time;
28 local: *;
29 };
30}
31
32VDSO64_PRELINK = VDSO_PRELINK;
diff --git a/arch/um/sys-x86_64/vdso/vma.c b/arch/um/sys-x86_64/vdso/vma.c
new file mode 100644
index 000000000000..9495c8d0ce37
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vma.c
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/slab.h>
10#include <linux/sched.h>
11#include <linux/mm.h>
12#include <asm/page.h>
13#include <linux/init.h>
14
15unsigned int __read_mostly vdso_enabled = 1;
16unsigned long um_vdso_addr;
17
18extern unsigned long task_size;
19extern char vdso_start[], vdso_end[];
20
21static struct page **vdsop;
22
23static int __init init_vdso(void)
24{
25 struct page *um_vdso;
26
27 BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
28
29 um_vdso_addr = task_size - PAGE_SIZE;
30
31 vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
32 if (!vdsop)
33 goto oom;
34
35 um_vdso = alloc_page(GFP_KERNEL);
36 if (!um_vdso) {
37 kfree(vdsop);
38
39 goto oom;
40 }
41
42 copy_page(page_address(um_vdso), vdso_start);
43 *vdsop = um_vdso;
44
45 return 0;
46
47oom:
48 printk(KERN_ERR "Cannot allocate vdso\n");
49 vdso_enabled = 0;
50
51 return -ENOMEM;
52}
53subsys_initcall(init_vdso);
54
55int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
56{
57 int err;
58 struct mm_struct *mm = current->mm;
59
60 if (!vdso_enabled)
61 return 0;
62
63 down_write(&mm->mmap_sem);
64
65 err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
66 VM_READ|VM_EXEC|
67 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
68 VM_ALWAYSDUMP,
69 vdsop);
70
71 up_write(&mm->mmap_sem);
72
73 return err;
74}
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h
index 82d4e3815c89..3fa526fd3c99 100644
--- a/arch/xtensa/include/asm/uaccess.h
+++ b/arch/xtensa/include/asm/uaccess.h
@@ -17,6 +17,7 @@
17#define _XTENSA_UACCESS_H 17#define _XTENSA_UACCESS_H
18 18
19#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/prefetch.h>
20#include <asm/types.h> 21#include <asm/types.h>
21 22
22#define VERIFY_READ 0 23#define VERIFY_READ 0
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index c72c9473ef99..a0d042aa2967 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -147,6 +147,9 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
147 elf_xtregs_t *xtregs = uregs; 147 elf_xtregs_t *xtregs = uregs;
148 int ret = 0; 148 int ret = 0;
149 149
150 if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
151 return -EFAULT;
152
150#if XTENSA_HAVE_COPROCESSORS 153#if XTENSA_HAVE_COPROCESSORS
151 /* Flush all coprocessors before we overwrite them. */ 154 /* Flush all coprocessors before we overwrite them. */
152 coprocessor_flush_all(ti); 155 coprocessor_flush_all(ti);