diff options
Diffstat (limited to 'arch')
40 files changed, 820 insertions, 389 deletions
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index e66a07a928cd..2687b730e2d0 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -163,6 +163,7 @@ add_reserved_region(resource_size_t start, resource_size_t end, new->start = start; new->end = end; new->name = name; + new->sibling = next; new->flags = IORESOURCE_MEM; *pprev = new; diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index cf6f686d9b0b..b835c4c01368 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -178,6 +178,7 @@ static int do_cop_absent(u32 insn) return 0; } +#ifdef CONFIG_BUG int is_valid_bugaddr(unsigned long pc) { unsigned short opcode; @@ -189,6 +190,7 @@ int is_valid_bugaddr(unsigned long pc) return opcode == AVR32_BUG_OPCODE; } +#endif asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) { @@ -197,6 +199,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) void __user *pc; long code; +#ifdef CONFIG_BUG if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) { enum bug_trap_type type; @@ -211,6 +214,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) die("Kernel BUG", regs, SIGKILL); } } +#endif local_irq_enable(); diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 250958d1e3cb..9d4bd2229493 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.25-rc1 -# Sun Feb 17 22:44:12 2008 +# Linux kernel version: 2.6.25-rc3 +# Wed Mar 26 04:33:35 2008 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -55,9 +55,11 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=18 # CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set +CONFIG_RT_GROUP_SCHED=y +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y CONFIG_NAMESPACES=y @@ -482,6 +484,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_QLOGIC_1280 is not set @@ -810,6 +813,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set # CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index dd5d28e3d798..0097c08dc600 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c @@ -15,6 +15,8 @@ #include <asm/spitfire.h> #include <asm/oplib.h> +#include "entry.h" + DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; struct cpu_iu_info { @@ -65,8 +67,6 @@ static struct cpu_iu_info linux_sparc_chips[] = { char *sparc_cpu_type; char *sparc_fpu_type; -unsigned int fsr_storage; - static void __init sun4v_cpu_probe(void) { switch (sun4v_chip_type) { @@ -94,8 +94,10 @@ void __init cpu_probe(void) unsigned long ver, fpu_vers, manuf, impl, fprs; int i; - if (tlb_type == hypervisor) - return sun4v_cpu_probe(); + if (tlb_type == hypervisor) { + sun4v_cpu_probe(); + return; + } fprs = fprs_read(); fprs_write(FPRS_FEF); diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 6be4d2d2904e..49eca4b1cf25 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1705,6 +1705,36 @@ __flushw_user: 2: retl nop + /* Flush %fp and %i7 to the stack for all register + * windows active inside of the cpu. This allows + * show_stack_trace() to avoid using an expensive + * 'flushw'. + */ + .globl stack_trace_flush + .type stack_trace_flush,#function +stack_trace_flush: + rdpr %pstate, %o0 + wrpr %o0, PSTATE_IE, %pstate + + rdpr %cwp, %g1 + rdpr %canrestore, %g2 + sub %g1, 1, %g3 + +1: brz,pn %g2, 2f + sub %g2, 1, %g2 + wrpr %g3, %cwp + stx %fp, [%sp + STACK_BIAS + RW_V9_I6] + stx %i7, [%sp + STACK_BIAS + RW_V9_I7] + ba,pt %xcc, 1b + sub %g3, 1, %g3 + +2: wrpr %g1, %cwp + wrpr %o0, %pstate + + retl + nop + .size stack_trace_flush,.-stack_trace_flush + #ifdef CONFIG_SMP .globl hard_smp_processor_id hard_smp_processor_id: diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h new file mode 100644 index 000000000000..4a91e9c6d31b --- /dev/null +++ b/arch/sparc64/kernel/entry.h @@ -0,0 +1,196 @@ +#ifndef _ENTRY_H +#define _ENTRY_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +extern char *sparc_cpu_type; +extern char *sparc_fpu_type; + +extern void __init per_cpu_patch(void); +extern void __init sun4v_patch(void); +extern void __init boot_cpu_id_too_large(int cpu); +extern unsigned int dcache_parity_tl1_occurred; +extern unsigned int icache_parity_tl1_occurred; + +extern asmlinkage void update_perfctrs(void); +extern asmlinkage void sparc_breakpoint(struct pt_regs *regs); +extern void timer_interrupt(int irq, struct pt_regs *regs); + +extern void do_notify_resume(struct pt_regs *regs, + unsigned long orig_i0, + int restart_syscall, + unsigned long thread_info_flags); + +extern asmlinkage void syscall_trace(struct pt_regs *regs, + int syscall_exit_p); + +extern void bad_trap_tl1(struct pt_regs *regs, long lvl); + +extern void do_fpe_common(struct pt_regs *regs); +extern void do_fpieee(struct pt_regs *regs); +extern void do_fpother(struct pt_regs *regs); +extern void do_tof(struct pt_regs *regs); +extern void do_div0(struct pt_regs *regs); +extern void do_illegal_instruction(struct pt_regs *regs); +extern void mem_address_unaligned(struct pt_regs *regs, + unsigned long sfar, + unsigned long sfsr); +extern void sun4v_do_mna(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void do_privop(struct pt_regs *regs); +extern void do_privact(struct pt_regs *regs); +extern void do_cee(struct pt_regs *regs); +extern void do_cee_tl1(struct pt_regs *regs); +extern void do_dae_tl1(struct pt_regs *regs); +extern void do_iae_tl1(struct pt_regs *regs); +extern void do_div0_tl1(struct pt_regs *regs); +extern void do_fpdis_tl1(struct pt_regs *regs); +extern void do_fpieee_tl1(struct pt_regs *regs); +extern void do_fpother_tl1(struct pt_regs *regs); +extern void do_ill_tl1(struct pt_regs *regs); +extern void do_irq_tl1(struct pt_regs *regs); +extern void do_lddfmna_tl1(struct pt_regs *regs); +extern void do_stdfmna_tl1(struct pt_regs *regs); +extern void do_paw(struct pt_regs *regs); +extern void do_paw_tl1(struct pt_regs *regs); +extern void do_vaw(struct pt_regs *regs); +extern void do_vaw_tl1(struct pt_regs *regs); +extern void do_tof_tl1(struct pt_regs *regs); +extern void do_getpsr(struct pt_regs *regs); + +extern void spitfire_insn_access_exception(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_insn_access_exception_tl1(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_data_access_exception(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_data_access_exception_tl1(struct pt_regs *regs, + unsigned long sfsr, + unsigned long sfar); +extern void spitfire_access_error(struct pt_regs *regs, + unsigned long status_encoded, + unsigned long afar); + +extern void cheetah_fecc_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_cee_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_deferred_handler(struct pt_regs *regs, + unsigned long afsr, + unsigned long afar); +extern void cheetah_plus_parity_error(int type, struct pt_regs *regs); + +extern void sun4v_insn_access_exception(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_insn_access_exception_tl1(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_data_access_exception(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_data_access_exception_tl1(struct pt_regs *regs, + unsigned long addr, + unsigned long type_ctx); +extern void sun4v_resum_error(struct pt_regs *regs, + unsigned long offset); +extern void sun4v_resum_overflow(struct pt_regs *regs); +extern void sun4v_nonresum_error(struct pt_regs *regs, + unsigned long offset); +extern void sun4v_nonresum_overflow(struct pt_regs *regs); + +extern unsigned long sun4v_err_itlb_vaddr; +extern unsigned long sun4v_err_itlb_ctx; +extern unsigned long sun4v_err_itlb_pte; +extern unsigned long sun4v_err_itlb_error; + +extern void sun4v_itlb_error_report(struct pt_regs *regs, int tl); + +extern unsigned long sun4v_err_dtlb_vaddr; +extern unsigned long sun4v_err_dtlb_ctx; +extern unsigned long sun4v_err_dtlb_pte; +extern unsigned long sun4v_err_dtlb_error; + +extern void sun4v_dtlb_error_report(struct pt_regs *regs, int tl); +extern void hypervisor_tlbop_error(unsigned long err, + unsigned long op); +extern void hypervisor_tlbop_error_xcall(unsigned long err, + unsigned long op); + +/* WARNING: The error trap handlers in assembly know the precise + * layout of the following structure. + * + * C-level handlers in traps.c use this information to log the + * error and then determine how to recover (if possible). + */ +struct cheetah_err_info { +/*0x00*/u64 afsr; +/*0x08*/u64 afar; + + /* D-cache state */ +/*0x10*/u64 dcache_data[4]; /* The actual data */ +/*0x30*/u64 dcache_index; /* D-cache index */ +/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ +/*0x40*/u64 dcache_utag; /* D-cache microtag */ +/*0x48*/u64 dcache_stag; /* D-cache snooptag */ + + /* I-cache state */ +/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ +/*0x90*/u64 icache_index; /* I-cache index */ +/*0x98*/u64 icache_tag; /* I-cache phys tag */ +/*0xa0*/u64 icache_utag; /* I-cache microtag */ +/*0xa8*/u64 icache_stag; /* I-cache snooptag */ +/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ +/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ + + /* E-cache state */ +/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ +/*0xe0*/u64 ecache_index; /* E-cache index */ +/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ + +/*0xf0*/u64 __pad[32 - 30]; +}; +#define CHAFSR_INVALID ((u64)-1L) + +/* This is allocated at boot time based upon the largest hardware + * cpu ID in the system. We allocate two entries per cpu, one for + * TL==0 logging and one for TL >= 1 logging. + */ +extern struct cheetah_err_info *cheetah_error_log; + +/* UPA nodes send interrupt packet to UltraSparc with first data reg + * value low 5 (7 on Starfire) bits holding the IRQ identifier being + * delivered. We must translate this into a non-vector IRQ so we can + * set the softint on this cpu. + * + * To make processing these packets efficient and race free we use + * an array of irq buckets below. The interrupt vector handler in + * entry.S feeds incoming packets into per-cpu pil-indexed lists. + * + * If you make changes to ino_bucket, please update hand coded assembler + * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S + */ +struct ino_bucket { +/*0x00*/unsigned long __irq_chain_pa; + + /* Virtual interrupt number assigned to this INO. */ +/*0x08*/unsigned int __virt_irq; +/*0x0c*/unsigned int __pad; +}; + +extern struct ino_bucket *ivector_table; +extern unsigned long ivector_table_pa; + +extern void handler_irq(int irq, struct pt_regs *regs); +extern void init_irqwork_curcpu(void); +extern void __cpuinit sun4v_register_mondo_queues(int this_cpu); + +#endif /* _ENTRY_H */ diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index fbaab3497bfd..b781d3d54fb8 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c @@ -626,7 +626,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, iommu_map_failed: for_each_sg(sglist, s, nelems, i) { if (s->dma_length != 0) { - unsigned long vaddr, npages, entry, i; + unsigned long vaddr, npages, entry, j; iopte_t *base; vaddr = s->dma_address & IO_PAGE_MASK; @@ -637,8 +637,8 @@ iommu_map_failed: >> IO_PAGE_SHIFT; base = iommu->page_table + entry; - for (i = 0; i < npages; i++) - iopte_make_dummy(iommu, base + i); + for (j = 0; j < npages; j++) + iopte_make_dummy(iommu, base + j); s->dma_address = DMA_ERROR_CODE; s->dma_length = 0; @@ -803,7 +803,7 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev, spin_unlock_irqrestore(&iommu->lock, flags); } -const struct dma_ops sun4u_dma_ops = { +static const struct dma_ops sun4u_dma_ops = { .alloc_coherent = dma_4u_alloc_coherent, .free_coherent = dma_4u_free_coherent, .map_single = dma_4u_map_single, diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 5ec06c8c7fea..eb88bd6e674e 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -44,27 +44,10 @@ #include <asm/hypervisor.h> #include <asm/cacheflush.h> -/* UPA nodes send interrupt packet to UltraSparc with first data reg - * value low 5 (7 on Starfire) bits holding the IRQ identifier being - * delivered. We must translate this into a non-vector IRQ so we can - * set the softint on this cpu. - * - * To make processing these packets efficient and race free we use - * an array of irq buckets below. The interrupt vector handler in - * entry.S feeds incoming packets into per-cpu pil-indexed lists. - * - * If you make changes to ino_bucket, please update hand coded assembler - * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S - */ -struct ino_bucket { -/*0x00*/unsigned long __irq_chain_pa; - - /* Virtual interrupt number assigned to this INO. */ -/*0x08*/unsigned int __virt_irq; -/*0x0c*/unsigned int __pad; -}; +#include "entry.h" #define NUM_IVECS (IMAP_INR + 1) + struct ino_bucket *ivector_table; unsigned long ivector_table_pa; diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 9a1ba1fe859d..aaae865e7932 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -35,6 +35,9 @@ #include <asm/spitfire.h> #include <asm/page.h> #include <asm/cpudata.h> +#include <asm/cacheflush.h> + +#include "entry.h" /* #define ALLOW_INIT_TRACING */ @@ -67,6 +70,8 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, if (tlb_type == hypervisor) return; + preempt_disable(); + #ifdef DCACHE_ALIASING_POSSIBLE /* If bit 13 of the kernel address we used to access the * user page is the same as the virtual address that page @@ -105,6 +110,8 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, for (; start < end; start += icache_line_size) flushi(start); } + + preempt_enable(); } enum sparc_regset { @@ -382,6 +389,7 @@ static const struct user_regset_view user_sparc64_view = { .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets) }; +#ifdef CONFIG_COMPAT static int genregs32_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, @@ -676,14 +684,18 @@ static const struct user_regset_view user_sparc32_view = { .name = "sparc", .e_machine = EM_SPARC, .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets) }; +#endif /* CONFIG_COMPAT */ const struct user_regset_view *task_user_regset_view(struct task_struct *task) { +#ifdef CONFIG_COMPAT if (test_tsk_thread_flag(task, TIF_32BIT)) return &user_sparc32_view; +#endif return &user_sparc64_view; } +#ifdef CONFIG_COMPAT struct compat_fps { unsigned int regs[32]; unsigned int fsr; @@ -798,6 +810,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, return ret; } +#endif /* CONFIG_COMPAT */ struct fps { unsigned int regs[64]; @@ -807,11 +820,14 @@ struct fps { long arch_ptrace(struct task_struct *child, long request, long addr, long data) { const struct user_regset_view *view = task_user_regset_view(child); - struct pt_regs __user *pregs = (struct pt_regs __user *) addr; unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; - struct fps __user *fps = (struct fps __user *) addr; + struct pt_regs __user *pregs; + struct fps __user *fps; int ret; + pregs = (struct pt_regs __user *) (unsigned long) addr; + fps = (struct fps __user *) (unsigned long) addr; + switch (request) { case PTRACE_PEEKUSR: ret = (addr != 0) ? -EIO : 0; diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index d036dbe72864..6acb4c51cfe4 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -51,6 +51,8 @@ #include <net/ipconfig.h> #endif +#include "entry.h" + /* Used to synchronize accesses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h */ @@ -335,9 +337,6 @@ void __init setup_arch(char **cmdline_p) /* BUFFER is PAGE_SIZE bytes long. */ -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; - extern void smp_info(struct seq_file *); extern void smp_bogo(struct seq_file *); extern void mmu_info(struct seq_file *); diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index fb13775b3682..94a9d64208ee 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -32,6 +32,9 @@ #include <asm/siginfo.h> #include <asm/visasm.h> +#include "entry.h" +#include "systbls.h" + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) /* {set, get}context() needed for 64-bit SparcLinux userland. */ diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 5a1126b363a4..59f020d69d4c 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -1,6 +1,6 @@ /* smp.c: Sparc64 SMP support. * - * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include <linux/module.h> @@ -30,6 +30,7 @@ #include <asm/cpudata.h> #include <asm/hvtramp.h> #include <asm/io.h> +#include <asm/timer.h> #include <asm/irq.h> #include <asm/irq_regs.h> diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c index 47f92a59be18..84d39e873e88 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc64/kernel/stacktrace.c @@ -2,13 +2,15 @@ #include <linux/stacktrace.h> #include <linux/thread_info.h> #include <asm/ptrace.h> +#include <asm/stacktrace.h> void save_stack_trace(struct stack_trace *trace) { unsigned long ksp, fp, thread_base; struct thread_info *tp = task_thread_info(current); - flushw_all(); + stack_trace_flush(); + __asm__ __volatile__( "mov %%fp, %0" : "=r" (ksp) diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 134d801579f9..f952745d0f3d 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,5 +1,4 @@ -/* $Id: sys_sparc.c,v 1.57 2002/02/09 19:49:30 davem Exp $ - * linux/arch/sparc64/kernel/sys_sparc.c +/* linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/sparc @@ -30,6 +29,9 @@ #include <asm/perfctr.h> #include <asm/unistd.h> +#include "entry.h" +#include "systbls.h" + /* #define DEBUG_UNIMP_SYSCALL */ asmlinkage unsigned long sys_getpagesize(void) @@ -445,7 +447,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, goto out; case SEMTIMEDOP: err = sys_semtimedop(first, ptr, (unsigned)second, - (const struct timespec __user *) fifth); + (const struct timespec __user *) + (unsigned long) fifth); goto out; case SEMGET: err = sys_semget(first, (int)second, (int)third); @@ -788,7 +791,7 @@ asmlinkage long sys_utrap_install(utrap_entry_t type, } else { if ((utrap_handler_t)current_thread_info()->utraps[type] != new_p && current_thread_info()->utraps[0] > 1) { - long *p = current_thread_info()->utraps; + unsigned long *p = current_thread_info()->utraps; current_thread_info()->utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), @@ -816,7 +819,8 @@ asmlinkage long sys_utrap_install(utrap_entry_t type, return 0; } -long sparc_memory_ordering(unsigned long model, struct pt_regs *regs) +asmlinkage long sparc_memory_ordering(unsigned long model, + struct pt_regs *regs) { if (model >= 3) return -EINVAL; diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc64/kernel/systbls.h new file mode 100644 index 000000000000..8a0d20a35d0c --- /dev/null +++ b/arch/sparc64/kernel/systbls.h @@ -0,0 +1,53 @@ +#ifndef _SYSTBLS_H +#define _SYSTBLS_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/utsname.h> +#include <asm/utrap.h> +#include <asm/signal.h> + +extern asmlinkage unsigned long sys_getpagesize(void); +extern asmlinkage unsigned long sparc_brk(unsigned long brk); +extern asmlinkage long sparc_pipe(struct pt_regs *regs); +extern asmlinkage long sys_ipc(unsigned int call, int first, + unsigned long second, + unsigned long third, + void __user *ptr, long fifth); +extern asmlinkage long sparc64_newuname(struct new_utsname __user *name); +extern asmlinkage long sparc64_personality(unsigned long personality); +extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off); +extern asmlinkage long sys64_munmap(unsigned long addr, size_t len); +extern asmlinkage unsigned long sys64_mremap(unsigned long addr, + unsigned long old_len, + unsigned long new_len, + unsigned long flags, + unsigned long new_addr); +extern asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs); +extern asmlinkage long sys_getdomainname(char __user *name, int len); +extern asmlinkage long solaris_syscall(struct pt_regs *regs); +extern asmlinkage long sunos_syscall(struct pt_regs *regs); +extern asmlinkage long sys_utrap_install(utrap_entry_t type, + utrap_handler_t new_p, + utrap_handler_t new_d, + utrap_handler_t __user *old_p, + utrap_handler_t __user *old_d); +extern asmlinkage long sparc_memory_ordering(unsigned long model, + struct pt_regs *regs); +extern asmlinkage long sys_rt_sigaction(int sig, + const struct sigaction __user *act, + struct sigaction __user *oact, + void __user *restorer, + size_t sigsetsize); +extern asmlinkage long sys_perfctr(int opcode, unsigned long arg0, + unsigned long arg1, unsigned long arg2); + +extern asmlinkage void sparc64_set_context(struct pt_regs *regs); +extern asmlinkage void sparc64_get_context(struct pt_regs *regs); +extern asmlinkage long sys_sigpause(unsigned int set); +extern asmlinkage long sys_sigsuspend(old_sigset_t set); +extern void do_rt_sigreturn(struct pt_regs *regs); + +#endif /* _SYSTBLS_H */ diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index d204f1ab1d4c..e5d238970c7e 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1,7 +1,6 @@ -/* $Id: time.c,v 1.42 2002/01/23 14:33:55 davem Exp $ - * time.c: UltraSparc timer and TOD clock support. +/* time.c: UltraSparc timer and TOD clock support. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * Based largely on code which is: @@ -48,6 +47,8 @@ #include <asm/uaccess.h> #include <asm/irq_regs.h> +#include "entry.h" + DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); void __iomem *mstk48t02_regs = NULL; @@ -508,6 +509,37 @@ static int __init has_low_battery(void) return (data1 == data2); /* Was the write blocked? */ } +static void __init mostek_set_system_time(void __iomem *mregs) +{ + unsigned int year, mon, day, hour, min, sec; + u8 tmp; + + spin_lock_irq(&mostek_lock); + + /* Traditional Mostek chip. */ + tmp = mostek_read(mregs + MOSTEK_CREG); + tmp |= MSTK_CREG_READ; + mostek_write(mregs + MOSTEK_CREG, tmp); + + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + + tmp = mostek_read(mregs + MOSTEK_CREG); + tmp &= ~MSTK_CREG_READ; + mostek_write(mregs + MOSTEK_CREG, tmp); + + spin_unlock_irq(&mostek_lock); +} + /* Probe for the real time clock chip. */ static void __init set_system_time(void) { @@ -520,7 +552,6 @@ static void __init set_system_time(void) unsigned long dregs = 0UL; void __iomem *bregs = 0UL; #endif - u8 tmp; if (!mregs && !dregs && !bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); @@ -528,20 +559,11 @@ static void __init set_system_time(void) } if (mregs) { - spin_lock_irq(&mostek_lock); - - /* Traditional Mostek chip. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); + mostek_set_system_time(mregs); + return; + } - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - } else if (bregs) { + if (bregs) { unsigned char val = readb(bregs + 0x0e); unsigned int century; @@ -596,14 +618,6 @@ static void __init set_system_time(void) xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - - if (mregs) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } } /* davem suggests we keep this within the 4M locked kernel image */ @@ -1027,7 +1041,7 @@ void __init time_init(void) setup_clockevent_multiplier(clock); sparc64_clockevent.max_delta_ns = - clockevent_delta2ns(0x7fffffffffffffff, &sparc64_clockevent); + clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 007f5317c0de..96da847023f3 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -42,6 +42,7 @@ #endif #include <asm/prom.h> +#include "entry.h" /* When an irrecoverable trap occurs at tl > 0, the trap entry * code logs the trap state registers at every level in the trap @@ -77,11 +78,6 @@ static void dump_tl1_traplog(struct tl1_traplog *p) } } -void do_call_debug(struct pt_regs *regs) -{ - notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); -} - void bad_trap(struct pt_regs *regs, long lvl) { char buffer[32]; @@ -550,41 +546,6 @@ static unsigned long ecache_flush_physbase; static unsigned long ecache_flush_linesize; static unsigned long ecache_flush_size; -/* WARNING: The error trap handlers in assembly know the precise - * layout of the following structure. - * - * C-level handlers below use this information to log the error - * and then determine how to recover (if possible). - */ -struct cheetah_err_info { -/*0x00*/u64 afsr; -/*0x08*/u64 afar; - - /* D-cache state */ -/*0x10*/u64 dcache_data[4]; /* The actual data */ -/*0x30*/u64 dcache_index; /* D-cache index */ -/*0x38*/u64 dcache_tag; /* D-cache tag/valid */ -/*0x40*/u64 dcache_utag; /* D-cache microtag */ -/*0x48*/u64 dcache_stag; /* D-cache snooptag */ - - /* I-cache state */ -/*0x50*/u64 icache_data[8]; /* The actual insns + predecode */ -/*0x90*/u64 icache_index; /* I-cache index */ -/*0x98*/u64 icache_tag; /* I-cache phys tag */ -/*0xa0*/u64 icache_utag; /* I-cache microtag */ -/*0xa8*/u64 icache_stag; /* I-cache snooptag */ -/*0xb0*/u64 icache_upper; /* I-cache upper-tag */ -/*0xb8*/u64 icache_lower; /* I-cache lower-tag */ - - /* E-cache state */ -/*0xc0*/u64 ecache_data[4]; /* 32 bytes from staging registers */ -/*0xe0*/u64 ecache_index; /* E-cache index */ -/*0xe8*/u64 ecache_tag; /* E-cache tag/state */ - -/*0xf0*/u64 __pad[32 - 30]; -}; -#define CHAFSR_INVALID ((u64)-1L) - /* This table is ordered in priority of errors and matches the * AFAR overwrite policy as well. */ @@ -758,10 +719,6 @@ static struct afsr_error_table __jalapeno_error_table[] = { static struct afsr_error_table *cheetah_error_table; static unsigned long cheetah_afsr_errors; -/* This is allocated at boot time based upon the largest hardware - * cpu ID in the system. We allocate two entries per cpu, one for - * TL==0 logging and one for TL >= 1 logging. - */ struct cheetah_err_info *cheetah_error_log; static inline struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr) @@ -2102,7 +2059,7 @@ void do_div0(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } -void instruction_dump (unsigned int *pc) +static void instruction_dump(unsigned int *pc) { int i; @@ -2115,7 +2072,7 @@ void instruction_dump (unsigned int *pc) printk("\n"); } -static void user_instruction_dump (unsigned int __user *pc) +static void user_instruction_dump(unsigned int __user *pc) { int i; unsigned int buf[9]; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 466fd6cffac9..f37078d96407 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -46,6 +46,7 @@ #include <asm/prom.h> #include <asm/sstate.h> #include <asm/mdesc.h> +#include <asm/cpudata.h> #define MAX_PHYS_ADDRESS (1UL << 42UL) #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) @@ -1273,10 +1274,6 @@ void __cpuinit sun4v_ktsb_register(void) /* paging_init() sets up the page tables */ -extern void cheetah_ecache_flush_init(void); -extern void sun4v_patch_tlb_handlers(void); - -extern void cpu_probe(void); extern void central_probe(void); static unsigned long last_valid_pfn; diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c index 3f10fc921b00..a0f000b293de 100644 --- a/arch/sparc64/mm/tlb.c +++ b/arch/sparc64/mm/tlb.c @@ -23,10 +23,11 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; void flush_tlb_pending(void) { - struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); + struct mmu_gather *mp; preempt_disable(); + mp = &__get_cpu_var(mmu_gathers); if (mp->tlb_nr) { flush_tsb_user(mp); diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 1e8f41a99511..1d43bdfc20c4 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -256,11 +256,7 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev) static void uml_net_set_multicast_list(struct net_device *dev) { - if (dev->flags & IFF_PROMISC) - return; - else if (dev->mc_count) - dev->flags |= IFF_ALLMULTI; - else dev->flags &= ~IFF_ALLMULTI; + return; } static void uml_net_tx_timeout(struct net_device *dev) diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c index f2b5a621d27b..8a85c93bd62a 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c @@ -63,7 +63,7 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { */ static int speedstep_smi_ownership (void) { - u32 command, result, magic; + u32 command, result, magic, dummy; u32 function = GET_SPEEDSTEP_OWNER; unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation"; @@ -73,8 +73,11 @@ static int speedstep_smi_ownership (void) dprintk("trying to obtain ownership with command %x at port %x\n", command, smi_port); __asm__ __volatile__( + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=D" (result) + "pop %%ebp\n" + : "=D" (result), "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy), + "=S" (dummy) : "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic) : "memory" @@ -96,7 +99,7 @@ static int speedstep_smi_ownership (void) */ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) { - u32 command, result = 0, edi, high_mhz, low_mhz; + u32 command, result = 0, edi, high_mhz, low_mhz, dummy; u32 state=0; u32 function = GET_SPEEDSTEP_FREQS; @@ -109,10 +112,12 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) dprintk("trying to determine frequencies with command %x at port %x\n", command, smi_port); - __asm__ __volatile__("movl $0, %%edi\n" + __asm__ __volatile__( + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi) - : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) + "pop %%ebp" + : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi), "=S" (dummy) + : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0) ); dprintk("result %x, low_freq %u, high_freq %u\n", result, low_mhz, high_mhz); @@ -135,16 +140,18 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) static int speedstep_get_state (void) { u32 function=GET_SPEEDSTEP_STATE; - u32 result, state, edi, command; + u32 result, state, edi, command, dummy; command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); dprintk("trying to determine current setting with command %x at port %x\n", command, smi_port); - __asm__ __volatile__("movl $0, %%edi\n" + __asm__ __volatile__( + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=a" (result), "=b" (state), "=D" (edi) - : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0) + "pop %%ebp\n" + : "=a" (result), "=b" (state), "=D" (edi), "=c" (dummy), "=d" (dummy), "=S" (dummy) + : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0), "D" (0) ); dprintk("state is %x, result is %x\n", state, result); @@ -160,7 +167,7 @@ static int speedstep_get_state (void) */ static void speedstep_set_state (unsigned int state) { - unsigned int result = 0, command, new_state; + unsigned int result = 0, command, new_state, dummy; unsigned long flags; unsigned int function=SET_SPEEDSTEP_STATE; unsigned int retry = 0; @@ -182,10 +189,12 @@ static void speedstep_set_state (unsigned int state) } retry++; __asm__ __volatile__( - "movl $0, %%edi\n" + "push %%ebp\n" "out %%al, (%%dx)\n" - : "=b" (new_state), "=D" (result) - : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) + "pop %%ebp" + : "=b" (new_state), "=D" (result), "=c" (dummy), "=a" (dummy), + "=d" (dummy), "=S" (dummy) + : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0) ); } while ((new_state != state) && (retry <= SMI_TRIES)); @@ -195,7 +204,7 @@ static void speedstep_set_state (unsigned int state) if (new_state == state) { dprintk("change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result); } else { - printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result); + printk(KERN_ERR "cpufreq: change to state %u failed with new_state %u and result %u\n", state, new_state, result); } return; diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 103d61a59b19..3e18db4cefee 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -176,12 +176,13 @@ static inline void k8_enable_fixed_iorrs(void) } /** - * Checks and updates an fixed-range MTRR if it differs from the value it - * should have. If K8 extentions are wanted, update the K8 SYSCFG MSR also. - * see AMD publication no. 24593, chapter 7.8.1, page 233 for more information - * \param msr MSR address of the MTTR which should be checked and updated - * \param changed pointer which indicates whether the MTRR needed to be changed - * \param msrwords pointer to the MSR values which the MSR should have + * set_fixed_range - checks & updates a fixed-range MTRR if it differs from the value it should have + * @msr: MSR address of the MTTR which should be checked and updated + * @changed: pointer which indicates whether the MTRR needed to be changed + * @msrwords: pointer to the MSR values which the MSR should have + * + * If K8 extentions are wanted, update the K8 SYSCFG MSR also. + * See AMD publication no. 24593, chapter 7.8.1, page 233 for more information. */ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords) { @@ -199,12 +200,15 @@ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords) } } +/** + * generic_get_free_region - Get a free MTRR. + * @base: The starting (base) address of the region. + * @size: The size (in bytes) of the region. + * @replace_reg: mtrr index to be replaced; set to invalid value if none. + * + * Returns: The index of the region on success, else negative on error. + */ int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg) -/* [SUMMARY] Get a free MTRR. - <base> The starting (base) address of the region. - <size> The size (in bytes) of the region. - [RETURNS] The index of the region on success, else -1 on error. -*/ { int i, max; mtrr_type ltype; @@ -249,8 +253,8 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, } /** - * Checks and updates the fixed-range MTRRs if they differ from the saved set - * \param frs pointer to fixed-range MTRR values, saved by get_fixed_ranges() + * set_fixed_ranges - checks & updates the fixed-range MTRRs if they differ from the saved set + * @frs: pointer to fixed-range MTRR values, saved by get_fixed_ranges() */ static int set_fixed_ranges(mtrr_type * frs) { @@ -294,13 +298,13 @@ static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) static u32 deftype_lo, deftype_hi; +/** + * set_mtrr_state - Set the MTRR state for this CPU. + * + * NOTE: The CPU must already be in a safe state for MTRR changes. + * RETURNS: 0 if no changes made, else a mask indicating what was changed. + */ static unsigned long set_mtrr_state(void) -/* [SUMMARY] Set the MTRR state for this CPU. - <state> The MTRR state information to read. - <ctxt> Some relevant CPU context. - [NOTE] The CPU must already be in a safe state for MTRR changes. - [RETURNS] 0 if no changes made, else a mask indication what was changed. -*/ { unsigned int i; unsigned long change_mask = 0; diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index c706a3061553..5921e5f0a640 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -78,6 +78,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { }, { .callback = dmi_io_delay_0xed_port, + .ident = "HP Pavilion dv6000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), + DMI_MATCH(DMI_BOARD_NAME, "30B8") + } + }, + { + .callback = dmi_io_delay_0xed_port, .ident = "HP Pavilion tx1000", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c index 027fc067b399..b402c0f3f192 100644 --- a/arch/x86/kernel/mfgpt_32.c +++ b/arch/x86/kernel/mfgpt_32.c @@ -30,6 +30,7 @@ #include <linux/kernel.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <asm/geode.h> static struct mfgpt_timer_t { diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index d5904eef1d31..eb92ccbb3502 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -600,21 +600,6 @@ static int ptrace_bts_read_record(struct task_struct *child, return sizeof(ret); } -static int ptrace_bts_write_record(struct task_struct *child, - const struct bts_struct *in) -{ - int retval; - - if (!child->thread.ds_area_msr) - return -ENXIO; - - retval = ds_write_bts((void *)child->thread.ds_area_msr, in); - if (retval) - return retval; - - return sizeof(*in); -} - static int ptrace_bts_clear(struct task_struct *child) { if (!child->thread.ds_area_msr) @@ -657,75 +642,6 @@ static int ptrace_bts_drain(struct task_struct *child, return end; } -static int ptrace_bts_realloc(struct task_struct *child, - int size, int reduce_size) -{ - unsigned long rlim, vm; - int ret, old_size; - - if (size < 0) - return -EINVAL; - - old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); - if (old_size < 0) - return old_size; - - ret = ds_free((void **)&child->thread.ds_area_msr); - if (ret < 0) - goto out; - - size >>= PAGE_SHIFT; - old_size >>= PAGE_SHIFT; - - current->mm->total_vm -= old_size; - current->mm->locked_vm -= old_size; - - if (size == 0) - goto out; - - rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; - vm = current->mm->total_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->total_vm; - if (size <= 0) - goto out; - } - - rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; - vm = current->mm->locked_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->locked_vm; - if (size <= 0) - goto out; - } - - ret = ds_allocate((void **)&child->thread.ds_area_msr, - size << PAGE_SHIFT); - if (ret < 0) - goto out; - - current->mm->total_vm += size; - current->mm->locked_vm += size; - -out: - if (child->thread.ds_area_msr) - set_tsk_thread_flag(child, TIF_DS_AREA_MSR); - else - clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); - - return ret; -} - static int ptrace_bts_config(struct task_struct *child, long cfg_size, const struct ptrace_bts_config __user *ucfg) @@ -828,6 +744,91 @@ static int ptrace_bts_status(struct task_struct *child, return sizeof(cfg); } + +static int ptrace_bts_write_record(struct task_struct *child, + const struct bts_struct *in) +{ + int retval; + + if (!child->thread.ds_area_msr) + return -ENXIO; + + retval = ds_write_bts((void *)child->thread.ds_area_msr, in); + if (retval) + return retval; + + return sizeof(*in); +} + +static int ptrace_bts_realloc(struct task_struct *child, + int size, int reduce_size) +{ + unsigned long rlim, vm; + int ret, old_size; + + if (size < 0) + return -EINVAL; + + old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); + if (old_size < 0) + return old_size; + + ret = ds_free((void **)&child->thread.ds_area_msr); + if (ret < 0) + goto out; + + size >>= PAGE_SHIFT; + old_size >>= PAGE_SHIFT; + + current->mm->total_vm -= old_size; + current->mm->locked_vm -= old_size; + + if (size == 0) + goto out; + + rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + vm = current->mm->total_vm + size; + if (rlim < vm) { + ret = -ENOMEM; + + if (!reduce_size) + goto out; + + size = rlim - current->mm->total_vm; + if (size <= 0) + goto out; + } + + rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; + vm = current->mm->locked_vm + size; + if (rlim < vm) { + ret = -ENOMEM; + + if (!reduce_size) + goto out; + + size = rlim - current->mm->locked_vm; + if (size <= 0) + goto out; + } + + ret = ds_allocate((void **)&child->thread.ds_area_msr, + size << PAGE_SHIFT); + if (ret < 0) + goto out; + + current->mm->total_vm += size; + current->mm->locked_vm += size; + +out: + if (child->thread.ds_area_msr) + set_tsk_thread_flag(child, TIF_DS_AREA_MSR); + else + clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); + + return ret; +} + void ptrace_bts_take_timestamp(struct task_struct *tsk, enum bts_qualifier qualifier) { diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index a1d7071a51c9..2b3e5d45176b 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -406,8 +406,6 @@ static unsigned long __init setup_memory(void) */ min_low_pfn = PFN_UP(init_pg_tables_end); - find_max_pfn(); - max_low_pfn = find_max_low_pfn(); #ifdef CONFIG_HIGHMEM @@ -764,12 +762,13 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled) efi_init(); - max_low_pfn = setup_memory(); - /* update e820 for memory not covered by WB MTRRs */ + find_max_pfn(); mtrr_bp_init(); if (mtrr_trim_uncached_memory(max_pfn)) - max_low_pfn = setup_memory(); + find_max_pfn(); + + max_low_pfn = setup_memory(); #ifdef CONFIG_VMI /* diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 7637dc91c79b..f4f7ecfb898c 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -801,7 +801,7 @@ static void __cpuinit srat_detect_node(void) /* Don't do the funky fallback heuristics the AMD version employs for now. */ node = apicid_to_node[apicid]; - if (node == NUMA_NO_NODE) + if (node == NUMA_NO_NODE || !node_online(node)) node = first_node(node_online_map); numa_set_node(cpu, node); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index d8172aabc660..e55af12e11b7 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -222,8 +222,7 @@ static int is_io_pte(unsigned long pte) static int is_rmap_pte(u64 pte) { - return pte != shadow_trap_nonpresent_pte - && pte != shadow_notrap_nonpresent_pte; + return is_shadow_present_pte(pte); } static gfn_t pse36_gfn_delta(u32 gpte) @@ -893,14 +892,25 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, int *ptwrite, gfn_t gfn, struct page *page) { u64 spte; - int was_rmapped = is_rmap_pte(*shadow_pte); + int was_rmapped = 0; int was_writeble = is_writeble_pte(*shadow_pte); + hfn_t host_pfn = (*shadow_pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; pgprintk("%s: spte %llx access %x write_fault %d" " user_fault %d gfn %lx\n", __FUNCTION__, *shadow_pte, pt_access, write_fault, user_fault, gfn); + if (is_rmap_pte(*shadow_pte)) { + if (host_pfn != page_to_pfn(page)) { + pgprintk("hfn old %lx new %lx\n", + host_pfn, page_to_pfn(page)); + rmap_remove(vcpu->kvm, shadow_pte); + } + else + was_rmapped = 1; + } + /* * We don't set the accessed bit, since we sometimes want to see * whether the guest actually used the pte (in order to detect @@ -1402,7 +1412,7 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, up_read(¤t->mm->mmap_sem); vcpu->arch.update_pte.gfn = gfn; - vcpu->arch.update_pte.page = gfn_to_page(vcpu->kvm, gfn); + vcpu->arch.update_pte.page = page; } void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 94ea724638fd..8e1462880d1f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -349,8 +349,6 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) static void reload_tss(void) { -#ifndef CONFIG_X86_64 - /* * VT restores TR but not its size. Useless. */ @@ -361,7 +359,6 @@ static void reload_tss(void) descs = (void *)gdt.base; descs[GDT_ENTRY_TSS].type = 9; /* available TSS */ load_TR_desc(); -#endif } static void load_transition_efer(struct vcpu_vmx *vmx) @@ -1436,7 +1433,7 @@ static int init_rmode_tss(struct kvm *kvm) int ret = 0; int r; - down_read(¤t->mm->mmap_sem); + down_read(&kvm->slots_lock); r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE); if (r < 0) goto out; @@ -1459,7 +1456,7 @@ static int init_rmode_tss(struct kvm *kvm) ret = 1; out: - up_read(¤t->mm->mmap_sem); + up_read(&kvm->slots_lock); return ret; } diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index a104c532ff70..3335b4595efd 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -10,21 +10,19 @@ * (such as the example in Documentation/lguest/lguest.c) is called the * Launcher. * - * Secondly, we only run specially modified Guests, not normal kernels. When - * you set CONFIG_LGUEST to 'y' or 'm', this automatically sets - * CONFIG_LGUEST_GUEST=y, which compiles this file into the kernel so it knows - * how to be a Guest. This means that you can use the same kernel you boot - * normally (ie. as a Host) as a Guest. + * Secondly, we only run specially modified Guests, not normal kernels: setting + * CONFIG_LGUEST_GUEST to "y" compiles this file into the kernel so it knows + * how to be a Guest at boot time. This means that you can use the same kernel + * you boot normally (ie. as a Host) as a Guest. * * These Guests know that they cannot do privileged operations, such as disable * interrupts, and that they have to ask the Host to do such things explicitly. * This file consists of all the replacements for such low-level native * hardware operations: these special Guest versions call the Host. * - * So how does the kernel know it's a Guest? The Guest starts at a special - * entry point marked with a magic string, which sets up a few things then - * calls here. We replace the native functions various "paravirt" structures - * with our Guest versions, then boot like normal. :*/ + * So how does the kernel know it's a Guest? We'll see that later, but let's + * just say that we end up here where we replace the native functions various + * "paravirt" structures with our Guest versions, then boot like normal. :*/ /* * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation. @@ -134,7 +132,7 @@ static void async_hcall(unsigned long call, unsigned long arg1, * lguest_leave_lazy_mode(). * * So, when we're in lazy mode, we call async_hcall() to store the call for - * future processing. */ + * future processing: */ static void lazy_hcall(unsigned long call, unsigned long arg1, unsigned long arg2, @@ -147,7 +145,7 @@ static void lazy_hcall(unsigned long call, } /* When lazy mode is turned off reset the per-cpu lazy mode variable and then - * issue a hypercall to flush any stored calls. */ + * issue the do-nothing hypercall to flush any stored calls. */ static void lguest_leave_lazy_mode(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); @@ -164,7 +162,7 @@ static void lguest_leave_lazy_mode(void) * * So instead we keep an "irq_enabled" field inside our "struct lguest_data", * which the Guest can update with a single instruction. The Host knows to - * check there when it wants to deliver an interrupt. + * check there before it tries to deliver an interrupt. */ /* save_flags() is expected to return the processor state (ie. "flags"). The @@ -196,10 +194,15 @@ static void irq_enable(void) /*M:003 Note that we don't check for outstanding interrupts when we re-enable * them (or when we unmask an interrupt). This seems to work for the moment, * since interrupts are rare and we'll just get the interrupt on the next timer - * tick, but when we turn on CONFIG_NO_HZ, we should revisit this. One way + * tick, but now we can run with CONFIG_NO_HZ, we should revisit this. One way * would be to put the "irq_enabled" field in a page by itself, and have the * Host write-protect it when an interrupt comes in when irqs are disabled. - * There will then be a page fault as soon as interrupts are re-enabled. :*/ + * There will then be a page fault as soon as interrupts are re-enabled. + * + * A better method is to implement soft interrupt disable generally for x86: + * instead of disabling interrupts, we set a flag. If an interrupt does come + * in, we then disable them for real. This is uncommon, so we could simply use + * a hypercall for interrupt control and not worry about efficiency. :*/ /*G:034 * The Interrupt Descriptor Table (IDT). @@ -212,6 +215,10 @@ static void irq_enable(void) static void lguest_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g) { + /* The gate_desc structure is 8 bytes long: we hand it to the Host in + * two 32-bit chunks. The whole 32-bit kernel used to hand descriptors + * around like this; typesafety wasn't a big concern in Linux's early + * years. */ u32 *desc = (u32 *)g; /* Keep the local copy up to date. */ native_write_idt_entry(dt, entrynum, g); @@ -243,7 +250,8 @@ static void lguest_load_idt(const struct desc_ptr *desc) * * This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY * hypercall and use that repeatedly to load a new IDT. I don't think it - * really matters, but wouldn't it be nice if they were the same? + * really matters, but wouldn't it be nice if they were the same? Wouldn't + * it be even better if you were the one to send the patch to fix it? */ static void lguest_load_gdt(const struct desc_ptr *desc) { @@ -298,9 +306,9 @@ static void lguest_load_tr_desc(void) /* The "cpuid" instruction is a way of querying both the CPU identity * (manufacturer, model, etc) and its features. It was introduced before the - * Pentium in 1993 and keeps getting extended by both Intel and AMD. As you - * might imagine, after a decade and a half this treatment, it is now a giant - * ball of hair. Its entry in the current Intel manual runs to 28 pages. + * Pentium in 1993 and keeps getting extended by both Intel, AMD and others. + * As you might imagine, after a decade and a half this treatment, it is now a + * giant ball of hair. Its entry in the current Intel manual runs to 28 pages. * * This instruction even it has its own Wikipedia entry. The Wikipedia entry * has been translated into 4 languages. I am not making this up! @@ -594,17 +602,17 @@ static unsigned long lguest_get_wallclock(void) return lguest_data.time.tv_sec; } -/* The TSC is a Time Stamp Counter. The Host tells us what speed it runs at, - * or 0 if it's unusable as a reliable clock source. This matches what we want - * here: if we return 0 from this function, the x86 TSC clock will not register - * itself. */ +/* The TSC is an Intel thing called the Time Stamp Counter. The Host tells us + * what speed it runs at, or 0 if it's unusable as a reliable clock source. + * This matches what we want here: if we return 0 from this function, the x86 + * TSC clock will give up and not register itself. */ static unsigned long lguest_cpu_khz(void) { return lguest_data.tsc_khz; } -/* If we can't use the TSC, the kernel falls back to our "lguest_clock", where - * we read the time value given to us by the Host. */ +/* If we can't use the TSC, the kernel falls back to our lower-priority + * "lguest_clock", where we read the time value given to us by the Host. */ static cycle_t lguest_clock_read(void) { unsigned long sec, nsec; @@ -648,12 +656,16 @@ static struct clocksource lguest_clock = { static int lguest_clockevent_set_next_event(unsigned long delta, struct clock_event_device *evt) { + /* FIXME: I don't think this can ever happen, but James tells me he had + * to put this code in. Maybe we should remove it now. Anyone? */ if (delta < LG_CLOCK_MIN_DELTA) { if (printk_ratelimit()) printk(KERN_DEBUG "%s: small delta %lu ns\n", __FUNCTION__, delta); return -ETIME; } + + /* Please wake us this far in the future. */ hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0); return 0; } @@ -738,7 +750,7 @@ static void lguest_time_init(void) * will not tolerate us trying to use that), the stack pointer, and the number * of pages in the stack. */ static void lguest_load_sp0(struct tss_struct *tss, - struct thread_struct *thread) + struct thread_struct *thread) { lazy_hcall(LHCALL_SET_STACK, __KERNEL_DS|0x1, thread->sp0, THREAD_SIZE/PAGE_SIZE); @@ -786,9 +798,8 @@ static void lguest_safe_halt(void) hcall(LHCALL_HALT, 0, 0, 0); } -/* Perhaps CRASH isn't the best name for this hypercall, but we use it to get a - * message out when we're crashing as well as elegant termination like powering - * off. +/* The SHUTDOWN hypercall takes a string to describe what's happening, and + * an argument which says whether this to restart (reboot) the Guest or not. * * Note that the Host always prefers that the Guest speak in physical addresses * rather than virtual addresses, so we use __pa() here. */ @@ -816,8 +827,9 @@ static struct notifier_block paniced = { /* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { - /* We do this here and not earlier because lockcheck barfs if we do it - * before start_kernel() */ + /* We do this here and not earlier because lockcheck used to barf if we + * did it before start_kernel(). I think we fixed that, so it'd be + * nice to move it back to lguest_init. Patch welcome... */ atomic_notifier_chain_register(&panic_notifier_list, &paniced); /* The Linux bootloader header contains an "e820" memory map: the @@ -850,12 +862,19 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) return len; } +/* Rebooting also tells the Host we're finished, but the RESTART flag tells the + * Launcher to reboot us. */ +static void lguest_restart(char *reason) +{ + hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); +} + /*G:050 * Patching (Powerfully Placating Performance Pedants) * - * We have already seen that pv_ops structures let us replace simple - * native instructions with calls to the appropriate back end all throughout - * the kernel. This allows the same kernel to run as a Guest and as a native + * We have already seen that pv_ops structures let us replace simple native + * instructions with calls to the appropriate back end all throughout the + * kernel. This allows the same kernel to run as a Guest and as a native * kernel, but it's slow because of all the indirect branches. * * Remember that David Wheeler quote about "Any problem in computer science can @@ -908,14 +927,9 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf, return insn_len; } -static void lguest_restart(char *reason) -{ - hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); -} - -/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops - * structures in the kernel provide points for (almost) every routine we have - * to override to avoid privileged instructions. */ +/*G:030 Once we get to lguest_init(), we know we're a Guest. The various + * pv_ops structures in the kernel provide points for (almost) every routine we + * have to override to avoid privileged instructions. */ __init void lguest_init(void) { /* We're under lguest, paravirt is enabled, and we're running at @@ -1003,9 +1017,9 @@ __init void lguest_init(void) * the normal data segment to get through booting. */ asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory"); - /* The Host uses the top of the Guest's virtual address space for the - * Host<->Guest Switcher, and it tells us how big that is in - * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */ + /* The Host<->Guest Switcher lives at the top of our address space, and + * the Host told us how big it is when we made LGUEST_INIT hypercall: + * it put the answer in lguest_data.reserve_mem */ reserve_top_address(lguest_data.reserve_mem); /* If we don't initialize the lock dependency checker now, it crashes @@ -1027,6 +1041,7 @@ __init void lguest_init(void) /* Math is always hard! */ new_cpu_data.hard_math = 1; + /* We don't have features. We have puppies! Puppies! */ #ifdef CONFIG_X86_MCE mce_disabled = 1; #endif @@ -1044,10 +1059,11 @@ __init void lguest_init(void) virtio_cons_early_init(early_put_chars); /* Last of all, we set the power management poweroff hook to point to - * the Guest routine to power off. */ + * the Guest routine to power off, and the reboot hook to our restart + * routine. */ pm_power_off = lguest_power_off; - machine_ops.restart = lguest_restart; + /* Now we're set up, call start_kernel() in init/main.c and we proceed * to boot as normal. It never returns. */ start_kernel(); diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 95b6fbcded63..5c7cef34c9e7 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S @@ -5,13 +5,20 @@ #include <asm/thread_info.h> #include <asm/processor-flags.h> -/*G:020 This is where we begin: head.S notes that the boot header's platform - * type field is "1" (lguest), so calls us here. +/*G:020 Our story starts with the kernel booting into startup_32 in + * arch/x86/kernel/head_32.S. It expects a boot header, which is created by + * the bootloader (the Launcher in our case). + * + * The startup_32 function does very little: it clears the uninitialized global + * C variables which we expect to be zero (ie. BSS) and then copies the boot + * header and kernel command line somewhere safe. Finally it checks the + * 'hardware_subarch' field. This was introduced in 2.6.24 for lguest and Xen: + * if it's set to '1' (lguest's assigned number), then it calls us here. * * WARNING: be very careful here! We're running at addresses equal to physical * addesses (around 0), not above PAGE_OFFSET as most code expectes * (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any - * data. + * data without remembering to subtract __PAGE_OFFSET! * * The .section line puts this code in .init.text so it will be discarded after * boot. */ @@ -24,7 +31,7 @@ ENTRY(lguest_entry) int $LGUEST_TRAP_ENTRY /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl - * instruction uses %esi implicitly as the source for the copy we' + * instruction uses %esi implicitly as the source for the copy we're * about to do. */ movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi diff --git a/arch/x86/mach-rdc321x/gpio.c b/arch/x86/mach-rdc321x/gpio.c index 031269163bd6..247f33d3a407 100644 --- a/arch/x86/mach-rdc321x/gpio.c +++ b/arch/x86/mach-rdc321x/gpio.c @@ -1,91 +1,194 @@ /* - * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org> - * RDC321x architecture specific GPIO support + * GPIO support for RDC SoC R3210/R8610 + * + * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org> + * Copyright (C) 2008, Volker Weiss <dev@tintuc.de> + * + * 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. * - * 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. */ -#include <linux/autoconf.h> -#include <linux/init.h> + +#include <linux/spinlock.h> #include <linux/io.h> #include <linux/types.h> #include <linux/module.h> -#include <linux/delay.h> +#include <asm/gpio.h> #include <asm/mach-rdc321x/rdc321x_defs.h> -static inline int rdc_gpio_is_valid(unsigned gpio) + +/* spin lock to protect our private copy of GPIO data register plus + the access to PCI conf registers. */ +static DEFINE_SPINLOCK(gpio_lock); + +/* copy of GPIO data registers */ +static u32 gpio_data_reg1; +static u32 gpio_data_reg2; + +static u32 gpio_request_data[2]; + + +static inline void rdc321x_conf_write(unsigned addr, u32 value) { - return (gpio <= RDC_MAX_GPIO); + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + outl(value, RDC3210_CFGREG_DATA); } -static unsigned int rdc_gpio_read(unsigned gpio) +static inline void rdc321x_conf_or(unsigned addr, u32 value) { - unsigned int val; - - val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48)); - outl(val, RDC3210_CFGREG_ADDR); - udelay(10); - val = inl(RDC3210_CFGREG_DATA); - val |= (0x1 << (gpio & 0x1F)); - outl(val, RDC3210_CFGREG_DATA); - udelay(10); - val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C)); - outl(val, RDC3210_CFGREG_ADDR); - udelay(10); - val = inl(RDC3210_CFGREG_DATA); - - return val; + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + value |= inl(RDC3210_CFGREG_DATA); + outl(value, RDC3210_CFGREG_DATA); } -static void rdc_gpio_write(unsigned int val) +static inline u32 rdc321x_conf_read(unsigned addr) { - if (val) { - outl(val, RDC3210_CFGREG_DATA); - udelay(10); - } + outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + + return inl(RDC3210_CFGREG_DATA); } -int rdc_gpio_get_value(unsigned gpio) +/* configure pin as GPIO */ +static void rdc321x_configure_gpio(unsigned gpio) +{ + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + rdc321x_conf_or(gpio < 32 + ? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2, + 1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); +} + +/* initially setup the 2 copies of the gpio data registers. + This function must be called by the platform setup code. */ +void __init rdc321x_gpio_setup() +{ + /* this might not be, what others (BIOS, bootloader, etc.) + wrote to these registers before, but it's a good guess. Still + better than just using 0xffffffff. */ + + gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); + gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); +} + +/* determine, if gpio number is valid */ +static inline int rdc321x_is_gpio(unsigned gpio) +{ + return gpio <= RDC321X_MAX_GPIO; +} + +/* request GPIO */ +int rdc_gpio_request(unsigned gpio, const char *label) { - if (rdc_gpio_is_valid(gpio)) - return (int)rdc_gpio_read(gpio); - else + unsigned long flags; + + if (!rdc321x_is_gpio(gpio)) return -EINVAL; + + spin_lock_irqsave(&gpio_lock, flags); + if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f))) + goto inuse; + gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +inuse: + spin_unlock_irqrestore(&gpio_lock, flags); + return -EINVAL; } -EXPORT_SYMBOL(rdc_gpio_get_value); +EXPORT_SYMBOL(rdc_gpio_request); -void rdc_gpio_set_value(unsigned gpio, int value) +/* release previously-claimed GPIO */ +void rdc_gpio_free(unsigned gpio) { - unsigned int val; + unsigned long flags; - if (!rdc_gpio_is_valid(gpio)) + if (!rdc321x_is_gpio(gpio)) return; - val = rdc_gpio_read(gpio); + spin_lock_irqsave(&gpio_lock, flags); + gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f)); + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(rdc_gpio_free); + +/* read GPIO pin */ +int rdc_gpio_get_value(unsigned gpio) +{ + u32 reg; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + reg = rdc321x_conf_read(gpio < 32 + ? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2); + spin_unlock_irqrestore(&gpio_lock, flags); - if (value) - val &= ~(0x1 << (gpio & 0x1F)); - else - val |= (0x1 << (gpio & 0x1F)); + return (1 << (gpio & 0x1f)) & reg ? 1 : 0; +} +EXPORT_SYMBOL(rdc_gpio_get_value); - rdc_gpio_write(val); +/* set GPIO pin to value */ +void rdc_gpio_set_value(unsigned gpio, int value) +{ + unsigned long flags; + u32 reg; + + reg = 1 << (gpio & 0x1f); + if (gpio < 32) { + spin_lock_irqsave(&gpio_lock, flags); + if (value) + gpio_data_reg1 |= reg; + else + gpio_data_reg1 &= ~reg; + rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1); + spin_unlock_irqrestore(&gpio_lock, flags); + } else { + spin_lock_irqsave(&gpio_lock, flags); + if (value) + gpio_data_reg2 |= reg; + else + gpio_data_reg2 &= ~reg; + rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2); + spin_unlock_irqrestore(&gpio_lock, flags); + } } EXPORT_SYMBOL(rdc_gpio_set_value); +/* configure GPIO pin as input */ int rdc_gpio_direction_input(unsigned gpio) { + if (!rdc321x_is_gpio(gpio)) + return -EINVAL; + + rdc321x_configure_gpio(gpio); + return 0; } EXPORT_SYMBOL(rdc_gpio_direction_input); +/* configure GPIO pin as output and set value */ int rdc_gpio_direction_output(unsigned gpio, int value) { + if (!rdc321x_is_gpio(gpio)) + return -EINVAL; + + gpio_set_value(gpio, value); + rdc321x_configure_gpio(gpio); + return 0; } EXPORT_SYMBOL(rdc_gpio_direction_output); - - diff --git a/arch/x86/mach-rdc321x/platform.c b/arch/x86/mach-rdc321x/platform.c index dda6024a5862..a037041817c7 100644 --- a/arch/x86/mach-rdc321x/platform.c +++ b/arch/x86/mach-rdc321x/platform.c @@ -62,6 +62,8 @@ static struct platform_device *rdc321x_devs[] = { static int __init rdc_board_setup(void) { + rdc321x_gpio_setup(); + return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); } diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index c394ca0720b8..8e25e06ff730 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c @@ -324,7 +324,6 @@ unsigned long __init setup_memory(void) * this space and use it to adjust the boundary between ZONE_NORMAL * and ZONE_HIGHMEM. */ - find_max_pfn(); get_memcfg_numa(); kva_pages = calculate_numa_remap_pages(); diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index fdc667422df9..ec08d8389850 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -91,12 +91,10 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr, int prefetch = 0; unsigned char *max_instr; -#ifdef CONFIG_X86_32 - if (!(__supported_pte_mask & _PAGE_NX)) - return 0; -#endif - - /* If it was a exec fault on NX page, ignore */ + /* + * If it was a exec (instruction fetch) fault on NX page, then + * do not ignore the fault: + */ if (error_code & PF_INSTR) return 0; diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 4fbafb4bc2f0..0b3d567e686d 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -178,7 +178,7 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; - WARN_ON(!PageCompound(page)); + WARN_ON(!PageHead(page)); return page; } diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 4afaba0ed722..794895c6dcc9 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -137,7 +137,11 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size, switch (mode) { case IOR_MODE_UNCACHED: default: - prot = PAGE_KERNEL_NOCACHE; + /* + * FIXME: we will use UC MINUS for now, as video fb drivers + * depend on it. Upcoming ioremap_wc() will fix this behavior. + */ + prot = PAGE_KERNEL_UC_MINUS; break; case IOR_MODE_CACHED: prot = PAGE_KERNEL; diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 14e48b5a94ba..7b79f6be4e7d 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -771,7 +771,7 @@ static inline int change_page_attr_clear(unsigned long addr, int numpages, int set_memory_uc(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, - __pgprot(_PAGE_PCD | _PAGE_PWT)); + __pgprot(_PAGE_PCD)); } EXPORT_SYMBOL(set_memory_uc); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 8b9ee27805fd..de4e6f05840b 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -95,7 +95,7 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info; * * 0: not available, 1: available */ -static int have_vcpu_info_placement = 0; +static int have_vcpu_info_placement = 1; static void __init xen_vcpu_setup(int cpu) { @@ -103,6 +103,7 @@ static void __init xen_vcpu_setup(int cpu) int err; struct vcpu_info *vcpup; + BUG_ON(HYPERVISOR_shared_info == &dummy_shared_info); per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; if (!have_vcpu_info_placement) @@ -805,33 +806,43 @@ static __init void xen_pagetable_setup_start(pgd_t *base) PFN_DOWN(__pa(xen_start_info->pt_base))); } -static __init void xen_pagetable_setup_done(pgd_t *base) +static __init void setup_shared_info(void) { - /* This will work as long as patching hasn't happened yet - (which it hasn't) */ - pv_mmu_ops.alloc_pt = xen_alloc_pt; - pv_mmu_ops.alloc_pd = xen_alloc_pd; - pv_mmu_ops.release_pt = xen_release_pt; - pv_mmu_ops.release_pd = xen_release_pt; - pv_mmu_ops.set_pte = xen_set_pte; - if (!xen_feature(XENFEAT_auto_translated_physmap)) { + unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP); + /* * Create a mapping for the shared info page. * Should be set_fixmap(), but shared_info is a machine * address with no corresponding pseudo-phys address. */ - set_pte_mfn(fix_to_virt(FIX_PARAVIRT_BOOTMAP), + set_pte_mfn(addr, PFN_DOWN(xen_start_info->shared_info), PAGE_KERNEL); - HYPERVISOR_shared_info = - (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); - + HYPERVISOR_shared_info = (struct shared_info *)addr; } else HYPERVISOR_shared_info = (struct shared_info *)__va(xen_start_info->shared_info); +#ifndef CONFIG_SMP + /* In UP this is as good a place as any to set up shared info */ + xen_setup_vcpu_info_placement(); +#endif +} + +static __init void xen_pagetable_setup_done(pgd_t *base) +{ + /* This will work as long as patching hasn't happened yet + (which it hasn't) */ + pv_mmu_ops.alloc_pt = xen_alloc_pt; + pv_mmu_ops.alloc_pd = xen_alloc_pd; + pv_mmu_ops.release_pt = xen_release_pt; + pv_mmu_ops.release_pd = xen_release_pt; + pv_mmu_ops.set_pte = xen_set_pte; + + setup_shared_info(); + /* Actually pin the pagetable down, but we can't set PG_pinned yet because the page structures don't exist yet. */ { @@ -1182,15 +1193,9 @@ asmlinkage void __init xen_start_kernel(void) x86_write_percpu(xen_cr3, __pa(pgd)); x86_write_percpu(xen_current_cr3, __pa(pgd)); -#ifdef CONFIG_SMP /* Don't do the full vcpu_info placement stuff until we have a - possible map. */ + possible map and a non-dummy shared_info. */ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; -#else - /* May as well do it now, since there's no good time to call - it later on UP. */ - xen_setup_vcpu_info_placement(); -#endif pv_info.kernel_rpl = 1; if (xen_feature(XENFEAT_supervisor_mode_kernel)) diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S index 1a43b60c0c62..6b7190449d07 100644 --- a/arch/x86/xen/xen-asm.S +++ b/arch/x86/xen/xen-asm.S @@ -33,12 +33,17 @@ events, then enter the hypervisor to get them handled. */ ENTRY(xen_irq_enable_direct) - /* Clear mask and test pending */ - andw $0x00ff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending + /* Unmask events */ + movb $0, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask + /* Preempt here doesn't matter because that will deal with any pending interrupts. The pending check may end up being run on the wrong CPU, but that doesn't hurt. */ + + /* Test for pending */ + testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending jz 1f + 2: call check_events 1: ENDPATCH(xen_irq_enable_direct) |