diff options
Diffstat (limited to 'arch')
226 files changed, 3195 insertions, 4414 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 8d24bacaa61e..26b0e2397a57 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -175,4 +175,7 @@ config HAVE_ARCH_JUMP_LABEL config HAVE_ARCH_MUTEX_CPU_RELAX bool +config HAVE_RCU_TABLE_FREE + bool + source "kernel/gcov/Kconfig" diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9808998cc073..e3a82775f9da 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -12,6 +12,7 @@ config ALPHA select GENERIC_IRQ_PROBE select AUTO_IRQ_AFFINITY if SMP select GENERIC_IRQ_SHOW + select ARCH_WANT_OPTIONAL_GPIOLIB help The Alpha is a 64-bit general-purpose processor designed and marketed by the Digital Equipment Corporation of blessed memory, @@ -51,6 +52,9 @@ config GENERIC_CALIBRATE_DELAY config GENERIC_CMOS_UPDATE def_bool y +config GENERIC_GPIO + def_bool y + config ZONE_DMA bool default y diff --git a/arch/alpha/include/asm/gpio.h b/arch/alpha/include/asm/gpio.h new file mode 100644 index 000000000000..7dc6a6343c06 --- /dev/null +++ b/arch/alpha/include/asm/gpio.h @@ -0,0 +1,55 @@ +/* + * Generic GPIO API implementation for Alpha. + * + * A stright copy of that for PowerPC which was: + * + * Copyright (c) 2007-2008 MontaVista Software, Inc. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _ASM_ALPHA_GPIO_H +#define _ASM_ALPHA_GPIO_H + +#include <linux/errno.h> +#include <asm-generic/gpio.h> + +#ifdef CONFIG_GPIOLIB + +/* + * We don't (yet) implement inlined/rapid versions for on-chip gpios. + * Just call gpiolib. + */ +static inline int gpio_get_value(unsigned int gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned int gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned int gpio) +{ + return __gpio_cansleep(gpio); +} + +static inline int gpio_to_irq(unsigned int gpio) +{ + return __gpio_to_irq(gpio); +} + +static inline int irq_to_gpio(unsigned int irq) +{ + return -EINVAL; +} + +#endif /* CONFIG_GPIOLIB */ + +#endif /* _ASM_ALPHA_GPIO_H */ diff --git a/arch/alpha/include/asm/smp.h b/arch/alpha/include/asm/smp.h index 3f390e8cc0b3..c46e714aa3e0 100644 --- a/arch/alpha/include/asm/smp.h +++ b/arch/alpha/include/asm/smp.h @@ -39,8 +39,6 @@ struct cpuinfo_alpha { extern struct cpuinfo_alpha cpu_data[NR_CPUS]; -#define PROC_CHANGE_PENALTY 20 - #define hard_smp_processor_id() __hard_smp_processor_id() #define raw_smp_processor_id() (current_thread_info()->cpu) diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 3ec35066f1dc..838eac128409 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -121,7 +121,7 @@ common_shutdown_1(void *generic_ptr) /* Wait for the secondaries to halt. */ set_cpu_present(boot_cpuid, false); set_cpu_possible(boot_cpuid, false); - while (cpus_weight(cpu_present_map)) + while (cpumask_weight(cpu_present_mask)) barrier(); #endif diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index edbddcbd5bc6..cc0fd862cf26 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -1257,7 +1257,7 @@ show_cpuinfo(struct seq_file *f, void *slot) #ifdef CONFIG_SMP seq_printf(f, "cpus active\t\t: %u\n" "cpu active mask\t\t: %016lx\n", - num_online_cpus(), cpus_addr(cpu_possible_map)[0]); + num_online_cpus(), cpumask_bits(cpu_possible_mask)[0]); #endif show_cache_size (f, "L1 Icache", alpha_l1i_cacheshape); diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 5a621c6d22ab..d739703608fc 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -451,7 +451,7 @@ setup_smp(void) } printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n", - smp_num_probed, cpu_present_map.bits[0]); + smp_num_probed, cpumask_bits(cpu_present_mask)[0]); } /* @@ -629,8 +629,9 @@ smp_send_reschedule(int cpu) void smp_send_stop(void) { - cpumask_t to_whom = cpu_possible_map; - cpu_clear(smp_processor_id(), to_whom); + cpumask_t to_whom; + cpumask_copy(&to_whom, cpu_possible_mask); + cpumask_clear_cpu(smp_processor_id(), &to_whom); #ifdef DEBUG_IPI_MSG if (hard_smp_processor_id() != boot_cpu_id) printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n"); diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 5ac00fd4cd0c..f8856829c22a 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -140,7 +140,7 @@ cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity) for (cpu = 0; cpu < 4; cpu++) { unsigned long aff = cpu_irq_affinity[cpu]; - if (cpu_isset(cpu, affinity)) + if (cpumask_test_cpu(cpu, &affinity)) aff |= 1UL << irq; else aff &= ~(1UL << irq); diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c index fea0e4620994..6994407e242a 100644 --- a/arch/alpha/kernel/sys_titan.c +++ b/arch/alpha/kernel/sys_titan.c @@ -65,10 +65,11 @@ titan_update_irq_hw(unsigned long mask) register int bcpu = boot_cpuid; #ifdef CONFIG_SMP - cpumask_t cpm = cpu_present_map; + cpumask_t cpm; volatile unsigned long *dim0, *dim1, *dim2, *dim3; unsigned long mask0, mask1, mask2, mask3, dummy; + cpumask_copy(&cpm, cpu_present_mask); mask &= ~isa_enable; mask0 = mask & titan_cpu_irq_affinity[0]; mask1 = mask & titan_cpu_irq_affinity[1]; @@ -84,10 +85,10 @@ titan_update_irq_hw(unsigned long mask) dim1 = &cchip->dim1.csr; dim2 = &cchip->dim2.csr; dim3 = &cchip->dim3.csr; - if (!cpu_isset(0, cpm)) dim0 = &dummy; - if (!cpu_isset(1, cpm)) dim1 = &dummy; - if (!cpu_isset(2, cpm)) dim2 = &dummy; - if (!cpu_isset(3, cpm)) dim3 = &dummy; + if (!cpumask_test_cpu(0, &cpm)) dim0 = &dummy; + if (!cpumask_test_cpu(1, &cpm)) dim1 = &dummy; + if (!cpumask_test_cpu(2, &cpm)) dim2 = &dummy; + if (!cpumask_test_cpu(3, &cpm)) dim3 = &dummy; *dim0 = mask0; *dim1 = mask1; @@ -137,7 +138,7 @@ titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity) int cpu; for (cpu = 0; cpu < 4; cpu++) { - if (cpu_isset(cpu, affinity)) + if (cpumask_test_cpu(cpu, &affinity)) titan_cpu_irq_affinity[cpu] |= 1UL << irq; else titan_cpu_irq_affinity[cpu] &= ~(1UL << irq); diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 3d890a98a08b..f937ad123852 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -39,7 +39,7 @@ SECTIONS __init_begin = ALIGN(PAGE_SIZE); INIT_TEXT_SECTION(PAGE_SIZE) INIT_DATA_SECTION(16) - PERCPU(L1_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(L1_CACHE_BYTES) /* Align to THREAD_SIZE rather than PAGE_SIZE here so any padding page needed for the THREAD_SIZE aligned init_task gets freed after init */ . = ALIGN(THREAD_SIZE); diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 86425ab53bf5..69d0c5761e2f 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -32,8 +32,6 @@ #include <asm/console.h> #include <asm/tlb.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - extern void die_if_kernel(char *,struct pt_regs *,long); static struct pcb_struct original_pcb; diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index 7b2c56d8f930..3973ae395772 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c @@ -313,6 +313,7 @@ void __init paging_init(void) zones_size[ZONE_DMA] = dma_local_pfn; zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn; } + node_set_state(nid, N_NORMAL_MEMORY); free_area_init_node(nid, zones_size, start_pfn, NULL); } diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 03d01d783e3b..81cbe40c159c 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -63,13 +63,6 @@ config DEBUG_USER 8 - SIGSEGV faults 16 - SIGBUS faults -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T output. - # These options are only for real kernel hackers who want to get their hands dirty. config DEBUG_LL bool "Kernel low-level debugging functions" diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index a87664f54f93..d2b514fd76f4 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -20,12 +20,6 @@ #define raw_smp_processor_id() (current_thread_info()->cpu) -/* - * at the moment, there's not a big penalty for changing CPUs - * (the >big< penalty is running SMP in the first place) - */ -#define PROC_CHANGE_PENALTY 15 - struct seq_file; /* diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 82dfe5d0c41e..265f908c4a6e 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -41,12 +41,12 @@ */ #if defined(CONFIG_SMP) || defined(CONFIG_CPU_32v7) #define tlb_fast_mode(tlb) 0 -#define FREE_PTE_NR 500 #else #define tlb_fast_mode(tlb) 1 -#define FREE_PTE_NR 0 #endif +#define MMU_GATHER_BUNDLE 8 + /* * TLB handling. This allows us to remove pages from the page * tables, and efficiently handle the TLB issues. @@ -58,7 +58,9 @@ struct mmu_gather { unsigned long range_start; unsigned long range_end; unsigned int nr; - struct page *pages[FREE_PTE_NR]; + unsigned int max; + struct page **pages; + struct page *local[MMU_GATHER_BUNDLE]; }; DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -97,26 +99,37 @@ static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) } } +static inline void __tlb_alloc_page(struct mmu_gather *tlb) +{ + unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); + + if (addr) { + tlb->pages = (void *)addr; + tlb->max = PAGE_SIZE / sizeof(struct page *); + } +} + static inline void tlb_flush_mmu(struct mmu_gather *tlb) { tlb_flush(tlb); if (!tlb_fast_mode(tlb)) { free_pages_and_swap_cache(tlb->pages, tlb->nr); tlb->nr = 0; + if (tlb->pages == tlb->local) + __tlb_alloc_page(tlb); } } -static inline struct mmu_gather * -tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +static inline void +tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); - tlb->mm = mm; - tlb->fullmm = full_mm_flush; + tlb->fullmm = fullmm; tlb->vma = NULL; + tlb->max = ARRAY_SIZE(tlb->local); + tlb->pages = tlb->local; tlb->nr = 0; - - return tlb; + __tlb_alloc_page(tlb); } static inline void @@ -127,7 +140,8 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) /* keep the page table cache within bounds */ check_pgt_cache(); - put_cpu_var(mmu_gathers); + if (tlb->pages != tlb->local) + free_pages((unsigned long)tlb->pages, 0); } /* @@ -162,15 +176,22 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) tlb_flush(tlb); } -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) { if (tlb_fast_mode(tlb)) { free_page_and_swap_cache(page); - } else { - tlb->pages[tlb->nr++] = page; - if (tlb->nr >= FREE_PTE_NR) - tlb_flush_mmu(tlb); + return 1; /* avoid calling tlb_flush_mmu */ } + + tlb->pages[tlb->nr++] = page; + VM_BUG_ON(tlb->nr > tlb->max); + return tlb->max - tlb->nr; +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + if (!__tlb_remove_page(tlb, page)) + tlb_flush_mmu(tlb); } static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index b4348e62ef06..e5287f21badc 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -82,7 +82,7 @@ SECTIONS #endif } - PERCPU(32, PAGE_SIZE) + PERCPU_SECTION(32) #ifndef CONFIG_XIP_KERNEL . = ALIGN(PAGE_SIZE); diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h new file mode 100644 index 000000000000..292d55ed2113 --- /dev/null +++ b/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h @@ -0,0 +1,78 @@ +/* + * PTP 1588 clock using the IXP46X + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _IXP46X_TS_H_ +#define _IXP46X_TS_H_ + +#define DEFAULT_ADDEND 0xF0000029 +#define TICKS_NS_SHIFT 4 + +struct ixp46x_channel_ctl { + u32 ch_control; /* 0x40 Time Synchronization Channel Control */ + u32 ch_event; /* 0x44 Time Synchronization Channel Event */ + u32 tx_snap_lo; /* 0x48 Transmit Snapshot Low Register */ + u32 tx_snap_hi; /* 0x4C Transmit Snapshot High Register */ + u32 rx_snap_lo; /* 0x50 Receive Snapshot Low Register */ + u32 rx_snap_hi; /* 0x54 Receive Snapshot High Register */ + u32 src_uuid_lo; /* 0x58 Source UUID0 Low Register */ + u32 src_uuid_hi; /* 0x5C Sequence Identifier/Source UUID0 High */ +}; + +struct ixp46x_ts_regs { + u32 control; /* 0x00 Time Sync Control Register */ + u32 event; /* 0x04 Time Sync Event Register */ + u32 addend; /* 0x08 Time Sync Addend Register */ + u32 accum; /* 0x0C Time Sync Accumulator Register */ + u32 test; /* 0x10 Time Sync Test Register */ + u32 unused; /* 0x14 */ + u32 rsystime_lo; /* 0x18 RawSystemTime_Low Register */ + u32 rsystime_hi; /* 0x1C RawSystemTime_High Register */ + u32 systime_lo; /* 0x20 SystemTime_Low Register */ + u32 systime_hi; /* 0x24 SystemTime_High Register */ + u32 trgt_lo; /* 0x28 TargetTime_Low Register */ + u32 trgt_hi; /* 0x2C TargetTime_High Register */ + u32 asms_lo; /* 0x30 Auxiliary Slave Mode Snapshot Low */ + u32 asms_hi; /* 0x34 Auxiliary Slave Mode Snapshot High */ + u32 amms_lo; /* 0x38 Auxiliary Master Mode Snapshot Low */ + u32 amms_hi; /* 0x3C Auxiliary Master Mode Snapshot High */ + + struct ixp46x_channel_ctl channel[3]; +}; + +/* 0x00 Time Sync Control Register Bits */ +#define TSCR_AMM (1<<3) +#define TSCR_ASM (1<<2) +#define TSCR_TTM (1<<1) +#define TSCR_RST (1<<0) + +/* 0x04 Time Sync Event Register Bits */ +#define TSER_SNM (1<<3) +#define TSER_SNS (1<<2) +#define TTIPEND (1<<1) + +/* 0x40 Time Synchronization Channel Control Register Bits */ +#define MASTER_MODE (1<<0) +#define TIMESTAMP_ALL (1<<1) + +/* 0x44 Time Synchronization Channel Event Register Bits */ +#define TX_SNAPSHOT_LOCKED (1<<0) +#define RX_SNAPSHOT_LOCKED (1<<1) + +#endif diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 9afd087cc29c..23244cd0a5b6 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -37,8 +37,8 @@ #include <plat/common.h> #include <plat/dma.h> #include <plat/gpmc.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <plat/gpmc-smc91x.h> diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 56702c5e577f..93edd7fcf451 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -36,7 +36,7 @@ #include <plat/usb.h> #include <plat/mmc.h> #include <plat/omap4-keypad.h> -#include <plat/display.h> +#include <video/omapdss.h> #include "mux.h" #include "hsmmc.h" @@ -680,6 +680,15 @@ static struct omap_dss_device sdp4430_hdmi_device = { .name = "hdmi", .driver_name = "hdmi_panel", .type = OMAP_DISPLAY_TYPE_HDMI, + .clocks = { + .dispc = { + .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK, + }, + .hdmi = { + .regn = 15, + .regm2 = 1, + }, + }, .platform_enable = sdp4430_panel_enable_hdmi, .platform_disable = sdp4430_panel_disable_hdmi, .channel = OMAP_DSS_CHANNEL_DIGIT, diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index ce7d5e6e4150..ff8c59be36e5 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -34,8 +34,8 @@ #include <plat/board.h> #include <plat/common.h> #include <plat/usb.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include "mux.h" #include "control.h" diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 02a12b41c0ff..9340f6a06f4a 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -45,8 +45,8 @@ #include <plat/nand.h> #include <plat/gpmc.h> #include <plat/usb.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <plat/mcspi.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 65f9fde2c567..1d1b56a29fb1 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -45,8 +45,8 @@ #include <plat/gpmc.h> #include <plat/nand.h> #include <plat/usb.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <plat/mcspi.h> #include <linux/input/matrix_keypad.h> diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 34cf982b9679..3da64d361651 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -31,8 +31,8 @@ #include <plat/common.h> #include <plat/gpmc.h> #include <plat/usb.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <plat/onenand.h> #include "mux.h" diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 33007fd4a083..97750d483a70 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -41,8 +41,8 @@ #include <plat/board.h> #include <plat/common.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <plat/gpmc.h> #include <plat/nand.h> #include <plat/usb.h> diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 5a1a916e5cc8..7f94cccdb076 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -44,8 +44,8 @@ #include <plat/usb.h> #include <plat/common.h> #include <plat/mcspi.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 07dba888f450..1db15492d82b 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -46,7 +46,7 @@ #include <mach/hardware.h> #include <plat/mcspi.h> #include <plat/usb.h> -#include <plat/display.h> +#include <video/omapdss.h> #include <plat/nand.h> #include "mux.h" diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index a6e0b9161c99..a72c90a08c8a 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -39,8 +39,8 @@ #include <plat/gpmc.h> #include <plat/nand.h> #include <plat/usb.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <plat/mcspi.h> #include <linux/input/matrix_keypad.h> diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index f3a7b1011914..e4973ac77cbc 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -34,13 +34,13 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <plat/display.h> +#include <video/omapdss.h> #include <plat/board.h> #include <plat/common.h> #include <plat/usb.h> #include <plat/mmc.h> -#include <plat/panel-generic-dpi.h> +#include <video/omap-panel-generic-dpi.h> #include "timer-gp.h" #include "hsmmc.h" diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 59ca33326b8c..9d192ff3b9ac 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -43,8 +43,8 @@ #include <plat/board.h> #include <plat/common.h> -#include <plat/display.h> -#include <plat/panel-generic-dpi.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> #include <mach/gpio.h> #include <plat/gpmc.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c index 89a66db8b77d..2df10b6a5940 100644 --- a/arch/arm/mach-omap2/board-rx51-video.c +++ b/arch/arm/mach-omap2/board-rx51-video.c @@ -15,7 +15,7 @@ #include <linux/spi/spi.h> #include <linux/mm.h> #include <asm/mach-types.h> -#include <plat/display.h> +#include <video/omapdss.h> #include <plat/vram.h> #include <plat/mcspi.h> diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c index 37b84c2b850f..60e8645db59d 100644 --- a/arch/arm/mach-omap2/board-zoom-display.c +++ b/arch/arm/mach-omap2/board-zoom-display.c @@ -15,7 +15,7 @@ #include <linux/i2c/twl.h> #include <linux/spi/spi.h> #include <plat/mcspi.h> -#include <plat/display.h> +#include <video/omapdss.h> #define LCD_PANEL_RESET_GPIO_PROD 96 #define LCD_PANEL_RESET_GPIO_PILOT 55 diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 256d23fb79ab..543fcb8b518c 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -22,7 +22,7 @@ #include <linux/clk.h> #include <linux/err.h> -#include <plat/display.h> +#include <video/omapdss.h> #include <plat/omap_hwmod.h> #include <plat/omap_device.h> @@ -56,37 +56,58 @@ static bool opt_clock_available(const char *clk_role) return false; } +struct omap_dss_hwmod_data { + const char *oh_name; + const char *dev_name; + const int id; +}; + +static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initdata = { + { "dss_core", "omapdss_dss", -1 }, + { "dss_dispc", "omapdss_dispc", -1 }, + { "dss_rfbi", "omapdss_rfbi", -1 }, + { "dss_venc", "omapdss_venc", -1 }, +}; + +static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = { + { "dss_core", "omapdss_dss", -1 }, + { "dss_dispc", "omapdss_dispc", -1 }, + { "dss_rfbi", "omapdss_rfbi", -1 }, + { "dss_venc", "omapdss_venc", -1 }, + { "dss_dsi1", "omapdss_dsi1", -1 }, +}; + +static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { + { "dss_core", "omapdss_dss", -1 }, + { "dss_dispc", "omapdss_dispc", -1 }, + { "dss_rfbi", "omapdss_rfbi", -1 }, + { "dss_venc", "omapdss_venc", -1 }, + { "dss_dsi1", "omapdss_dsi1", -1 }, + { "dss_dsi2", "omapdss_dsi2", -1 }, + { "dss_hdmi", "omapdss_hdmi", -1 }, +}; + int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; struct omap_hwmod *oh; struct omap_device *od; - int i; + int i, oh_count; struct omap_display_platform_data pdata; - - /* - * omap: valid DSS hwmod names - * omap2,3,4: dss_core, dss_dispc, dss_rfbi, dss_venc - * omap3,4: dss_dsi1 - * omap4: dss_dsi2, dss_hdmi - */ - char *oh_name[] = { "dss_core", "dss_dispc", "dss_rfbi", "dss_venc", - "dss_dsi1", "dss_dsi2", "dss_hdmi" }; - char *dev_name[] = { "omapdss_dss", "omapdss_dispc", "omapdss_rfbi", - "omapdss_venc", "omapdss_dsi1", "omapdss_dsi2", - "omapdss_hdmi" }; - int oh_count; + const struct omap_dss_hwmod_data *curr_dss_hwmod; memset(&pdata, 0, sizeof(pdata)); - if (cpu_is_omap24xx()) - oh_count = ARRAY_SIZE(oh_name) - 3; - /* last 3 hwmod dev in oh_name are not available for omap2 */ - else if (cpu_is_omap44xx()) - oh_count = ARRAY_SIZE(oh_name); - else - oh_count = ARRAY_SIZE(oh_name) - 2; - /* last 2 hwmod dev in oh_name are not available for omap3 */ + if (cpu_is_omap24xx()) { + curr_dss_hwmod = omap2_dss_hwmod_data; + oh_count = ARRAY_SIZE(omap2_dss_hwmod_data); + } else if (cpu_is_omap34xx()) { + curr_dss_hwmod = omap3_dss_hwmod_data; + oh_count = ARRAY_SIZE(omap3_dss_hwmod_data); + } else { + curr_dss_hwmod = omap4_dss_hwmod_data; + oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); + } /* opt_clks are always associated with dss hwmod */ oh_core = omap_hwmod_lookup("dss_core"); @@ -100,19 +121,21 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) pdata.opt_clock_available = opt_clock_available; for (i = 0; i < oh_count; i++) { - oh = omap_hwmod_lookup(oh_name[i]); + oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); if (!oh) { - pr_err("Could not look up %s\n", oh_name[i]); + pr_err("Could not look up %s\n", + curr_dss_hwmod[i].oh_name); return -ENODEV; } - od = omap_device_build(dev_name[i], -1, oh, &pdata, + od = omap_device_build(curr_dss_hwmod[i].dev_name, + curr_dss_hwmod[i].id, oh, &pdata, sizeof(struct omap_display_platform_data), omap_dss_latency, ARRAY_SIZE(omap_dss_latency), 0); if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n", - oh_name[i])) + curr_dss_hwmod[i].oh_name)) return -ENODEV; } omap_display_device.dev.platform_data = board_data; diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h index d20bd9c1a106..775fdc3b000b 100644 --- a/arch/arm/mach-omap2/include/mach/board-zoom.h +++ b/arch/arm/mach-omap2/include/mach/board-zoom.h @@ -1,7 +1,7 @@ /* * Defines for zoom boards */ -#include <plat/display.h> +#include <video/omapdss.h> #define ZOOM_NAND_CS 0 diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/arch/arm/mach-tegra/include/mach/kbc.h index 04c779832c78..4f3572a1c684 100644 --- a/arch/arm/mach-tegra/include/mach/kbc.h +++ b/arch/arm/mach-tegra/include/mach/kbc.h @@ -50,13 +50,11 @@ struct tegra_kbc_platform_data { unsigned int debounce_cnt; unsigned int repeat_cnt; - unsigned int wake_cnt; /* 0:wake on any key >1:wake on wake_cfg */ - const struct tegra_kbc_wake_key *wake_cfg; - struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; const struct matrix_keymap_data *keymap_data; bool wakeup; bool use_fn_map; + bool use_ghost_filter; }; #endif diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 6e1907fa94f0..bb26f40493e6 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -204,7 +204,7 @@ static struct i2c_board_info __initdata mop500_i2c2_devices[] = { }, }; -#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ +#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm) \ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* \ * slave data setup time, which is \ @@ -219,19 +219,21 @@ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ .rft = _rft, \ /* std. mode operation */ \ .clk_freq = clk, \ + /* Slave response timeout(ms) */\ + .timeout = t_out, \ .sm = _sm, \ } /* * The board uses 4 i2c controllers, initialize all of * them with slave data setup time of 250 ns, - * Tx & Rx FIFO threshold values as 1 and standard + * Tx & Rx FIFO threshold values as 8 and standard * mode of operation */ -U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); -U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); -U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); -U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); +U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); +U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); static void __init mop500_i2c_init(void) { diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 76f82ae44efb..3f17ea146f0e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -85,7 +85,7 @@ void show_mem(unsigned int filter) struct meminfo * mi = &meminfo; printk("Mem-info:\n"); - show_free_areas(); + show_free_areas(filter); for_each_bank (i, mi) { struct membank *bank = &mi->bank[i]; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6cf76b3b68d1..08a92368d9d3 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -31,8 +31,6 @@ #include "mm.h" -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * empty_zero_page is a special page that is used for * zero-initialized data and COW. diff --git a/arch/arm/plat-nomadik/include/plat/i2c.h b/arch/arm/plat-nomadik/include/plat/i2c.h index 1621db67a53d..8ba70ffc31ec 100644 --- a/arch/arm/plat-nomadik/include/plat/i2c.h +++ b/arch/arm/plat-nomadik/include/plat/i2c.h @@ -11,8 +11,8 @@ enum i2c_freq_mode { I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */ + I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */ I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */ - I2C_FREQ_MODE_HIGH_SPEED /* up to 3.4 Mb/s */ }; /** @@ -24,13 +24,15 @@ enum i2c_freq_mode { * to the values of 14, 6, 2 for a 48 MHz i2c clk * @tft: Tx FIFO Threshold in bytes * @rft: Rx FIFO Threshold in bytes + * @timeout Slave response timeout(ms) * @sm: speed mode */ struct nmk_i2c_controller { unsigned long clk_freq; unsigned short slsu; - unsigned char tft; - unsigned char rft; + unsigned char tft; + unsigned char rft; + int timeout; enum i2c_freq_mode sm; }; diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h deleted file mode 100644 index 5e04ddc18fa8..000000000000 --- a/arch/arm/plat-omap/include/plat/display.h +++ /dev/null @@ -1,591 +0,0 @@ -/* - * linux/include/asm-arm/arch-omap/display.h - * - * Copyright (C) 2008 Nokia Corporation - * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __ASM_ARCH_OMAP_DISPLAY_H -#define __ASM_ARCH_OMAP_DISPLAY_H - -#include <linux/list.h> -#include <linux/kobject.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <asm/atomic.h> - -#define DISPC_IRQ_FRAMEDONE (1 << 0) -#define DISPC_IRQ_VSYNC (1 << 1) -#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) -#define DISPC_IRQ_EVSYNC_ODD (1 << 3) -#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) -#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) -#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) -#define DISPC_IRQ_GFX_END_WIN (1 << 7) -#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) -#define DISPC_IRQ_OCP_ERR (1 << 9) -#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) -#define DISPC_IRQ_VID1_END_WIN (1 << 11) -#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) -#define DISPC_IRQ_VID2_END_WIN (1 << 13) -#define DISPC_IRQ_SYNC_LOST (1 << 14) -#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) -#define DISPC_IRQ_WAKEUP (1 << 16) -#define DISPC_IRQ_SYNC_LOST2 (1 << 17) -#define DISPC_IRQ_VSYNC2 (1 << 18) -#define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21) -#define DISPC_IRQ_FRAMEDONE2 (1 << 22) - -struct omap_dss_device; -struct omap_overlay_manager; - -enum omap_display_type { - OMAP_DISPLAY_TYPE_NONE = 0, - OMAP_DISPLAY_TYPE_DPI = 1 << 0, - OMAP_DISPLAY_TYPE_DBI = 1 << 1, - OMAP_DISPLAY_TYPE_SDI = 1 << 2, - OMAP_DISPLAY_TYPE_DSI = 1 << 3, - OMAP_DISPLAY_TYPE_VENC = 1 << 4, - OMAP_DISPLAY_TYPE_HDMI = 1 << 5, -}; - -enum omap_plane { - OMAP_DSS_GFX = 0, - OMAP_DSS_VIDEO1 = 1, - OMAP_DSS_VIDEO2 = 2 -}; - -enum omap_channel { - OMAP_DSS_CHANNEL_LCD = 0, - OMAP_DSS_CHANNEL_DIGIT = 1, - OMAP_DSS_CHANNEL_LCD2 = 2, -}; - -enum omap_color_mode { - OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */ - OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */ - OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */ - OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */ - OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */ - OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */ - OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */ - OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */ - OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */ - OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */ - OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */ - OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */ - OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */ - OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */ -}; - -enum omap_lcd_display_type { - OMAP_DSS_LCD_DISPLAY_STN, - OMAP_DSS_LCD_DISPLAY_TFT, -}; - -enum omap_dss_load_mode { - OMAP_DSS_LOAD_CLUT_AND_FRAME = 0, - OMAP_DSS_LOAD_CLUT_ONLY = 1, - OMAP_DSS_LOAD_FRAME_ONLY = 2, - OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3, -}; - -enum omap_dss_trans_key_type { - OMAP_DSS_COLOR_KEY_GFX_DST = 0, - OMAP_DSS_COLOR_KEY_VID_SRC = 1, -}; - -enum omap_rfbi_te_mode { - OMAP_DSS_RFBI_TE_MODE_1 = 1, - OMAP_DSS_RFBI_TE_MODE_2 = 2, -}; - -enum omap_panel_config { - OMAP_DSS_LCD_IVS = 1<<0, - OMAP_DSS_LCD_IHS = 1<<1, - OMAP_DSS_LCD_IPC = 1<<2, - OMAP_DSS_LCD_IEO = 1<<3, - OMAP_DSS_LCD_RF = 1<<4, - OMAP_DSS_LCD_ONOFF = 1<<5, - - OMAP_DSS_LCD_TFT = 1<<20, -}; - -enum omap_dss_venc_type { - OMAP_DSS_VENC_TYPE_COMPOSITE, - OMAP_DSS_VENC_TYPE_SVIDEO, -}; - -enum omap_display_caps { - OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, - OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1, -}; - -enum omap_dss_update_mode { - OMAP_DSS_UPDATE_DISABLED = 0, - OMAP_DSS_UPDATE_AUTO, - OMAP_DSS_UPDATE_MANUAL, -}; - -enum omap_dss_display_state { - OMAP_DSS_DISPLAY_DISABLED = 0, - OMAP_DSS_DISPLAY_ACTIVE, - OMAP_DSS_DISPLAY_SUSPENDED, -}; - -/* XXX perhaps this should be removed */ -enum omap_dss_overlay_managers { - OMAP_DSS_OVL_MGR_LCD, - OMAP_DSS_OVL_MGR_TV, - OMAP_DSS_OVL_MGR_LCD2, -}; - -enum omap_dss_rotation_type { - OMAP_DSS_ROT_DMA = 0, - OMAP_DSS_ROT_VRFB = 1, -}; - -/* clockwise rotation angle */ -enum omap_dss_rotation_angle { - OMAP_DSS_ROT_0 = 0, - OMAP_DSS_ROT_90 = 1, - OMAP_DSS_ROT_180 = 2, - OMAP_DSS_ROT_270 = 3, -}; - -enum omap_overlay_caps { - OMAP_DSS_OVL_CAP_SCALE = 1 << 0, - OMAP_DSS_OVL_CAP_DISPC = 1 << 1, -}; - -enum omap_overlay_manager_caps { - OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, -}; - -/* RFBI */ - -struct rfbi_timings { - int cs_on_time; - int cs_off_time; - int we_on_time; - int we_off_time; - int re_on_time; - int re_off_time; - int we_cycle_time; - int re_cycle_time; - int cs_pulse_width; - int access_time; - - int clk_div; - - u32 tim[5]; /* set by rfbi_convert_timings() */ - - int converted; -}; - -void omap_rfbi_write_command(const void *buf, u32 len); -void omap_rfbi_read_data(void *buf, u32 len); -void omap_rfbi_write_data(const void *buf, u32 len); -void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, - u16 x, u16 y, - u16 w, u16 h); -int omap_rfbi_enable_te(bool enable, unsigned line); -int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, - unsigned hs_pulse_time, unsigned vs_pulse_time, - int hs_pol_inv, int vs_pol_inv, int extif_div); - -/* DSI */ -void dsi_bus_lock(void); -void dsi_bus_unlock(void); -int dsi_vc_dcs_write(int channel, u8 *data, int len); -int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd); -int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param); -int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); -int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); -int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data); -int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2); -int dsi_vc_set_max_rx_packet_size(int channel, u16 len); -int dsi_vc_send_null(int channel); -int dsi_vc_send_bta_sync(int channel); - -/* Board specific data */ -struct omap_dss_board_info { - int (*get_last_off_on_transaction_id)(struct device *dev); - int num_devices; - struct omap_dss_device **devices; - struct omap_dss_device *default_device; -}; - -#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) -/* Init with the board info */ -extern int omap_display_init(struct omap_dss_board_info *board_data); -#else -static inline int omap_display_init(struct omap_dss_board_info *board_data) -{ - return 0; -} -#endif - -struct omap_display_platform_data { - struct omap_dss_board_info *board_data; - /* TODO: Additional members to be added when PM is considered */ - - bool (*opt_clock_available)(const char *clk_role); -}; - -struct omap_video_timings { - /* Unit: pixels */ - u16 x_res; - /* Unit: pixels */ - u16 y_res; - /* Unit: KHz */ - u32 pixel_clock; - /* Unit: pixel clocks */ - u16 hsw; /* Horizontal synchronization pulse width */ - /* Unit: pixel clocks */ - u16 hfp; /* Horizontal front porch */ - /* Unit: pixel clocks */ - u16 hbp; /* Horizontal back porch */ - /* Unit: line clocks */ - u16 vsw; /* Vertical synchronization pulse width */ - /* Unit: line clocks */ - u16 vfp; /* Vertical front porch */ - /* Unit: line clocks */ - u16 vbp; /* Vertical back porch */ -}; - -#ifdef CONFIG_OMAP2_DSS_VENC -/* Hardcoded timings for tv modes. Venc only uses these to - * identify the mode, and does not actually use the configs - * itself. However, the configs should be something that - * a normal monitor can also show */ -extern const struct omap_video_timings omap_dss_pal_timings; -extern const struct omap_video_timings omap_dss_ntsc_timings; -#endif - -struct omap_overlay_info { - bool enabled; - - u32 paddr; - void __iomem *vaddr; - u16 screen_width; - u16 width; - u16 height; - enum omap_color_mode color_mode; - u8 rotation; - enum omap_dss_rotation_type rotation_type; - bool mirror; - - u16 pos_x; - u16 pos_y; - u16 out_width; /* if 0, out_width == width */ - u16 out_height; /* if 0, out_height == height */ - u8 global_alpha; - u8 pre_mult_alpha; -}; - -struct omap_overlay { - struct kobject kobj; - struct list_head list; - - /* static fields */ - const char *name; - int id; - enum omap_color_mode supported_modes; - enum omap_overlay_caps caps; - - /* dynamic fields */ - struct omap_overlay_manager *manager; - struct omap_overlay_info info; - - /* if true, info has been changed, but not applied() yet */ - bool info_dirty; - - int (*set_manager)(struct omap_overlay *ovl, - struct omap_overlay_manager *mgr); - int (*unset_manager)(struct omap_overlay *ovl); - - int (*set_overlay_info)(struct omap_overlay *ovl, - struct omap_overlay_info *info); - void (*get_overlay_info)(struct omap_overlay *ovl, - struct omap_overlay_info *info); - - int (*wait_for_go)(struct omap_overlay *ovl); -}; - -struct omap_overlay_manager_info { - u32 default_color; - - enum omap_dss_trans_key_type trans_key_type; - u32 trans_key; - bool trans_enabled; - - bool alpha_enabled; -}; - -struct omap_overlay_manager { - struct kobject kobj; - struct list_head list; - - /* static fields */ - const char *name; - int id; - enum omap_overlay_manager_caps caps; - int num_overlays; - struct omap_overlay **overlays; - enum omap_display_type supported_displays; - - /* dynamic fields */ - struct omap_dss_device *device; - struct omap_overlay_manager_info info; - - bool device_changed; - /* if true, info has been changed but not applied() yet */ - bool info_dirty; - - int (*set_device)(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev); - int (*unset_device)(struct omap_overlay_manager *mgr); - - int (*set_manager_info)(struct omap_overlay_manager *mgr, - struct omap_overlay_manager_info *info); - void (*get_manager_info)(struct omap_overlay_manager *mgr, - struct omap_overlay_manager_info *info); - - int (*apply)(struct omap_overlay_manager *mgr); - int (*wait_for_go)(struct omap_overlay_manager *mgr); - int (*wait_for_vsync)(struct omap_overlay_manager *mgr); - - int (*enable)(struct omap_overlay_manager *mgr); - int (*disable)(struct omap_overlay_manager *mgr); -}; - -struct omap_dss_device { - struct device dev; - - enum omap_display_type type; - - enum omap_channel channel; - - union { - struct { - u8 data_lines; - } dpi; - - struct { - u8 channel; - u8 data_lines; - } rfbi; - - struct { - u8 datapairs; - } sdi; - - struct { - u8 clk_lane; - u8 clk_pol; - u8 data1_lane; - u8 data1_pol; - u8 data2_lane; - u8 data2_pol; - - struct { - u16 regn; - u16 regm; - u16 regm_dispc; - u16 regm_dsi; - - u16 lp_clk_div; - - u16 lck_div; - u16 pck_div; - } div; - - bool ext_te; - u8 ext_te_gpio; - } dsi; - - struct { - enum omap_dss_venc_type type; - bool invert_polarity; - } venc; - } phy; - - struct { - struct omap_video_timings timings; - - int acbi; /* ac-bias pin transitions per interrupt */ - /* Unit: line clocks */ - int acb; /* ac-bias pin frequency */ - - enum omap_panel_config config; - } panel; - - struct { - u8 pixel_size; - struct rfbi_timings rfbi_timings; - } ctrl; - - int reset_gpio; - - int max_backlight_level; - - const char *name; - - /* used to match device to driver */ - const char *driver_name; - - void *data; - - struct omap_dss_driver *driver; - - /* helper variable for driver suspend/resume */ - bool activate_after_resume; - - enum omap_display_caps caps; - - struct omap_overlay_manager *manager; - - enum omap_dss_display_state state; - - /* platform specific */ - int (*platform_enable)(struct omap_dss_device *dssdev); - void (*platform_disable)(struct omap_dss_device *dssdev); - int (*set_backlight)(struct omap_dss_device *dssdev, int level); - int (*get_backlight)(struct omap_dss_device *dssdev); -}; - -struct omap_dss_driver { - struct device_driver driver; - - int (*probe)(struct omap_dss_device *); - void (*remove)(struct omap_dss_device *); - - int (*enable)(struct omap_dss_device *display); - void (*disable)(struct omap_dss_device *display); - int (*suspend)(struct omap_dss_device *display); - int (*resume)(struct omap_dss_device *display); - int (*run_test)(struct omap_dss_device *display, int test); - - int (*set_update_mode)(struct omap_dss_device *dssdev, - enum omap_dss_update_mode); - enum omap_dss_update_mode (*get_update_mode)( - struct omap_dss_device *dssdev); - - int (*update)(struct omap_dss_device *dssdev, - u16 x, u16 y, u16 w, u16 h); - int (*sync)(struct omap_dss_device *dssdev); - - int (*enable_te)(struct omap_dss_device *dssdev, bool enable); - int (*get_te)(struct omap_dss_device *dssdev); - - u8 (*get_rotate)(struct omap_dss_device *dssdev); - int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); - - bool (*get_mirror)(struct omap_dss_device *dssdev); - int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); - - int (*memory_read)(struct omap_dss_device *dssdev, - void *buf, size_t size, - u16 x, u16 y, u16 w, u16 h); - - void (*get_resolution)(struct omap_dss_device *dssdev, - u16 *xres, u16 *yres); - int (*get_recommended_bpp)(struct omap_dss_device *dssdev); - - int (*check_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); - void (*set_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); - void (*get_timings)(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); - - int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); - u32 (*get_wss)(struct omap_dss_device *dssdev); -}; - -int omap_dss_register_driver(struct omap_dss_driver *); -void omap_dss_unregister_driver(struct omap_dss_driver *); - -int omap_dss_register_device(struct omap_dss_device *); -void omap_dss_unregister_device(struct omap_dss_device *); - -void omap_dss_get_device(struct omap_dss_device *dssdev); -void omap_dss_put_device(struct omap_dss_device *dssdev); -#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL) -struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); -struct omap_dss_device *omap_dss_find_device(void *data, - int (*match)(struct omap_dss_device *dssdev, void *data)); - -int omap_dss_start_device(struct omap_dss_device *dssdev); -void omap_dss_stop_device(struct omap_dss_device *dssdev); - -int omap_dss_get_num_overlay_managers(void); -struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); - -int omap_dss_get_num_overlays(void); -struct omap_overlay *omap_dss_get_overlay(int num); - -void omapdss_default_get_resolution(struct omap_dss_device *dssdev, - u16 *xres, u16 *yres); -int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); - -typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); -int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); -int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); - -int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); -int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, - unsigned long timeout); - -#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) -#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) - -void omapdss_dsi_vc_enable_hs(int channel, bool enable); -int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); - -int omap_dsi_prepare_update(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h, - bool enlarge_update_area); -int omap_dsi_update(struct omap_dss_device *dssdev, - int channel, - u16 x, u16 y, u16 w, u16 h, - void (*callback)(int, void *), void *data); -int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel); -int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id); -void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel); - -int omapdss_dsi_display_enable(struct omap_dss_device *dssdev); -void omapdss_dsi_display_disable(struct omap_dss_device *dssdev); - -int omapdss_dpi_display_enable(struct omap_dss_device *dssdev); -void omapdss_dpi_display_disable(struct omap_dss_device *dssdev); -void dpi_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); -int dpi_check_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); - -int omapdss_sdi_display_enable(struct omap_dss_device *dssdev); -void omapdss_sdi_display_disable(struct omap_dss_device *dssdev); - -int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev); -void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev); -int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h); -int omap_rfbi_update(struct omap_dss_device *dssdev, - u16 x, u16 y, u16 w, u16 h, - void (*callback)(void *), void *data); - -#endif diff --git a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h deleted file mode 100644 index 01ab6572ccbb..000000000000 --- a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H -#define __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H - -#include "display.h" - -/** - * struct nokia_dsi_panel_data - Nokia DSI panel driver configuration - * @name: panel name - * @use_ext_te: use external TE - * @ext_te_gpio: external TE GPIO - * @use_esd_check: perform ESD checks - * @max_backlight_level: maximum backlight level - * @set_backlight: pointer to backlight set function - * @get_backlight: pointer to backlight get function - */ -struct nokia_dsi_panel_data { - const char *name; - - int reset_gpio; - - bool use_ext_te; - int ext_te_gpio; - - bool use_esd_check; - - int max_backlight_level; - int (*set_backlight)(struct omap_dss_device *dssdev, int level); - int (*get_backlight)(struct omap_dss_device *dssdev); -}; - -#endif /* __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H */ diff --git a/arch/arm/plat-omap/include/plat/panel-generic-dpi.h b/arch/arm/plat-omap/include/plat/panel-generic-dpi.h deleted file mode 100644 index 790619734bcd..000000000000 --- a/arch/arm/plat-omap/include/plat/panel-generic-dpi.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Header for generic DPI panel driver - * - * Copyright (C) 2010 Canonical Ltd. - * Author: Bryan Wu <bryan.wu@canonical.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H -#define __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H - -#include "display.h" - -/** - * struct panel_generic_dpi_data - panel driver configuration data - * @name: panel name - * @platform_enable: platform specific panel enable function - * @platform_disable: platform specific panel disable function - */ -struct panel_generic_dpi_data { - const char *name; - int (*platform_enable)(struct omap_dss_device *dssdev); - void (*platform_disable)(struct omap_dss_device *dssdev); -}; - -#endif /* __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H */ diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c index a7314d44b17b..2798c2d4a1cf 100644 --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c @@ -25,8 +25,6 @@ #include <asm/setup.h> #include <asm/sections.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_data; struct page *empty_zero_page; diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 2641731f24cd..19ccfb3b67d3 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug @@ -9,15 +9,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T output. - - This option will slow down process creation somewhat. - config DEBUG_VERBOSE bool "Verbose fault messages" default y diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 854fa49f1c3e..8d85c8c6f857 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -136,7 +136,7 @@ SECTIONS . = ALIGN(16); INIT_DATA_SECTION(16) - PERCPU(32, PAGE_SIZE) + PERCPU_SECTION(32) .exit.data : { diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c index 68a1a5901ca5..5ebe6e841820 100644 --- a/arch/cris/arch-v32/kernel/irq.c +++ b/arch/cris/arch-v32/kernel/irq.c @@ -266,11 +266,11 @@ static int irq_cpu(int irq) /* Let the interrupt stay if possible */ - if (cpu_isset(cpu, irq_allocations[irq - FIRST_IRQ].mask)) + if (cpumask_test_cpu(cpu, &irq_allocations[irq - FIRST_IRQ].mask)) goto out; /* IRQ must be moved to another CPU. */ - cpu = first_cpu(irq_allocations[irq - FIRST_IRQ].mask); + cpu = cpumask_first(&irq_allocations[irq - FIRST_IRQ].mask); irq_allocations[irq - FIRST_IRQ].cpu = cpu; out: spin_unlock_irqrestore(&irq_lock, flags); diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 66cc75657e2f..a0843a71aaee 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -81,7 +81,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) /* Mark all possible CPUs as present */ for (i = 0; i < max_cpus; i++) - cpu_set(i, phys_cpu_present_map); + cpumask_set_cpu(i, &phys_cpu_present_map); } void __devinit smp_prepare_boot_cpu(void) @@ -98,7 +98,7 @@ void __devinit smp_prepare_boot_cpu(void) SUPP_REG_WR(RW_MM_TLB_PGD, pgd); set_cpu_online(0, true); - cpu_set(0, phys_cpu_present_map); + cpumask_set_cpu(0, &phys_cpu_present_map); set_cpu_possible(0, true); } @@ -112,8 +112,9 @@ smp_boot_one_cpu(int cpuid) { unsigned timeout; struct task_struct *idle; - cpumask_t cpu_mask = CPU_MASK_NONE; + cpumask_t cpu_mask; + cpumask_clear(&cpu_mask); idle = fork_idle(cpuid); if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); @@ -125,10 +126,10 @@ smp_boot_one_cpu(int cpuid) cpu_now_booting = cpuid; /* Kick it */ - cpu_set(cpuid, cpu_online_map); - cpu_set(cpuid, cpu_mask); + set_cpu_online(cpuid, true); + cpumask_set_cpu(cpuid, &cpu_mask); send_ipi(IPI_BOOT, 0, cpu_mask); - cpu_clear(cpuid, cpu_online_map); + set_cpu_online(cpuid, false); /* Wait for CPU to come online */ for (timeout = 0; timeout < 10000; timeout++) { @@ -176,7 +177,7 @@ void __init smp_callin(void) notify_cpu_starting(cpu); local_irq_enable(); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); cpu_idle(); } @@ -214,8 +215,9 @@ int __cpuinit __cpu_up(unsigned int cpu) void smp_send_reschedule(int cpu) { - cpumask_t cpu_mask = CPU_MASK_NONE; - cpu_set(cpu, cpu_mask); + cpumask_t cpu_mask; + cpumask_clear(&cpu_mask); + cpumask_set_cpu(cpu, &cpu_mask); send_ipi(IPI_SCHEDULE, 0, cpu_mask); } @@ -232,7 +234,7 @@ void flush_tlb_common(struct mm_struct* mm, struct vm_area_struct* vma, unsigned spin_lock_irqsave(&tlbstate_lock, flags); cpu_mask = (mm == FLUSH_ALL ? cpu_all_mask : *mm_cpumask(mm)); - cpu_clear(smp_processor_id(), cpu_mask); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); flush_mm = mm; flush_vma = vma; flush_addr = addr; @@ -277,10 +279,10 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask) int ret = 0; /* Calculate CPUs to send to. */ - cpus_and(cpu_mask, cpu_mask, cpu_online_map); + cpumask_and(&cpu_mask, &cpu_mask, cpu_online_mask); /* Send the IPI. */ - for_each_cpu_mask(i, cpu_mask) + for_each_cpu(i, &cpu_mask) { ipi.vector |= vector; REG_WR(intr_vect, irq_regs[i], rw_ipi, ipi); @@ -288,7 +290,7 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask) /* Wait for IPI to finish on other CPUS */ if (wait) { - for_each_cpu_mask(i, cpu_mask) { + for_each_cpu(i, &cpu_mask) { int j; for (j = 0 ; j < 1000; j++) { ipi = REG_RD(intr_vect, irq_regs[i], rw_ipi); @@ -314,11 +316,12 @@ int send_ipi(int vector, int wait, cpumask_t cpu_mask) */ int smp_call_function(void (*func)(void *info), void *info, int wait) { - cpumask_t cpu_mask = CPU_MASK_ALL; + cpumask_t cpu_mask; struct call_data_struct data; int ret; - cpu_clear(smp_processor_id(), cpu_mask); + cpumask_setall(&cpu_mask); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); WARN_ON(irqs_disabled()); diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index 728bbd9e7d4c..a6990cb0f098 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -102,7 +102,7 @@ SECTIONS #endif __vmlinux_end = .; /* Last address of the physical file. */ #ifdef CONFIG_ETRAX_ARCH_V32 - PERCPU(32, PAGE_SIZE) + PERCPU_SECTION(32) .init.ramfs : { INIT_RAM_FS diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c index df33ab89d70f..d72ab58fd83e 100644 --- a/arch/cris/mm/init.c +++ b/arch/cris/mm/init.c @@ -13,8 +13,6 @@ #include <linux/bootmem.h> #include <asm/tlb.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - unsigned long empty_zero_page; extern char _stext, _edata, _etext; /* From linkerscript */ diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index 0daae8af5787..7e958d829ec9 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -37,7 +37,7 @@ SECTIONS _einittext = .; INIT_DATA_SECTION(8) - PERCPU(L1_CACHE_BYTES, 4096) + PERCPU_SECTION(L1_CACHE_BYTES) . = ALIGN(PAGE_SIZE); __init_end = .; diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index ed64588ac3a7..fbe5f0dbae06 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -41,8 +41,6 @@ #undef DEBUG -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h index 23cce999eb1c..c3ffe3e54edc 100644 --- a/arch/ia64/include/asm/tlb.h +++ b/arch/ia64/include/asm/tlb.h @@ -47,21 +47,27 @@ #include <asm/machvec.h> #ifdef CONFIG_SMP -# define FREE_PTE_NR 2048 # define tlb_fast_mode(tlb) ((tlb)->nr == ~0U) #else -# define FREE_PTE_NR 0 # define tlb_fast_mode(tlb) (1) #endif +/* + * If we can't allocate a page to make a big batch of page pointers + * to work on, then just handle a few from the on-stack structure. + */ +#define IA64_GATHER_BUNDLE 8 + struct mmu_gather { struct mm_struct *mm; unsigned int nr; /* == ~0U => fast mode */ + unsigned int max; unsigned char fullmm; /* non-zero means full mm flush */ unsigned char need_flush; /* really unmapped some PTEs? */ unsigned long start_addr; unsigned long end_addr; - struct page *pages[FREE_PTE_NR]; + struct page **pages; + struct page *local[IA64_GATHER_BUNDLE]; }; struct ia64_tr_entry { @@ -90,9 +96,6 @@ extern struct ia64_tr_entry *ia64_idtrs[NR_CPUS]; #define RR_RID_MASK 0x00000000ffffff00L #define RR_TO_RID(val) ((val >> 8) & 0xffffff) -/* Users of the generic TLB shootdown code must declare this storage space. */ -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * Flush the TLB for address range START to END and, if not in fast mode, release the * freed pages that where gathered up to this point. @@ -147,15 +150,23 @@ ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long e } } -/* - * Return a pointer to an initialized struct mmu_gather. - */ -static inline struct mmu_gather * -tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush) +static inline void __tlb_alloc_page(struct mmu_gather *tlb) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); + unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); + if (addr) { + tlb->pages = (void *)addr; + tlb->max = PAGE_SIZE / sizeof(void *); + } +} + + +static inline void +tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) +{ tlb->mm = mm; + tlb->max = ARRAY_SIZE(tlb->local); + tlb->pages = tlb->local; /* * Use fast mode if only 1 CPU is online. * @@ -172,7 +183,6 @@ tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush) tlb->nr = (num_online_cpus() == 1) ? ~0U : 0; tlb->fullmm = full_mm_flush; tlb->start_addr = ~0UL; - return tlb; } /* @@ -180,7 +190,7 @@ tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush) * collected. */ static inline void -tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end) +tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { /* * Note: tlb->nr may be 0 at this point, so we can't rely on tlb->start_addr and @@ -191,7 +201,8 @@ tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end) /* keep the page table cache within bounds */ check_pgt_cache(); - put_cpu_var(mmu_gathers); + if (tlb->pages != tlb->local) + free_pages((unsigned long)tlb->pages, 0); } /* @@ -199,18 +210,33 @@ tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end) * must be delayed until after the TLB has been flushed (see comments at the beginning of * this file). */ -static inline void -tlb_remove_page (struct mmu_gather *tlb, struct page *page) +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) { tlb->need_flush = 1; if (tlb_fast_mode(tlb)) { free_page_and_swap_cache(page); - return; + return 1; /* avoid calling tlb_flush_mmu */ } + + if (!tlb->nr && tlb->pages == tlb->local) + __tlb_alloc_page(tlb); + tlb->pages[tlb->nr++] = page; - if (tlb->nr >= FREE_PTE_NR) - ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr); + VM_BUG_ON(tlb->nr > tlb->max); + + return tlb->max - tlb->nr; +} + +static inline void tlb_flush_mmu(struct mmu_gather *tlb) +{ + ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr); +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + if (!__tlb_remove_page(tlb, page)) + tlb_flush_mmu(tlb); } /* diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 9a018cde5d84..f114a3b14c6a 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -44,13 +44,16 @@ void show_mem(unsigned int filter) pg_data_t *pgdat; printk(KERN_INFO "Mem-info:\n"); - show_free_areas(); + show_free_areas(filter); printk(KERN_INFO "Node memory in pages:\n"); for_each_online_pgdat(pgdat) { unsigned long present; unsigned long flags; int shared = 0, cached = 0, reserved = 0; + int nid = pgdat->node_id; + if (skip_free_areas_node(filter, nid)) + continue; pgdat_resize_lock(pgdat, &flags); present = pgdat->node_present_pages; for(i = 0; i < pgdat->node_spanned_pages; i++) { @@ -64,8 +67,7 @@ void show_mem(unsigned int filter) if (max_gap < LARGE_GAP) continue; #endif - i = vmemmap_find_next_valid_pfn(pgdat->node_id, - i) - 1; + i = vmemmap_find_next_valid_pfn(nid, i) - 1; continue; } if (PageReserved(page)) @@ -81,7 +83,7 @@ void show_mem(unsigned int filter) total_cached += cached; total_shared += shared; printk(KERN_INFO "Node %4d: RAM: %11ld, rsvd: %8d, " - "shrd: %10d, swpd: %10d\n", pgdat->node_id, + "shrd: %10d, swpd: %10d\n", nid, present, reserved, shared, cached); } printk(KERN_INFO "%ld pages of RAM\n", total_present); diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 82ab1bc6afb1..c641333cd997 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -622,13 +622,16 @@ void show_mem(unsigned int filter) pg_data_t *pgdat; printk(KERN_INFO "Mem-info:\n"); - show_free_areas(); + show_free_areas(filter); printk(KERN_INFO "Node memory in pages:\n"); for_each_online_pgdat(pgdat) { unsigned long present; unsigned long flags; int shared = 0, cached = 0, reserved = 0; + int nid = pgdat->node_id; + if (skip_free_areas_node(filter, nid)) + continue; pgdat_resize_lock(pgdat, &flags); present = pgdat->node_present_pages; for(i = 0; i < pgdat->node_spanned_pages; i++) { @@ -638,8 +641,7 @@ void show_mem(unsigned int filter) if (pfn_valid(pgdat->node_start_pfn + i)) page = pfn_to_page(pgdat->node_start_pfn + i); else { - i = vmemmap_find_next_valid_pfn(pgdat->node_id, - i) - 1; + i = vmemmap_find_next_valid_pfn(nid, i) - 1; continue; } if (PageReserved(page)) @@ -655,7 +657,7 @@ void show_mem(unsigned int filter) total_cached += cached; total_shared += shared; printk(KERN_INFO "Node %4d: RAM: %11ld, rsvd: %8d, " - "shrd: %10d, swpd: %10d\n", pgdat->node_id, + "shrd: %10d, swpd: %10d\n", nid, present, reserved, shared, cached); } printk(KERN_INFO "%ld pages of RAM\n", total_present); diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index ed41759efcac..00cb0e26c64e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -36,8 +36,6 @@ #include <asm/mca.h> #include <asm/paravirt.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - extern void ia64_tlb_init (void); unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; diff --git a/arch/m32r/Kconfig.debug b/arch/m32r/Kconfig.debug index 2e1019ddbb22..bb1afc1a31cc 100644 --- a/arch/m32r/Kconfig.debug +++ b/arch/m32r/Kconfig.debug @@ -9,15 +9,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL && BROKEN diff --git a/arch/m32r/include/asm/smp.h b/arch/m32r/include/asm/smp.h index e67ded1aab91..8accc1bb0263 100644 --- a/arch/m32r/include/asm/smp.h +++ b/arch/m32r/include/asm/smp.h @@ -94,8 +94,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); #define NO_PROC_ID (0xff) /* No processor magic marker */ -#define PROC_CHANGE_PENALTY (15) /* Schedule penalty */ - /* * M32R-mp IPI */ diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S index cf95aec77460..018e4a711d79 100644 --- a/arch/m32r/kernel/vmlinux.lds.S +++ b/arch/m32r/kernel/vmlinux.lds.S @@ -54,7 +54,7 @@ SECTIONS __init_begin = .; INIT_TEXT_SECTION(PAGE_SIZE) INIT_DATA_SECTION(16) - PERCPU(32, PAGE_SIZE) + PERCPU_SECTION(32) . = ALIGN(PAGE_SIZE); __init_end = .; /* freed after init ends here */ diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c index 5d2858f6eede..2c468e8b5853 100644 --- a/arch/m32r/mm/discontig.c +++ b/arch/m32r/mm/discontig.c @@ -149,6 +149,7 @@ unsigned long __init zone_sizes_init(void) zholes_size[ZONE_DMA] = mp->holes; holes += zholes_size[ZONE_DMA]; + node_set_state(nid, N_NORMAL_MEMORY); free_area_init_node(nid, zones_size, start_pfn, zholes_size); } diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index 73e2205ebf5a..78b660e903da 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c @@ -35,8 +35,6 @@ extern char __init_begin, __init_end; pgd_t swapper_pg_dir[1024]; -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * Cache of MMU context last used. */ diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 75531da02a40..d66e34c718d0 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -5,6 +5,7 @@ config M68K select HAVE_AOUT if MMU select GENERIC_ATOMIC64 if MMU select HAVE_GENERIC_HARDIRQS if !MMU + select GENERIC_IRQ_SHOW if !MMU config RWSEM_GENERIC_SPINLOCK bool diff --git a/arch/m68k/include/asm/bitops_no.h b/arch/m68k/include/asm/bitops_no.h index 7d3779fdc5b6..6b0e2d349f0e 100644 --- a/arch/m68k/include/asm/bitops_no.h +++ b/arch/m68k/include/asm/bitops_no.h @@ -246,23 +246,7 @@ static inline int __test_and_clear_bit_le(int nr, volatile void *addr) return retval; } -#define ext2_set_bit_atomic(lock, nr, addr) \ - ({ \ - int ret; \ - spin_lock(lock); \ - ret = __test_and_set_bit_le((nr), (addr)); \ - spin_unlock(lock); \ - ret; \ - }) - -#define ext2_clear_bit_atomic(lock, nr, addr) \ - ({ \ - int ret; \ - spin_lock(lock); \ - ret = __test_and_clear_bit_le((nr), (addr)); \ - spin_unlock(lock); \ - ret; \ - }) +#include <asm-generic/bitops/ext2-atomic.h> static inline int test_bit_le(int nr, const volatile void *addr) { diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h index cf20f3097af6..353bf754a972 100644 --- a/arch/m68k/include/asm/io_no.h +++ b/arch/m68k/include/asm/io_no.h @@ -144,8 +144,10 @@ static inline void io_insl(unsigned int addr, void *buf, int len) #define IOMAP_NOCACHE_NONSER 2 #define IOMAP_WRITETHROUGH 3 -extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag); - +static inline void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +{ + return (void *) physaddr; +} static inline void *ioremap(unsigned long physaddr, unsigned long size) { return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); @@ -163,7 +165,7 @@ static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size return __ioremap(physaddr, size, IOMAP_FULL_CACHING); } -extern void iounmap(void *addr); +#define iounmap(addr) do { } while(0) /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index 59a69a5c62f2..983fed9d469b 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -1,5 +1,105 @@ -#ifdef CONFIG_MMU -#include "asm-offsets_mm.c" +/* + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ + +#define ASM_OFFSETS_C + +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/kbuild.h> +#include <asm/bootinfo.h> +#include <asm/irq.h> +#include <asm/amigahw.h> +#include <linux/font.h> + +int main(void) +{ + /* offsets into the task struct */ + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); + DEFINE(TASK_MM, offsetof(struct task_struct, mm)); + DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); + DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); + + /* offsets into the thread struct */ + DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); + DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); + DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); + DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); + DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); + DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); + DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); + DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); + DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); + + /* offsets into the thread_info struct */ + DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); + DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); + + /* offsets into the pt_regs */ + DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0)); + DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0)); + DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1)); + DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2)); + DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3)); + DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4)); + DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5)); + DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); + + /* bitfields are a bit difficult */ +#ifdef CONFIG_COLDFIRE + DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2); #else -#include "asm-offsets_no.c" + DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4); +#endif + + /* offsets into the irq_cpustat_t struct */ + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); + + /* signal defines */ + DEFINE(LSIGSEGV, SIGSEGV); + DEFINE(LSEGV_MAPERR, SEGV_MAPERR); + DEFINE(LSIGTRAP, SIGTRAP); + DEFINE(LTRAP_TRACE, TRAP_TRACE); + +#ifdef CONFIG_MMU + /* offsets into the bi_record struct */ + DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); + DEFINE(BIR_SIZE, offsetof(struct bi_record, size)); + DEFINE(BIR_DATA, offsetof(struct bi_record, data)); + + /* offsets into font_desc (drivers/video/console/font.h) */ + DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx)); + DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name)); + DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); + DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height)); + DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data)); + DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); + + /* offsets into the custom struct */ + DEFINE(CUSTOMBASE, &amiga_custom); + DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); + DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); + DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); + DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq)); + DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr)); + DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat)); + DEFINE(C_SERPER, offsetof(struct CUSTOM, serper)); + DEFINE(CIAABASE, &ciaa); + DEFINE(CIABBASE, &ciab); + DEFINE(C_PRA, offsetof(struct CIA, pra)); + DEFINE(ZTWOBASE, zTwoBase); #endif + + return 0; +} diff --git a/arch/m68k/kernel/asm-offsets_mm.c b/arch/m68k/kernel/asm-offsets_mm.c deleted file mode 100644 index 78e59b82ebc3..000000000000 --- a/arch/m68k/kernel/asm-offsets_mm.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#define ASM_OFFSETS_C - -#include <linux/stddef.h> -#include <linux/sched.h> -#include <linux/kernel_stat.h> -#include <linux/kbuild.h> -#include <asm/bootinfo.h> -#include <asm/irq.h> -#include <asm/amigahw.h> -#include <linux/font.h> - -int main(void) -{ - /* offsets into the task struct */ - DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); - DEFINE(TASK_MM, offsetof(struct task_struct, mm)); -#ifdef CONFIG_MMU - DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); -#endif - - /* offsets into the thread struct */ - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); - DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); - DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); - DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); - DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); - DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); - DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); - DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); - - /* offsets into the thread_info struct */ - DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); - - /* offsets into the pt_regs */ - DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0)); - DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0)); - DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1)); - DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2)); - DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3)); - DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4)); - DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5)); - DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0)); - DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1)); - DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2)); - DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc)); - DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); - /* bitfields are a bit difficult */ - DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4); - - /* offsets into the irq_cpustat_t struct */ - DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); - - /* offsets into the bi_record struct */ - DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); - DEFINE(BIR_SIZE, offsetof(struct bi_record, size)); - DEFINE(BIR_DATA, offsetof(struct bi_record, data)); - - /* offsets into font_desc (drivers/video/console/font.h) */ - DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx)); - DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name)); - DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); - DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height)); - DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data)); - DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); - - /* signal defines */ - DEFINE(LSIGSEGV, SIGSEGV); - DEFINE(LSEGV_MAPERR, SEGV_MAPERR); - DEFINE(LSIGTRAP, SIGTRAP); - DEFINE(LTRAP_TRACE, TRAP_TRACE); - - /* offsets into the custom struct */ - DEFINE(CUSTOMBASE, &amiga_custom); - DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); - DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); - DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); - DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq)); - DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr)); - DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat)); - DEFINE(C_SERPER, offsetof(struct CUSTOM, serper)); - DEFINE(CIAABASE, &ciaa); - DEFINE(CIABBASE, &ciab); - DEFINE(C_PRA, offsetof(struct CIA, pra)); - DEFINE(ZTWOBASE, zTwoBase); - - return 0; -} diff --git a/arch/m68k/kernel/asm-offsets_no.c b/arch/m68k/kernel/asm-offsets_no.c deleted file mode 100644 index ffe02f41ad46..000000000000 --- a/arch/m68k/kernel/asm-offsets_no.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#include <linux/stddef.h> -#include <linux/sched.h> -#include <linux/kernel_stat.h> -#include <linux/ptrace.h> -#include <linux/hardirq.h> -#include <linux/kbuild.h> -#include <asm/bootinfo.h> -#include <asm/irq.h> -#include <asm/thread_info.h> - -int main(void) -{ - /* offsets into the task struct */ - DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_MM, offsetof(struct task_struct, mm)); - - /* offsets into the irq_cpustat_t struct */ - DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); - - /* offsets into the thread struct */ - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); - DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); - DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); - DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); - DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); - DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); - DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); - DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); - - /* offsets into the pt_regs */ - DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0)); - DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0)); - DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1)); - DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2)); - DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3)); - DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4)); - DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5)); - DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0)); - DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1)); - DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2)); - DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc)); - DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); - -#ifdef CONFIG_COLDFIRE - /* bitfields are a bit difficult */ - DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2); -#else - /* bitfields are a bit difficult */ - DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4); -#endif - - /* signal defines */ - DEFINE(SIGSEGV, SIGSEGV); - DEFINE(SEGV_MAPERR, SEGV_MAPERR); - DEFINE(SIGTRAP, SIGTRAP); - DEFINE(TRAP_TRACE, TRAP_TRACE); - - DEFINE(PT_PTRACED, PT_PTRACED); - - /* Offsets in thread_info structure */ - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count)); - - return 0; -} diff --git a/arch/m68k/kernel/entry_no.S b/arch/m68k/kernel/entry_no.S index 2783f25e38bd..5f0f6b598b5a 100644 --- a/arch/m68k/kernel/entry_no.S +++ b/arch/m68k/kernel/entry_no.S @@ -24,7 +24,6 @@ * linux 2.4 support David McCullough <davidm@snapgear.com> */ -#include <linux/sys.h> #include <linux/linkage.h> #include <asm/errno.h> #include <asm/setup.h> diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c index 15dbc3e9d20c..544b8717d499 100644 --- a/arch/m68k/kernel/irq.c +++ b/arch/m68k/kernel/irq.c @@ -28,31 +28,3 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) set_irq_regs(oldregs); } - -int show_interrupts(struct seq_file *p, void *v) -{ - struct irqaction *ap; - int irq = *((loff_t *) v); - - if (irq == 0) - seq_puts(p, " CPU0\n"); - - if (irq < NR_IRQS) { - struct irq_desc *desc = irq_to_desc(irq); - - ap = desc->action; - if (ap) { - seq_printf(p, "%3d: ", irq); - seq_printf(p, "%10u ", kstat_irqs(irq)); - seq_printf(p, "%14s ", irq_desc_get_chip(desc)->name); - - seq_printf(p, "%s", ap->name); - for (ap = ap->next; ap; ap = ap->next) - seq_printf(p, ", %s", ap->name); - seq_putc(p, '\n'); - } - } - - return 0; -} - diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 4752c28ce0ac..33f82769547c 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -1,5 +1,33 @@ -#ifdef CONFIG_MMU -#include "m68k_ksyms_mm.c" -#else -#include "m68k_ksyms_no.c" +#include <linux/module.h> + +asmlinkage long long __ashldi3 (long long, int); +asmlinkage long long __ashrdi3 (long long, int); +asmlinkage long long __lshrdi3 (long long, int); +asmlinkage long long __muldi3 (long long, long long); + +/* The following are special because they're not called + explicitly (the C compiler generates them). Fortunately, + their interface isn't gonna change any time soon now, so + it's OK to leave it out of version control. */ +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__muldi3); + +#if !defined(__mc68020__) && !defined(__mc68030__) && \ + !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcpu32__) +/* + * Simpler 68k and ColdFire parts also need a few other gcc functions. + */ +extern long long __divsi3(long long, long long); +extern long long __modsi3(long long, long long); +extern long long __mulsi3(long long, long long); +extern long long __udivsi3(long long, long long); +extern long long __umodsi3(long long, long long); + +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__mulsi3); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__umodsi3); #endif diff --git a/arch/m68k/kernel/m68k_ksyms_mm.c b/arch/m68k/kernel/m68k_ksyms_mm.c deleted file mode 100644 index d900e77e5363..000000000000 --- a/arch/m68k/kernel/m68k_ksyms_mm.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <linux/module.h> - -asmlinkage long long __ashldi3 (long long, int); -asmlinkage long long __ashrdi3 (long long, int); -asmlinkage long long __lshrdi3 (long long, int); -asmlinkage long long __muldi3 (long long, long long); - -/* The following are special because they're not called - explicitly (the C compiler generates them). Fortunately, - their interface isn't gonna change any time soon now, so - it's OK to leave it out of version control. */ -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__muldi3); - diff --git a/arch/m68k/kernel/m68k_ksyms_no.c b/arch/m68k/kernel/m68k_ksyms_no.c deleted file mode 100644 index 39fe0a7aec32..000000000000 --- a/arch/m68k/kernel/m68k_ksyms_no.c +++ /dev/null @@ -1,78 +0,0 @@ -#include <linux/module.h> -#include <linux/linkage.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/user.h> -#include <linux/elfcore.h> -#include <linux/in6.h> -#include <linux/interrupt.h> - -#include <asm/setup.h> -#include <asm/machdep.h> -#include <asm/pgalloc.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/checksum.h> -#include <asm/current.h> - -extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); - -/* platform dependent support */ - -EXPORT_SYMBOL(__ioremap); -EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(dump_fpu); - -EXPORT_SYMBOL(ip_fast_csum); - -EXPORT_SYMBOL(kernel_thread); - -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy_nocheck); - -/* The following are special because they're not called - explicitly (the C compiler generates them). Fortunately, - their interface isn't gonna change any time soon now, so - it's OK to leave it out of version control. */ -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); - -/* - * libgcc functions - functions that are used internally by the - * compiler... (prototypes are not correct though, but that - * doesn't really matter since they're not versioned). - */ -extern void __ashldi3(void); -extern void __ashrdi3(void); -extern void __divsi3(void); -extern void __lshrdi3(void); -extern void __modsi3(void); -extern void __muldi3(void); -extern void __mulsi3(void); -extern void __udivsi3(void); -extern void __umodsi3(void); - - /* gcc lib functions */ -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__divsi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__modsi3); -EXPORT_SYMBOL(__muldi3); -EXPORT_SYMBOL(__mulsi3); -EXPORT_SYMBOL(__udivsi3); -EXPORT_SYMBOL(__umodsi3); - -#ifdef CONFIG_COLDFIRE -extern unsigned int *dma_device_address; -extern unsigned long dma_base_addr, _ramend; -EXPORT_SYMBOL(dma_base_addr); -EXPORT_SYMBOL(dma_device_address); -EXPORT_SYMBOL(_ramend); - -extern asmlinkage void trap(void); -extern void *_ramvec; -EXPORT_SYMBOL(trap); -EXPORT_SYMBOL(_ramvec); -#endif /* CONFIG_COLDFIRE */ diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c index e2a63af5d517..9b86ad11c68e 100644 --- a/arch/m68k/kernel/process_no.c +++ b/arch/m68k/kernel/process_no.c @@ -151,6 +151,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) set_fs(fs); return retval; } +EXPORT_SYMBOL(kernel_thread); void flush_thread(void) { @@ -283,6 +284,7 @@ int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu) #endif return 1; } +EXPORT_SYMBOL(dump_fpu); /* * Generic dumping code. Used for panic and debug. diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 63013df33584..8623f8dc16f8 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -1,5 +1,580 @@ +/* + * linux/arch/m68k/kernel/sys_m68k.c + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/m68k + * platform. + */ + +#include <linux/capability.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/fs.h> +#include <linux/smp.h> +#include <linux/sem.h> +#include <linux/msg.h> +#include <linux/shm.h> +#include <linux/stat.h> +#include <linux/syscalls.h> +#include <linux/mman.h> +#include <linux/file.h> +#include <linux/ipc.h> + +#include <asm/setup.h> +#include <asm/uaccess.h> +#include <asm/cachectl.h> +#include <asm/traps.h> +#include <asm/page.h> +#include <asm/unistd.h> +#include <asm/cacheflush.h> + #ifdef CONFIG_MMU -#include "sys_m68k_mm.c" + +#include <asm/tlb.h> + +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code); + +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + /* + * This is wrong for sun3 - there PAGE_SIZE is 8Kb, + * so we need to shift the argument down by 1; m68k mmap64(3) + * (in libc) expects the last argument of mmap2 in 4Kb units. + */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); +} + +/* Convert virtual (user) address VADDR to physical address PADDR */ +#define virt_to_phys_040(vaddr) \ +({ \ + unsigned long _mmusr, _paddr; \ + \ + __asm__ __volatile__ (".chip 68040\n\t" \ + "ptestr (%1)\n\t" \ + "movec %%mmusr,%0\n\t" \ + ".chip 68k" \ + : "=r" (_mmusr) \ + : "a" (vaddr)); \ + _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \ + _paddr; \ +}) + +static inline int +cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len) +{ + unsigned long paddr, i; + + switch (scope) + { + case FLUSH_SCOPE_ALL: + switch (cache) + { + case FLUSH_CACHE_DATA: + /* This nop is needed for some broken versions of the 68040. */ + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpusha %dc\n\t" + ".chip 68k"); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpusha %ic\n\t" + ".chip 68k"); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpusha %bc\n\t" + ".chip 68k"); + break; + } + break; + + case FLUSH_SCOPE_LINE: + /* Find the physical address of the first mapped page in the + address range. */ + if ((paddr = virt_to_phys_040(addr))) { + paddr += addr & ~(PAGE_MASK | 15); + len = (len + (addr & 15) + 15) >> 4; + } else { + unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); + + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + tmp = PAGE_SIZE; + for (;;) + { + if ((paddr = virt_to_phys_040(addr))) + break; + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + } + len = (len + 15) >> 4; + } + i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; + while (len--) + { + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushl %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushl %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushl %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + if (!--i && len) + { + /* + * No need to page align here since it is done by + * virt_to_phys_040(). + */ + addr += PAGE_SIZE; + i = PAGE_SIZE / 16; + /* Recompute physical address when crossing a page + boundary. */ + for (;;) + { + if ((paddr = virt_to_phys_040(addr))) + break; + if (len <= i) + return 0; + len -= i; + addr += PAGE_SIZE; + } + } + else + paddr += 16; + } + break; + + default: + case FLUSH_SCOPE_PAGE: + len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); + for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) + { + if (!(paddr = virt_to_phys_040(addr))) + continue; + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + } + break; + } + return 0; +} + +#define virt_to_phys_060(vaddr) \ +({ \ + unsigned long paddr; \ + __asm__ __volatile__ (".chip 68060\n\t" \ + "plpar (%0)\n\t" \ + ".chip 68k" \ + : "=a" (paddr) \ + : "0" (vaddr)); \ + (paddr); /* XXX */ \ +}) + +static inline int +cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len) +{ + unsigned long paddr, i; + + /* + * 68060 manual says: + * cpush %dc : flush DC, remains valid (with our %cacr setup) + * cpush %ic : invalidate IC + * cpush %bc : flush DC + invalidate IC + */ + switch (scope) + { + case FLUSH_SCOPE_ALL: + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ (".chip 68060\n\t" + "cpusha %dc\n\t" + ".chip 68k"); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ (".chip 68060\n\t" + "cpusha %ic\n\t" + ".chip 68k"); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ (".chip 68060\n\t" + "cpusha %bc\n\t" + ".chip 68k"); + break; + } + break; + + case FLUSH_SCOPE_LINE: + /* Find the physical address of the first mapped page in the + address range. */ + len += addr & 15; + addr &= -16; + if (!(paddr = virt_to_phys_060(addr))) { + unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); + + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + tmp = PAGE_SIZE; + for (;;) + { + if ((paddr = virt_to_phys_060(addr))) + break; + if (len <= tmp) + return 0; + addr += tmp; + len -= tmp; + } + } + len = (len + 15) >> 4; + i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; + while (len--) + { + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushl %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + if (!--i && len) + { + + /* + * We just want to jump to the first cache line + * in the next page. + */ + addr += PAGE_SIZE; + addr &= PAGE_MASK; + + i = PAGE_SIZE / 16; + /* Recompute physical address when crossing a page + boundary. */ + for (;;) + { + if ((paddr = virt_to_phys_060(addr))) + break; + if (len <= i) + return 0; + len -= i; + addr += PAGE_SIZE; + } + } + else + paddr += 16; + } + break; + + default: + case FLUSH_SCOPE_PAGE: + len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); + addr &= PAGE_MASK; /* Workaround for bug in some + revisions of the 68060 */ + for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) + { + if (!(paddr = virt_to_phys_060(addr))) + continue; + switch (cache) + { + case FLUSH_CACHE_DATA: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushp %%dc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + case FLUSH_CACHE_INSN: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushp %%ic,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + default: + case FLUSH_CACHE_BOTH: + __asm__ __volatile__ (".chip 68060\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (paddr)); + break; + } + } + break; + } + return 0; +} + +/* sys_cacheflush -- flush (part of) the processor cache. */ +asmlinkage int +sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) +{ + struct vm_area_struct *vma; + int ret = -EINVAL; + + if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL || + cache & ~FLUSH_CACHE_BOTH) + goto out; + + if (scope == FLUSH_SCOPE_ALL) { + /* Only the superuser may explicitly flush the whole cache. */ + ret = -EPERM; + if (!capable(CAP_SYS_ADMIN)) + goto out; + } else { + /* + * Verify that the specified address region actually belongs + * to this process. + */ + vma = find_vma (current->mm, addr); + ret = -EINVAL; + /* Check for overflow. */ + if (addr + len < addr) + goto out; + if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) + goto out; + } + + if (CPU_IS_020_OR_030) { + if (scope == FLUSH_SCOPE_LINE && len < 256) { + unsigned long cacr; + __asm__ ("movec %%cacr, %0" : "=r" (cacr)); + if (cache & FLUSH_CACHE_INSN) + cacr |= 4; + if (cache & FLUSH_CACHE_DATA) + cacr |= 0x400; + len >>= 2; + while (len--) { + __asm__ __volatile__ ("movec %1, %%caar\n\t" + "movec %0, %%cacr" + : /* no outputs */ + : "r" (cacr), "r" (addr)); + addr += 4; + } + } else { + /* Flush the whole cache, even if page granularity requested. */ + unsigned long cacr; + __asm__ ("movec %%cacr, %0" : "=r" (cacr)); + if (cache & FLUSH_CACHE_INSN) + cacr |= 8; + if (cache & FLUSH_CACHE_DATA) + cacr |= 0x800; + __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); + } + ret = 0; + goto out; + } else { + /* + * 040 or 060: don't blindly trust 'scope', someone could + * try to flush a few megs of memory. + */ + + if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE) + scope=FLUSH_SCOPE_PAGE; + if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL) + scope=FLUSH_SCOPE_ALL; + if (CPU_IS_040) { + ret = cache_flush_040 (addr, scope, cache, len); + } else if (CPU_IS_060) { + ret = cache_flush_060 (addr, scope, cache, len); + } + } +out: + return ret; +} + +/* This syscall gets its arguments in A0 (mem), D2 (oldval) and + D1 (newval). */ +asmlinkage int +sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, + unsigned long __user * mem) +{ + /* This was borrowed from ARM's implementation. */ + for (;;) { + struct mm_struct *mm = current->mm; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + spinlock_t *ptl; + unsigned long mem_value; + + down_read(&mm->mmap_sem); + pgd = pgd_offset(mm, (unsigned long)mem); + if (!pgd_present(*pgd)) + goto bad_access; + pmd = pmd_offset(pgd, (unsigned long)mem); + if (!pmd_present(*pmd)) + goto bad_access; + pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl); + if (!pte_present(*pte) || !pte_dirty(*pte) + || !pte_write(*pte)) { + pte_unmap_unlock(pte, ptl); + goto bad_access; + } + + mem_value = *mem; + if (mem_value == oldval) + *mem = newval; + + pte_unmap_unlock(pte, ptl); + up_read(&mm->mmap_sem); + return mem_value; + + bad_access: + up_read(&mm->mmap_sem); + /* This is not necessarily a bad access, we can get here if + a memory we're trying to write to should be copied-on-write. + Make the kernel do the necessary page stuff, then re-iterate. + Simulate a write access fault to do that. */ + { + /* The first argument of the function corresponds to + D1, which is the first field of struct pt_regs. */ + struct pt_regs *fp = (struct pt_regs *)&newval; + + /* '3' is an RMW flag. */ + if (do_page_fault(fp, (unsigned long)mem, 3)) + /* If the do_page_fault() failed, we don't + have anything meaningful to return. + There should be a SIGSEGV pending for + the process. */ + return 0xdeadbeef; + } + } +} + #else -#include "sys_m68k_no.c" -#endif + +/* sys_cacheflush -- flush (part of) the processor cache. */ +asmlinkage int +sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) +{ + flush_cache_all(); + return 0; +} + +/* This syscall gets its arguments in A0 (mem), D2 (oldval) and + D1 (newval). */ +asmlinkage int +sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, + unsigned long __user * mem) +{ + struct mm_struct *mm = current->mm; + unsigned long mem_value; + + down_read(&mm->mmap_sem); + + mem_value = *mem; + if (mem_value == oldval) + *mem = newval; + + up_read(&mm->mmap_sem); + return mem_value; +} + +#endif /* CONFIG_MMU */ + +asmlinkage int sys_getpagesize(void) +{ + return PAGE_SIZE; +} + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) +{ + register long __res asm ("%d0") = __NR_execve; + register long __a asm ("%d1") = (long)(filename); + register long __b asm ("%d2") = (long)(argv); + register long __c asm ("%d3") = (long)(envp); + asm volatile ("trap #0" : "+d" (__res) + : "d" (__a), "d" (__b), "d" (__c)); + return __res; +} + +asmlinkage unsigned long sys_get_thread_area(void) +{ + return current_thread_info()->tp_value; +} + +asmlinkage int sys_set_thread_area(unsigned long tp) +{ + current_thread_info()->tp_value = tp; + return 0; +} + +asmlinkage int sys_atomic_barrier(void) +{ + /* no code needed for uniprocs */ + return 0; +} diff --git a/arch/m68k/kernel/sys_m68k_mm.c b/arch/m68k/kernel/sys_m68k_mm.c deleted file mode 100644 index 3db2e7f902aa..000000000000 --- a/arch/m68k/kernel/sys_m68k_mm.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * linux/arch/m68k/kernel/sys_m68k.c - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/m68k - * platform. - */ - -#include <linux/capability.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/smp.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/stat.h> -#include <linux/syscalls.h> -#include <linux/mman.h> -#include <linux/file.h> -#include <linux/ipc.h> - -#include <asm/setup.h> -#include <asm/uaccess.h> -#include <asm/cachectl.h> -#include <asm/traps.h> -#include <asm/page.h> -#include <asm/unistd.h> -#include <linux/elf.h> -#include <asm/tlb.h> - -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code); - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - /* - * This is wrong for sun3 - there PAGE_SIZE is 8Kb, - * so we need to shift the argument down by 1; m68k mmap64(3) - * (in libc) expects the last argument of mmap2 in 4Kb units. - */ - return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); -} - -/* Convert virtual (user) address VADDR to physical address PADDR */ -#define virt_to_phys_040(vaddr) \ -({ \ - unsigned long _mmusr, _paddr; \ - \ - __asm__ __volatile__ (".chip 68040\n\t" \ - "ptestr (%1)\n\t" \ - "movec %%mmusr,%0\n\t" \ - ".chip 68k" \ - : "=r" (_mmusr) \ - : "a" (vaddr)); \ - _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \ - _paddr; \ -}) - -static inline int -cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len) -{ - unsigned long paddr, i; - - switch (scope) - { - case FLUSH_SCOPE_ALL: - switch (cache) - { - case FLUSH_CACHE_DATA: - /* This nop is needed for some broken versions of the 68040. */ - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpusha %dc\n\t" - ".chip 68k"); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpusha %ic\n\t" - ".chip 68k"); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpusha %bc\n\t" - ".chip 68k"); - break; - } - break; - - case FLUSH_SCOPE_LINE: - /* Find the physical address of the first mapped page in the - address range. */ - if ((paddr = virt_to_phys_040(addr))) { - paddr += addr & ~(PAGE_MASK | 15); - len = (len + (addr & 15) + 15) >> 4; - } else { - unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); - - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - tmp = PAGE_SIZE; - for (;;) - { - if ((paddr = virt_to_phys_040(addr))) - break; - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - } - len = (len + 15) >> 4; - } - i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; - while (len--) - { - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushl %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushl %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - if (!--i && len) - { - /* - * No need to page align here since it is done by - * virt_to_phys_040(). - */ - addr += PAGE_SIZE; - i = PAGE_SIZE / 16; - /* Recompute physical address when crossing a page - boundary. */ - for (;;) - { - if ((paddr = virt_to_phys_040(addr))) - break; - if (len <= i) - return 0; - len -= i; - addr += PAGE_SIZE; - } - } - else - paddr += 16; - } - break; - - default: - case FLUSH_SCOPE_PAGE: - len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); - for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) - { - if (!(paddr = virt_to_phys_040(addr))) - continue; - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ ("nop\n\t" - ".chip 68040\n\t" - "cpushp %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - } - break; - } - return 0; -} - -#define virt_to_phys_060(vaddr) \ -({ \ - unsigned long paddr; \ - __asm__ __volatile__ (".chip 68060\n\t" \ - "plpar (%0)\n\t" \ - ".chip 68k" \ - : "=a" (paddr) \ - : "0" (vaddr)); \ - (paddr); /* XXX */ \ -}) - -static inline int -cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len) -{ - unsigned long paddr, i; - - /* - * 68060 manual says: - * cpush %dc : flush DC, remains valid (with our %cacr setup) - * cpush %ic : invalidate IC - * cpush %bc : flush DC + invalidate IC - */ - switch (scope) - { - case FLUSH_SCOPE_ALL: - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ (".chip 68060\n\t" - "cpusha %dc\n\t" - ".chip 68k"); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ (".chip 68060\n\t" - "cpusha %ic\n\t" - ".chip 68k"); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ (".chip 68060\n\t" - "cpusha %bc\n\t" - ".chip 68k"); - break; - } - break; - - case FLUSH_SCOPE_LINE: - /* Find the physical address of the first mapped page in the - address range. */ - len += addr & 15; - addr &= -16; - if (!(paddr = virt_to_phys_060(addr))) { - unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); - - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - tmp = PAGE_SIZE; - for (;;) - { - if ((paddr = virt_to_phys_060(addr))) - break; - if (len <= tmp) - return 0; - addr += tmp; - len -= tmp; - } - } - len = (len + 15) >> 4; - i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; - while (len--) - { - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - if (!--i && len) - { - - /* - * We just want to jump to the first cache line - * in the next page. - */ - addr += PAGE_SIZE; - addr &= PAGE_MASK; - - i = PAGE_SIZE / 16; - /* Recompute physical address when crossing a page - boundary. */ - for (;;) - { - if ((paddr = virt_to_phys_060(addr))) - break; - if (len <= i) - return 0; - len -= i; - addr += PAGE_SIZE; - } - } - else - paddr += 16; - } - break; - - default: - case FLUSH_SCOPE_PAGE: - len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); - addr &= PAGE_MASK; /* Workaround for bug in some - revisions of the 68060 */ - for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) - { - if (!(paddr = virt_to_phys_060(addr))) - continue; - switch (cache) - { - case FLUSH_CACHE_DATA: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushp %%dc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - case FLUSH_CACHE_INSN: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushp %%ic,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - default: - case FLUSH_CACHE_BOTH: - __asm__ __volatile__ (".chip 68060\n\t" - "cpushp %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (paddr)); - break; - } - } - break; - } - return 0; -} - -/* sys_cacheflush -- flush (part of) the processor cache. */ -asmlinkage int -sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) -{ - struct vm_area_struct *vma; - int ret = -EINVAL; - - if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL || - cache & ~FLUSH_CACHE_BOTH) - goto out; - - if (scope == FLUSH_SCOPE_ALL) { - /* Only the superuser may explicitly flush the whole cache. */ - ret = -EPERM; - if (!capable(CAP_SYS_ADMIN)) - goto out; - } else { - /* - * Verify that the specified address region actually belongs - * to this process. - */ - vma = find_vma (current->mm, addr); - ret = -EINVAL; - /* Check for overflow. */ - if (addr + len < addr) - goto out; - if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) - goto out; - } - - if (CPU_IS_020_OR_030) { - if (scope == FLUSH_SCOPE_LINE && len < 256) { - unsigned long cacr; - __asm__ ("movec %%cacr, %0" : "=r" (cacr)); - if (cache & FLUSH_CACHE_INSN) - cacr |= 4; - if (cache & FLUSH_CACHE_DATA) - cacr |= 0x400; - len >>= 2; - while (len--) { - __asm__ __volatile__ ("movec %1, %%caar\n\t" - "movec %0, %%cacr" - : /* no outputs */ - : "r" (cacr), "r" (addr)); - addr += 4; - } - } else { - /* Flush the whole cache, even if page granularity requested. */ - unsigned long cacr; - __asm__ ("movec %%cacr, %0" : "=r" (cacr)); - if (cache & FLUSH_CACHE_INSN) - cacr |= 8; - if (cache & FLUSH_CACHE_DATA) - cacr |= 0x800; - __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); - } - ret = 0; - goto out; - } else { - /* - * 040 or 060: don't blindly trust 'scope', someone could - * try to flush a few megs of memory. - */ - - if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE) - scope=FLUSH_SCOPE_PAGE; - if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL) - scope=FLUSH_SCOPE_ALL; - if (CPU_IS_040) { - ret = cache_flush_040 (addr, scope, cache, len); - } else if (CPU_IS_060) { - ret = cache_flush_060 (addr, scope, cache, len); - } - } -out: - return ret; -} - -asmlinkage int sys_getpagesize(void) -{ - return PAGE_SIZE; -} - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register long __res asm ("%d0") = __NR_execve; - register long __a asm ("%d1") = (long)(filename); - register long __b asm ("%d2") = (long)(argv); - register long __c asm ("%d3") = (long)(envp); - asm volatile ("trap #0" : "+d" (__res) - : "d" (__a), "d" (__b), "d" (__c)); - return __res; -} - -asmlinkage unsigned long sys_get_thread_area(void) -{ - return current_thread_info()->tp_value; -} - -asmlinkage int sys_set_thread_area(unsigned long tp) -{ - current_thread_info()->tp_value = tp; - return 0; -} - -/* This syscall gets its arguments in A0 (mem), D2 (oldval) and - D1 (newval). */ -asmlinkage int -sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, - unsigned long __user * mem) -{ - /* This was borrowed from ARM's implementation. */ - for (;;) { - struct mm_struct *mm = current->mm; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - spinlock_t *ptl; - unsigned long mem_value; - - down_read(&mm->mmap_sem); - pgd = pgd_offset(mm, (unsigned long)mem); - if (!pgd_present(*pgd)) - goto bad_access; - pmd = pmd_offset(pgd, (unsigned long)mem); - if (!pmd_present(*pmd)) - goto bad_access; - pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl); - if (!pte_present(*pte) || !pte_dirty(*pte) - || !pte_write(*pte)) { - pte_unmap_unlock(pte, ptl); - goto bad_access; - } - - mem_value = *mem; - if (mem_value == oldval) - *mem = newval; - - pte_unmap_unlock(pte, ptl); - up_read(&mm->mmap_sem); - return mem_value; - - bad_access: - up_read(&mm->mmap_sem); - /* This is not necessarily a bad access, we can get here if - a memory we're trying to write to should be copied-on-write. - Make the kernel do the necessary page stuff, then re-iterate. - Simulate a write access fault to do that. */ - { - /* The first argument of the function corresponds to - D1, which is the first field of struct pt_regs. */ - struct pt_regs *fp = (struct pt_regs *)&newval; - - /* '3' is an RMW flag. */ - if (do_page_fault(fp, (unsigned long)mem, 3)) - /* If the do_page_fault() failed, we don't - have anything meaningful to return. - There should be a SIGSEGV pending for - the process. */ - return 0xdeadbeef; - } - } -} - -asmlinkage int sys_atomic_barrier(void) -{ - /* no code needed for uniprocs */ - return 0; -} diff --git a/arch/m68k/kernel/sys_m68k_no.c b/arch/m68k/kernel/sys_m68k_no.c deleted file mode 100644 index 68488ae47f0a..000000000000 --- a/arch/m68k/kernel/sys_m68k_no.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * linux/arch/m68knommu/kernel/sys_m68k.c - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/m68k - * platform. - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/stat.h> -#include <linux/syscalls.h> -#include <linux/mman.h> -#include <linux/file.h> -#include <linux/ipc.h> -#include <linux/fs.h> - -#include <asm/setup.h> -#include <asm/uaccess.h> -#include <asm/cachectl.h> -#include <asm/traps.h> -#include <asm/cacheflush.h> -#include <asm/unistd.h> - -/* sys_cacheflush -- flush (part of) the processor cache. */ -asmlinkage int -sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) -{ - flush_cache_all(); - return(0); -} - -asmlinkage int sys_getpagesize(void) -{ - return PAGE_SIZE; -} - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register long __res asm ("%d0") = __NR_execve; - register long __a asm ("%d1") = (long)(filename); - register long __b asm ("%d2") = (long)(argv); - register long __c asm ("%d3") = (long)(envp); - asm volatile ("trap #0" : "+d" (__res) - : "d" (__a), "d" (__b), "d" (__c)); - return __res; -} - -asmlinkage unsigned long sys_get_thread_area(void) -{ - return current_thread_info()->tp_value; -} - -asmlinkage int sys_set_thread_area(unsigned long tp) -{ - current_thread_info()->tp_value = tp; - return 0; -} - -/* This syscall gets its arguments in A0 (mem), D2 (oldval) and - D1 (newval). */ -asmlinkage int -sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, - unsigned long __user * mem) -{ - struct mm_struct *mm = current->mm; - unsigned long mem_value; - - down_read(&mm->mmap_sem); - - mem_value = *mem; - if (mem_value == oldval) - *mem = newval; - - up_read(&mm->mmap_sem); - return mem_value; -} - -asmlinkage int sys_atomic_barrier(void) -{ - /* no code needed for uniprocs */ - return 0; -} diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index 5909e392cb1e..6f7b09122a00 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -11,7 +11,6 @@ * Linux/m68k support by Hamish Macdonald */ -#include <linux/sys.h> #include <linux/linkage.h> #ifndef CONFIG_MMU diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index 1f95881d8437..df421e501436 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile @@ -1,5 +1,14 @@ + +# +# Makefile for m68k-specific library files.. +# + +lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ + memcpy.o memset.o memmove.o + ifdef CONFIG_MMU -include arch/m68k/lib/Makefile_mm +lib-y += string.o uaccess.o checksum_mm.o else -include arch/m68k/lib/Makefile_no +lib-y += mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o delay.o checksum_no.o endif + diff --git a/arch/m68k/lib/Makefile_mm b/arch/m68k/lib/Makefile_mm deleted file mode 100644 index af9abf8d9d98..000000000000 --- a/arch/m68k/lib/Makefile_mm +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for m68k-specific library files.. -# - -lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ - checksum.o string.o uaccess.o diff --git a/arch/m68k/lib/Makefile_no b/arch/m68k/lib/Makefile_no deleted file mode 100644 index 32d852e586d7..000000000000 --- a/arch/m68k/lib/Makefile_no +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for m68knommu specific library files.. -# - -lib-y := ashldi3.o ashrdi3.o lshrdi3.o \ - muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \ - checksum.o memcpy.o memmove.o memset.o delay.o diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c deleted file mode 100644 index 1297536060de..000000000000 --- a/arch/m68k/lib/checksum.c +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef CONFIG_MMU -#include "checksum_mm.c" -#else -#include "checksum_no.c" -#endif diff --git a/arch/m68k/lib/checksum_no.c b/arch/m68k/lib/checksum_no.c index eccf25d3d73e..e4c6354da765 100644 --- a/arch/m68k/lib/checksum_no.c +++ b/arch/m68k/lib/checksum_no.c @@ -101,6 +101,7 @@ __sum16 ip_fast_csum(const void *iph, unsigned int ihl) { return (__force __sum16)~do_csum(iph,ihl*4); } +EXPORT_SYMBOL(ip_fast_csum); #endif /* @@ -140,6 +141,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, memcpy(dst, (__force const void *)src, len); return csum_partial(dst, len, sum); } +EXPORT_SYMBOL(csum_partial_copy_from_user); /* * copy from ds while checksumming, otherwise like csum_partial @@ -151,3 +153,4 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) memcpy(dst, src, len); return csum_partial(dst, len, sum); } +EXPORT_SYMBOL(csum_partial_copy_nocheck); diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c index b50dbcad4746..62182c81e91c 100644 --- a/arch/m68k/lib/memcpy.c +++ b/arch/m68k/lib/memcpy.c @@ -1,62 +1,80 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ -#include <linux/types.h> +#include <linux/module.h> +#include <linux/string.h> -void * memcpy(void * to, const void * from, size_t n) +void *memcpy(void *to, const void *from, size_t n) { -#ifdef CONFIG_COLDFIRE - void *xto = to; - size_t temp; + void *xto = to; + size_t temp, temp1; - if (!n) - return xto; - if ((long) to & 1) - { - char *cto = to; - const char *cfrom = from; - *cto++ = *cfrom++; - to = cto; - from = cfrom; - n--; - } - if (n > 2 && (long) to & 2) - { - short *sto = to; - const short *sfrom = from; - *sto++ = *sfrom++; - to = sto; - from = sfrom; - n -= 2; - } - temp = n >> 2; - if (temp) - { - long *lto = to; - const long *lfrom = from; - for (; temp; temp--) - *lto++ = *lfrom++; - to = lto; - from = lfrom; - } - if (n & 2) - { - short *sto = to; - const short *sfrom = from; - *sto++ = *sfrom++; - to = sto; - from = sfrom; - } - if (n & 1) - { - char *cto = to; - const char *cfrom = from; - *cto = *cfrom; - } - return xto; + if (!n) + return xto; + if ((long)to & 1) { + char *cto = to; + const char *cfrom = from; + *cto++ = *cfrom++; + to = cto; + from = cfrom; + n--; + } + if (n > 2 && (long)to & 2) { + short *sto = to; + const short *sfrom = from; + *sto++ = *sfrom++; + to = sto; + from = sfrom; + n -= 2; + } + temp = n >> 2; + if (temp) { + long *lto = to; + const long *lfrom = from; +#if defined(__mc68020__) || defined(__mc68030__) || \ + defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) + asm volatile ( + " movel %2,%3\n" + " andw #7,%3\n" + " lsrl #3,%2\n" + " negw %3\n" + " jmp %%pc@(1f,%3:w:2)\n" + "4: movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + " movel %0@+,%1@+\n" + "1: dbra %2,4b\n" + " clrw %2\n" + " subql #1,%2\n" + " jpl 4b" + : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1) + : "0" (lfrom), "1" (lto), "2" (temp)); #else - const char *c_from = from; - char *c_to = to; - while (n-- > 0) - *c_to++ = *c_from++; - return((void *) to); + for (; temp; temp--) + *lto++ = *lfrom++; #endif + to = lto; + from = lfrom; + } + if (n & 2) { + short *sto = to; + const short *sfrom = from; + *sto++ = *sfrom++; + to = sto; + from = sfrom; + } + if (n & 1) { + char *cto = to; + const char *cfrom = from; + *cto = *cfrom; + } + return xto; } +EXPORT_SYMBOL(memcpy); diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c index b3dcfe9dab7e..6519f7f349f6 100644 --- a/arch/m68k/lib/memmove.c +++ b/arch/m68k/lib/memmove.c @@ -4,8 +4,6 @@ * for more details. */ -#define __IN_STRING_C - #include <linux/module.h> #include <linux/string.h> diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c index 1389bf455633..f649e6a2e644 100644 --- a/arch/m68k/lib/memset.c +++ b/arch/m68k/lib/memset.c @@ -1,47 +1,75 @@ -#include <linux/types.h> +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ -void * memset(void * s, int c, size_t count) +#include <linux/module.h> +#include <linux/string.h> + +void *memset(void *s, int c, size_t count) { - void *xs = s; - size_t temp; + void *xs = s; + size_t temp; - if (!count) - return xs; - c &= 0xff; - c |= c << 8; - c |= c << 16; - if ((long) s & 1) - { - char *cs = s; - *cs++ = c; - s = cs; - count--; - } - if (count > 2 && (long) s & 2) - { - short *ss = s; - *ss++ = c; - s = ss; - count -= 2; - } - temp = count >> 2; - if (temp) - { - long *ls = s; - for (; temp; temp--) - *ls++ = c; - s = ls; - } - if (count & 2) - { - short *ss = s; - *ss++ = c; - s = ss; - } - if (count & 1) - { - char *cs = s; - *cs = c; - } - return xs; + if (!count) + return xs; + c &= 0xff; + c |= c << 8; + c |= c << 16; + if ((long)s & 1) { + char *cs = s; + *cs++ = c; + s = cs; + count--; + } + if (count > 2 && (long)s & 2) { + short *ss = s; + *ss++ = c; + s = ss; + count -= 2; + } + temp = count >> 2; + if (temp) { + long *ls = s; +#if defined(__mc68020__) || defined(__mc68030__) || \ + defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) + size_t temp1; + asm volatile ( + " movel %1,%2\n" + " andw #7,%2\n" + " lsrl #3,%1\n" + " negw %2\n" + " jmp %%pc@(2f,%2:w:2)\n" + "1: movel %3,%0@+\n" + " movel %3,%0@+\n" + " movel %3,%0@+\n" + " movel %3,%0@+\n" + " movel %3,%0@+\n" + " movel %3,%0@+\n" + " movel %3,%0@+\n" + " movel %3,%0@+\n" + "2: dbra %1,1b\n" + " clrw %1\n" + " subql #1,%1\n" + " jpl 1b" + : "=a" (ls), "=d" (temp), "=&d" (temp1) + : "d" (c), "0" (ls), "1" (temp)); +#else + for (; temp; temp--) + *ls++ = c; +#endif + s = ls; + } + if (count & 2) { + short *ss = s; + *ss++ = c; + s = ss; + } + if (count & 1) { + char *cs = s; + *cs = c; + } + return xs; } +EXPORT_SYMBOL(memset); diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c index 16e0eb338ee0..079bafca073e 100644 --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c @@ -1,5 +1,98 @@ -#ifdef CONFIG_MMU -#include "muldi3_mm.c" +/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and + gcc-2.7.2.3/longlong.h which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#if defined(__mc68020__) || defined(__mc68030__) || \ + defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) + +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) + #else -#include "muldi3_no.c" + +#define SI_TYPE_SIZE 32 +#define __BITS4 (SI_TYPE_SIZE / 4) +#define __ll_B (1L << (SI_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((USItype) (t) % __ll_B) +#define __ll_highpart(t) ((USItype) (t) / __ll_B) + +#define umul_ppmm(w1, w0, u, v) \ + do { \ + USItype __x0, __x1, __x2, __x3; \ + USItype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (USItype) __ul * __vl; \ + __x1 = (USItype) __ul * __vh; \ + __x2 = (USItype) __uh * __vl; \ + __x3 = (USItype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) + #endif + +#define __umulsidi3(u, v) \ + ({DIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__muldi3 (DItype u, DItype v) +{ + DIunion w; + DIunion uu, vv; + + uu.ll = u, + vv.ll = v; + + w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high + + (USItype) uu.s.high * (USItype) vv.s.low); + + return w.ll; +} diff --git a/arch/m68k/lib/muldi3_mm.c b/arch/m68k/lib/muldi3_mm.c deleted file mode 100644 index be4f275649e3..000000000000 --- a/arch/m68k/lib/muldi3_mm.c +++ /dev/null @@ -1,63 +0,0 @@ -/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and - gcc-2.7.2.3/longlong.h which is: */ -/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define BITS_PER_UNIT 8 - -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "%0" ((USItype)(u)), \ - "dmi" ((USItype)(v))) - -#define __umulsidi3(u, v) \ - ({DIunion __w; \ - umul_ppmm (__w.s.high, __w.s.low, u, v); \ - __w.ll; }) - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); - -struct DIstruct {SItype high, low;}; - -typedef union -{ - struct DIstruct s; - DItype ll; -} DIunion; - -DItype -__muldi3 (DItype u, DItype v) -{ - DIunion w; - DIunion uu, vv; - - uu.ll = u, - vv.ll = v; - - w.ll = __umulsidi3 (uu.s.low, vv.s.low); - w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high - + (USItype) uu.s.high * (USItype) vv.s.low); - - return w.ll; -} diff --git a/arch/m68k/lib/muldi3_no.c b/arch/m68k/lib/muldi3_no.c deleted file mode 100644 index 34af72c30303..000000000000 --- a/arch/m68k/lib/muldi3_no.c +++ /dev/null @@ -1,86 +0,0 @@ -/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and - gcc-2.7.2.3/longlong.h which is: */ -/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define BITS_PER_UNIT 8 -#define SI_TYPE_SIZE 32 - -#define __BITS4 (SI_TYPE_SIZE / 4) -#define __ll_B (1L << (SI_TYPE_SIZE / 2)) -#define __ll_lowpart(t) ((USItype) (t) % __ll_B) -#define __ll_highpart(t) ((USItype) (t) / __ll_B) - -#define umul_ppmm(w1, w0, u, v) \ - do { \ - USItype __x0, __x1, __x2, __x3; \ - USItype __ul, __vl, __uh, __vh; \ - \ - __ul = __ll_lowpart (u); \ - __uh = __ll_highpart (u); \ - __vl = __ll_lowpart (v); \ - __vh = __ll_highpart (v); \ - \ - __x0 = (USItype) __ul * __vl; \ - __x1 = (USItype) __ul * __vh; \ - __x2 = (USItype) __uh * __vl; \ - __x3 = (USItype) __uh * __vh; \ - \ - __x1 += __ll_highpart (__x0);/* this can't give carry */ \ - __x1 += __x2; /* but this indeed can */ \ - if (__x1 < __x2) /* did we get it? */ \ - __x3 += __ll_B; /* yes, add it in the proper pos. */ \ - \ - (w1) = __x3 + __ll_highpart (__x1); \ - (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ - } while (0) - -#define __umulsidi3(u, v) \ - ({DIunion __w; \ - umul_ppmm (__w.s.high, __w.s.low, u, v); \ - __w.ll; }) - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); - -struct DIstruct {SItype high, low;}; - -typedef union -{ - struct DIstruct s; - DItype ll; -} DIunion; - -DItype -__muldi3 (DItype u, DItype v) -{ - DIunion w; - DIunion uu, vv; - - uu.ll = u, - vv.ll = v; - - w.ll = __umulsidi3 (uu.s.low, vv.s.low); - w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high - + (USItype) uu.s.high * (USItype) vv.s.low); - - return w.ll; -} diff --git a/arch/m68k/lib/string.c b/arch/m68k/lib/string.c index d399c5f25636..b9a57abfad08 100644 --- a/arch/m68k/lib/string.c +++ b/arch/m68k/lib/string.c @@ -20,226 +20,3 @@ char *strcat(char *dest, const char *src) return __kernel_strcpy(dest + __kernel_strlen(dest), src); } EXPORT_SYMBOL(strcat); - -void *memset(void *s, int c, size_t count) -{ - void *xs = s; - size_t temp, temp1; - - if (!count) - return xs; - c &= 0xff; - c |= c << 8; - c |= c << 16; - if ((long)s & 1) { - char *cs = s; - *cs++ = c; - s = cs; - count--; - } - if (count > 2 && (long)s & 2) { - short *ss = s; - *ss++ = c; - s = ss; - count -= 2; - } - temp = count >> 2; - if (temp) { - long *ls = s; - - asm volatile ( - " movel %1,%2\n" - " andw #7,%2\n" - " lsrl #3,%1\n" - " negw %2\n" - " jmp %%pc@(2f,%2:w:2)\n" - "1: movel %3,%0@+\n" - " movel %3,%0@+\n" - " movel %3,%0@+\n" - " movel %3,%0@+\n" - " movel %3,%0@+\n" - " movel %3,%0@+\n" - " movel %3,%0@+\n" - " movel %3,%0@+\n" - "2: dbra %1,1b\n" - " clrw %1\n" - " subql #1,%1\n" - " jpl 1b" - : "=a" (ls), "=d" (temp), "=&d" (temp1) - : "d" (c), "0" (ls), "1" (temp)); - s = ls; - } - if (count & 2) { - short *ss = s; - *ss++ = c; - s = ss; - } - if (count & 1) { - char *cs = s; - *cs = c; - } - return xs; -} -EXPORT_SYMBOL(memset); - -void *memcpy(void *to, const void *from, size_t n) -{ - void *xto = to; - size_t temp, temp1; - - if (!n) - return xto; - if ((long)to & 1) { - char *cto = to; - const char *cfrom = from; - *cto++ = *cfrom++; - to = cto; - from = cfrom; - n--; - } - if (n > 2 && (long)to & 2) { - short *sto = to; - const short *sfrom = from; - *sto++ = *sfrom++; - to = sto; - from = sfrom; - n -= 2; - } - temp = n >> 2; - if (temp) { - long *lto = to; - const long *lfrom = from; - - asm volatile ( - " movel %2,%3\n" - " andw #7,%3\n" - " lsrl #3,%2\n" - " negw %3\n" - " jmp %%pc@(1f,%3:w:2)\n" - "4: movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - " movel %0@+,%1@+\n" - "1: dbra %2,4b\n" - " clrw %2\n" - " subql #1,%2\n" - " jpl 4b" - : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1) - : "0" (lfrom), "1" (lto), "2" (temp)); - to = lto; - from = lfrom; - } - if (n & 2) { - short *sto = to; - const short *sfrom = from; - *sto++ = *sfrom++; - to = sto; - from = sfrom; - } - if (n & 1) { - char *cto = to; - const char *cfrom = from; - *cto = *cfrom; - } - return xto; -} -EXPORT_SYMBOL(memcpy); - -void *memmove(void *dest, const void *src, size_t n) -{ - void *xdest = dest; - size_t temp; - - if (!n) - return xdest; - - if (dest < src) { - if ((long)dest & 1) { - char *cdest = dest; - const char *csrc = src; - *cdest++ = *csrc++; - dest = cdest; - src = csrc; - n--; - } - if (n > 2 && (long)dest & 2) { - short *sdest = dest; - const short *ssrc = src; - *sdest++ = *ssrc++; - dest = sdest; - src = ssrc; - n -= 2; - } - temp = n >> 2; - if (temp) { - long *ldest = dest; - const long *lsrc = src; - temp--; - do - *ldest++ = *lsrc++; - while (temp--); - dest = ldest; - src = lsrc; - } - if (n & 2) { - short *sdest = dest; - const short *ssrc = src; - *sdest++ = *ssrc++; - dest = sdest; - src = ssrc; - } - if (n & 1) { - char *cdest = dest; - const char *csrc = src; - *cdest = *csrc; - } - } else { - dest = (char *)dest + n; - src = (const char *)src + n; - if ((long)dest & 1) { - char *cdest = dest; - const char *csrc = src; - *--cdest = *--csrc; - dest = cdest; - src = csrc; - n--; - } - if (n > 2 && (long)dest & 2) { - short *sdest = dest; - const short *ssrc = src; - *--sdest = *--ssrc; - dest = sdest; - src = ssrc; - n -= 2; - } - temp = n >> 2; - if (temp) { - long *ldest = dest; - const long *lsrc = src; - temp--; - do - *--ldest = *--lsrc; - while (temp--); - dest = ldest; - src = lsrc; - } - if (n & 2) { - short *sdest = dest; - const short *ssrc = src; - *--sdest = *--ssrc; - dest = sdest; - src = ssrc; - } - if (n & 1) { - char *cdest = dest; - const char *csrc = src; - *--cdest = *--csrc; - } - } - return xdest; -} -EXPORT_SYMBOL(memmove); diff --git a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile index b60270e4954b..09cadf1058d5 100644 --- a/arch/m68k/mm/Makefile +++ b/arch/m68k/mm/Makefile @@ -1,5 +1,9 @@ -ifdef CONFIG_MMU -include arch/m68k/mm/Makefile_mm -else -include arch/m68k/mm/Makefile_no -endif +# +# Makefile for the linux m68k-specific parts of the memory manager. +# + +obj-y := init.o + +obj-$(CONFIG_MMU) += cache.o fault.o hwtest.o +obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o +obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o diff --git a/arch/m68k/mm/Makefile_mm b/arch/m68k/mm/Makefile_mm deleted file mode 100644 index 5eaa43c4cb3c..000000000000 --- a/arch/m68k/mm/Makefile_mm +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the linux m68k-specific parts of the memory manager. -# - -obj-y := cache.o init.o fault.o hwtest.o - -obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o -obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o diff --git a/arch/m68k/mm/Makefile_no b/arch/m68k/mm/Makefile_no deleted file mode 100644 index b54ab6b4b523..000000000000 --- a/arch/m68k/mm/Makefile_no +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux m68knommu specific parts of the memory manager. -# - -obj-y += init.o kmap.o diff --git a/arch/m68k/mm/init_mm.c b/arch/m68k/mm/init_mm.c index 8bc842554e5b..9113c2f17607 100644 --- a/arch/m68k/mm/init_mm.c +++ b/arch/m68k/mm/init_mm.c @@ -32,8 +32,6 @@ #include <asm/sections.h> #include <asm/tlb.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - pg_data_t pg_data_map[MAX_NUMNODES]; EXPORT_SYMBOL(pg_data_map); diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c index 8a6653f56bd8..7cbd7bd1f8bc 100644 --- a/arch/m68k/mm/init_no.c +++ b/arch/m68k/mm/init_no.c @@ -38,28 +38,10 @@ #include <asm/system.h> #include <asm/machdep.h> -#undef DEBUG - -extern void die_if_kernel(char *,struct pt_regs *,long); -extern void free_initmem(void); - /* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving a inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -static unsigned long empty_bad_page_table; - -static unsigned long empty_bad_page; - unsigned long empty_zero_page; extern unsigned long memory_start; @@ -77,22 +59,9 @@ void __init paging_init(void) * Make sure start_mem is page aligned, otherwise bootmem and * page_alloc get different views of the world. */ -#ifdef DEBUG - unsigned long start_mem = PAGE_ALIGN(memory_start); -#endif unsigned long end_mem = memory_end & PAGE_MASK; + unsigned long zones_size[MAX_NR_ZONES] = {0, }; -#ifdef DEBUG - printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n", - start_mem, end_mem); -#endif - - /* - * Initialize the bad page table and bad page to point - * to a couple of allocated pages. - */ - empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); memset((void *)empty_zero_page, 0, PAGE_SIZE); @@ -101,19 +70,8 @@ void __init paging_init(void) */ set_fs (USER_DS); -#ifdef DEBUG - printk (KERN_DEBUG "before free_area_init\n"); - - printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n", - start_mem, end_mem); -#endif - - { - unsigned long zones_size[MAX_NR_ZONES] = {0, }; - - zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; - free_area_init(zones_size); - } + zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; + free_area_init(zones_size); } void __init mem_init(void) @@ -166,8 +124,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) } #endif -void -free_initmem() +void free_initmem(void) { #ifdef CONFIG_RAMKERNEL unsigned long addr; diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index a373d136b2b2..69345849454b 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -1,5 +1,367 @@ -#ifdef CONFIG_MMU -#include "kmap_mm.c" +/* + * linux/arch/m68k/mm/kmap.c + * + * Copyright (C) 1997 Roman Hodek + * + * 10/01/99 cleaned up the code and changing to the same interface + * used by other architectures /Roman Zippel + */ + +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> + +#include <asm/setup.h> +#include <asm/segment.h> +#include <asm/page.h> +#include <asm/pgalloc.h> +#include <asm/io.h> +#include <asm/system.h> + +#undef DEBUG + +#define PTRTREESIZE (256*1024) + +/* + * For 040/060 we can use the virtual memory area like other architectures, + * but for 020/030 we want to use early termination page descriptor and we + * can't mix this with normal page descriptors, so we have to copy that code + * (mm/vmalloc.c) and return appriorate aligned addresses. + */ + +#ifdef CPU_M68040_OR_M68060_ONLY + +#define IO_SIZE PAGE_SIZE + +static inline struct vm_struct *get_io_area(unsigned long size) +{ + return get_vm_area(size, VM_IOREMAP); +} + + +static inline void free_io_area(void *addr) +{ + vfree((void *)(PAGE_MASK & (unsigned long)addr)); +} + #else -#include "kmap_no.c" + +#define IO_SIZE (256*1024) + +static struct vm_struct *iolist; + +static struct vm_struct *get_io_area(unsigned long size) +{ + unsigned long addr; + struct vm_struct **p, *tmp, *area; + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + return NULL; + addr = KMAP_START; + for (p = &iolist; (tmp = *p) ; p = &tmp->next) { + if (size + addr < (unsigned long)tmp->addr) + break; + if (addr > KMAP_END-size) { + kfree(area); + return NULL; + } + addr = tmp->size + (unsigned long)tmp->addr; + } + area->addr = (void *)addr; + area->size = size + IO_SIZE; + area->next = *p; + *p = area; + return area; +} + +static inline void free_io_area(void *addr) +{ + struct vm_struct **p, *tmp; + + if (!addr) + return; + addr = (void *)((unsigned long)addr & -IO_SIZE); + for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { + if (tmp->addr == addr) { + *p = tmp->next; + __iounmap(tmp->addr, tmp->size); + kfree(tmp); + return; + } + } +} + #endif + +/* + * Map some physical address range into the kernel address space. + */ +/* Rewritten by Andreas Schwab to remove all races. */ + +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +{ + struct vm_struct *area; + unsigned long virtaddr, retaddr; + long offset; + pgd_t *pgd_dir; + pmd_t *pmd_dir; + pte_t *pte_dir; + + /* + * Don't allow mappings that wrap.. + */ + if (!size || physaddr > (unsigned long)(-size)) + return NULL; + +#ifdef CONFIG_AMIGA + if (MACH_IS_AMIGA) { + if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) + && (cacheflag == IOMAP_NOCACHE_SER)) + return (void __iomem *)physaddr; + } +#endif + +#ifdef DEBUG + printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag); +#endif + /* + * Mappings have to be aligned + */ + offset = physaddr & (IO_SIZE - 1); + physaddr &= -IO_SIZE; + size = (size + offset + IO_SIZE - 1) & -IO_SIZE; + + /* + * Ok, go for it.. + */ + area = get_io_area(size); + if (!area) + return NULL; + + virtaddr = (unsigned long)area->addr; + retaddr = virtaddr + offset; +#ifdef DEBUG + printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr); +#endif + + /* + * add cache and table flags to physical address + */ + if (CPU_IS_040_OR_060) { + physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 | + _PAGE_ACCESSED | _PAGE_DIRTY); + switch (cacheflag) { + case IOMAP_FULL_CACHING: + physaddr |= _PAGE_CACHE040; + break; + case IOMAP_NOCACHE_SER: + default: + physaddr |= _PAGE_NOCACHE_S; + break; + case IOMAP_NOCACHE_NONSER: + physaddr |= _PAGE_NOCACHE; + break; + case IOMAP_WRITETHROUGH: + physaddr |= _PAGE_CACHE040W; + break; + } + } else { + physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); + switch (cacheflag) { + case IOMAP_NOCACHE_SER: + case IOMAP_NOCACHE_NONSER: + default: + physaddr |= _PAGE_NOCACHE030; + break; + case IOMAP_FULL_CACHING: + case IOMAP_WRITETHROUGH: + break; + } + } + + while ((long)size > 0) { +#ifdef DEBUG + if (!(virtaddr & (PTRTREESIZE-1))) + printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr); +#endif + pgd_dir = pgd_offset_k(virtaddr); + pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr); + if (!pmd_dir) { + printk("ioremap: no mem for pmd_dir\n"); + return NULL; + } + + if (CPU_IS_020_OR_030) { + pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr; + physaddr += PTRTREESIZE; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + } else { + pte_dir = pte_alloc_kernel(pmd_dir, virtaddr); + if (!pte_dir) { + printk("ioremap: no mem for pte_dir\n"); + return NULL; + } + + pte_val(*pte_dir) = physaddr; + virtaddr += PAGE_SIZE; + physaddr += PAGE_SIZE; + size -= PAGE_SIZE; + } + } +#ifdef DEBUG + printk("\n"); +#endif + flush_tlb_all(); + + return (void __iomem *)retaddr; +} +EXPORT_SYMBOL(__ioremap); + +/* + * Unmap a ioremap()ed region again + */ +void iounmap(void __iomem *addr) +{ +#ifdef CONFIG_AMIGA + if ((!MACH_IS_AMIGA) || + (((unsigned long)addr < 0x40000000) || + ((unsigned long)addr > 0x60000000))) + free_io_area((__force void *)addr); +#else + free_io_area((__force void *)addr); +#endif +} +EXPORT_SYMBOL(iounmap); + +/* + * __iounmap unmaps nearly everything, so be careful + * it doesn't free currently pointer/page tables anymore but it + * wans't used anyway and might be added later. + */ +void __iounmap(void *addr, unsigned long size) +{ + unsigned long virtaddr = (unsigned long)addr; + pgd_t *pgd_dir; + pmd_t *pmd_dir; + pte_t *pte_dir; + + while ((long)size > 0) { + pgd_dir = pgd_offset_k(virtaddr); + if (pgd_bad(*pgd_dir)) { + printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); + pgd_clear(pgd_dir); + return; + } + pmd_dir = pmd_offset(pgd_dir, virtaddr); + + if (CPU_IS_020_OR_030) { + int pmd_off = (virtaddr/PTRTREESIZE) & 15; + int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK; + + if (pmd_type == _PAGE_PRESENT) { + pmd_dir->pmd[pmd_off] = 0; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + continue; + } else if (pmd_type == 0) + continue; + } + + if (pmd_bad(*pmd_dir)) { + printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); + pmd_clear(pmd_dir); + return; + } + pte_dir = pte_offset_kernel(pmd_dir, virtaddr); + + pte_val(*pte_dir) = 0; + virtaddr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + flush_tlb_all(); +} + +/* + * Set new cache mode for some kernel address space. + * The caller must push data for that range itself, if such data may already + * be in the cache. + */ +void kernel_set_cachemode(void *addr, unsigned long size, int cmode) +{ + unsigned long virtaddr = (unsigned long)addr; + pgd_t *pgd_dir; + pmd_t *pmd_dir; + pte_t *pte_dir; + + if (CPU_IS_040_OR_060) { + switch (cmode) { + case IOMAP_FULL_CACHING: + cmode = _PAGE_CACHE040; + break; + case IOMAP_NOCACHE_SER: + default: + cmode = _PAGE_NOCACHE_S; + break; + case IOMAP_NOCACHE_NONSER: + cmode = _PAGE_NOCACHE; + break; + case IOMAP_WRITETHROUGH: + cmode = _PAGE_CACHE040W; + break; + } + } else { + switch (cmode) { + case IOMAP_NOCACHE_SER: + case IOMAP_NOCACHE_NONSER: + default: + cmode = _PAGE_NOCACHE030; + break; + case IOMAP_FULL_CACHING: + case IOMAP_WRITETHROUGH: + cmode = 0; + } + } + + while ((long)size > 0) { + pgd_dir = pgd_offset_k(virtaddr); + if (pgd_bad(*pgd_dir)) { + printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); + pgd_clear(pgd_dir); + return; + } + pmd_dir = pmd_offset(pgd_dir, virtaddr); + + if (CPU_IS_020_OR_030) { + int pmd_off = (virtaddr/PTRTREESIZE) & 15; + + if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { + pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] & + _CACHEMASK040) | cmode; + virtaddr += PTRTREESIZE; + size -= PTRTREESIZE; + continue; + } + } + + if (pmd_bad(*pmd_dir)) { + printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); + pmd_clear(pmd_dir); + return; + } + pte_dir = pte_offset_kernel(pmd_dir, virtaddr); + + pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode; + virtaddr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + flush_tlb_all(); +} +EXPORT_SYMBOL(kernel_set_cachemode); diff --git a/arch/m68k/mm/kmap_mm.c b/arch/m68k/mm/kmap_mm.c deleted file mode 100644 index 69345849454b..000000000000 --- a/arch/m68k/mm/kmap_mm.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * linux/arch/m68k/mm/kmap.c - * - * Copyright (C) 1997 Roman Hodek - * - * 10/01/99 cleaned up the code and changing to the same interface - * used by other architectures /Roman Zippel - */ - -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> - -#include <asm/setup.h> -#include <asm/segment.h> -#include <asm/page.h> -#include <asm/pgalloc.h> -#include <asm/io.h> -#include <asm/system.h> - -#undef DEBUG - -#define PTRTREESIZE (256*1024) - -/* - * For 040/060 we can use the virtual memory area like other architectures, - * but for 020/030 we want to use early termination page descriptor and we - * can't mix this with normal page descriptors, so we have to copy that code - * (mm/vmalloc.c) and return appriorate aligned addresses. - */ - -#ifdef CPU_M68040_OR_M68060_ONLY - -#define IO_SIZE PAGE_SIZE - -static inline struct vm_struct *get_io_area(unsigned long size) -{ - return get_vm_area(size, VM_IOREMAP); -} - - -static inline void free_io_area(void *addr) -{ - vfree((void *)(PAGE_MASK & (unsigned long)addr)); -} - -#else - -#define IO_SIZE (256*1024) - -static struct vm_struct *iolist; - -static struct vm_struct *get_io_area(unsigned long size) -{ - unsigned long addr; - struct vm_struct **p, *tmp, *area; - - area = kmalloc(sizeof(*area), GFP_KERNEL); - if (!area) - return NULL; - addr = KMAP_START; - for (p = &iolist; (tmp = *p) ; p = &tmp->next) { - if (size + addr < (unsigned long)tmp->addr) - break; - if (addr > KMAP_END-size) { - kfree(area); - return NULL; - } - addr = tmp->size + (unsigned long)tmp->addr; - } - area->addr = (void *)addr; - area->size = size + IO_SIZE; - area->next = *p; - *p = area; - return area; -} - -static inline void free_io_area(void *addr) -{ - struct vm_struct **p, *tmp; - - if (!addr) - return; - addr = (void *)((unsigned long)addr & -IO_SIZE); - for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { - if (tmp->addr == addr) { - *p = tmp->next; - __iounmap(tmp->addr, tmp->size); - kfree(tmp); - return; - } - } -} - -#endif - -/* - * Map some physical address range into the kernel address space. - */ -/* Rewritten by Andreas Schwab to remove all races. */ - -void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) -{ - struct vm_struct *area; - unsigned long virtaddr, retaddr; - long offset; - pgd_t *pgd_dir; - pmd_t *pmd_dir; - pte_t *pte_dir; - - /* - * Don't allow mappings that wrap.. - */ - if (!size || physaddr > (unsigned long)(-size)) - return NULL; - -#ifdef CONFIG_AMIGA - if (MACH_IS_AMIGA) { - if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000) - && (cacheflag == IOMAP_NOCACHE_SER)) - return (void __iomem *)physaddr; - } -#endif - -#ifdef DEBUG - printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag); -#endif - /* - * Mappings have to be aligned - */ - offset = physaddr & (IO_SIZE - 1); - physaddr &= -IO_SIZE; - size = (size + offset + IO_SIZE - 1) & -IO_SIZE; - - /* - * Ok, go for it.. - */ - area = get_io_area(size); - if (!area) - return NULL; - - virtaddr = (unsigned long)area->addr; - retaddr = virtaddr + offset; -#ifdef DEBUG - printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr); -#endif - - /* - * add cache and table flags to physical address - */ - if (CPU_IS_040_OR_060) { - physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 | - _PAGE_ACCESSED | _PAGE_DIRTY); - switch (cacheflag) { - case IOMAP_FULL_CACHING: - physaddr |= _PAGE_CACHE040; - break; - case IOMAP_NOCACHE_SER: - default: - physaddr |= _PAGE_NOCACHE_S; - break; - case IOMAP_NOCACHE_NONSER: - physaddr |= _PAGE_NOCACHE; - break; - case IOMAP_WRITETHROUGH: - physaddr |= _PAGE_CACHE040W; - break; - } - } else { - physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); - switch (cacheflag) { - case IOMAP_NOCACHE_SER: - case IOMAP_NOCACHE_NONSER: - default: - physaddr |= _PAGE_NOCACHE030; - break; - case IOMAP_FULL_CACHING: - case IOMAP_WRITETHROUGH: - break; - } - } - - while ((long)size > 0) { -#ifdef DEBUG - if (!(virtaddr & (PTRTREESIZE-1))) - printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr); -#endif - pgd_dir = pgd_offset_k(virtaddr); - pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr); - if (!pmd_dir) { - printk("ioremap: no mem for pmd_dir\n"); - return NULL; - } - - if (CPU_IS_020_OR_030) { - pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr; - physaddr += PTRTREESIZE; - virtaddr += PTRTREESIZE; - size -= PTRTREESIZE; - } else { - pte_dir = pte_alloc_kernel(pmd_dir, virtaddr); - if (!pte_dir) { - printk("ioremap: no mem for pte_dir\n"); - return NULL; - } - - pte_val(*pte_dir) = physaddr; - virtaddr += PAGE_SIZE; - physaddr += PAGE_SIZE; - size -= PAGE_SIZE; - } - } -#ifdef DEBUG - printk("\n"); -#endif - flush_tlb_all(); - - return (void __iomem *)retaddr; -} -EXPORT_SYMBOL(__ioremap); - -/* - * Unmap a ioremap()ed region again - */ -void iounmap(void __iomem *addr) -{ -#ifdef CONFIG_AMIGA - if ((!MACH_IS_AMIGA) || - (((unsigned long)addr < 0x40000000) || - ((unsigned long)addr > 0x60000000))) - free_io_area((__force void *)addr); -#else - free_io_area((__force void *)addr); -#endif -} -EXPORT_SYMBOL(iounmap); - -/* - * __iounmap unmaps nearly everything, so be careful - * it doesn't free currently pointer/page tables anymore but it - * wans't used anyway and might be added later. - */ -void __iounmap(void *addr, unsigned long size) -{ - unsigned long virtaddr = (unsigned long)addr; - pgd_t *pgd_dir; - pmd_t *pmd_dir; - pte_t *pte_dir; - - while ((long)size > 0) { - pgd_dir = pgd_offset_k(virtaddr); - if (pgd_bad(*pgd_dir)) { - printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); - pgd_clear(pgd_dir); - return; - } - pmd_dir = pmd_offset(pgd_dir, virtaddr); - - if (CPU_IS_020_OR_030) { - int pmd_off = (virtaddr/PTRTREESIZE) & 15; - int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK; - - if (pmd_type == _PAGE_PRESENT) { - pmd_dir->pmd[pmd_off] = 0; - virtaddr += PTRTREESIZE; - size -= PTRTREESIZE; - continue; - } else if (pmd_type == 0) - continue; - } - - if (pmd_bad(*pmd_dir)) { - printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); - pmd_clear(pmd_dir); - return; - } - pte_dir = pte_offset_kernel(pmd_dir, virtaddr); - - pte_val(*pte_dir) = 0; - virtaddr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - flush_tlb_all(); -} - -/* - * Set new cache mode for some kernel address space. - * The caller must push data for that range itself, if such data may already - * be in the cache. - */ -void kernel_set_cachemode(void *addr, unsigned long size, int cmode) -{ - unsigned long virtaddr = (unsigned long)addr; - pgd_t *pgd_dir; - pmd_t *pmd_dir; - pte_t *pte_dir; - - if (CPU_IS_040_OR_060) { - switch (cmode) { - case IOMAP_FULL_CACHING: - cmode = _PAGE_CACHE040; - break; - case IOMAP_NOCACHE_SER: - default: - cmode = _PAGE_NOCACHE_S; - break; - case IOMAP_NOCACHE_NONSER: - cmode = _PAGE_NOCACHE; - break; - case IOMAP_WRITETHROUGH: - cmode = _PAGE_CACHE040W; - break; - } - } else { - switch (cmode) { - case IOMAP_NOCACHE_SER: - case IOMAP_NOCACHE_NONSER: - default: - cmode = _PAGE_NOCACHE030; - break; - case IOMAP_FULL_CACHING: - case IOMAP_WRITETHROUGH: - cmode = 0; - } - } - - while ((long)size > 0) { - pgd_dir = pgd_offset_k(virtaddr); - if (pgd_bad(*pgd_dir)) { - printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir)); - pgd_clear(pgd_dir); - return; - } - pmd_dir = pmd_offset(pgd_dir, virtaddr); - - if (CPU_IS_020_OR_030) { - int pmd_off = (virtaddr/PTRTREESIZE) & 15; - - if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { - pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] & - _CACHEMASK040) | cmode; - virtaddr += PTRTREESIZE; - size -= PTRTREESIZE; - continue; - } - } - - if (pmd_bad(*pmd_dir)) { - printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir)); - pmd_clear(pmd_dir); - return; - } - pte_dir = pte_offset_kernel(pmd_dir, virtaddr); - - pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode; - virtaddr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - flush_tlb_all(); -} -EXPORT_SYMBOL(kernel_set_cachemode); diff --git a/arch/m68k/mm/kmap_no.c b/arch/m68k/mm/kmap_no.c deleted file mode 100644 index ece8d5ad4e6c..000000000000 --- a/arch/m68k/mm/kmap_no.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/arch/m68knommu/mm/kmap.c - * - * Copyright (C) 2000 Lineo, <davidm@snapgear.com> - * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com> - */ - -#include <linux/mm.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/vmalloc.h> - -#include <asm/setup.h> -#include <asm/segment.h> -#include <asm/page.h> -#include <asm/pgalloc.h> -#include <asm/io.h> -#include <asm/system.h> - -#undef DEBUG - -/* - * Map some physical address range into the kernel address space. - */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) -{ - return (void *)physaddr; -} - -/* - * Unmap a ioremap()ed region again. - */ -void iounmap(void *addr) -{ -} - -/* - * Set new cache mode for some kernel address space. - * The caller must push data for that range itself, if such data may already - * be in the cache. - */ -void kernel_set_cachemode(void *addr, unsigned long size, int cmode) -{ -} diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S index 676960cf022a..f68dce766c0a 100644 --- a/arch/m68k/platform/68328/entry.S +++ b/arch/m68k/platform/68328/entry.S @@ -10,7 +10,6 @@ * Linux/m68k support by Hamish Macdonald */ -#include <linux/sys.h> #include <linux/linkage.h> #include <asm/thread_info.h> #include <asm/unistd.h> @@ -80,7 +79,7 @@ ENTRY(system_call) movel %sp,%d1 /* get thread_info pointer */ andl #-THREAD_SIZE,%d1 movel %d1,%a2 - btst #(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8) + btst #(TIF_SYSCALL_TRACE%8),%a2@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8) jne do_trace cmpl #NR_syscalls,%d0 jcc badsys @@ -107,12 +106,12 @@ Luser_return: andl #-THREAD_SIZE,%d1 movel %d1,%a2 1: - move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + move %a2@(TINFO_FLAGS),%d1 /* thread_info->flags */ jne Lwork_to_do RESTORE_ALL Lwork_to_do: - movel %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + movel %a2@(TINFO_FLAGS),%d1 /* thread_info->flags */ btst #TIF_NEED_RESCHED,%d1 jne reschedule diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S index 46c1b18c9dcb..a07b14feed92 100644 --- a/arch/m68k/platform/68360/entry.S +++ b/arch/m68k/platform/68360/entry.S @@ -12,7 +12,6 @@ * M68360 Port by SED Systems, and Lineo. */ -#include <linux/sys.h> #include <linux/linkage.h> #include <asm/thread_info.h> #include <asm/unistd.h> @@ -76,7 +75,7 @@ ENTRY(system_call) movel %sp,%d1 /* get thread_info pointer */ andl #-THREAD_SIZE,%d1 movel %d1,%a2 - btst #(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8) + btst #(TIF_SYSCALL_TRACE%8),%a2@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8) jne do_trace cmpl #NR_syscalls,%d0 jcc badsys @@ -103,12 +102,12 @@ Luser_return: andl #-THREAD_SIZE,%d1 movel %d1,%a2 1: - move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + move %a2@(TINFO_FLAGS),%d1 /* thread_info->flags */ jne Lwork_to_do RESTORE_ALL Lwork_to_do: - movel %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + movel %a2@(TINFO_FLAGS),%d1 /* thread_info->flags */ btst #TIF_NEED_RESCHED,%d1 jne reschedule diff --git a/arch/m68k/platform/coldfire/dma.c b/arch/m68k/platform/coldfire/dma.c index e88b95e2cc62..df5ce20d181c 100644 --- a/arch/m68k/platform/coldfire/dma.c +++ b/arch/m68k/platform/coldfire/dma.c @@ -9,6 +9,7 @@ /***************************************************************************/ #include <linux/kernel.h> +#include <linux/module.h> #include <asm/dma.h> #include <asm/coldfire.h> #include <asm/mcfsim.h> @@ -33,7 +34,9 @@ unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { MCFDMA_BASE3, #endif }; +EXPORT_SYMBOL(dma_base_addr); unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; +EXPORT_SYMBOL(dma_device_address); /***************************************************************************/ diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S index eab63f09965b..27c2b001161e 100644 --- a/arch/m68k/platform/coldfire/entry.S +++ b/arch/m68k/platform/coldfire/entry.S @@ -26,7 +26,6 @@ * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be> */ -#include <linux/sys.h> #include <linux/linkage.h> #include <asm/unistd.h> #include <asm/thread_info.h> @@ -78,7 +77,7 @@ ENTRY(system_call) movel %d2,%a0 movel %a0@,%a1 /* save top of frame */ movel %sp,%a1@(TASK_THREAD+THREAD_ESP0) - btst #(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8) + btst #(TIF_SYSCALL_TRACE%8),%a0@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8) bnes 1f movel %d3,%a0 @@ -113,11 +112,11 @@ ret_from_exception: movel %sp,%d1 /* get thread_info pointer */ andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ movel %d1,%a0 - movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ + movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */ andl #(1<<TIF_NEED_RESCHED),%d1 jeq Lkernel_return - movel %a0@(TI_PREEMPTCOUNT),%d1 + movel %a0@(TINFO_PREEMPT),%d1 cmpl #0,%d1 jne Lkernel_return @@ -137,14 +136,14 @@ Luser_return: movel %sp,%d1 /* get thread_info pointer */ andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ movel %d1,%a0 - movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ + movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */ jne Lwork_to_do /* still work to do */ Lreturn: RESTORE_USER Lwork_to_do: - movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ + movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */ move #0x2000,%sr /* enable intrs again */ btst #TIF_NEED_RESCHED,%d1 jne reschedule diff --git a/arch/m68k/platform/coldfire/head.S b/arch/m68k/platform/coldfire/head.S index 6ae91a499184..c33483824a2e 100644 --- a/arch/m68k/platform/coldfire/head.S +++ b/arch/m68k/platform/coldfire/head.S @@ -8,7 +8,6 @@ /*****************************************************************************/ -#include <linux/sys.h> #include <linux/linkage.h> #include <linux/init.h> #include <asm/asm-offsets.h> diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index c8437866d3b7..213f2d671669 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -32,8 +32,6 @@ unsigned int __page_offset; EXPORT_SYMBOL(__page_offset); #else -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - static int init_bootmem_done; #endif /* CONFIG_MMU */ diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 5358f90b4dd2..83ed00a5644a 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug @@ -76,15 +76,6 @@ config DEBUG_STACKOVERFLOW provides another way to check stack overflow happened on kernel mode stack usually caused by nested interruption. -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config SMTC_IDLE_HOOK_DEBUG bool "Enable additional debug checks before going into CPU idle loop" depends on DEBUG_KERNEL && MIPS_MT_SMTC diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 01af3876cf90..a81176f44c74 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -118,7 +118,7 @@ SECTIONS EXIT_DATA } - PERCPU(1 << CONFIG_MIPS_L1_CACHE_SHIFT, PAGE_SIZE) + PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT) . = ALIGN(PAGE_SIZE); __init_end = .; /* freed after init ends here */ diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 279599e9a779..1aadeb42c5a5 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -64,8 +64,6 @@ #endif /* CONFIG_MIPS_MT_SMTC */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * We have up to 8 empty zeroed pages so we can map one of the right colour * when needed. This is necessary only on R4000 / R4400 SC and MC versions diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 86af0d7d0771..2623d19f4f4c 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -87,7 +87,7 @@ static void mn10300_cpupic_mask_ack(struct irq_data *d) tmp2 = GxICR(irq); irq_affinity_online[irq] = - any_online_cpu(*d->affinity); + cpumask_any_and(d->affinity, cpu_online_mask); CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); @@ -124,7 +124,8 @@ static void mn10300_cpupic_unmask_clear(struct irq_data *d) } else { tmp = GxICR(irq); - irq_affinity_online[irq] = any_online_cpu(*d->affinity); + irq_affinity_online[irq] = cpumask_any_and(d->affinity, + cpu_online_mask); CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); } @@ -366,11 +367,11 @@ void migrate_irqs(void) if (irqd_is_per_cpu(data)) continue; - if (cpu_isset(self, data->affinity) && - !cpus_intersects(irq_affinity[irq], cpu_online_map)) { + if (cpumask_test_cpu(self, &data->affinity) && + !cpumask_intersects(&irq_affinity[irq], cpu_online_mask)) { int cpu_id; - cpu_id = first_cpu(cpu_online_map); - cpu_set(cpu_id, data->affinity); + cpu_id = cpumask_first(cpu_online_mask); + cpumask_set_cpu(cpu_id, &data->affinity); } /* We need to operate irq_affinity_online atomically. */ arch_local_cli_save(flags); @@ -381,7 +382,8 @@ void migrate_irqs(void) GxICR(irq) = x & GxICR_LEVEL; tmp = GxICR(irq); - new = any_online_cpu(data->affinity); + new = cpumask_any_and(&data->affinity, + cpu_online_mask); irq_affinity_online[irq] = new; CROSS_GxICR(irq, new) = diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 83fb27912231..9242e9fcc564 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c @@ -309,7 +309,7 @@ static void send_IPI_mask(const cpumask_t *cpumask, int irq) u16 tmp; for (i = 0; i < NR_CPUS; i++) { - if (cpu_isset(i, *cpumask)) { + if (cpumask_test_cpu(i, cpumask)) { /* send IPI */ tmp = CROSS_GxICR(irq, i); CROSS_GxICR(irq, i) = @@ -342,8 +342,8 @@ void send_IPI_allbutself(int irq) { cpumask_t cpumask; - cpumask = cpu_online_map; - cpu_clear(smp_processor_id(), cpumask); + cpumask_copy(&cpumask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &cpumask); send_IPI_mask(&cpumask, irq); } @@ -393,8 +393,8 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait) data.func = func; data.info = info; - data.started = cpu_online_map; - cpu_clear(smp_processor_id(), data.started); + cpumask_copy(&data.started, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &data.started); data.wait = wait; if (wait) data.finished = data.started; @@ -410,14 +410,14 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait) if (CALL_FUNCTION_NMI_IPI_TIMEOUT > 0) { for (cnt = 0; cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT && - !cpus_empty(data.started); + !cpumask_empty(&data.started); cnt++) mdelay(1); if (wait && cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT) { for (cnt = 0; cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT && - !cpus_empty(data.finished); + !cpumask_empty(&data.finished); cnt++) mdelay(1); } @@ -428,10 +428,10 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait) } else { /* If timeout value is zero, wait until cpumask has been * cleared */ - while (!cpus_empty(data.started)) + while (!cpumask_empty(&data.started)) barrier(); if (wait) - while (!cpus_empty(data.finished)) + while (!cpumask_empty(&data.finished)) barrier(); } @@ -472,12 +472,12 @@ void stop_this_cpu(void *unused) #endif /* CONFIG_GDBSTUB */ flags = arch_local_cli_save(); - cpu_clear(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), false); while (!stopflag) cpu_relax(); - cpu_set(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), true); arch_local_irq_restore(flags); } @@ -529,12 +529,13 @@ void smp_nmi_call_function_interrupt(void) * execute the function */ smp_mb(); - cpu_clear(smp_processor_id(), nmi_call_data->started); + cpumask_clear_cpu(smp_processor_id(), &nmi_call_data->started); (*func)(info); if (wait) { smp_mb(); - cpu_clear(smp_processor_id(), nmi_call_data->finished); + cpumask_clear_cpu(smp_processor_id(), + &nmi_call_data->finished); } } @@ -657,7 +658,7 @@ int __init start_secondary(void *unused) { smp_cpu_init(); smp_callin(); - while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) + while (!cpumask_test_cpu(smp_processor_id(), &smp_commenced_mask)) cpu_relax(); local_flush_tlb(); @@ -780,13 +781,14 @@ static int __init do_boot_cpu(int phy_id) if (send_status == 0) { /* Allow AP to start initializing */ - cpu_set(cpu_id, cpu_callout_map); + cpumask_set_cpu(cpu_id, &cpu_callout_map); /* Wait for setting cpu_callin_map */ timeout = 0; do { udelay(1000); - callin_status = cpu_isset(cpu_id, cpu_callin_map); + callin_status = cpumask_test_cpu(cpu_id, + &cpu_callin_map); } while (callin_status == 0 && timeout++ < 5000); if (callin_status == 0) @@ -796,9 +798,9 @@ static int __init do_boot_cpu(int phy_id) } if (send_status == GxICR_REQUEST || callin_status == 0) { - cpu_clear(cpu_id, cpu_callout_map); - cpu_clear(cpu_id, cpu_callin_map); - cpu_clear(cpu_id, cpu_initialized); + cpumask_clear_cpu(cpu_id, &cpu_callout_map); + cpumask_clear_cpu(cpu_id, &cpu_callin_map); + cpumask_clear_cpu(cpu_id, &cpu_initialized); cpucount--; return 1; } @@ -833,7 +835,7 @@ static void __init smp_callin(void) cpu = smp_processor_id(); timeout = jiffies + (2 * HZ); - if (cpu_isset(cpu, cpu_callin_map)) { + if (cpumask_test_cpu(cpu, &cpu_callin_map)) { printk(KERN_ERR "CPU#%d already present.\n", cpu); BUG(); } @@ -841,7 +843,7 @@ static void __init smp_callin(void) /* Wait for AP startup 2s total */ while (time_before(jiffies, timeout)) { - if (cpu_isset(cpu, cpu_callout_map)) + if (cpumask_test_cpu(cpu, &cpu_callout_map)) break; cpu_relax(); } @@ -861,11 +863,11 @@ static void __init smp_callin(void) smp_store_cpu_info(cpu); /* Allow the boot processor to continue */ - cpu_set(cpu, cpu_callin_map); + cpumask_set_cpu(cpu, &cpu_callin_map); } /** - * smp_online - Set cpu_online_map + * smp_online - Set cpu_online_mask */ static void __init smp_online(void) { @@ -875,7 +877,7 @@ static void __init smp_online(void) local_irq_enable(); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); smp_wmb(); } @@ -892,13 +894,13 @@ void __init smp_cpus_done(unsigned int max_cpus) /* * smp_prepare_boot_cpu - Set up stuff for the boot processor. * - * Set up the cpu_online_map, cpu_callout_map and cpu_callin_map of the boot + * Set up the cpu_online_mask, cpu_callout_map and cpu_callin_map of the boot * processor (CPU 0). */ void __devinit smp_prepare_boot_cpu(void) { - cpu_set(0, cpu_callout_map); - cpu_set(0, cpu_callin_map); + cpumask_set_cpu(0, &cpu_callout_map); + cpumask_set_cpu(0, &cpu_callin_map); current_thread_info()->cpu = 0; } @@ -931,16 +933,16 @@ int __devinit __cpu_up(unsigned int cpu) run_wakeup_cpu(cpu); #endif /* CONFIG_HOTPLUG_CPU */ - cpu_set(cpu, smp_commenced_mask); + cpumask_set_cpu(cpu, &smp_commenced_mask); /* Wait 5s total for a response */ for (timeout = 0 ; timeout < 5000 ; timeout++) { - if (cpu_isset(cpu, cpu_online_map)) + if (cpu_online(cpu)) break; udelay(1000); } - BUG_ON(!cpu_isset(cpu, cpu_online_map)); + BUG_ON(!cpu_online(cpu)); return 0; } @@ -986,7 +988,7 @@ int __cpu_disable(void) return -EBUSY; migrate_irqs(); - cpu_clear(cpu, current->active_mm->cpu_vm_mask); + cpumask_clear_cpu(cpu, &mm_cpumask(current->active_mm)); return 0; } @@ -1091,13 +1093,13 @@ static int hotplug_cpu_nmi_call_function(cpumask_t cpumask, do { mn10300_local_dcache_inv_range(start, end); barrier(); - } while (!cpus_empty(nmi_call_func_mask_data.started)); + } while (!cpumask_empty(&nmi_call_func_mask_data.started)); if (wait) { do { mn10300_local_dcache_inv_range(start, end); barrier(); - } while (!cpus_empty(nmi_call_func_mask_data.finished)); + } while (!cpumask_empty(&nmi_call_func_mask_data.finished)); } spin_unlock(&smp_nmi_call_lock); @@ -1108,9 +1110,9 @@ static void restart_wakeup_cpu(void) { unsigned int cpu = smp_processor_id(); - cpu_set(cpu, cpu_callin_map); + cpumask_set_cpu(cpu, &cpu_callin_map); local_flush_tlb(); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); smp_wmb(); } @@ -1141,8 +1143,9 @@ static void sleep_cpu(void *unused) static void run_sleep_cpu(unsigned int cpu) { unsigned long flags; - cpumask_t cpumask = cpumask_of(cpu); + cpumask_t cpumask; + cpumask_copy(&cpumask, &cpumask_of(cpu)); flags = arch_local_cli_save(); hotplug_cpu_nmi_call_function(cpumask, prepare_sleep_cpu, NULL, 1); hotplug_cpu_nmi_call_function(cpumask, sleep_cpu, NULL, 0); diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S index 968bcd2cb022..6f702a6ab395 100644 --- a/arch/mn10300/kernel/vmlinux.lds.S +++ b/arch/mn10300/kernel/vmlinux.lds.S @@ -70,7 +70,7 @@ SECTIONS .exit.text : { EXIT_TEXT; } .exit.data : { EXIT_DATA; } - PERCPU(32, PAGE_SIZE) + PERCPU_SECTION(32) . = ALIGN(PAGE_SIZE); __init_end = .; /* freed after init ends here */ diff --git a/arch/mn10300/mm/cache-smp.c b/arch/mn10300/mm/cache-smp.c index 4a6e9a4b5b27..2d23b9eeee62 100644 --- a/arch/mn10300/mm/cache-smp.c +++ b/arch/mn10300/mm/cache-smp.c @@ -74,7 +74,7 @@ void smp_cache_interrupt(void) break; } - cpu_clear(smp_processor_id(), smp_cache_ipi_map); + cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map); } /** @@ -94,12 +94,12 @@ void smp_cache_call(unsigned long opr_mask, smp_cache_mask = opr_mask; smp_cache_start = start; smp_cache_end = end; - smp_cache_ipi_map = cpu_online_map; - cpu_clear(smp_processor_id(), smp_cache_ipi_map); + cpumask_copy(&smp_cache_ipi_map, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map); send_IPI_allbutself(FLUSH_CACHE_IPI); - while (!cpus_empty(smp_cache_ipi_map)) + while (!cpumask_empty(&smp_cache_ipi_map)) /* nothing. lockup detection does not belong here */ mb(); } diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c index 48907cc3bdb7..13801824e3ee 100644 --- a/arch/mn10300/mm/init.c +++ b/arch/mn10300/mm/init.c @@ -37,8 +37,6 @@ #include <asm/tlb.h> #include <asm/sections.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - unsigned long highstart_pfn, highend_pfn; #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT diff --git a/arch/mn10300/mm/tlb-smp.c b/arch/mn10300/mm/tlb-smp.c index 0b6a5ad1960e..9a777498a916 100644 --- a/arch/mn10300/mm/tlb-smp.c +++ b/arch/mn10300/mm/tlb-smp.c @@ -64,7 +64,7 @@ void smp_flush_tlb(void *unused) cpu_id = get_cpu(); - if (!cpu_isset(cpu_id, flush_cpumask)) + if (!cpumask_test_cpu(cpu_id, &flush_cpumask)) /* This was a BUG() but until someone can quote me the line * from the intel manual that guarantees an IPI to multiple * CPUs is retried _only_ on the erroring CPUs its staying as a @@ -80,7 +80,7 @@ void smp_flush_tlb(void *unused) local_flush_tlb_page(flush_mm, flush_va); smp_mb__before_clear_bit(); - cpu_clear(cpu_id, flush_cpumask); + cpumask_clear_cpu(cpu_id, &flush_cpumask); smp_mb__after_clear_bit(); out: put_cpu(); @@ -103,11 +103,11 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, * - we do not send IPIs to as-yet unbooted CPUs. */ BUG_ON(!mm); - BUG_ON(cpus_empty(cpumask)); - BUG_ON(cpu_isset(smp_processor_id(), cpumask)); + BUG_ON(cpumask_empty(&cpumask)); + BUG_ON(cpumask_test_cpu(smp_processor_id(), &cpumask)); - cpus_and(tmp, cpumask, cpu_online_map); - BUG_ON(!cpus_equal(cpumask, tmp)); + cpumask_and(&tmp, &cpumask, cpu_online_mask); + BUG_ON(!cpumask_equal(&cpumask, &tmp)); /* I'm not happy about this global shared spinlock in the MM hot path, * but we'll see how contended it is. @@ -128,7 +128,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, /* FIXME: if NR_CPUS>=3, change send_IPI_mask */ smp_call_function(smp_flush_tlb, NULL, 1); - while (!cpus_empty(flush_cpumask)) + while (!cpumask_empty(&flush_cpumask)) /* Lockup detection does not belong here */ smp_mb(); @@ -146,11 +146,11 @@ void flush_tlb_mm(struct mm_struct *mm) cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); local_flush_tlb(); - if (!cpus_empty(cpu_mask)) + if (!cpumask_empty(&cpu_mask)) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); @@ -165,11 +165,11 @@ void flush_tlb_current_task(void) cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); local_flush_tlb(); - if (!cpus_empty(cpu_mask)) + if (!cpumask_empty(&cpu_mask)) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); @@ -186,11 +186,11 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); local_flush_tlb_page(mm, va); - if (!cpus_empty(cpu_mask)) + if (!cpumask_empty(&cpu_mask)) flush_tlb_others(cpu_mask, mm, va); preempt_enable(); diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h index 2e73623feb6b..e8f8037d872b 100644 --- a/arch/parisc/include/asm/smp.h +++ b/arch/parisc/include/asm/smp.h @@ -33,15 +33,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); #endif /* !ASSEMBLY */ -/* - * This magic constant controls our willingness to transfer - * a process across CPUs. Such a transfer incurs cache and tlb - * misses. The current value is inherited from i386. Still needs - * to be tuned for parisc. - */ - -#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */ - #define raw_smp_processor_id() (current_thread_info()->cpu) #else /* CONFIG_SMP */ diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index e1a55849bfa7..fa6f2b8163e0 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -149,7 +149,7 @@ SECTIONS EXIT_DATA } - PERCPU(L1_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(L1_CACHE_BYTES) . = ALIGN(PAGE_SIZE); __init_end = .; /* freed after init ends here */ diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 5fa1e273006e..82f364e209fc 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -31,8 +31,6 @@ #include <asm/mmzone.h> #include <asm/sections.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - extern int data_start; #ifdef CONFIG_DISCONTIGMEM @@ -686,7 +684,7 @@ void show_mem(unsigned int filter) int shared = 0, cached = 0; printk(KERN_INFO "Mem-info:\n"); - show_free_areas(); + show_free_areas(filter); #ifndef CONFIG_DISCONTIGMEM i = max_mapnr; while (i-- > 0) { diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a3128ca0fe11..423145a6f7ba 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -140,6 +140,7 @@ config PPC select IRQ_PER_CPU select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW_LEVEL + select HAVE_RCU_TABLE_FREE if SMP config EARLY_PRINTK bool diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index a597dd77b903..e72dcf6a421d 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -35,27 +35,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_PER_CPU_MAPS - bool "Debug access to per_cpu maps" - depends on DEBUG_KERNEL - depends on SMP - default n - ---help--- - Say Y to verify that the per_cpu map being accessed has - been setup. Adds a fair amount of code to kernel memory - and decreases performance. - - Say N if unsure. - config HCALL_STATS bool "Hypervisor call instrumentation" depends on PPC_PSERIES && DEBUG_FS && TRACEPOINTS diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 761faa7b6964..ac1eb320c7b4 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts @@ -176,6 +176,19 @@ sleep = <&pmc 0x00300000>; }; + ptp_clock@24E00 { + compatible = "fsl,etsec-ptp"; + reg = <0x24E00 0xB0>; + interrupts = <12 0x8 13 0x8>; + interrupt-parent = < &ipic >; + fsl,tclk-period = <10>; + fsl,tmr-prsc = <100>; + fsl,tmr-add = <0x999999A4>; + fsl,tmr-fiper1 = <0x3B9AC9F6>; + fsl,tmr-fiper2 = <0x00018696>; + fsl,max-adj = <659999998>; + }; + enet0: ethernet@24000 { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts index cafc1285c140..f6c04d25e916 100644 --- a/arch/powerpc/boot/dts/mpc8572ds.dts +++ b/arch/powerpc/boot/dts/mpc8572ds.dts @@ -324,6 +324,19 @@ }; }; + ptp_clock@24E00 { + compatible = "fsl,etsec-ptp"; + reg = <0x24E00 0xB0>; + interrupts = <68 2 69 2 70 2 71 2>; + interrupt-parent = < &mpic >; + fsl,tclk-period = <5>; + fsl,tmr-prsc = <200>; + fsl,tmr-add = <0xAAAAAAAB>; + fsl,tmr-fiper1 = <0x3B9AC9FB>; + fsl,tmr-fiper2 = <0x3B9AC9FB>; + fsl,max-adj = <499999999>; + }; + enet0: ethernet@24000 { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/powerpc/boot/dts/p2020ds.dts b/arch/powerpc/boot/dts/p2020ds.dts index 2bcf3683d223..dae403100f2f 100644 --- a/arch/powerpc/boot/dts/p2020ds.dts +++ b/arch/powerpc/boot/dts/p2020ds.dts @@ -178,6 +178,19 @@ }; + ptp_clock@24E00 { + compatible = "fsl,etsec-ptp"; + reg = <0x24E00 0xB0>; + interrupts = <68 2 69 2 70 2>; + interrupt-parent = < &mpic >; + fsl,tclk-period = <5>; + fsl,tmr-prsc = <200>; + fsl,tmr-add = <0xCCCCCCCD>; + fsl,tmr-fiper1 = <0x3B9AC9FB>; + fsl,tmr-fiper2 = <0x0001869B>; + fsl,max-adj = <249999999>; + }; + enet0: ethernet@24000 { tbi-handle = <&tbi0>; phy-handle = <&phy0>; diff --git a/arch/powerpc/boot/dts/p2020rdb.dts b/arch/powerpc/boot/dts/p2020rdb.dts index 3782a58f13be..1d7a05f3021e 100644 --- a/arch/powerpc/boot/dts/p2020rdb.dts +++ b/arch/powerpc/boot/dts/p2020rdb.dts @@ -224,6 +224,19 @@ status = "disabled"; }; + ptp_clock@24E00 { + compatible = "fsl,etsec-ptp"; + reg = <0x24E00 0xB0>; + interrupts = <68 2 69 2 70 2>; + interrupt-parent = < &mpic >; + fsl,tclk-period = <5>; + fsl,tmr-prsc = <200>; + fsl,tmr-add = <0xCCCCCCCD>; + fsl,tmr-fiper1 = <0x3B9AC9FB>; + fsl,tmr-fiper2 = <0x0001869B>; + fsl,max-adj = <249999999>; + }; + enet0: ethernet@24000 { fixed-link = <1 1 1000 0 0>; phy-connection-type = "rgmii-id"; diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index abe8532bd14e..bf301ac62f35 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h @@ -31,14 +31,29 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) #endif #ifdef CONFIG_SMP -extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift); -extern void pte_free_finish(void); +struct mmu_gather; +extern void tlb_remove_table(struct mmu_gather *, void *); + +static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) +{ + unsigned long pgf = (unsigned long)table; + BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); + pgf |= shift; + tlb_remove_table(tlb, (void *)pgf); +} + +static inline void __tlb_remove_table(void *_table) +{ + void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE); + unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE; + + pgtable_free(table, shift); +} #else /* CONFIG_SMP */ static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) { pgtable_free(table, shift); } -static inline void pte_free_finish(void) { } #endif /* !CONFIG_SMP */ static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index d8529ef13b23..37c353e8af7c 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -139,10 +139,12 @@ static inline struct thread_info *current_thread_info(void) #define TLF_NAPPING 0 /* idle thread enabled NAP mode */ #define TLF_SLEEPING 1 /* suspend code enabled SLEEP mode */ #define TLF_RESTORE_SIGMASK 2 /* Restore signal mask in do_signal */ +#define TLF_LAZY_MMU 3 /* tlb_batch is active */ #define _TLF_NAPPING (1 << TLF_NAPPING) #define _TLF_SLEEPING (1 << TLF_SLEEPING) #define _TLF_RESTORE_SIGMASK (1 << TLF_RESTORE_SIGMASK) +#define _TLF_LAZY_MMU (1 << TLF_LAZY_MMU) #ifndef __ASSEMBLY__ #define HAVE_SET_RESTORE_SIGMASK 1 diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 095043d79946..91e52df3d81d 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -395,6 +395,9 @@ struct task_struct *__switch_to(struct task_struct *prev, struct thread_struct *new_thread, *old_thread; unsigned long flags; struct task_struct *last; +#ifdef CONFIG_PPC_BOOK3S_64 + struct ppc64_tlb_batch *batch; +#endif #ifdef CONFIG_SMP /* avoid complexity of lazy save/restore of fpu @@ -513,7 +516,17 @@ struct task_struct *__switch_to(struct task_struct *prev, old_thread->accum_tb += (current_tb - start_tb); new_thread->start_tb = current_tb; } -#endif +#endif /* CONFIG_PPC64 */ + +#ifdef CONFIG_PPC_BOOK3S_64 + batch = &__get_cpu_var(ppc64_tlb_batch); + if (batch->active) { + current_thread_info()->local_flags |= _TLF_LAZY_MMU; + if (batch->index) + __flush_tlb_pending(batch); + batch->active = 0; + } +#endif /* CONFIG_PPC_BOOK3S_64 */ local_irq_save(flags); @@ -528,6 +541,14 @@ struct task_struct *__switch_to(struct task_struct *prev, hard_irq_disable(); last = _switch(old_thread, new_thread); +#ifdef CONFIG_PPC_BOOK3S_64 + if (current_thread_info()->local_flags & _TLF_LAZY_MMU) { + current_thread_info()->local_flags &= ~_TLF_LAZY_MMU; + batch = &__get_cpu_var(ppc64_tlb_batch); + batch->active = 1; + } +#endif /* CONFIG_PPC_BOOK3S_64 */ + local_irq_restore(flags); return last; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index b9150f07d266..920276c0f6a1 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -160,7 +160,7 @@ SECTIONS INIT_RAM_FS } - PERCPU(L1_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(L1_CACHE_BYTES) . = ALIGN(8); .machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) { diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 6a3997f98dfb..af40c8768a78 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -33,110 +33,6 @@ #include "mmu_decl.h" -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -#ifdef CONFIG_SMP - -/* - * Handle batching of page table freeing on SMP. Page tables are - * queued up and send to be freed later by RCU in order to avoid - * freeing a page table page that is being walked without locks - */ - -static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); -static unsigned long pte_freelist_forced_free; - -struct pte_freelist_batch -{ - struct rcu_head rcu; - unsigned int index; - unsigned long tables[0]; -}; - -#define PTE_FREELIST_SIZE \ - ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ - / sizeof(unsigned long)) - -static void pte_free_smp_sync(void *arg) -{ - /* Do nothing, just ensure we sync with all CPUs */ -} - -/* This is only called when we are critically out of memory - * (and fail to get a page in pte_free_tlb). - */ -static void pgtable_free_now(void *table, unsigned shift) -{ - pte_freelist_forced_free++; - - smp_call_function(pte_free_smp_sync, NULL, 1); - - pgtable_free(table, shift); -} - -static void pte_free_rcu_callback(struct rcu_head *head) -{ - struct pte_freelist_batch *batch = - container_of(head, struct pte_freelist_batch, rcu); - unsigned int i; - - for (i = 0; i < batch->index; i++) { - void *table = (void *)(batch->tables[i] & ~MAX_PGTABLE_INDEX_SIZE); - unsigned shift = batch->tables[i] & MAX_PGTABLE_INDEX_SIZE; - - pgtable_free(table, shift); - } - - free_page((unsigned long)batch); -} - -static void pte_free_submit(struct pte_freelist_batch *batch) -{ - call_rcu_sched(&batch->rcu, pte_free_rcu_callback); -} - -void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) -{ - /* This is safe since tlb_gather_mmu has disabled preemption */ - struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); - unsigned long pgf; - - if (atomic_read(&tlb->mm->mm_users) < 2 || - cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){ - pgtable_free(table, shift); - return; - } - - if (*batchp == NULL) { - *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); - if (*batchp == NULL) { - pgtable_free_now(table, shift); - return; - } - (*batchp)->index = 0; - } - BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); - pgf = (unsigned long)table | shift; - (*batchp)->tables[(*batchp)->index++] = pgf; - if ((*batchp)->index == PTE_FREELIST_SIZE) { - pte_free_submit(*batchp); - *batchp = NULL; - } -} - -void pte_free_finish(void) -{ - /* This is safe since tlb_gather_mmu has disabled preemption */ - struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); - - if (*batchp == NULL) - return; - pte_free_submit(*batchp); - *batchp = NULL; -} - -#endif /* CONFIG_SMP */ - static inline int is_exec_fault(void) { return current->thread.regs && TRAP(current->thread.regs) == 0x400; diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c index 690566b66e8e..27b863c14941 100644 --- a/arch/powerpc/mm/tlb_hash32.c +++ b/arch/powerpc/mm/tlb_hash32.c @@ -71,9 +71,6 @@ void tlb_flush(struct mmu_gather *tlb) */ _tlbia(); } - - /* Push out batch of freed page tables */ - pte_free_finish(); } /* diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index c14d09f614f3..31f18207970b 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -155,7 +155,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) void tlb_flush(struct mmu_gather *tlb) { - struct ppc64_tlb_batch *tlbbatch = &__get_cpu_var(ppc64_tlb_batch); + struct ppc64_tlb_batch *tlbbatch = &get_cpu_var(ppc64_tlb_batch); /* If there's a TLB batch pending, then we must flush it because the * pages are going to be freed and we really don't want to have a CPU @@ -164,8 +164,7 @@ void tlb_flush(struct mmu_gather *tlb) if (tlbbatch->index) __flush_tlb_pending(tlbbatch); - /* Push out batch of freed page tables */ - pte_free_finish(); + put_cpu_var(ppc64_tlb_batch); } /** diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 2a030d89bbc6..0bdad3aecc67 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -299,9 +299,6 @@ EXPORT_SYMBOL(flush_tlb_range); void tlb_flush(struct mmu_gather *tlb) { flush_tlb_mm(tlb->mm); - - /* Push out batch of freed page tables */ - pte_free_finish(); } /* diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 4a7f14079e03..ff2d2371b2e9 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -230,17 +230,6 @@ config SYSVIPC_COMPAT config AUDIT_ARCH def_bool y -config S390_EXEC_PROTECT - def_bool y - prompt "Data execute protection" - help - This option allows to enable a buffer overflow protection for user - space programs and it also selects the addressing mode option above. - The kernel parameter noexec=on will enable this feature and also - switch the addressing modes, default is disabled. Enabling this (via - kernel parameter) on machines earlier than IBM System z9 this will - reduce system performance. - comment "Code generation options" choice diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 5c91995b74e4..24bff4f1cc52 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -130,9 +130,7 @@ static void appldata_work_fn(struct work_struct *work) { struct list_head *lh; struct appldata_ops *ops; - int i; - i = 0; get_online_cpus(); mutex_lock(&appldata_ops_mutex); list_for_each(lh, &appldata_ops_list) { diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index 7488e52efa97..81d7908416cf 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h @@ -167,7 +167,6 @@ static inline unsigned long __cmpxchg(void *ptr, unsigned long old, #ifdef CONFIG_64BIT #define cmpxchg64(ptr, o, n) \ ({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ cmpxchg((ptr), (o), (n)); \ }) #else /* CONFIG_64BIT */ diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 10c029cfcc7d..64b61bf72e93 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -196,18 +196,6 @@ do { \ } while (0) #endif /* __s390x__ */ -/* - * An executable for which elf_read_implies_exec() returns TRUE will - * have the READ_IMPLIES_EXEC personality flag set automatically. - */ -#define elf_read_implies_exec(ex, executable_stack) \ -({ \ - if (current->mm->context.noexec && \ - executable_stack != EXSTACK_DISABLE_X) \ - disable_noexec(current->mm, current); \ - current->mm->context.noexec == 0; \ -}) - #define STACK_RND_MASK 0x7ffUL #define ARCH_DLINFO \ diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h index b56403c2df28..799ed0f1643d 100644 --- a/arch/s390/include/asm/hugetlb.h +++ b/arch/s390/include/asm/hugetlb.h @@ -111,21 +111,10 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, { pmd_t *pmdp = (pmd_t *) ptep; - if (!MACHINE_HAS_IDTE) { - __pmd_csp(pmdp); - if (mm->context.noexec) { - pmdp = get_shadow_table(pmdp); - __pmd_csp(pmdp); - } - return; - } - - __pmd_idte(address, pmdp); - if (mm->context.noexec) { - pmdp = get_shadow_table(pmdp); + if (MACHINE_HAS_IDTE) __pmd_idte(address, pmdp); - } - return; + else + __pmd_csp(pmdp); } #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index db14a311f1d2..1544b90bd6d6 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h @@ -15,6 +15,7 @@ enum interruption_class { EXTINT_VRT, EXTINT_SCP, EXTINT_IUC, + EXTINT_CPM, IOINT_QAI, IOINT_QDI, IOINT_DAS, diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 65e172f8209d..228cf0b295db 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -124,7 +124,7 @@ struct _lowcore { /* Address space pointer. */ __u32 kernel_asce; /* 0x02ac */ __u32 user_asce; /* 0x02b0 */ - __u32 user_exec_asce; /* 0x02b4 */ + __u32 current_pid; /* 0x02b4 */ /* SMP info area */ __u32 cpu_nr; /* 0x02b8 */ @@ -255,7 +255,7 @@ struct _lowcore { /* Address space pointer. */ __u64 kernel_asce; /* 0x0310 */ __u64 user_asce; /* 0x0318 */ - __u64 user_exec_asce; /* 0x0320 */ + __u64 current_pid; /* 0x0320 */ /* SMP info area */ __u32 cpu_nr; /* 0x0328 */ diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index 78522cdefdd4..82d0847896a0 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h @@ -5,19 +5,18 @@ typedef struct { atomic_t attach_count; unsigned int flush_mm; spinlock_t list_lock; - struct list_head crst_list; struct list_head pgtable_list; unsigned long asce_bits; unsigned long asce_limit; unsigned long vdso_base; - int noexec; - int has_pgste; /* The mmu context has extended page tables */ - int alloc_pgste; /* cloned contexts will have extended page tables */ + /* Cloned contexts will be created with extended page tables. */ + unsigned int alloc_pgste:1; + /* The mmu context has extended page tables. */ + unsigned int has_pgste:1; } mm_context_t; #define INIT_MM_CONTEXT(name) \ .context.list_lock = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \ - .context.crst_list = LIST_HEAD_INIT(name.context.crst_list), \ .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), #endif diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 8c277caa8d3a..5682f160ff82 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -35,11 +35,9 @@ static inline int init_new_context(struct task_struct *tsk, * and if has_pgste is set, it will create extended page * tables. */ - mm->context.noexec = 0; mm->context.has_pgste = 1; mm->context.alloc_pgste = 1; } else { - mm->context.noexec = (user_mode == SECONDARY_SPACE_MODE); mm->context.has_pgste = 0; mm->context.alloc_pgste = 0; } @@ -63,10 +61,8 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); if (user_mode != HOME_SPACE_MODE) { /* Load primary space page table origin. */ - pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd; - S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd); asm volatile(LCTL_OPCODE" 1,1,%0\n" - : : "m" (S390_lowcore.user_exec_asce) ); + : : "m" (S390_lowcore.user_asce) ); } else /* Load home space page table origin. */ asm volatile(LCTL_OPCODE" 13,13,%0" diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 3c987e9ec8d6..accb372ddc7e 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -90,6 +90,7 @@ static inline void copy_page(void *to, void *from) */ typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct { unsigned long pgste; } pgste_t; typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pud; } pud_t; @@ -97,18 +98,21 @@ typedef struct { unsigned long pgd; } pgd_t; typedef pte_t *pgtable_t; #define pgprot_val(x) ((x).pgprot) +#define pgste_val(x) ((x).pgste) #define pte_val(x) ((x).pte) #define pmd_val(x) ((x).pmd) #define pud_val(x) ((x).pud) #define pgd_val(x) ((x).pgd) +#define __pgste(x) ((pgste_t) { (x) } ) #define __pte(x) ((pte_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } ) +#define __pud(x) ((pud_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) -static inline void -page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) +static inline void page_set_storage_key(unsigned long addr, + unsigned char skey, int mapped) { if (!mapped) asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" @@ -117,15 +121,59 @@ page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); } -static inline unsigned int -page_get_storage_key(unsigned long addr) +static inline unsigned char page_get_storage_key(unsigned long addr) { - unsigned int skey; + unsigned char skey; - asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0)); + asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr)); return skey; } +static inline int page_reset_referenced(unsigned long addr) +{ + unsigned int ipm; + + asm volatile( + " rrbe 0,%1\n" + " ipm %0\n" + : "=d" (ipm) : "a" (addr) : "cc"); + return !!(ipm & 0x20000000); +} + +/* Bits int the storage key */ +#define _PAGE_CHANGED 0x02 /* HW changed bit */ +#define _PAGE_REFERENCED 0x04 /* HW referenced bit */ +#define _PAGE_FP_BIT 0x08 /* HW fetch protection bit */ +#define _PAGE_ACC_BITS 0xf0 /* HW access control bits */ + +/* + * Test and clear dirty bit in storage key. + * We can't clear the changed bit atomically. This is a potential + * race against modification of the referenced bit. This function + * should therefore only be called if it is not mapped in any + * address space. + */ +#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY +static inline int page_test_and_clear_dirty(unsigned long pfn, int mapped) +{ + unsigned char skey; + + skey = page_get_storage_key(pfn << PAGE_SHIFT); + if (!(skey & _PAGE_CHANGED)) + return 0; + page_set_storage_key(pfn << PAGE_SHIFT, skey & ~_PAGE_CHANGED, mapped); + return 1; +} + +/* + * Test and clear referenced bit in storage key. + */ +#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG +static inline int page_test_and_clear_young(unsigned long pfn) +{ + return page_reset_referenced(pfn << PAGE_SHIFT); +} + struct page; void arch_free_page(struct page *page, int order); void arch_alloc_page(struct page *page, int order); diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h index f7ad8719d02d..5325c89a5843 100644 --- a/arch/s390/include/asm/percpu.h +++ b/arch/s390/include/asm/percpu.h @@ -1,6 +1,9 @@ #ifndef __ARCH_S390_PERCPU__ #define __ARCH_S390_PERCPU__ +#include <linux/preempt.h> +#include <asm/cmpxchg.h> + /* * s390 uses its own implementation for per cpu data, the offset of * the cpu local data area is cached in the cpu's lowcore memory. @@ -16,6 +19,71 @@ #define ARCH_NEEDS_WEAK_PER_CPU #endif +#define arch_irqsafe_cpu_to_op(pcp, val, op) \ +do { \ + typedef typeof(pcp) pcp_op_T__; \ + pcp_op_T__ old__, new__, prev__; \ + pcp_op_T__ *ptr__; \ + preempt_disable(); \ + ptr__ = __this_cpu_ptr(&(pcp)); \ + prev__ = *ptr__; \ + do { \ + old__ = prev__; \ + new__ = old__ op (val); \ + switch (sizeof(*ptr__)) { \ + case 8: \ + prev__ = cmpxchg64(ptr__, old__, new__); \ + break; \ + default: \ + prev__ = cmpxchg(ptr__, old__, new__); \ + } \ + } while (prev__ != old__); \ + preempt_enable(); \ +} while (0) + +#define irqsafe_cpu_add_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) +#define irqsafe_cpu_add_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) +#define irqsafe_cpu_add_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) +#define irqsafe_cpu_add_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, +) + +#define irqsafe_cpu_and_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) +#define irqsafe_cpu_and_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) +#define irqsafe_cpu_and_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) +#define irqsafe_cpu_and_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, &) + +#define irqsafe_cpu_or_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) +#define irqsafe_cpu_or_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) +#define irqsafe_cpu_or_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) +#define irqsafe_cpu_or_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, |) + +#define irqsafe_cpu_xor_1(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) +#define irqsafe_cpu_xor_2(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) +#define irqsafe_cpu_xor_4(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) +#define irqsafe_cpu_xor_8(pcp, val) arch_irqsafe_cpu_to_op(pcp, val, ^) + +#define arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) \ +({ \ + typedef typeof(pcp) pcp_op_T__; \ + pcp_op_T__ ret__; \ + pcp_op_T__ *ptr__; \ + preempt_disable(); \ + ptr__ = __this_cpu_ptr(&(pcp)); \ + switch (sizeof(*ptr__)) { \ + case 8: \ + ret__ = cmpxchg64(ptr__, oval, nval); \ + break; \ + default: \ + ret__ = cmpxchg(ptr__, oval, nval); \ + } \ + preempt_enable(); \ + ret__; \ +}) + +#define irqsafe_cpu_cmpxchg_1(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) +#define irqsafe_cpu_cmpxchg_2(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) +#define irqsafe_cpu_cmpxchg_4(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) +#define irqsafe_cpu_cmpxchg_8(pcp, oval, nval) arch_irqsafe_cpu_cmpxchg(pcp, oval, nval) + #include <asm-generic/percpu.h> #endif /* __ARCH_S390_PERCPU__ */ diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 082eb4e50e8b..f6314af3b354 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h @@ -19,14 +19,13 @@ #define check_pgt_cache() do {} while (0) -unsigned long *crst_table_alloc(struct mm_struct *, int); +unsigned long *crst_table_alloc(struct mm_struct *); void crst_table_free(struct mm_struct *, unsigned long *); void crst_table_free_rcu(struct mm_struct *, unsigned long *); unsigned long *page_table_alloc(struct mm_struct *); void page_table_free(struct mm_struct *, unsigned long *); void page_table_free_rcu(struct mm_struct *, unsigned long *); -void disable_noexec(struct mm_struct *, struct task_struct *); static inline void clear_table(unsigned long *s, unsigned long val, size_t n) { @@ -50,9 +49,6 @@ static inline void clear_table(unsigned long *s, unsigned long val, size_t n) static inline void crst_table_init(unsigned long *crst, unsigned long entry) { clear_table(crst, entry, sizeof(unsigned long)*2048); - crst = get_shadow_table(crst); - if (crst) - clear_table(crst, entry, sizeof(unsigned long)*2048); } #ifndef __s390x__ @@ -69,10 +65,7 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm) #define pmd_free(mm, x) do { } while (0) #define pgd_populate(mm, pgd, pud) BUG() -#define pgd_populate_kernel(mm, pgd, pud) BUG() - #define pud_populate(mm, pud, pmd) BUG() -#define pud_populate_kernel(mm, pud, pmd) BUG() #else /* __s390x__ */ @@ -90,7 +83,7 @@ void crst_table_downgrade(struct mm_struct *, unsigned long limit); static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) { - unsigned long *table = crst_table_alloc(mm, mm->context.noexec); + unsigned long *table = crst_table_alloc(mm); if (table) crst_table_init(table, _REGION3_ENTRY_EMPTY); return (pud_t *) table; @@ -99,43 +92,21 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) { - unsigned long *table = crst_table_alloc(mm, mm->context.noexec); + unsigned long *table = crst_table_alloc(mm); if (table) crst_table_init(table, _SEGMENT_ENTRY_EMPTY); return (pmd_t *) table; } #define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd) -static inline void pgd_populate_kernel(struct mm_struct *mm, - pgd_t *pgd, pud_t *pud) -{ - pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud); -} - static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) { - pgd_populate_kernel(mm, pgd, pud); - if (mm->context.noexec) { - pgd = get_shadow_table(pgd); - pud = get_shadow_table(pud); - pgd_populate_kernel(mm, pgd, pud); - } -} - -static inline void pud_populate_kernel(struct mm_struct *mm, - pud_t *pud, pmd_t *pmd) -{ - pud_val(*pud) = _REGION3_ENTRY | __pa(pmd); + pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud); } static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) { - pud_populate_kernel(mm, pud, pmd); - if (mm->context.noexec) { - pud = get_shadow_table(pud); - pmd = get_shadow_table(pmd); - pud_populate_kernel(mm, pud, pmd); - } + pud_val(*pud) = _REGION3_ENTRY | __pa(pmd); } #endif /* __s390x__ */ @@ -143,29 +114,19 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) static inline pgd_t *pgd_alloc(struct mm_struct *mm) { spin_lock_init(&mm->context.list_lock); - INIT_LIST_HEAD(&mm->context.crst_list); INIT_LIST_HEAD(&mm->context.pgtable_list); - return (pgd_t *) - crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE); + return (pgd_t *) crst_table_alloc(mm); } #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) -static inline void pmd_populate_kernel(struct mm_struct *mm, - pmd_t *pmd, pte_t *pte) -{ - pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte); -} - static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t pte) { - pmd_populate_kernel(mm, pmd, pte); - if (mm->context.noexec) { - pmd = get_shadow_table(pmd); - pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE); - } + pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte); } +#define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte) + #define pmd_pgtable(pmd) \ (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 02ace3491c51..c4773a2ef3d3 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -31,9 +31,8 @@ #ifndef __ASSEMBLY__ #include <linux/sched.h> #include <linux/mm_types.h> -#include <asm/bitops.h> #include <asm/bug.h> -#include <asm/processor.h> +#include <asm/page.h> extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); extern void paging_init(void); @@ -243,11 +242,13 @@ extern unsigned long VMALLOC_START; /* Software bits in the page table entry */ #define _PAGE_SWT 0x001 /* SW pte type bit t */ #define _PAGE_SWX 0x002 /* SW pte type bit x */ -#define _PAGE_SPECIAL 0x004 /* SW associated with special page */ +#define _PAGE_SWC 0x004 /* SW pte changed bit (for KVM) */ +#define _PAGE_SWR 0x008 /* SW pte referenced bit (for KVM) */ +#define _PAGE_SPECIAL 0x010 /* SW associated with special page */ #define __HAVE_ARCH_PTE_SPECIAL /* Set of bits not changed in pte_modify */ -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL | _PAGE_SWC | _PAGE_SWR) /* Six different types of pages. */ #define _PAGE_TYPE_EMPTY 0x400 @@ -256,8 +257,6 @@ extern unsigned long VMALLOC_START; #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ #define _PAGE_TYPE_RO 0x200 #define _PAGE_TYPE_RW 0x000 -#define _PAGE_TYPE_EX_RO 0x202 -#define _PAGE_TYPE_EX_RW 0x002 /* * Only four types for huge pages, using the invalid bit and protection bit @@ -287,8 +286,6 @@ extern unsigned long VMALLOC_START; * _PAGE_TYPE_FILE 11?1 -> 11?1 * _PAGE_TYPE_RO 0100 -> 1100 * _PAGE_TYPE_RW 0000 -> 1000 - * _PAGE_TYPE_EX_RO 0110 -> 1110 - * _PAGE_TYPE_EX_RW 0010 -> 1010 * * pte_none is true for bits combinations 1000, 1010, 1100, 1110 * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 @@ -297,14 +294,17 @@ extern unsigned long VMALLOC_START; */ /* Page status table bits for virtualization */ -#define RCP_PCL_BIT 55 -#define RCP_HR_BIT 54 -#define RCP_HC_BIT 53 -#define RCP_GR_BIT 50 -#define RCP_GC_BIT 49 - -/* User dirty bit for KVM's migration feature */ -#define KVM_UD_BIT 47 +#define RCP_ACC_BITS 0xf000000000000000UL +#define RCP_FP_BIT 0x0800000000000000UL +#define RCP_PCL_BIT 0x0080000000000000UL +#define RCP_HR_BIT 0x0040000000000000UL +#define RCP_HC_BIT 0x0020000000000000UL +#define RCP_GR_BIT 0x0004000000000000UL +#define RCP_GC_BIT 0x0002000000000000UL + +/* User dirty / referenced bit for KVM's migration feature */ +#define KVM_UR_BIT 0x0000800000000000UL +#define KVM_UC_BIT 0x0000400000000000UL #ifndef __s390x__ @@ -377,85 +377,54 @@ extern unsigned long VMALLOC_START; #define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \ _ASCE_ALT_EVENT) -/* Bits int the storage key */ -#define _PAGE_CHANGED 0x02 /* HW changed bit */ -#define _PAGE_REFERENCED 0x04 /* HW referenced bit */ - /* * Page protection definitions. */ #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) #define PAGE_RO __pgprot(_PAGE_TYPE_RO) #define PAGE_RW __pgprot(_PAGE_TYPE_RW) -#define PAGE_EX_RO __pgprot(_PAGE_TYPE_EX_RO) -#define PAGE_EX_RW __pgprot(_PAGE_TYPE_EX_RW) #define PAGE_KERNEL PAGE_RW #define PAGE_COPY PAGE_RO /* - * Dependent on the EXEC_PROTECT option s390 can do execute protection. - * Write permission always implies read permission. In theory with a - * primary/secondary page table execute only can be implemented but - * it would cost an additional bit in the pte to distinguish all the - * different pte types. To avoid that execute permission currently - * implies read permission as well. + * On s390 the page table entry has an invalid bit and a read-only bit. + * Read permission implies execute permission and write permission + * implies read permission. */ /*xwr*/ #define __P000 PAGE_NONE #define __P001 PAGE_RO #define __P010 PAGE_RO #define __P011 PAGE_RO -#define __P100 PAGE_EX_RO -#define __P101 PAGE_EX_RO -#define __P110 PAGE_EX_RO -#define __P111 PAGE_EX_RO +#define __P100 PAGE_RO +#define __P101 PAGE_RO +#define __P110 PAGE_RO +#define __P111 PAGE_RO #define __S000 PAGE_NONE #define __S001 PAGE_RO #define __S010 PAGE_RW #define __S011 PAGE_RW -#define __S100 PAGE_EX_RO -#define __S101 PAGE_EX_RO -#define __S110 PAGE_EX_RW -#define __S111 PAGE_EX_RW - -#ifndef __s390x__ -# define PxD_SHADOW_SHIFT 1 -#else /* __s390x__ */ -# define PxD_SHADOW_SHIFT 2 -#endif /* __s390x__ */ +#define __S100 PAGE_RO +#define __S101 PAGE_RO +#define __S110 PAGE_RW +#define __S111 PAGE_RW -static inline void *get_shadow_table(void *table) +static inline int mm_exclusive(struct mm_struct *mm) { - unsigned long addr, offset; - struct page *page; - - addr = (unsigned long) table; - offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1); - page = virt_to_page((void *)(addr ^ offset)); - return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL); + return likely(mm == current->active_mm && + atomic_read(&mm->context.attach_count) <= 1); } -/* - * Certain architectures need to do special things when PTEs - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t entry) +static inline int mm_has_pgste(struct mm_struct *mm) { - *ptep = entry; - if (mm->context.noexec) { - if (!(pte_val(entry) & _PAGE_INVALID) && - (pte_val(entry) & _PAGE_SWX)) - pte_val(entry) |= _PAGE_RO; - else - pte_val(entry) = _PAGE_TYPE_EMPTY; - ptep[PTRS_PER_PTE] = entry; - } +#ifdef CONFIG_PGSTE + if (unlikely(mm->context.has_pgste)) + return 1; +#endif + return 0; } - /* * pgd/pmd/pte query functions */ @@ -568,52 +537,127 @@ static inline int pte_special(pte_t pte) } #define __HAVE_ARCH_PTE_SAME -#define pte_same(a,b) (pte_val(a) == pte_val(b)) +static inline int pte_same(pte_t a, pte_t b) +{ + return pte_val(a) == pte_val(b); +} -static inline void rcp_lock(pte_t *ptep) +static inline pgste_t pgste_get_lock(pte_t *ptep) { + unsigned long new = 0; #ifdef CONFIG_PGSTE - unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); + unsigned long old; + preempt_disable(); - while (test_and_set_bit(RCP_PCL_BIT, pgste)) - ; + asm( + " lg %0,%2\n" + "0: lgr %1,%0\n" + " nihh %0,0xff7f\n" /* clear RCP_PCL_BIT in old */ + " oihh %1,0x0080\n" /* set RCP_PCL_BIT in new */ + " csg %0,%1,%2\n" + " jl 0b\n" + : "=&d" (old), "=&d" (new), "=Q" (ptep[PTRS_PER_PTE]) + : "Q" (ptep[PTRS_PER_PTE]) : "cc"); #endif + return __pgste(new); } -static inline void rcp_unlock(pte_t *ptep) +static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste) { #ifdef CONFIG_PGSTE - unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); - clear_bit(RCP_PCL_BIT, pgste); + asm( + " nihh %1,0xff7f\n" /* clear RCP_PCL_BIT */ + " stg %1,%0\n" + : "=Q" (ptep[PTRS_PER_PTE]) + : "d" (pgste_val(pgste)), "Q" (ptep[PTRS_PER_PTE]) : "cc"); preempt_enable(); #endif } -/* forward declaration for SetPageUptodate in page-flags.h*/ -static inline void page_clear_dirty(struct page *page, int mapped); -#include <linux/page-flags.h> - -static inline void ptep_rcp_copy(pte_t *ptep) +static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste) { #ifdef CONFIG_PGSTE - struct page *page = virt_to_page(pte_val(*ptep)); - unsigned int skey; - unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); - - skey = page_get_storage_key(page_to_phys(page)); - if (skey & _PAGE_CHANGED) { - set_bit_simple(RCP_GC_BIT, pgste); - set_bit_simple(KVM_UD_BIT, pgste); + unsigned long pfn, bits; + unsigned char skey; + + pfn = pte_val(*ptep) >> PAGE_SHIFT; + skey = page_get_storage_key(pfn); + bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); + /* Clear page changed & referenced bit in the storage key */ + if (bits) { + skey ^= bits; + page_set_storage_key(pfn, skey, 1); } - if (skey & _PAGE_REFERENCED) - set_bit_simple(RCP_GR_BIT, pgste); - if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { - SetPageDirty(page); - set_bit_simple(KVM_UD_BIT, pgste); - } - if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) - SetPageReferenced(page); + /* Transfer page changed & referenced bit to guest bits in pgste */ + pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */ + /* Get host changed & referenced bits from pgste */ + bits |= (pgste_val(pgste) & (RCP_HR_BIT | RCP_HC_BIT)) >> 52; + /* Clear host bits in pgste. */ + pgste_val(pgste) &= ~(RCP_HR_BIT | RCP_HC_BIT); + pgste_val(pgste) &= ~(RCP_ACC_BITS | RCP_FP_BIT); + /* Copy page access key and fetch protection bit to pgste */ + pgste_val(pgste) |= + (unsigned long) (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56; + /* Transfer changed and referenced to kvm user bits */ + pgste_val(pgste) |= bits << 45; /* KVM_UR_BIT & KVM_UC_BIT */ + /* Transfer changed & referenced to pte sofware bits */ + pte_val(*ptep) |= bits << 1; /* _PAGE_SWR & _PAGE_SWC */ #endif + return pgste; + +} + +static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste) +{ +#ifdef CONFIG_PGSTE + int young; + + young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK); + /* Transfer page referenced bit to pte software bit (host view) */ + if (young || (pgste_val(pgste) & RCP_HR_BIT)) + pte_val(*ptep) |= _PAGE_SWR; + /* Clear host referenced bit in pgste. */ + pgste_val(pgste) &= ~RCP_HR_BIT; + /* Transfer page referenced bit to guest bit in pgste */ + pgste_val(pgste) |= (unsigned long) young << 50; /* set RCP_GR_BIT */ +#endif + return pgste; + +} + +static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste) +{ +#ifdef CONFIG_PGSTE + unsigned long pfn; + unsigned long okey, nkey; + + pfn = pte_val(*ptep) >> PAGE_SHIFT; + okey = nkey = page_get_storage_key(pfn); + nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT); + /* Set page access key and fetch protection bit from pgste */ + nkey |= (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56; + if (okey != nkey) + page_set_storage_key(pfn, nkey, 1); +#endif +} + +/* + * Certain architectures need to do special things when PTEs + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t entry) +{ + pgste_t pgste; + + if (mm_has_pgste(mm)) { + pgste = pgste_get_lock(ptep); + pgste_set_pte(ptep, pgste); + *ptep = entry; + pgste_set_unlock(ptep, pgste); + } else + *ptep = entry; } /* @@ -627,19 +671,19 @@ static inline int pte_write(pte_t pte) static inline int pte_dirty(pte_t pte) { - /* A pte is neither clean nor dirty on s/390. The dirty bit - * is in the storage key. See page_test_and_clear_dirty for - * details. - */ +#ifdef CONFIG_PGSTE + if (pte_val(pte) & _PAGE_SWC) + return 1; +#endif return 0; } static inline int pte_young(pte_t pte) { - /* A pte is neither young nor old on s/390. The young bit - * is in the storage key. See page_test_and_clear_young for - * details. - */ +#ifdef CONFIG_PGSTE + if (pte_val(pte) & _PAGE_SWR) + return 1; +#endif return 0; } @@ -647,64 +691,30 @@ static inline int pte_young(pte_t pte) * pgd/pmd/pte modification functions */ -#ifndef __s390x__ - -#define pgd_clear(pgd) do { } while (0) -#define pud_clear(pud) do { } while (0) - -#else /* __s390x__ */ - -static inline void pgd_clear_kernel(pgd_t * pgd) +static inline void pgd_clear(pgd_t *pgd) { +#ifdef __s390x__ if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; +#endif } -static inline void pgd_clear(pgd_t * pgd) -{ - pgd_t *shadow = get_shadow_table(pgd); - - pgd_clear_kernel(pgd); - if (shadow) - pgd_clear_kernel(shadow); -} - -static inline void pud_clear_kernel(pud_t *pud) +static inline void pud_clear(pud_t *pud) { +#ifdef __s390x__ if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) pud_val(*pud) = _REGION3_ENTRY_EMPTY; +#endif } -static inline void pud_clear(pud_t *pud) -{ - pud_t *shadow = get_shadow_table(pud); - - pud_clear_kernel(pud); - if (shadow) - pud_clear_kernel(shadow); -} - -#endif /* __s390x__ */ - -static inline void pmd_clear_kernel(pmd_t * pmdp) +static inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY; } -static inline void pmd_clear(pmd_t *pmd) -{ - pmd_t *shadow = get_shadow_table(pmd); - - pmd_clear_kernel(pmd); - if (shadow) - pmd_clear_kernel(shadow); -} - static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_val(*ptep) = _PAGE_TYPE_EMPTY; - if (mm->context.noexec) - pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY; } /* @@ -734,35 +744,27 @@ static inline pte_t pte_mkwrite(pte_t pte) static inline pte_t pte_mkclean(pte_t pte) { - /* The only user of pte_mkclean is the fork() code. - We must *not* clear the *physical* page dirty bit - just because fork() wants to clear the dirty bit in - *one* of the page's mappings. So we just do nothing. */ +#ifdef CONFIG_PGSTE + pte_val(pte) &= ~_PAGE_SWC; +#endif return pte; } static inline pte_t pte_mkdirty(pte_t pte) { - /* We do not explicitly set the dirty bit because the - * sske instruction is slow. It is faster to let the - * next instruction set the dirty bit. - */ return pte; } static inline pte_t pte_mkold(pte_t pte) { - /* S/390 doesn't keep its dirty/referenced bit in the pte. - * There is no point in clearing the real referenced bit. - */ +#ifdef CONFIG_PGSTE + pte_val(pte) &= ~_PAGE_SWR; +#endif return pte; } static inline pte_t pte_mkyoung(pte_t pte) { - /* S/390 doesn't keep its dirty/referenced bit in the pte. - * There is no point in setting the real referenced bit. - */ return pte; } @@ -800,62 +802,60 @@ static inline pte_t pte_mkhuge(pte_t pte) } #endif -#ifdef CONFIG_PGSTE /* - * Get (and clear) the user dirty bit for a PTE. + * Get (and clear) the user dirty bit for a pte. */ -static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm, - pte_t *ptep) +static inline int ptep_test_and_clear_user_dirty(struct mm_struct *mm, + pte_t *ptep) { - int dirty; - unsigned long *pgste; - struct page *page; - unsigned int skey; - - if (!mm->context.has_pgste) - return -EINVAL; - rcp_lock(ptep); - pgste = (unsigned long *) (ptep + PTRS_PER_PTE); - page = virt_to_page(pte_val(*ptep)); - skey = page_get_storage_key(page_to_phys(page)); - if (skey & _PAGE_CHANGED) { - set_bit_simple(RCP_GC_BIT, pgste); - set_bit_simple(KVM_UD_BIT, pgste); + pgste_t pgste; + int dirty = 0; + + if (mm_has_pgste(mm)) { + pgste = pgste_get_lock(ptep); + pgste = pgste_update_all(ptep, pgste); + dirty = !!(pgste_val(pgste) & KVM_UC_BIT); + pgste_val(pgste) &= ~KVM_UC_BIT; + pgste_set_unlock(ptep, pgste); + return dirty; } - if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { - SetPageDirty(page); - set_bit_simple(KVM_UD_BIT, pgste); - } - dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste); - if (skey & _PAGE_CHANGED) - page_clear_dirty(page, 1); - rcp_unlock(ptep); return dirty; } -#endif + +/* + * Get (and clear) the user referenced bit for a pte. + */ +static inline int ptep_test_and_clear_user_young(struct mm_struct *mm, + pte_t *ptep) +{ + pgste_t pgste; + int young = 0; + + if (mm_has_pgste(mm)) { + pgste = pgste_get_lock(ptep); + pgste = pgste_update_young(ptep, pgste); + young = !!(pgste_val(pgste) & KVM_UR_BIT); + pgste_val(pgste) &= ~KVM_UR_BIT; + pgste_set_unlock(ptep, pgste); + } + return young; +} #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { -#ifdef CONFIG_PGSTE - unsigned long physpage; - int young; - unsigned long *pgste; + pgste_t pgste; + pte_t pte; - if (!vma->vm_mm->context.has_pgste) - return 0; - physpage = pte_val(*ptep) & PAGE_MASK; - pgste = (unsigned long *) (ptep + PTRS_PER_PTE); - - young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0); - rcp_lock(ptep); - if (young) - set_bit_simple(RCP_GR_BIT, pgste); - young |= test_and_clear_bit_simple(RCP_HR_BIT, pgste); - rcp_unlock(ptep); - return young; -#endif + if (mm_has_pgste(vma->vm_mm)) { + pgste = pgste_get_lock(ptep); + pgste = pgste_update_young(ptep, pgste); + pte = *ptep; + *ptep = pte_mkold(pte); + pgste_set_unlock(ptep, pgste); + return pte_young(pte); + } return 0; } @@ -867,10 +867,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, * On s390 reference bits are in storage key and never in TLB * With virtualization we handle the reference bit, without we * we can simply return */ -#ifdef CONFIG_PGSTE return ptep_test_and_clear_young(vma, address, ptep); -#endif - return 0; } static inline void __ptep_ipte(unsigned long address, pte_t *ptep) @@ -890,25 +887,6 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep) } } -static inline void ptep_invalidate(struct mm_struct *mm, - unsigned long address, pte_t *ptep) -{ - if (mm->context.has_pgste) { - rcp_lock(ptep); - __ptep_ipte(address, ptep); - ptep_rcp_copy(ptep); - pte_val(*ptep) = _PAGE_TYPE_EMPTY; - rcp_unlock(ptep); - return; - } - __ptep_ipte(address, ptep); - pte_val(*ptep) = _PAGE_TYPE_EMPTY; - if (mm->context.noexec) { - __ptep_ipte(address, ptep + PTRS_PER_PTE); - pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY; - } -} - /* * This is hard to understand. ptep_get_and_clear and ptep_clear_flush * both clear the TLB for the unmapped pte. The reason is that @@ -923,24 +901,72 @@ static inline void ptep_invalidate(struct mm_struct *mm, * is a nop. */ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR -#define ptep_get_and_clear(__mm, __address, __ptep) \ -({ \ - pte_t __pte = *(__ptep); \ - (__mm)->context.flush_mm = 1; \ - if (atomic_read(&(__mm)->context.attach_count) > 1 || \ - (__mm) != current->active_mm) \ - ptep_invalidate(__mm, __address, __ptep); \ - else \ - pte_clear((__mm), (__address), (__ptep)); \ - __pte; \ -}) +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, + unsigned long address, pte_t *ptep) +{ + pgste_t pgste; + pte_t pte; + + mm->context.flush_mm = 1; + if (mm_has_pgste(mm)) + pgste = pgste_get_lock(ptep); + + pte = *ptep; + if (!mm_exclusive(mm)) + __ptep_ipte(address, ptep); + pte_val(*ptep) = _PAGE_TYPE_EMPTY; + + if (mm_has_pgste(mm)) { + pgste = pgste_update_all(&pte, pgste); + pgste_set_unlock(ptep, pgste); + } + return pte; +} + +#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION +static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, + unsigned long address, + pte_t *ptep) +{ + pte_t pte; + + mm->context.flush_mm = 1; + if (mm_has_pgste(mm)) + pgste_get_lock(ptep); + + pte = *ptep; + if (!mm_exclusive(mm)) + __ptep_ipte(address, ptep); + return pte; +} + +static inline void ptep_modify_prot_commit(struct mm_struct *mm, + unsigned long address, + pte_t *ptep, pte_t pte) +{ + *ptep = pte; + if (mm_has_pgste(mm)) + pgste_set_unlock(ptep, *(pgste_t *)(ptep + PTRS_PER_PTE)); +} #define __HAVE_ARCH_PTEP_CLEAR_FLUSH static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { - pte_t pte = *ptep; - ptep_invalidate(vma->vm_mm, address, ptep); + pgste_t pgste; + pte_t pte; + + if (mm_has_pgste(vma->vm_mm)) + pgste = pgste_get_lock(ptep); + + pte = *ptep; + __ptep_ipte(address, ptep); + pte_val(*ptep) = _PAGE_TYPE_EMPTY; + + if (mm_has_pgste(vma->vm_mm)) { + pgste = pgste_update_all(&pte, pgste); + pgste_set_unlock(ptep, pgste); + } return pte; } @@ -953,76 +979,67 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, */ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, - unsigned long addr, + unsigned long address, pte_t *ptep, int full) { - pte_t pte = *ptep; + pgste_t pgste; + pte_t pte; + + if (mm_has_pgste(mm)) + pgste = pgste_get_lock(ptep); + + pte = *ptep; + if (!full) + __ptep_ipte(address, ptep); + pte_val(*ptep) = _PAGE_TYPE_EMPTY; - if (full) - pte_clear(mm, addr, ptep); - else - ptep_invalidate(mm, addr, ptep); + if (mm_has_pgste(mm)) { + pgste = pgste_update_all(&pte, pgste); + pgste_set_unlock(ptep, pgste); + } return pte; } #define __HAVE_ARCH_PTEP_SET_WRPROTECT -#define ptep_set_wrprotect(__mm, __addr, __ptep) \ -({ \ - pte_t __pte = *(__ptep); \ - if (pte_write(__pte)) { \ - (__mm)->context.flush_mm = 1; \ - if (atomic_read(&(__mm)->context.attach_count) > 1 || \ - (__mm) != current->active_mm) \ - ptep_invalidate(__mm, __addr, __ptep); \ - set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \ - } \ -}) +static inline pte_t ptep_set_wrprotect(struct mm_struct *mm, + unsigned long address, pte_t *ptep) +{ + pgste_t pgste; + pte_t pte = *ptep; -#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ -({ \ - int __changed = !pte_same(*(__ptep), __entry); \ - if (__changed) { \ - ptep_invalidate((__vma)->vm_mm, __addr, __ptep); \ - set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry); \ - } \ - __changed; \ -}) + if (pte_write(pte)) { + mm->context.flush_mm = 1; + if (mm_has_pgste(mm)) + pgste = pgste_get_lock(ptep); -/* - * Test and clear dirty bit in storage key. - * We can't clear the changed bit atomically. This is a potential - * race against modification of the referenced bit. This function - * should therefore only be called if it is not mapped in any - * address space. - */ -#define __HAVE_ARCH_PAGE_TEST_DIRTY -static inline int page_test_dirty(struct page *page) -{ - return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0; -} + if (!mm_exclusive(mm)) + __ptep_ipte(address, ptep); + *ptep = pte_wrprotect(pte); -#define __HAVE_ARCH_PAGE_CLEAR_DIRTY -static inline void page_clear_dirty(struct page *page, int mapped) -{ - page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped); + if (mm_has_pgste(mm)) + pgste_set_unlock(ptep, pgste); + } + return pte; } -/* - * Test and clear referenced bit in storage key. - */ -#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG -static inline int page_test_and_clear_young(struct page *page) +#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +static inline int ptep_set_access_flags(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep, + pte_t entry, int dirty) { - unsigned long physpage = page_to_phys(page); - int ccode; - - asm volatile( - " rrbe 0,%1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (ccode) : "a" (physpage) : "cc" ); - return ccode & 2; + pgste_t pgste; + + if (pte_same(*ptep, entry)) + return 0; + if (mm_has_pgste(vma->vm_mm)) + pgste = pgste_get_lock(ptep); + + __ptep_ipte(address, ptep); + *ptep = entry; + + if (mm_has_pgste(vma->vm_mm)) + pgste_set_unlock(ptep, pgste); + return 1; } /* diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 2c79b6416271..1300c3025334 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -84,6 +84,7 @@ struct thread_struct { struct per_event per_event; /* Cause of the last PER trap */ /* pfault_wait is used to block the process on a pfault event */ unsigned long pfault_wait; + struct list_head list; }; typedef struct thread_struct thread_struct; diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index 9074a54c4d10..77eee5477a52 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h @@ -29,65 +29,77 @@ #include <asm/smp.h> #include <asm/tlbflush.h> -#ifndef CONFIG_SMP -#define TLB_NR_PTRS 1 -#else -#define TLB_NR_PTRS 508 -#endif - struct mmu_gather { struct mm_struct *mm; unsigned int fullmm; unsigned int nr_ptes; unsigned int nr_pxds; - void *array[TLB_NR_PTRS]; + unsigned int max; + void **array; + void *local[8]; }; -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - -static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, - unsigned int full_mm_flush) +static inline void __tlb_alloc_page(struct mmu_gather *tlb) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); + unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); + if (addr) { + tlb->array = (void *) addr; + tlb->max = PAGE_SIZE / sizeof(void *); + } +} + +static inline void tlb_gather_mmu(struct mmu_gather *tlb, + struct mm_struct *mm, + unsigned int full_mm_flush) +{ tlb->mm = mm; + tlb->max = ARRAY_SIZE(tlb->local); + tlb->array = tlb->local; tlb->fullmm = full_mm_flush; - tlb->nr_ptes = 0; - tlb->nr_pxds = TLB_NR_PTRS; if (tlb->fullmm) __tlb_flush_mm(mm); - return tlb; + else + __tlb_alloc_page(tlb); + tlb->nr_ptes = 0; + tlb->nr_pxds = tlb->max; } -static inline void tlb_flush_mmu(struct mmu_gather *tlb, - unsigned long start, unsigned long end) +static inline void tlb_flush_mmu(struct mmu_gather *tlb) { - if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < TLB_NR_PTRS)) + if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < tlb->max)) __tlb_flush_mm(tlb->mm); while (tlb->nr_ptes > 0) page_table_free_rcu(tlb->mm, tlb->array[--tlb->nr_ptes]); - while (tlb->nr_pxds < TLB_NR_PTRS) + while (tlb->nr_pxds < tlb->max) crst_table_free_rcu(tlb->mm, tlb->array[tlb->nr_pxds++]); } static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - tlb_flush_mmu(tlb, start, end); + tlb_flush_mmu(tlb); rcu_table_freelist_finish(); /* keep the page table cache within bounds */ check_pgt_cache(); - put_cpu_var(mmu_gathers); + if (tlb->array != tlb->local) + free_pages((unsigned long) tlb->array, 0); } /* * Release the page cache reference for a pte removed by - * tlb_ptep_clear_flush. In both flush modes the tlb fo a page cache page + * tlb_ptep_clear_flush. In both flush modes the tlb for a page cache page * has already been freed, so just do free_page_and_swap_cache. */ +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + free_page_and_swap_cache(page); + return 1; /* avoid calling tlb_flush_mmu */ +} + static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) { free_page_and_swap_cache(page); @@ -103,7 +115,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, if (!tlb->fullmm) { tlb->array[tlb->nr_ptes++] = pte; if (tlb->nr_ptes >= tlb->nr_pxds) - tlb_flush_mmu(tlb, 0, 0); + tlb_flush_mmu(tlb); } else page_table_free(tlb->mm, (unsigned long *) pte); } @@ -124,7 +136,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, if (!tlb->fullmm) { tlb->array[--tlb->nr_pxds] = pmd; if (tlb->nr_ptes >= tlb->nr_pxds) - tlb_flush_mmu(tlb, 0, 0); + tlb_flush_mmu(tlb); } else crst_table_free(tlb->mm, (unsigned long *) pmd); #endif @@ -146,7 +158,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, if (!tlb->fullmm) { tlb->array[--tlb->nr_pxds] = pud; if (tlb->nr_ptes >= tlb->nr_pxds) - tlb_flush_mmu(tlb, 0, 0); + tlb_flush_mmu(tlb); } else crst_table_free(tlb->mm, (unsigned long *) pud); #endif diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 29d5d6d4becc..b7a4f2eb0057 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h @@ -50,7 +50,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm) /* * If the process only ran on the local cpu, do a local flush. */ - local_cpumask = cpumask_of_cpu(smp_processor_id()); + cpumask_copy(&local_cpumask, cpumask_of(smp_processor_id())); if (cpumask_equal(mm_cpumask(mm), &local_cpumask)) __tlb_flush_local(); else @@ -80,16 +80,11 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) * on all cpus instead of doing a local flush if the mm * only ran on the local cpu. */ - if (MACHINE_HAS_IDTE) { - if (mm->context.noexec) - __tlb_flush_idte((unsigned long) - get_shadow_table(mm->pgd) | - mm->context.asce_bits); + if (MACHINE_HAS_IDTE) __tlb_flush_idte((unsigned long) mm->pgd | mm->context.asce_bits); - return; - } - __tlb_flush_full(mm); + else + __tlb_flush_full(mm); } static inline void __tlb_flush_mm_cond(struct mm_struct * mm) diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index e82152572377..9208e69245a0 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -385,6 +385,7 @@ /* Ignore system calls that are also reachable via sys_socket */ #define __IGNORE_recvmmsg +#define __IGNORE_sendmmsg #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index fe03c140002a..edfbd17d7082 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -124,13 +124,11 @@ int main(void) DEFINE(__LC_LAST_UPDATE_TIMER, offsetof(struct _lowcore, last_update_timer)); DEFINE(__LC_LAST_UPDATE_CLOCK, offsetof(struct _lowcore, last_update_clock)); DEFINE(__LC_CURRENT, offsetof(struct _lowcore, current_task)); + DEFINE(__LC_CURRENT_PID, offsetof(struct _lowcore, current_pid)); DEFINE(__LC_THREAD_INFO, offsetof(struct _lowcore, thread_info)); DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack)); DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack)); DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); - DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce)); - DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); - DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1b67fc6ebdc2..0476174dfff5 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -212,6 +212,7 @@ __switch_to: lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task st %r3,__LC_CURRENT # store task struct of next + mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next st %r5,__LC_THREAD_INFO # store thread info of next ahi %r5,STACK_SIZE # end of kernel stack of next st %r5,__LC_KERNEL_STACK # store end of kernel stack diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 9fd864563499..d61967e2eab0 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -220,6 +220,7 @@ __switch_to: lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task stg %r3,__LC_CURRENT # store task struct of next + mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next stg %r5,__LC_THREAD_INFO # store thread info of next aghi %r5,STACK_SIZE # end of kernel stack of next stg %r5,__LC_KERNEL_STACK # store end of kernel stack diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index ea5099c9709c..e204f9597aaf 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -32,6 +32,7 @@ static const struct irq_class intrclass_names[] = { {.name = "VRT", .desc = "[EXT] Virtio" }, {.name = "SCP", .desc = "[EXT] Service Call" }, {.name = "IUC", .desc = "[EXT] IUCV" }, + {.name = "CPM", .desc = "[EXT] CPU Measurement" }, {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" }, {.name = "QDI", .desc = "[I/O] QDIO Interrupt" }, {.name = "DAS", .desc = "[I/O] DASD" }, diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index a895e69379f7..541a7509faeb 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -9,41 +9,26 @@ #include <linux/compiler.h> #include <linux/cpu.h> -#include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> -#include <linux/fs.h> #include <linux/smp.h> -#include <linux/stddef.h> #include <linux/slab.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/vmalloc.h> -#include <linux/user.h> #include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/reboot.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/notifier.h> #include <linux/tick.h> -#include <linux/elfcore.h> -#include <linux/kernel_stat.h> #include <linux/personality.h> #include <linux/syscalls.h> #include <linux/compat.h> #include <linux/kprobes.h> #include <linux/random.h> -#include <asm/compat.h> -#include <asm/uaccess.h> -#include <asm/pgtable.h> +#include <linux/module.h> #include <asm/system.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/irq.h> #include <asm/timer.h> #include <asm/nmi.h> +#include <asm/compat.h> #include <asm/smp.h> #include "entry.h" diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f5434d1ecb31..0c35dee10b00 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -305,8 +305,7 @@ static int set_amode_and_uaccess(unsigned long user_amode, */ static int __init early_parse_switch_amode(char *p) { - if (user_mode != SECONDARY_SPACE_MODE) - user_mode = PRIMARY_SPACE_MODE; + user_mode = PRIMARY_SPACE_MODE; return 0; } early_param("switch_amode", early_parse_switch_amode); @@ -315,10 +314,6 @@ static int __init early_parse_user_mode(char *p) { if (p && strcmp(p, "primary") == 0) user_mode = PRIMARY_SPACE_MODE; -#ifdef CONFIG_S390_EXEC_PROTECT - else if (p && strcmp(p, "secondary") == 0) - user_mode = SECONDARY_SPACE_MODE; -#endif else if (!p || strcmp(p, "home") == 0) user_mode = HOME_SPACE_MODE; else @@ -327,31 +322,9 @@ static int __init early_parse_user_mode(char *p) } early_param("user_mode", early_parse_user_mode); -#ifdef CONFIG_S390_EXEC_PROTECT -/* - * Enable execute protection? - */ -static int __init early_parse_noexec(char *p) -{ - if (!strncmp(p, "off", 3)) - return 0; - user_mode = SECONDARY_SPACE_MODE; - return 0; -} -early_param("noexec", early_parse_noexec); -#endif /* CONFIG_S390_EXEC_PROTECT */ - static void setup_addressing_mode(void) { - if (user_mode == SECONDARY_SPACE_MODE) { - if (set_amode_and_uaccess(PSW_ASC_SECONDARY, - PSW32_ASC_SECONDARY)) - pr_info("Execute protection active, " - "mvcos available\n"); - else - pr_info("Execute protection active, " - "mvcos not available\n"); - } else if (user_mode == PRIMARY_SPACE_MODE) { + if (user_mode == PRIMARY_SPACE_MODE) { if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) pr_info("Address spaces switched, " "mvcos available\n"); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 63c7d9ff220d..f8e85ecbc459 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -335,7 +335,7 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; if (!cpu_stopped(logical_cpu)) continue; - cpu_set(logical_cpu, cpu_present_map); + set_cpu_present(logical_cpu, true); smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; logical_cpu = cpumask_next(logical_cpu, &avail); if (logical_cpu >= nr_cpu_ids) @@ -367,7 +367,7 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) continue; __cpu_logical_map[logical_cpu] = cpu_id; smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN; - cpu_set(logical_cpu, cpu_present_map); + set_cpu_present(logical_cpu, true); if (cpu >= info->configured) smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; else @@ -385,7 +385,7 @@ static int __smp_rescan_cpus(void) { cpumask_t avail; - cpus_xor(avail, cpu_possible_map, cpu_present_map); + cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask); if (smp_use_sigp_detection) return smp_rescan_cpus_sigp(avail); else @@ -467,7 +467,7 @@ int __cpuinit start_secondary(void *cpuvoid) notify_cpu_starting(smp_processor_id()); /* Mark this cpu as online */ ipi_call_lock(); - cpu_set(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), true); ipi_call_unlock(); /* Switch on interrupts */ local_irq_enable(); @@ -644,7 +644,7 @@ int __cpu_disable(void) struct ec_creg_mask_parms cr_parms; int cpu = smp_processor_id(); - cpu_clear(cpu, cpu_online_map); + set_cpu_online(cpu, false); /* Disable pfault pseudo page faults on this cpu. */ pfault_fini(); @@ -654,8 +654,8 @@ int __cpu_disable(void) /* disable all external interrupts */ cr_parms.orvals[0] = 0; - cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 12 | - 1 << 11 | 1 << 10 | 1 << 6 | 1 << 4); + cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 11 | + 1 << 10 | 1 << 9 | 1 << 6 | 1 << 4); /* disable all I/O interrupts */ cr_parms.orvals[6] = 0; cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 | @@ -681,7 +681,7 @@ void __cpu_die(unsigned int cpu) atomic_dec(&init_mm.context.attach_count); } -void cpu_die(void) +void __noreturn cpu_die(void) { idle_task_exit(); while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) @@ -738,8 +738,8 @@ void __init smp_prepare_boot_cpu(void) BUG_ON(smp_processor_id() != 0); current_thread_info()->cpu = 0; - cpu_set(0, cpu_present_map); - cpu_set(0, cpu_online_map); + set_cpu_present(0, true); + set_cpu_online(0, true); S390_lowcore.percpu_offset = __per_cpu_offset[0]; current_set[0] = current; smp_cpu_state[0] = CPU_STATE_CONFIGURED; @@ -1016,21 +1016,21 @@ int __ref smp_rescan_cpus(void) get_online_cpus(); mutex_lock(&smp_cpu_state_mutex); - newcpus = cpu_present_map; + cpumask_copy(&newcpus, cpu_present_mask); rc = __smp_rescan_cpus(); if (rc) goto out; - cpus_andnot(newcpus, cpu_present_map, newcpus); - for_each_cpu_mask(cpu, newcpus) { + cpumask_andnot(&newcpus, cpu_present_mask, &newcpus); + for_each_cpu(cpu, &newcpus) { rc = smp_add_present_cpu(cpu); if (rc) - cpu_clear(cpu, cpu_present_map); + set_cpu_present(cpu, false); } rc = 0; out: mutex_unlock(&smp_cpu_state_mutex); put_online_cpus(); - if (!cpus_empty(newcpus)) + if (!cpumask_empty(&newcpus)) topology_schedule_update(); return rc; } diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 87be655557aa..a59557f1fb5f 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -810,7 +810,7 @@ static int etr_sync_clock_stop(struct etr_aib *aib, int port) etr_sync.etr_port = port; get_online_cpus(); atomic_set(&etr_sync.cpus, num_online_cpus() - 1); - rc = stop_machine(etr_sync_clock, &etr_sync, &cpu_online_map); + rc = stop_machine(etr_sync_clock, &etr_sync, cpu_online_mask); put_online_cpus(); return rc; } @@ -1579,7 +1579,7 @@ static void stp_work_fn(struct work_struct *work) memset(&stp_sync, 0, sizeof(stp_sync)); get_online_cpus(); atomic_set(&stp_sync.cpus, num_online_cpus() - 1); - stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map); + stop_machine(stp_sync_clock, &stp_sync, cpu_online_mask); put_online_cpus(); if (!check_sync_clock()) diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 94b06c31fc8a..2eafb8c7a746 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -52,20 +52,20 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) { cpumask_t mask; - cpus_clear(mask); + cpumask_clear(&mask); if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) { cpumask_copy(&mask, cpumask_of(cpu)); return mask; } while (info) { - if (cpu_isset(cpu, info->mask)) { + if (cpumask_test_cpu(cpu, &info->mask)) { mask = info->mask; break; } info = info->next; } - if (cpus_empty(mask)) - mask = cpumask_of_cpu(cpu); + if (cpumask_empty(&mask)) + cpumask_copy(&mask, cpumask_of(cpu)); return mask; } @@ -85,10 +85,10 @@ static void add_cpus_to_mask(struct topology_cpu *tl_cpu, if (cpu_logical_map(lcpu) != rcpu) continue; #ifdef CONFIG_SCHED_BOOK - cpu_set(lcpu, book->mask); + cpumask_set_cpu(lcpu, &book->mask); cpu_book_id[lcpu] = book->id; #endif - cpu_set(lcpu, core->mask); + cpumask_set_cpu(lcpu, &core->mask); cpu_core_id[lcpu] = core->id; smp_cpu_polarization[lcpu] = tl_cpu->pp; } @@ -101,13 +101,13 @@ static void clear_masks(void) info = &core_info; while (info) { - cpus_clear(info->mask); + cpumask_clear(&info->mask); info = info->next; } #ifdef CONFIG_SCHED_BOOK info = &book_info; while (info) { - cpus_clear(info->mask); + cpumask_clear(&info->mask); info = info->next; } #endif diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile index d13e8755a8cc..8ad2b34ad151 100644 --- a/arch/s390/kernel/vdso32/Makefile +++ b/arch/s390/kernel/vdso32/Makefile @@ -22,6 +22,9 @@ obj-y += vdso32_wrapper.o extra-y += vdso32.lds CPPFLAGS_vdso32.lds += -P -C -U$(ARCH) +# Disable gcov profiling for VDSO code +GCOV_PROFILE := n + # Force dependency (incbin is bad) $(obj)/vdso32_wrapper.o : $(obj)/vdso32.so diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile index 449352dda9cd..2a8ddfd12a5b 100644 --- a/arch/s390/kernel/vdso64/Makefile +++ b/arch/s390/kernel/vdso64/Makefile @@ -22,6 +22,9 @@ obj-y += vdso64_wrapper.o extra-y += vdso64.lds CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) +# Disable gcov profiling for VDSO code +GCOV_PROFILE := n + # Force dependency (incbin is bad) $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 1bc18cdb525b..56fe6bc81fee 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -77,7 +77,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); INIT_DATA_SECTION(0x100) - PERCPU(0x100, PAGE_SIZE) + PERCPU_SECTION(0x100) . = ALIGN(PAGE_SIZE); __init_end = .; /* freed after init ends here */ diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 3cc95dd0a3a6..075ddada4911 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -412,6 +412,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long struct dcss_segment *seg; int rc, diag_cc; + start_addr = end_addr = 0; seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA); if (seg == NULL) { rc = -ENOMEM; @@ -573,6 +574,7 @@ segment_modify_shared (char *name, int do_nonshared) unsigned long start_addr, end_addr, dummy; int rc, diag_cc; + start_addr = end_addr = 0; mutex_lock(&dcss_lock); seg = segment_by_name (name); if (seg == NULL) { @@ -681,8 +683,6 @@ void segment_save(char *name) { struct dcss_segment *seg; - int startpfn = 0; - int endpfn = 0; char cmd1[160]; char cmd2[80]; int i, response; @@ -698,8 +698,6 @@ segment_save(char *name) goto out; } - startpfn = seg->start_addr >> PAGE_SHIFT; - endpfn = (seg->end) >> PAGE_SHIFT; sprintf(cmd1, "DEFSEG %s", name); for (i=0; i<seg->segcnt; i++) { sprintf(cmd1+strlen(cmd1), " %lX-%lX %s", diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index ab988135e5c6..a0f9e730f26a 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -225,33 +225,6 @@ static noinline void do_sigbus(struct pt_regs *regs, long int_code, force_sig_info(SIGBUS, &si, tsk); } -#ifdef CONFIG_S390_EXEC_PROTECT -static noinline int signal_return(struct pt_regs *regs, long int_code, - unsigned long trans_exc_code) -{ - u16 instruction; - int rc; - - rc = __get_user(instruction, (u16 __user *) regs->psw.addr); - - if (!rc && instruction == 0x0a77) { - clear_tsk_thread_flag(current, TIF_PER_TRAP); - if (is_compat_task()) - sys32_sigreturn(); - else - sys_sigreturn(); - } else if (!rc && instruction == 0x0aad) { - clear_tsk_thread_flag(current, TIF_PER_TRAP); - if (is_compat_task()) - sys32_rt_sigreturn(); - else - sys_rt_sigreturn(); - } else - do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code); - return 0; -} -#endif /* CONFIG_S390_EXEC_PROTECT */ - static noinline void do_fault_error(struct pt_regs *regs, long int_code, unsigned long trans_exc_code, int fault) { @@ -259,13 +232,6 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code, switch (fault) { case VM_FAULT_BADACCESS: -#ifdef CONFIG_S390_EXEC_PROTECT - if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && - (trans_exc_code & 3) == 0) { - signal_return(regs, int_code, trans_exc_code); - break; - } -#endif /* CONFIG_S390_EXEC_PROTECT */ case VM_FAULT_BADMAP: /* Bad memory access. Check if it is kernel or user space. */ if (regs->psw.mask & PSW_MASK_PSTATE) { @@ -414,11 +380,6 @@ void __kprobes do_dat_exception(struct pt_regs *regs, long pgm_int_code, int access, fault; access = VM_READ | VM_EXEC | VM_WRITE; -#ifdef CONFIG_S390_EXEC_PROTECT - if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY && - (trans_exc_code & 3) == 0) - access = VM_EXEC; -#endif fault = do_exception(regs, access, trans_exc_code); if (unlikely(fault)) do_fault_error(regs, pgm_int_code & 255, trans_exc_code, fault); @@ -491,22 +452,28 @@ static int __init nopfault(char *str) __setup("nopfault", nopfault); -typedef struct { - __u16 refdiagc; - __u16 reffcode; - __u16 refdwlen; - __u16 refversn; - __u64 refgaddr; - __u64 refselmk; - __u64 refcmpmk; - __u64 reserved; -} __attribute__ ((packed, aligned(8))) pfault_refbk_t; +struct pfault_refbk { + u16 refdiagc; + u16 reffcode; + u16 refdwlen; + u16 refversn; + u64 refgaddr; + u64 refselmk; + u64 refcmpmk; + u64 reserved; +} __attribute__ ((packed, aligned(8))); int pfault_init(void) { - pfault_refbk_t refbk = - { 0x258, 0, 5, 2, __LC_CURRENT, 1ULL << 48, 1ULL << 48, - __PF_RES_FIELD }; + struct pfault_refbk refbk = { + .refdiagc = 0x258, + .reffcode = 0, + .refdwlen = 5, + .refversn = 2, + .refgaddr = __LC_CURRENT_PID, + .refselmk = 1ULL << 48, + .refcmpmk = 1ULL << 48, + .reserved = __PF_RES_FIELD }; int rc; if (!MACHINE_IS_VM || pfault_disable) @@ -524,8 +491,12 @@ int pfault_init(void) void pfault_fini(void) { - pfault_refbk_t refbk = - { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL }; + struct pfault_refbk refbk = { + .refdiagc = 0x258, + .reffcode = 1, + .refdwlen = 5, + .refversn = 2, + }; if (!MACHINE_IS_VM || pfault_disable) return; @@ -537,11 +508,15 @@ void pfault_fini(void) : : "a" (&refbk), "m" (refbk) : "cc"); } +static DEFINE_SPINLOCK(pfault_lock); +static LIST_HEAD(pfault_list); + static void pfault_interrupt(unsigned int ext_int_code, unsigned int param32, unsigned long param64) { struct task_struct *tsk; __u16 subcode; + pid_t pid; /* * Get the external interruption subcode & pfault @@ -553,44 +528,79 @@ static void pfault_interrupt(unsigned int ext_int_code, if ((subcode & 0xff00) != __SUBCODE_MASK) return; kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; - - /* - * Get the token (= address of the task structure of the affected task). - */ -#ifdef CONFIG_64BIT - tsk = (struct task_struct *) param64; -#else - tsk = (struct task_struct *) param32; -#endif - + if (subcode & 0x0080) { + /* Get the token (= pid of the affected task). */ + pid = sizeof(void *) == 4 ? param32 : param64; + rcu_read_lock(); + tsk = find_task_by_pid_ns(pid, &init_pid_ns); + if (tsk) + get_task_struct(tsk); + rcu_read_unlock(); + if (!tsk) + return; + } else { + tsk = current; + } + spin_lock(&pfault_lock); if (subcode & 0x0080) { /* signal bit is set -> a page has been swapped in by VM */ - if (xchg(&tsk->thread.pfault_wait, -1) != 0) { + if (tsk->thread.pfault_wait == 1) { /* Initial interrupt was faster than the completion * interrupt. pfault_wait is valid. Set pfault_wait * back to zero and wake up the process. This can * safely be done because the task is still sleeping * and can't produce new pfaults. */ tsk->thread.pfault_wait = 0; + list_del(&tsk->thread.list); wake_up_process(tsk); - put_task_struct(tsk); + } else { + /* Completion interrupt was faster than initial + * interrupt. Set pfault_wait to -1 so the initial + * interrupt doesn't put the task to sleep. */ + tsk->thread.pfault_wait = -1; } + put_task_struct(tsk); } else { /* signal bit not set -> a real page is missing. */ - get_task_struct(tsk); - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - if (xchg(&tsk->thread.pfault_wait, 1) != 0) { + if (tsk->thread.pfault_wait == -1) { /* Completion interrupt was faster than the initial - * interrupt (swapped in a -1 for pfault_wait). Set - * pfault_wait back to zero and exit. This can be - * done safely because tsk is running in kernel - * mode and can't produce new pfaults. */ + * interrupt (pfault_wait == -1). Set pfault_wait + * back to zero and exit. */ tsk->thread.pfault_wait = 0; - set_task_state(tsk, TASK_RUNNING); - put_task_struct(tsk); - } else + } else { + /* Initial interrupt arrived before completion + * interrupt. Let the task sleep. */ + tsk->thread.pfault_wait = 1; + list_add(&tsk->thread.list, &pfault_list); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); set_tsk_need_resched(tsk); + } + } + spin_unlock(&pfault_lock); +} + +static int __cpuinit pfault_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + struct thread_struct *thread, *next; + struct task_struct *tsk; + + switch (action) { + case CPU_DEAD: + case CPU_DEAD_FROZEN: + spin_lock_irq(&pfault_lock); + list_for_each_entry_safe(thread, next, &pfault_list, list) { + thread->pfault_wait = 0; + list_del(&thread->list); + tsk = container_of(thread, struct task_struct, thread); + wake_up_process(tsk); + } + spin_unlock_irq(&pfault_lock); + break; + default: + break; } + return NOTIFY_OK; } static int __init pfault_irq_init(void) @@ -599,22 +609,21 @@ static int __init pfault_irq_init(void) if (!MACHINE_IS_VM) return 0; - /* - * Try to get pfault pseudo page faults going. - */ rc = register_external_interrupt(0x2603, pfault_interrupt); - if (rc) { - pfault_disable = 1; - return rc; - } - if (pfault_init() == 0) - return 0; + if (rc) + goto out_extint; + rc = pfault_init() == 0 ? 0 : -EOPNOTSUPP; + if (rc) + goto out_pfault; + hotcpu_notifier(pfault_cpu_notify, 0); + return 0; - /* Tough luck, no pfault. */ - pfault_disable = 1; +out_pfault: unregister_external_interrupt(0x2603, pfault_interrupt); - return 0; +out_extint: + pfault_disable = 1; + return rc; } early_initcall(pfault_irq_init); -#endif +#endif /* CONFIG_PFAULT */ diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index 639cd21f2218..a4d856db9154 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c @@ -13,7 +13,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *pteptr, pte_t pteval) { pmd_t *pmdp = (pmd_t *) pteptr; - pte_t shadow_pteval = pteval; unsigned long mask; if (!MACHINE_HAS_HPAGE) { @@ -21,18 +20,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, mask = pte_val(pteval) & (_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO); pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask; - if (mm->context.noexec) { - pteptr += PTRS_PER_PTE; - pte_val(shadow_pteval) = - (_SEGMENT_ENTRY + __pa(pteptr)) | mask; - } } pmd_val(*pmdp) = pte_val(pteval); - if (mm->context.noexec) { - pmdp = get_shadow_table(pmdp); - pmd_val(*pmdp) = pte_val(shadow_pteval); - } } int arch_prepare_hugepage(struct page *page) diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index bb409332a484..dfefc2171691 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -175,7 +175,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) pmd = pmd_offset(pud, address); pte = pte_offset_kernel(pmd, address); if (!enable) { - ptep_invalidate(&init_mm, address, pte); + __ptep_ipte(address, pte); + pte_val(*pte) = _PAGE_TYPE_EMPTY; continue; } *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW)); diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index f05edcc3beff..d013ed39743b 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -28,7 +28,7 @@ static void change_page_attr(unsigned long addr, int numpages, pte = *ptep; pte = set(pte); - ptep_invalidate(&init_mm, addr, ptep); + __ptep_ipte(addr, ptep); *ptep = pte; addr += PAGE_SIZE; } diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index e1850c28cd68..14c6fae6fe6b 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -36,11 +36,9 @@ struct rcu_table_freelist { ((PAGE_SIZE - sizeof(struct rcu_table_freelist)) \ / sizeof(unsigned long)) -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); static DEFINE_PER_CPU(struct rcu_table_freelist *, rcu_table_freelist); static void __page_table_free(struct mm_struct *mm, unsigned long *table); -static void __crst_table_free(struct mm_struct *mm, unsigned long *table); static struct rcu_table_freelist *rcu_table_freelist_get(struct mm_struct *mm) { @@ -67,7 +65,7 @@ static void rcu_table_freelist_callback(struct rcu_head *head) while (batch->pgt_index > 0) __page_table_free(batch->mm, batch->table[--batch->pgt_index]); while (batch->crst_index < RCU_FREELIST_SIZE) - __crst_table_free(batch->mm, batch->table[batch->crst_index++]); + crst_table_free(batch->mm, batch->table[batch->crst_index++]); free_page((unsigned long) batch); } @@ -125,63 +123,33 @@ static int __init parse_vmalloc(char *arg) } early_param("vmalloc", parse_vmalloc); -unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec) +unsigned long *crst_table_alloc(struct mm_struct *mm) { struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER); if (!page) return NULL; - page->index = 0; - if (noexec) { - struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER); - if (!shadow) { - __free_pages(page, ALLOC_ORDER); - return NULL; - } - page->index = page_to_phys(shadow); - } - spin_lock_bh(&mm->context.list_lock); - list_add(&page->lru, &mm->context.crst_list); - spin_unlock_bh(&mm->context.list_lock); return (unsigned long *) page_to_phys(page); } -static void __crst_table_free(struct mm_struct *mm, unsigned long *table) -{ - unsigned long *shadow = get_shadow_table(table); - - if (shadow) - free_pages((unsigned long) shadow, ALLOC_ORDER); - free_pages((unsigned long) table, ALLOC_ORDER); -} - void crst_table_free(struct mm_struct *mm, unsigned long *table) { - struct page *page = virt_to_page(table); - - spin_lock_bh(&mm->context.list_lock); - list_del(&page->lru); - spin_unlock_bh(&mm->context.list_lock); - __crst_table_free(mm, table); + free_pages((unsigned long) table, ALLOC_ORDER); } void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table) { struct rcu_table_freelist *batch; - struct page *page = virt_to_page(table); - spin_lock_bh(&mm->context.list_lock); - list_del(&page->lru); - spin_unlock_bh(&mm->context.list_lock); if (atomic_read(&mm->mm_users) < 2 && cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { - __crst_table_free(mm, table); + crst_table_free(mm, table); return; } batch = rcu_table_freelist_get(mm); if (!batch) { smp_call_function(smp_sync, NULL, 1); - __crst_table_free(mm, table); + crst_table_free(mm, table); return; } batch->table[--batch->crst_index] = table; @@ -197,7 +165,7 @@ int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) BUG_ON(limit > (1UL << 53)); repeat: - table = crst_table_alloc(mm, mm->context.noexec); + table = crst_table_alloc(mm); if (!table) return -ENOMEM; spin_lock_bh(&mm->page_table_lock); @@ -273,7 +241,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm) unsigned long *table; unsigned long bits; - bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL; + bits = (mm->context.has_pgste) ? 3UL : 1UL; spin_lock_bh(&mm->context.list_lock); page = NULL; if (!list_empty(&mm->context.pgtable_list)) { @@ -329,7 +297,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table) struct page *page; unsigned long bits; - bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL; + bits = (mm->context.has_pgste) ? 3UL : 1UL; bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); page = pfn_to_page(__pa(table) >> PAGE_SHIFT); spin_lock_bh(&mm->context.list_lock); @@ -366,7 +334,7 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table) page_table_free(mm, table); return; } - bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL; + bits = (mm->context.has_pgste) ? 3UL : 1UL; bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); page = pfn_to_page(__pa(table) >> PAGE_SHIFT); spin_lock_bh(&mm->context.list_lock); @@ -379,25 +347,6 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table) rcu_table_freelist_finish(); } -void disable_noexec(struct mm_struct *mm, struct task_struct *tsk) -{ - struct page *page; - - spin_lock_bh(&mm->context.list_lock); - /* Free shadow region and segment tables. */ - list_for_each_entry(page, &mm->context.crst_list, lru) - if (page->index) { - free_pages((unsigned long) page->index, ALLOC_ORDER); - page->index = 0; - } - /* "Free" second halves of page tables. */ - list_for_each_entry(page, &mm->context.pgtable_list, lru) - page->flags &= ~SECOND_HALVES; - spin_unlock_bh(&mm->context.list_lock); - mm->context.noexec = 0; - update_mm(mm, tsk); -} - /* * switch on pgstes for its userspace process (for kvm) */ diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 34c43f23b28c..8c1970d1dd91 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -95,7 +95,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) pu_dir = vmem_pud_alloc(); if (!pu_dir) goto out; - pgd_populate_kernel(&init_mm, pg_dir, pu_dir); + pgd_populate(&init_mm, pg_dir, pu_dir); } pu_dir = pud_offset(pg_dir, address); @@ -103,7 +103,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) pm_dir = vmem_pmd_alloc(); if (!pm_dir) goto out; - pud_populate_kernel(&init_mm, pu_dir, pm_dir); + pud_populate(&init_mm, pu_dir, pm_dir); } pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); @@ -123,7 +123,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) pt_dir = vmem_pte_alloc(); if (!pt_dir) goto out; - pmd_populate_kernel(&init_mm, pm_dir, pt_dir); + pmd_populate(&init_mm, pm_dir, pt_dir); } pt_dir = pte_offset_kernel(pm_dir, address); @@ -159,7 +159,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size) continue; if (pmd_huge(*pm_dir)) { - pmd_clear_kernel(pm_dir); + pmd_clear(pm_dir); address += HPAGE_SIZE - PAGE_SIZE; continue; } @@ -192,7 +192,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) pu_dir = vmem_pud_alloc(); if (!pu_dir) goto out; - pgd_populate_kernel(&init_mm, pg_dir, pu_dir); + pgd_populate(&init_mm, pg_dir, pu_dir); } pu_dir = pud_offset(pg_dir, address); @@ -200,7 +200,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) pm_dir = vmem_pmd_alloc(); if (!pm_dir) goto out; - pud_populate_kernel(&init_mm, pu_dir, pm_dir); + pud_populate(&init_mm, pu_dir, pm_dir); } pm_dir = pmd_offset(pu_dir, address); @@ -208,7 +208,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) pt_dir = vmem_pte_alloc(); if (!pt_dir) goto out; - pmd_populate_kernel(&init_mm, pm_dir, pt_dir); + pmd_populate(&init_mm, pm_dir, pt_dir); } pt_dir = pte_offset_kernel(pm_dir, address); diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c index 33cbd373cce4..053caa0fd276 100644 --- a/arch/s390/oprofile/hwsampler.c +++ b/arch/s390/oprofile/hwsampler.c @@ -5,6 +5,7 @@ * Author: Heinz Graalfs <graalfs@de.ibm.com> */ +#include <linux/kernel_stat.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/smp.h> @@ -674,17 +675,11 @@ int hwsampler_activate(unsigned int cpu) static void hws_ext_handler(unsigned int ext_int_code, unsigned int param32, unsigned long param64) { - int cpu; struct hws_cpu_buffer *cb; - cpu = smp_processor_id(); - cb = &per_cpu(sampler_cpu_buffer, cpu); - - atomic_xchg( - &cb->ext_params, - atomic_read(&cb->ext_params) - | S390_lowcore.ext_params); - + kstat_cpu(smp_processor_id()).irqs[EXTINT_CPM]++; + cb = &__get_cpu_var(sampler_cpu_buffer); + atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); if (hws_wq) queue_work(hws_wq, &cb->worker); } @@ -764,7 +759,7 @@ static int worker_check_error(unsigned int cpu, int ext_params) if (!sdbt || !*sdbt) return -EINVAL; - if (ext_params & EI_IEA) + if (ext_params & EI_PRA) cb->req_alert++; if (ext_params & EI_LSDA) @@ -1009,7 +1004,7 @@ int hwsampler_deallocate() if (hws_state != HWS_STOPPED) goto deallocate_exit; - smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ + ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ deallocate_sdbt(); hws_state = HWS_DEALLOCATED; @@ -1123,7 +1118,7 @@ int hwsampler_shutdown() mutex_lock(&hws_sem); if (hws_state == HWS_STOPPED) { - smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ + ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ deallocate_sdbt(); } if (hws_wq) { @@ -1198,7 +1193,7 @@ start_all_exit: hws_oom = 1; hws_flush_all = 0; /* now let them in, 1407 CPUMF external interrupts */ - smp_ctl_set_bit(0, 5); /* set CR0 bit 58 */ + ctl_set_bit(0, 5); /* set CR0 bit 58 */ return 0; } diff --git a/arch/score/Kconfig.debug b/arch/score/Kconfig.debug index 451ed54ce646..a1f346df0a71 100644 --- a/arch/score/Kconfig.debug +++ b/arch/score/Kconfig.debug @@ -16,15 +16,6 @@ config CMDLINE other cases you can specify kernel args so that you don't have to set them up in board prom initialization routines. -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config RUNTIME_DEBUG bool "Enable run-time debugging" depends on DEBUG_KERNEL diff --git a/arch/score/mm/init.c b/arch/score/mm/init.c index 50fdec54c70a..cee6bce1e30c 100644 --- a/arch/score/mm/init.c +++ b/arch/score/mm/init.c @@ -38,8 +38,6 @@ #include <asm/sections.h> #include <asm/tlb.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - unsigned long empty_zero_page; EXPORT_SYMBOL_GPL(empty_zero_page); diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 1553d56cf4e0..c1d5a820b1aa 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -28,15 +28,6 @@ config STACK_DEBUG every function call and will therefore incur a major performance hit. Most users should say N. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" depends on DEBUG_KERNEL && (MMU || BROKEN) && !PAGE_SIZE_64KB diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h index 75abb38dffd5..6c308d8b9a50 100644 --- a/arch/sh/include/asm/tlb.h +++ b/arch/sh/include/asm/tlb.h @@ -23,8 +23,6 @@ struct mmu_gather { unsigned long start, end; }; -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - static inline void init_tlb_gather(struct mmu_gather *tlb) { tlb->start = TASK_SIZE; @@ -36,17 +34,13 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) } } -static inline struct mmu_gather * -tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +static inline void +tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); - tlb->mm = mm; tlb->fullmm = full_mm_flush; init_tlb_gather(tlb); - - return tlb; } static inline void @@ -57,8 +51,6 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) /* keep the page table cache within bounds */ check_pgt_cache(); - - put_cpu_var(mmu_gathers); } static inline void @@ -91,7 +83,21 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) } } -#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page) +static inline void tlb_flush_mmu(struct mmu_gather *tlb) +{ +} + +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + free_page_and_swap_cache(page); + return 1; /* avoid calling tlb_flush_mmu */ +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + __tlb_remove_page(tlb, page); +} + #define pte_free_tlb(tlb, ptep, addr) pte_free((tlb)->mm, ptep) #define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp) #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index af4d46187a79..731c10ce67b5 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -66,7 +66,7 @@ SECTIONS __machvec_end = .; } - PERCPU(L1_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(L1_CACHE_BYTES) /* * .exit.text is discarded at runtime, not link time, to deal with diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 0d3f912e3334..58a93fb3d965 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -28,7 +28,6 @@ #include <asm/cache.h> #include <asm/sizes.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); pgd_t swapper_pg_dir[PTRS_PER_PGD]; void __init generic_mem_init(void) diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index d9a795efbc04..6db35fba79fd 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug @@ -6,15 +6,6 @@ config TRACE_IRQFLAGS_SUPPORT source "lib/Kconfig.debug" -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config DEBUG_DCFLUSH bool "D-cache flush debugging" depends on SPARC64 && DEBUG_KERNEL diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h index 5bdfa2c6e400..4e5e0878144f 100644 --- a/arch/sparc/include/asm/pgalloc_64.h +++ b/arch/sparc/include/asm/pgalloc_64.h @@ -78,4 +78,7 @@ static inline void check_pgt_cache(void) quicklist_trim(0, NULL, 25, 16); } +#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte) +#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) + #endif /* _SPARC64_PGALLOC_H */ diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index b77128c80524..1e03c5a6b4f7 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -655,9 +655,11 @@ static inline int pte_special(pte_t pte) #define pte_unmap(pte) do { } while (0) /* Actual page table PTE updates. */ -extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig); +extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, + pte_t *ptep, pte_t orig, int fullmm); -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) +static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte, int fullmm) { pte_t orig = *ptep; @@ -670,12 +672,19 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p * and SUN4V pte layout, so this inline test is fine. */ if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID)) - tlb_batch_add(mm, addr, ptep, orig); + tlb_batch_add(mm, addr, ptep, orig, fullmm); } +#define set_pte_at(mm,addr,ptep,pte) \ + __set_pte_at((mm), (addr), (ptep), (pte), 0) + #define pte_clear(mm,addr,ptep) \ set_pte_at((mm), (addr), (ptep), __pte(0UL)) +#define __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL +#define pte_clear_not_present_full(mm,addr,ptep,fullmm) \ + __set_pte_at((mm), (addr), (ptep), __pte(0UL), (fullmm)) + #ifdef DCACHE_ALIASING_POSSIBLE #define __HAVE_ARCH_MOVE_PTE #define move_pte(pte, prot, old_addr, new_addr) \ diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h index dca406b9b6fc..190e18913cc6 100644 --- a/arch/sparc/include/asm/tlb_64.h +++ b/arch/sparc/include/asm/tlb_64.h @@ -7,66 +7,11 @@ #include <asm/tlbflush.h> #include <asm/mmu_context.h> -#define TLB_BATCH_NR 192 - -/* - * For UP we don't need to worry about TLB flush - * and page free order so much.. - */ -#ifdef CONFIG_SMP - #define FREE_PTE_NR 506 - #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U) -#else - #define FREE_PTE_NR 1 - #define tlb_fast_mode(bp) 1 -#endif - -struct mmu_gather { - struct mm_struct *mm; - unsigned int pages_nr; - unsigned int need_flush; - unsigned int fullmm; - unsigned int tlb_nr; - unsigned long vaddrs[TLB_BATCH_NR]; - struct page *pages[FREE_PTE_NR]; -}; - -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - #ifdef CONFIG_SMP extern void smp_flush_tlb_pending(struct mm_struct *, unsigned long, unsigned long *); #endif -extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *); -extern void flush_tlb_pending(void); - -static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) -{ - struct mmu_gather *mp = &get_cpu_var(mmu_gathers); - - BUG_ON(mp->tlb_nr); - - mp->mm = mm; - mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U; - mp->fullmm = full_mm_flush; - - return mp; -} - - -static inline void tlb_flush_mmu(struct mmu_gather *mp) -{ - if (!mp->fullmm) - flush_tlb_pending(); - if (mp->need_flush) { - free_pages_and_swap_cache(mp->pages, mp->pages_nr); - mp->pages_nr = 0; - mp->need_flush = 0; - } - -} - #ifdef CONFIG_SMP extern void smp_flush_tlb_mm(struct mm_struct *mm); #define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm) @@ -74,38 +19,14 @@ extern void smp_flush_tlb_mm(struct mm_struct *mm); #define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT) #endif -static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end) -{ - tlb_flush_mmu(mp); - - if (mp->fullmm) - mp->fullmm = 0; - - /* keep the page table cache within bounds */ - check_pgt_cache(); - - put_cpu_var(mmu_gathers); -} - -static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page) -{ - if (tlb_fast_mode(mp)) { - free_page_and_swap_cache(page); - return; - } - mp->need_flush = 1; - mp->pages[mp->pages_nr++] = page; - if (mp->pages_nr >= FREE_PTE_NR) - tlb_flush_mmu(mp); -} - -#define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0) -#define pte_free_tlb(mp, ptepage, addr) pte_free((mp)->mm, ptepage) -#define pmd_free_tlb(mp, pmdp, addr) pmd_free((mp)->mm, pmdp) -#define pud_free_tlb(tlb,pudp, addr) __pud_free_tlb(tlb,pudp,addr) +extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *); +extern void flush_tlb_pending(void); -#define tlb_migrate_finish(mm) do { } while (0) #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) +#define tlb_flush(tlb) flush_tlb_pending() + +#include <asm-generic/tlb.h> #endif /* _SPARC64_TLB_H */ diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h index fbb675dbe0c9..2ef463494153 100644 --- a/arch/sparc/include/asm/tlbflush_64.h +++ b/arch/sparc/include/asm/tlbflush_64.h @@ -5,9 +5,17 @@ #include <asm/mmu_context.h> /* TSB flush operations. */ -struct mmu_gather; + +#define TLB_BATCH_NR 192 + +struct tlb_batch { + struct mm_struct *mm; + unsigned long tlb_nr; + unsigned long vaddrs[TLB_BATCH_NR]; +}; + extern void flush_tsb_kernel_range(unsigned long start, unsigned long end); -extern void flush_tsb_user(struct mmu_gather *mp); +extern void flush_tsb_user(struct tlb_batch *tb); /* TLB flush operations. */ diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index 3609bdee9ed2..3249d3f3234d 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -82,7 +82,7 @@ static void prom_sync_me(void) "nop\n\t" : : "r" (&trapbase)); prom_printf("PROM SYNC COMMAND...\n"); - show_free_areas(); + show_free_areas(0); if(current->pid != 0) { local_irq_enable(); sys_sync(); diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 92b557afe535..c0220759003e 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -108,7 +108,7 @@ SECTIONS __sun4v_2insn_patch_end = .; } - PERCPU(SMP_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(SMP_CACHE_BYTES) . = ALIGN(PAGE_SIZE); __init_end = .; diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index 4c31e2b6e71b..ca217327e8d2 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -37,8 +37,6 @@ #include <asm/prom.h> #include <asm/leon.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - unsigned long *sparc_valid_addr_bitmap; EXPORT_SYMBOL(sparc_valid_addr_bitmap); @@ -78,7 +76,7 @@ void __init kmap_init(void) void show_mem(unsigned int filter) { printk("Mem-info:\n"); - show_free_areas(); + show_free_areas(filter); printk("Free swap: %6ldkB\n", nr_swap_pages << (PAGE_SHIFT-10)); printk("%ld pages of RAM\n", totalram_pages); diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index d8f21e24a82f..b1f279cd00bf 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -19,33 +19,34 @@ /* Heavily inspired by the ppc64 code. */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +static DEFINE_PER_CPU(struct tlb_batch, tlb_batch); void flush_tlb_pending(void) { - struct mmu_gather *mp = &get_cpu_var(mmu_gathers); + struct tlb_batch *tb = &get_cpu_var(tlb_batch); - if (mp->tlb_nr) { - flush_tsb_user(mp); + if (tb->tlb_nr) { + flush_tsb_user(tb); - if (CTX_VALID(mp->mm->context)) { + if (CTX_VALID(tb->mm->context)) { #ifdef CONFIG_SMP - smp_flush_tlb_pending(mp->mm, mp->tlb_nr, - &mp->vaddrs[0]); + smp_flush_tlb_pending(tb->mm, tb->tlb_nr, + &tb->vaddrs[0]); #else - __flush_tlb_pending(CTX_HWBITS(mp->mm->context), - mp->tlb_nr, &mp->vaddrs[0]); + __flush_tlb_pending(CTX_HWBITS(tb->mm->context), + tb->tlb_nr, &tb->vaddrs[0]); #endif } - mp->tlb_nr = 0; + tb->tlb_nr = 0; } - put_cpu_var(mmu_gathers); + put_cpu_var(tlb_batch); } -void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig) +void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, + pte_t *ptep, pte_t orig, int fullmm) { - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); + struct tlb_batch *tb = &get_cpu_var(tlb_batch); unsigned long nr; vaddr &= PAGE_MASK; @@ -77,21 +78,25 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t no_cache_flush: - if (mp->fullmm) + if (fullmm) { + put_cpu_var(tlb_batch); return; + } - nr = mp->tlb_nr; + nr = tb->tlb_nr; - if (unlikely(nr != 0 && mm != mp->mm)) { + if (unlikely(nr != 0 && mm != tb->mm)) { flush_tlb_pending(); nr = 0; } if (nr == 0) - mp->mm = mm; + tb->mm = mm; - mp->vaddrs[nr] = vaddr; - mp->tlb_nr = ++nr; + tb->vaddrs[nr] = vaddr; + tb->tlb_nr = ++nr; if (nr >= TLB_BATCH_NR) flush_tlb_pending(); + + put_cpu_var(tlb_batch); } diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 101d7c82870b..948461513499 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -47,12 +47,13 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) } } -static void __flush_tsb_one(struct mmu_gather *mp, unsigned long hash_shift, unsigned long tsb, unsigned long nentries) +static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift, + unsigned long tsb, unsigned long nentries) { unsigned long i; - for (i = 0; i < mp->tlb_nr; i++) { - unsigned long v = mp->vaddrs[i]; + for (i = 0; i < tb->tlb_nr; i++) { + unsigned long v = tb->vaddrs[i]; unsigned long tag, ent, hash; v &= ~0x1UL; @@ -65,9 +66,9 @@ static void __flush_tsb_one(struct mmu_gather *mp, unsigned long hash_shift, uns } } -void flush_tsb_user(struct mmu_gather *mp) +void flush_tsb_user(struct tlb_batch *tb) { - struct mm_struct *mm = mp->mm; + struct mm_struct *mm = tb->mm; unsigned long nentries, base, flags; spin_lock_irqsave(&mm->context.lock, flags); @@ -76,7 +77,7 @@ void flush_tsb_user(struct mmu_gather *mp) nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; if (tlb_type == cheetah_plus || tlb_type == hypervisor) base = __pa(base); - __flush_tsb_one(mp, PAGE_SHIFT, base, nentries); + __flush_tsb_one(tb, PAGE_SHIFT, base, nentries); #ifdef CONFIG_HUGETLB_PAGE if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { @@ -84,7 +85,7 @@ void flush_tsb_user(struct mmu_gather *mp) nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; if (tlb_type == cheetah_plus || tlb_type == hypervisor) base = __pa(base); - __flush_tsb_one(mp, HPAGE_SHIFT, base, nentries); + __flush_tsb_one(tb, HPAGE_SHIFT, base, nentries); } #endif spin_unlock_irqrestore(&mm->context.lock, flags); diff --git a/arch/tile/Kconfig.debug b/arch/tile/Kconfig.debug index 9bc161a02c71..ddbfc3322d7f 100644 --- a/arch/tile/Kconfig.debug +++ b/arch/tile/Kconfig.debug @@ -21,15 +21,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config DEBUG_EXTRA_FLAGS string "Additional compiler arguments when building with '-g'" depends on DEBUG_INFO diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S index 38f64fafdc10..631f10de12fe 100644 --- a/arch/tile/kernel/vmlinux.lds.S +++ b/arch/tile/kernel/vmlinux.lds.S @@ -60,7 +60,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); VMLINUX_SYMBOL(_sinitdata) = .; INIT_DATA_SECTION(16) :data =0 - PERCPU(L2_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(L2_CACHE_BYTES) . = ALIGN(PAGE_SIZE); VMLINUX_SYMBOL(_einitdata) = .; diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c index d6e87fda2fb2..4e10c4023028 100644 --- a/arch/tile/mm/init.c +++ b/arch/tile/mm/init.c @@ -60,8 +60,6 @@ unsigned long VMALLOC_RESERVE = CONFIG_VMALLOC_RESERVE; EXPORT_SYMBOL(VMALLOC_RESERVE); #endif -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* Create an L2 page table */ static pte_t * __init alloc_pte(void) { diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index 8fce5e536b0f..68205fd3b08c 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -28,13 +28,13 @@ config GCOV 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" - default N - help - Track the maximum kernel stack usage - this will look at each - kernel stack at process exit and log it if it's the deepest - stack seen so far. +config EARLY_PRINTK + bool "Early printk" + default y + ---help--- + Write kernel log output directly to stdout. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. - This option will slow down process creation and destruction somewhat. endmenu diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86 index a9da516a5274..795ea8e869f4 100644 --- a/arch/um/Kconfig.x86 +++ b/arch/um/Kconfig.x86 @@ -29,10 +29,10 @@ config X86_64 def_bool 64BIT config RWSEM_XCHGADD_ALGORITHM - def_bool X86_XADD + def_bool X86_XADD && 64BIT config RWSEM_GENERIC_SPINLOCK - def_bool !X86_XADD + def_bool !RWSEM_XCHGADD_ALGORITHM config 3_LEVEL_PGTABLES bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 1d9b6ae967b0..e7582e1d248c 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -9,7 +9,7 @@ slip-objs := slip_kern.o slip_user.o slirp-objs := slirp_kern.o slirp_user.o daemon-objs := daemon_kern.o daemon_user.o -mcast-objs := mcast_kern.o mcast_user.o +umcast-objs := umcast_kern.o umcast_user.o net-objs := net_kern.o net_user.o mconsole-objs := mconsole_kern.o mconsole_user.o hostaudio-objs := hostaudio_kern.o @@ -44,7 +44,7 @@ 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_MCAST) += umcast.o obj-$(CONFIG_UML_NET_PCAP) += pcap.o obj-$(CONFIG_UML_NET) += net.o obj-$(CONFIG_MCONSOLE) += mconsole.o diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h deleted file mode 100644 index 6fa282e896be..000000000000 --- a/arch/um/drivers/mcast.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 { - char *addr; - unsigned short port; - void *mcast_addr; - int ttl; - void *dev; -}; - -extern const struct net_user_info mcast_user_info; - -extern int mcast_user_write(int fd, void *buf, int len, - struct mcast_data *pri); - -#endif diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c deleted file mode 100644 index ffc6416d5ed7..000000000000 --- a/arch/um/drivers/mcast_kern.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 - * 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/init.h" -#include <linux/netdevice.h> -#include "mcast.h" -#include "net_kern.h" - -struct mcast_init { - char *addr; - int port; - int ttl; -}; - -static void mcast_init(struct net_device *dev, void *data) -{ - struct uml_net_private *pri; - struct mcast_data *dpri; - struct mcast_init *init = data; - - pri = netdev_priv(dev); - dpri = (struct mcast_data *) pri->user; - dpri->addr = init->addr; - dpri->port = init->port; - dpri->ttl = init->ttl; - dpri->dev = dev; - - printk("mcast backend multicast address: %s:%u, TTL:%u\n", - dpri->addr, dpri->port, dpri->ttl); -} - -static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - 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) -{ - return mcast_user_write(fd, skb->data, skb->len, - (struct mcast_data *) &lp->user); -} - -static const struct net_kern_info mcast_kern_info = { - .init = mcast_init, - .protocol = eth_protocol, - .read = mcast_read, - .write = mcast_write, -}; - -static int mcast_setup(char *str, char **mac_out, void *data) -{ - struct mcast_init *init = data; - char *port_str = NULL, *ttl_str = NULL, *remain; - char *last; - - *init = ((struct mcast_init) - { .addr = "239.192.168.1", - .port = 1102, - .ttl = 1 }); - - remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, - NULL); - if (remain != NULL) { - printk(KERN_ERR "mcast_setup - Extra garbage on " - "specification : '%s'\n", remain); - return 0; - } - - 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", - port_str); - return 0; - } - } - - 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", - ttl_str); - return 0; - } - } - - printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, - init->port, init->ttl); - - return 1; -} - -static struct transport mcast_transport = { - .list = LIST_HEAD_INIT(mcast_transport.list), - .name = "mcast", - .setup = mcast_setup, - .user = &mcast_user_info, - .kern = &mcast_kern_info, - .private_size = sizeof(struct mcast_data), - .setup_size = sizeof(struct mcast_init), -}; - -static int register_mcast(void) -{ - register_transport(&mcast_transport); - return 0; -} - -late_initcall(register_mcast); diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c deleted file mode 100644 index ee19e91568a2..000000000000 --- a/arch/um/drivers/mcast_user.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 - * James Leu (jleu@mindspring.net). - * Copyright (C) 2001 by various other people who didn't put their name here. - * - * Licensed under the GPL. - * - */ - -#include <unistd.h> -#include <errno.h> -#include <netinet/in.h> -#include "kern_constants.h" -#include "mcast.h" -#include "net_user.h" -#include "um_malloc.h" -#include "user.h" - -static struct sockaddr_in *new_addr(char *addr, unsigned short port) -{ - struct sockaddr_in *sin; - - sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); - if (sin == NULL) { - printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " - "failed\n"); - return NULL; - } - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = in_aton(addr); - sin->sin_port = htons(port); - return sin; -} - -static int mcast_user_init(void *data, void *dev) -{ - struct mcast_data *pri = data; - - pri->mcast_addr = new_addr(pri->addr, pri->port); - pri->dev = dev; - return 0; -} - -static void mcast_remove(void *data) -{ - struct mcast_data *pri = data; - - kfree(pri->mcast_addr); - pri->mcast_addr = NULL; -} - -static int mcast_open(void *data) -{ - struct mcast_data *pri = data; - struct sockaddr_in *sin = pri->mcast_addr; - struct ip_mreq mreq; - int fd, yes = 1, err = -EINVAL; - - - if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) - goto out; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - - if (fd < 0) { - err = -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(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " - "errno = %d\n", errno); - goto out_close; - } - - /* set ttl according to config */ - if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, - sizeof(pri->ttl)) < 0) { - err = -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(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(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, - &mreq, sizeof(mreq)) < 0) { - err = -errno; - 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: - close(fd); - out: - return err; -} - -static void mcast_close(int fd, void *data) -{ - struct ip_mreq mreq; - struct mcast_data *pri = data; - struct sockaddr_in *sin = pri->mcast_addr; - - mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; - mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " - "error = %d\n", errno); - } - - close(fd); -} - -int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) -{ - struct sockaddr_in *data_addr = pri->mcast_addr; - - return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); -} - -const struct net_user_info mcast_user_info = { - .init = mcast_user_init, - .open = mcast_open, - .close = mcast_close, - .remove = mcast_remove, - .add_address = NULL, - .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, -}; diff --git a/arch/um/drivers/umcast.h b/arch/um/drivers/umcast.h new file mode 100644 index 000000000000..6f8c0fe890fb --- /dev/null +++ b/arch/um/drivers/umcast.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + +#ifndef __DRIVERS_UMCAST_H +#define __DRIVERS_UMCAST_H + +#include "net_user.h" + +struct umcast_data { + char *addr; + unsigned short lport; + unsigned short rport; + void *listen_addr; + void *remote_addr; + int ttl; + int unicast; + void *dev; +}; + +extern const struct net_user_info umcast_user_info; + +extern int umcast_user_write(int fd, void *buf, int len, + struct umcast_data *pri); + +#endif diff --git a/arch/um/drivers/umcast_kern.c b/arch/um/drivers/umcast_kern.c new file mode 100644 index 000000000000..42dab11d2ecf --- /dev/null +++ b/arch/um/drivers/umcast_kern.c @@ -0,0 +1,188 @@ +/* + * 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 + * 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/init.h" +#include <linux/netdevice.h> +#include "umcast.h" +#include "net_kern.h" + +struct umcast_init { + char *addr; + int lport; + int rport; + int ttl; + bool unicast; +}; + +static void umcast_init(struct net_device *dev, void *data) +{ + struct uml_net_private *pri; + struct umcast_data *dpri; + struct umcast_init *init = data; + + pri = netdev_priv(dev); + dpri = (struct umcast_data *) pri->user; + dpri->addr = init->addr; + dpri->lport = init->lport; + dpri->rport = init->rport; + dpri->unicast = init->unicast; + dpri->ttl = init->ttl; + dpri->dev = dev; + + if (dpri->unicast) { + printk(KERN_INFO "ucast backend address: %s:%u listen port: " + "%u\n", dpri->addr, dpri->rport, dpri->lport); + } else { + printk(KERN_INFO "mcast backend multicast address: %s:%u, " + "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl); + } +} + +static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + return net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); +} + +static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + return umcast_user_write(fd, skb->data, skb->len, + (struct umcast_data *) &lp->user); +} + +static const struct net_kern_info umcast_kern_info = { + .init = umcast_init, + .protocol = eth_protocol, + .read = umcast_read, + .write = umcast_write, +}; + +static int mcast_setup(char *str, char **mac_out, void *data) +{ + struct umcast_init *init = data; + char *port_str = NULL, *ttl_str = NULL, *remain; + char *last; + + *init = ((struct umcast_init) + { .addr = "239.192.168.1", + .lport = 1102, + .ttl = 1 }); + + remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, + NULL); + if (remain != NULL) { + printk(KERN_ERR "mcast_setup - Extra garbage on " + "specification : '%s'\n", remain); + return 0; + } + + if (port_str != NULL) { + init->lport = simple_strtoul(port_str, &last, 10); + if ((*last != '\0') || (last == port_str)) { + printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", + port_str); + return 0; + } + } + + 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", + ttl_str); + return 0; + } + } + + init->unicast = false; + init->rport = init->lport; + + printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, + init->lport, init->ttl); + + return 1; +} + +static int ucast_setup(char *str, char **mac_out, void *data) +{ + struct umcast_init *init = data; + char *lport_str = NULL, *rport_str = NULL, *remain; + char *last; + + *init = ((struct umcast_init) + { .addr = "", + .lport = 1102, + .rport = 1102 }); + + remain = split_if_spec(str, mac_out, &init->addr, + &lport_str, &rport_str, NULL); + if (remain != NULL) { + printk(KERN_ERR "ucast_setup - Extra garbage on " + "specification : '%s'\n", remain); + return 0; + } + + if (lport_str != NULL) { + init->lport = simple_strtoul(lport_str, &last, 10); + if ((*last != '\0') || (last == lport_str)) { + printk(KERN_ERR "ucast_setup - Bad listen port : " + "'%s'\n", lport_str); + return 0; + } + } + + if (rport_str != NULL) { + init->rport = simple_strtoul(rport_str, &last, 10); + if ((*last != '\0') || (last == rport_str)) { + printk(KERN_ERR "ucast_setup - Bad remote port : " + "'%s'\n", rport_str); + return 0; + } + } + + init->unicast = true; + + printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n", + init->lport, init->addr, init->rport); + + return 1; +} + +static struct transport mcast_transport = { + .list = LIST_HEAD_INIT(mcast_transport.list), + .name = "mcast", + .setup = mcast_setup, + .user = &umcast_user_info, + .kern = &umcast_kern_info, + .private_size = sizeof(struct umcast_data), + .setup_size = sizeof(struct umcast_init), +}; + +static struct transport ucast_transport = { + .list = LIST_HEAD_INIT(ucast_transport.list), + .name = "ucast", + .setup = ucast_setup, + .user = &umcast_user_info, + .kern = &umcast_kern_info, + .private_size = sizeof(struct umcast_data), + .setup_size = sizeof(struct umcast_init), +}; + +static int register_umcast(void) +{ + register_transport(&mcast_transport); + register_transport(&ucast_transport); + return 0; +} + +late_initcall(register_umcast); diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c new file mode 100644 index 000000000000..59c56fd6f52a --- /dev/null +++ b/arch/um/drivers/umcast_user.c @@ -0,0 +1,186 @@ +/* + * 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 + * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 by various other people who didn't put their name here. + * + * Licensed under the GPL. + * + */ + +#include <unistd.h> +#include <errno.h> +#include <netinet/in.h> +#include "kern_constants.h" +#include "umcast.h" +#include "net_user.h" +#include "um_malloc.h" +#include "user.h" + +static struct sockaddr_in *new_addr(char *addr, unsigned short port) +{ + struct sockaddr_in *sin; + + sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); + if (sin == NULL) { + printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " + "failed\n"); + return NULL; + } + sin->sin_family = AF_INET; + if (addr) + sin->sin_addr.s_addr = in_aton(addr); + else + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(port); + return sin; +} + +static int umcast_user_init(void *data, void *dev) +{ + struct umcast_data *pri = data; + + pri->remote_addr = new_addr(pri->addr, pri->rport); + if (pri->unicast) + pri->listen_addr = new_addr(NULL, pri->lport); + else + pri->listen_addr = pri->remote_addr; + pri->dev = dev; + return 0; +} + +static void umcast_remove(void *data) +{ + struct umcast_data *pri = data; + + kfree(pri->listen_addr); + if (pri->unicast) + kfree(pri->remote_addr); + pri->listen_addr = pri->remote_addr = NULL; +} + +static int umcast_open(void *data) +{ + struct umcast_data *pri = data; + struct sockaddr_in *lsin = pri->listen_addr; + struct sockaddr_in *rsin = pri->remote_addr; + struct ip_mreq mreq; + int fd, yes = 1, err = -EINVAL; + + + if ((!pri->unicast && lsin->sin_addr.s_addr == 0) || + (rsin->sin_addr.s_addr == 0) || + (lsin->sin_port == 0) || (rsin->sin_port == 0)) + goto out; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + + if (fd < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open : data socket failed, " + "errno = %d\n", errno); + goto out; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: SO_REUSEADDR failed, " + "errno = %d\n", errno); + goto out_close; + } + + if (!pri->unicast) { + /* set ttl according to config */ + if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, + sizeof(pri->ttl)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_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(UM_KERN_ERR "umcast_open: IP_MULTICAST_LOOP " + "failed, error = %d\n", errno); + goto out_close; + } + } + + /* bind socket to the address */ + if (bind(fd, (struct sockaddr *) lsin, sizeof(*lsin)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open : data bind failed, " + "errno = %d\n", errno); + goto out_close; + } + + if (!pri->unicast) { + /* subscribe to the multicast group */ + mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; + mreq.imr_interface.s_addr = 0; + if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_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: + close(fd); + out: + return err; +} + +static void umcast_close(int fd, void *data) +{ + struct umcast_data *pri = data; + + if (!pri->unicast) { + struct ip_mreq mreq; + struct sockaddr_in *lsin = pri->listen_addr; + + mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; + mreq.imr_interface.s_addr = 0; + if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + printk(UM_KERN_ERR "umcast_close: IP_DROP_MEMBERSHIP " + "failed, error = %d\n", errno); + } + } + + close(fd); +} + +int umcast_user_write(int fd, void *buf, int len, struct umcast_data *pri) +{ + struct sockaddr_in *data_addr = pri->remote_addr; + + return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); +} + +const struct net_user_info umcast_user_info = { + .init = umcast_user_init, + .open = umcast_open, + .close = umcast_close, + .remove = umcast_remove, + .add_address = NULL, + .delete_address = NULL, + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, +}; diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index da2caa5a21ef..8ac7146c237f 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -90,7 +90,7 @@ static int xterm_open(int input, int output, int primary, void *d, int pid, fd, new, err; char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; char *argv[] = { terminal_emulator, title_switch, title, exec_switch, - "/usr/lib/uml/port-helper", "-uml-socket", + OS_LIB_PATH "/uml/port-helper", "-uml-socket", file, NULL }; if (access(argv[4], X_OK) < 0) diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S index 34bede8aad4a..4938de5512d2 100644 --- a/arch/um/include/asm/common.lds.S +++ b/arch/um/include/asm/common.lds.S @@ -42,7 +42,7 @@ INIT_SETUP(0) } - PERCPU(32, 32) + PERCPU_SECTION(32) .initcall.init : { INIT_CALLS diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index d1d1b0d8a0cd..98d01bc4fa92 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h @@ -14,6 +14,8 @@ struct task_struct; #include "registers.h" #include "sysdep/archsetjmp.h" +#include <linux/prefetch.h> + struct mm_struct; struct thread_struct { diff --git a/arch/um/include/asm/smp.h b/arch/um/include/asm/smp.h index f27a96313174..4a4b09d4f366 100644 --- a/arch/um/include/asm/smp.h +++ b/arch/um/include/asm/smp.h @@ -11,7 +11,6 @@ #define cpu_logical_map(n) (n) #define cpu_number_map(n) (n) -#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ extern int hard_smp_processor_id(void); #define NO_PROC_ID -1 diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h index 660caedac9eb..4febacd1a8a1 100644 --- a/arch/um/include/asm/tlb.h +++ b/arch/um/include/asm/tlb.h @@ -22,9 +22,6 @@ struct mmu_gather { unsigned int fullmm; /* non-zero means full mm flush */ }; -/* Users of the generic TLB shootdown code must declare this storage space. */ -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address) { @@ -47,27 +44,20 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) } } -/* tlb_gather_mmu - * Return a pointer to an initialized struct mmu_gather. - */ -static inline struct mmu_gather * -tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +static inline void +tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); - tlb->mm = mm; tlb->fullmm = full_mm_flush; init_tlb_gather(tlb); - - return tlb; } extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end); static inline void -tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) +tlb_flush_mmu(struct mmu_gather *tlb) { if (!tlb->need_flush) return; @@ -83,12 +73,10 @@ tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - tlb_flush_mmu(tlb, start, end); + tlb_flush_mmu(tlb); /* keep the page table cache within bounds */ check_pgt_cache(); - - put_cpu_var(mmu_gathers); } /* tlb_remove_page @@ -96,11 +84,16 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) * while handling the additional races in SMP caused by other CPUs * caching valid mappings in their TLBs. */ -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) { tlb->need_flush = 1; free_page_and_swap_cache(page); - return; + return 1; /* avoid calling tlb_flush_mmu */ +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + __tlb_remove_page(tlb, page); } /** diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index c4617baaa4f2..83c7c2ecd614 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -29,6 +29,12 @@ #define OS_ACC_R_OK 4 /* Test for read permission. */ #define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ +#ifdef CONFIG_64BIT +#define OS_LIB_PATH "/usr/lib64/" +#else +#define OS_LIB_PATH "/usr/lib/" +#endif + /* * types taken from stat_file() in hostfs_user.c * (if they are wrong here, they are wrong there...). @@ -238,6 +244,7 @@ extern int raw(int fd); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(char *buf, int len); extern void os_dump_core(void) __attribute__ ((noreturn)); +extern void um_early_printk(const char *s, unsigned int n); /* time.c */ extern void idle_sleep(unsigned long long nsecs); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 1119233597a1..c4491c15afb2 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -17,6 +17,7 @@ obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o USER_OBJS := config.o diff --git a/arch/um/kernel/early_printk.c b/arch/um/kernel/early_printk.c new file mode 100644 index 000000000000..ec649bf72f68 --- /dev/null +++ b/arch/um/kernel/early_printk.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/console.h> +#include <linux/init.h> +#include "os.h" + +static void early_console_write(struct console *con, const char *s, unsigned int n) +{ + um_early_printk(s, n); +} + +static struct console early_console = { + .name = "earlycon", + .write = early_console_write, + .flags = CON_BOOT, + .index = -1, +}; + +static int __init setup_early_printk(char *buf) +{ + register_console(&early_console); + + return 0; +} + +early_param("earlyprintk", setup_early_printk); diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index eefb107d2d73..155206a66908 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -7,9 +7,6 @@ #include "asm/pgalloc.h" #include "asm/tlb.h" -/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - #ifdef CONFIG_SMP #include "linux/sched.h" diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 637c6505dc00..8c7b8823d1f0 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -113,6 +113,27 @@ out_of_memory: return 0; } +static void show_segv_info(struct uml_pt_regs *regs) +{ + struct task_struct *tsk = current; + struct faultinfo *fi = UPT_FAULTINFO(regs); + + if (!unhandled_signal(tsk, SIGSEGV)) + return; + + if (!printk_ratelimit()) + return; + + printk("%s%s[%d]: segfault at %lx ip %p sp %p error %x", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), FAULT_ADDRESS(*fi), + (void *)UPT_IP(regs), (void *)UPT_SP(regs), + fi->error_code); + + print_vma_addr(KERN_CONT " in ", UPT_IP(regs)); + printk(KERN_CONT "\n"); +} + static void bad_segv(struct faultinfo fi, unsigned long ip) { struct siginfo si; @@ -141,6 +162,7 @@ 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)) { + show_segv_info(regs); bad_segv(*fi, UPT_IP(regs)); return; } @@ -202,6 +224,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, address, ip); } + show_segv_info(regs); + if (err == -EACCES) { si.si_signo = SIGBUS; si.si_errno = 0; diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index eee69b9f52c9..fb2a97a75fb1 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -78,7 +78,7 @@ static void install_fatal_handler(int sig) } } -#define UML_LIB_PATH ":/usr/lib/uml" +#define UML_LIB_PATH ":" OS_LIB_PATH "/uml" static void setup_env_path(void) { @@ -142,7 +142,6 @@ int __init main(int argc, char **argv, char **envp) */ install_fatal_handler(SIGINT); install_fatal_handler(SIGTERM); - install_fatal_handler(SIGHUP); scan_elf_aux(envp); diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index e0477c3ee894..0c45dc8efb05 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -253,6 +253,7 @@ void init_new_thread_signals(void) SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGWINCH, SIG_IGN); + signal(SIGTERM, SIG_DFL); } int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 42827cafa6af..5803b1887672 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -139,3 +139,8 @@ void os_dump_core(void) uml_abort(); } + +void um_early_printk(const char *s, unsigned int n) +{ + printf("%.*s", n, s); +} diff --git a/arch/unicore32/Kconfig.debug b/arch/unicore32/Kconfig.debug index 3140151ede45..ae2ec334c3c6 100644 --- a/arch/unicore32/Kconfig.debug +++ b/arch/unicore32/Kconfig.debug @@ -27,13 +27,6 @@ config EARLY_PRINTK with klogd/syslogd or the X server. You should normally N here, unless you want to debug such a crash. -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T output. - # These options are only for real kernel hackers who want to get their hands dirty. config DEBUG_LL bool "Kernel low-level debugging functions" diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c index 1fc02633f700..2d3e7112d2a3 100644 --- a/arch/unicore32/mm/init.c +++ b/arch/unicore32/mm/init.c @@ -62,7 +62,7 @@ void show_mem(unsigned int filter) struct meminfo *mi = &meminfo; printk(KERN_DEFAULT "Mem-info:\n"); - show_free_areas(); + show_free_areas(filter); for_each_bank(i, mi) { struct membank *bank = &mi->bank[i]; diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c index db2d334941b4..3e5c3e5a0b45 100644 --- a/arch/unicore32/mm/mmu.c +++ b/arch/unicore32/mm/mmu.c @@ -30,8 +30,6 @@ #include "mm.h" -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * empty_zero_page is a special page that is used for * zero-initialized data and COW. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 880fcb6c86f4..fa2cc8c5d01c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -17,8 +17,6 @@ config X86_64 config X86 def_bool y select HAVE_AOUT if X86_32 - select HAVE_READQ - select HAVE_WRITEQ select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_IDE select HAVE_OPROFILE diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 615e18810f48..c0f8a5c88910 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -66,26 +66,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - ---help--- - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_PER_CPU_MAPS - bool "Debug access to per_cpu maps" - depends on DEBUG_KERNEL - depends on SMP - ---help--- - Say Y to verify that the per_cpu map being accessed has - been setup. Adds a fair amount of code to kernel memory - and decreases performance. - - Say N if unsure. - config X86_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 072273082528..d02804d650c4 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -38,7 +38,6 @@ #include <linux/string.h> #include <linux/compiler.h> -#include <asm-generic/int-ll64.h> #include <asm/page.h> #include <xen/xen.h> @@ -87,27 +86,6 @@ build_mmio_write(__writel, "l", unsigned int, "r", ) build_mmio_read(readq, "q", unsigned long, "=r", :"memory") build_mmio_write(writeq, "q", unsigned long, "r", :"memory") -#else - -static inline __u64 readq(const volatile void __iomem *addr) -{ - const volatile u32 __iomem *p = addr; - u32 low, high; - - low = readl(p); - high = readl(p + 1); - - return low + ((u64)high << 32); -} - -static inline void writeq(__u64 val, volatile void __iomem *addr) -{ - writel(val, addr); - writel(val >> 32, addr+4); -} - -#endif - #define readq_relaxed(a) readq(a) #define __raw_readq(a) readq(a) @@ -117,6 +95,8 @@ static inline void writeq(__u64 val, volatile void __iomem *addr) #define readq readq #define writeq writeq +#endif + /** * virt_to_phys - map virtual addresses to physical * @address: address to remap diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h index 12d55e773eb6..48142971b25d 100644 --- a/arch/x86/include/asm/linkage.h +++ b/arch/x86/include/asm/linkage.h @@ -8,11 +8,6 @@ #ifdef CONFIG_X86_32 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) -/* - * For 32-bit UML - mark functions implemented in assembly that use - * regparm input parameters: - */ -#define asmregparm __attribute__((regparm(3))) /* * Make sure the compiler doesn't do anything stupid with the diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 53278b0dfdf6..a0a9779084d1 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -509,6 +509,11 @@ do { \ * it in software. The address used in the cmpxchg16 instruction must be * aligned to a 16 byte boundary. */ +#ifdef CONFIG_SMP +#define CMPXCHG16B_EMU_CALL "call this_cpu_cmpxchg16b_emu\n\t" ASM_NOP3 +#else +#define CMPXCHG16B_EMU_CALL "call this_cpu_cmpxchg16b_emu\n\t" ASM_NOP2 +#endif #define percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2) \ ({ \ char __ret; \ @@ -517,7 +522,7 @@ do { \ typeof(o2) __o2 = o2; \ typeof(o2) __n2 = n2; \ typeof(o2) __dummy; \ - alternative_io("call this_cpu_cmpxchg16b_emu\n\t" ASM_NOP4, \ + alternative_io(CMPXCHG16B_EMU_CALL, \ "cmpxchg16b " __percpu_prefix "(%%rsi)\n\tsetz %0\n\t", \ X86_FEATURE_CX16, \ ASM_OUTPUT2("=a"(__ret), "=d"(__dummy)), \ diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 9488dcff7aec..e5293394b548 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -676,7 +676,7 @@ void mask_ioapic_entries(void) int apic, pin; for (apic = 0; apic < nr_ioapics; apic++) { - if (ioapics[apic].saved_registers) + if (!ioapics[apic].saved_registers) continue; for (pin = 0; pin < ioapics[apic].nr_registers; pin++) { @@ -699,7 +699,7 @@ int restore_ioapic_entries(void) int apic, pin; for (apic = 0; apic < nr_ioapics; apic++) { - if (ioapics[apic].saved_registers) + if (!ioapics[apic].saved_registers) continue; for (pin = 0; pin < ioapics[apic].nr_registers; pin++) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index f65e5b521dbd..807c2a2b80f1 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1363,7 +1363,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, * We must return the syscall number to actually look up in the table. * This can be -1L to skip running any syscall at all. */ -asmregparm long syscall_trace_enter(struct pt_regs *regs) +long syscall_trace_enter(struct pt_regs *regs) { long ret = 0; @@ -1408,7 +1408,7 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs) return ret ?: regs->orig_ax; } -asmregparm void syscall_trace_leave(struct pt_regs *regs) +void syscall_trace_leave(struct pt_regs *regs) { bool step; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 605e5ae19c7f..a3e5948670c2 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -946,6 +946,8 @@ void __init setup_arch(char **cmdline_p) if (init_ohci1394_dma_early) init_ohci1394_dma_on_all_controllers(); #endif + /* Allocate bigger log buffer */ + setup_log_buf(1); reserve_initrd(); diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 998e972f3b1a..30ac65df7d4e 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -110,7 +110,6 @@ static struct mm_struct tboot_mm = { .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem), .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), .mmlist = LIST_HEAD_INIT(init_mm.mmlist), - .cpu_vm_mask = CPU_MASK_ALL, }; static inline void switch_to_tboot_pt(void) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 49927a863cc1..61682f0ac264 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -326,7 +326,7 @@ SECTIONS } #if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP) - PERCPU(INTERNODE_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(INTERNODE_CACHE_BYTES) #endif . = ALIGN(PAGE_SIZE); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 28418054b880..bd14bb4c8594 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3545,10 +3545,11 @@ static int kvm_mmu_remove_some_alloc_mmu_pages(struct kvm *kvm, return kvm_mmu_prepare_zap_page(kvm, page, invalid_list); } -static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) +static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc) { struct kvm *kvm; struct kvm *kvm_freed = NULL; + int nr_to_scan = sc->nr_to_scan; if (nr_to_scan == 0) goto out; diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index bcb394dfbb35..f7a2a054a3c0 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -965,7 +965,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) struct mm_struct *mm; int fault; int write = error_code & PF_WRITE; - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | (write ? FAULT_FLAG_WRITE : 0); tsk = current; @@ -1139,6 +1139,16 @@ good_area: } /* + * Pagefault was interrupted by SIGKILL. We have no reason to + * continue pagefault. + */ + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) { + if (!(error_code & PF_USER)) + no_context(regs, error_code, address); + return; + } + + /* * Major/minor page fault accounting is only done on the * initial attempt. If we go through a retry, it is extremely * likely that the page will be found in page cache at that point. diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index d4203988504a..f581a18c0d4d 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -72,7 +72,7 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) if (!vma_shareable(vma, addr)) return; - spin_lock(&mapping->i_mmap_lock); + mutex_lock(&mapping->i_mmap_mutex); vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { if (svma == vma) continue; @@ -97,7 +97,7 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) put_page(virt_to_page(spte)); spin_unlock(&mm->page_table_lock); out: - spin_unlock(&mapping->i_mmap_lock); + mutex_unlock(&mapping->i_mmap_mutex); } /* diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 37b8b0fe8320..30326443ab81 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -16,8 +16,6 @@ #include <asm/tlb.h> #include <asm/proto.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - unsigned long __initdata pgt_buf_start; unsigned long __meminitdata pgt_buf_end; unsigned long __meminitdata pgt_buf_top; diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 161bb89e98c8..7a5591a71f85 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h @@ -171,10 +171,6 @@ extern void copy_user_page(void*, void*, unsigned long, struct page*); #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) -#ifdef CONFIG_MMU -#define WANT_PAGE_VIRTUAL -#endif - #endif /* __ASSEMBLY__ */ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index a2820065927e..88ecea3facb4 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -155,7 +155,7 @@ SECTIONS INIT_RAM_FS } - PERCPU(XCHAL_ICACHE_LINESIZE, PAGE_SIZE) + PERCPU_SECTION(XCHAL_ICACHE_LINESIZE) /* We need this dummy segment here */ diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index 4bb91a970f1f..ca81654f3ec2 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c @@ -14,8 +14,6 @@ #include <asm/mmu_context.h> #include <asm/page.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - void __init paging_init(void) { memset(swapper_pg_dir, 0, PAGE_SIZE); diff --git a/arch/xtensa/mm/pgtable.c b/arch/xtensa/mm/pgtable.c deleted file mode 100644 index 697992738205..000000000000 --- a/arch/xtensa/mm/pgtable.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * arch/xtensa/mm/pgtable.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - * - * Chris Zankel <chris@zankel.net> - */ - -#if (DCACHE_SIZE > PAGE_SIZE) - -pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) -{ - pte_t *pte = NULL, *p; - int color = ADDR_COLOR(address); - int i; - - p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER); - - if (likely(p)) { - split_page(virt_to_page(p), COLOR_ORDER); - - for (i = 0; i < COLOR_SIZE; i++) { - if (ADDR_COLOR(p) == color) - pte = p; - else - free_page(p); - p += PTRS_PER_PTE; - } - clear_page(pte); - } - return pte; -} - -#ifdef PROFILING - -int mask; -int hit; -int flush; - -#endif - -struct page* pte_alloc_one(struct mm_struct *mm, unsigned long address) -{ - struct page *page = NULL, *p; - int color = ADDR_COLOR(address); - - p = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER); - - if (likely(p)) { - split_page(p, COLOR_ORDER); - - for (i = 0; i < PAGE_ORDER; i++) { - if (PADDR_COLOR(page_address(p)) == color) - page = p; - else - __free_page(p); - p++; - } - clear_highpage(page); - } - - return page; -} - -#endif - - - |