From e3f37a54f690d3e64995ea7ecea08c5ab3070faf Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: x86: assign IRQs to HPET timers The userspace API for the HPET (see Documentation/hpet.txt) did not work. The HPET_IE_ON ioctl was failing as there was no IRQ assigned to the timer device. This patch fixes it by allocating IRQs to timer blocks in the HPET. arch/x86/kernel/hpet.c | 13 +++++-------- drivers/char/hpet.c | 45 ++++++++++++++++++++++++++++++++++++++------- include/linux/hpet.h | 2 +- 3 files changed, 44 insertions(+), 16 deletions(-) Signed-off-by: Balaji Rao Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/char/hpet.c | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 4c16778e3f84..593b32cfbc33 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -806,14 +806,14 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) int hpet_alloc(struct hpet_data *hdp) { - u64 cap, mcfg; + u64 cap, mcfg, hpet_config; struct hpet_dev *devp; - u32 i, ntimer; + u32 i, ntimer, irq; struct hpets *hpetp; size_t siz; struct hpet __iomem *hpet; static struct hpets *last = NULL; - unsigned long period; + unsigned long period, irq_bitmap; unsigned long long temp; /* @@ -840,11 +840,41 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_hpet_phys = hdp->hd_phys_address; hpetp->hp_ntimer = hdp->hd_nirqs; + hpet = hpetp->hp_hpet; - for (i = 0; i < hdp->hd_nirqs; i++) - hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; + /* Assign IRQs statically for legacy devices */ + hpetp->hp_dev[0].hd_hdwirq = hdp->hd_irq[0]; + hpetp->hp_dev[1].hd_hdwirq = hdp->hd_irq[1]; - hpet = hpetp->hp_hpet; + /* Assign IRQs dynamically for the others */ + for (i = 2, devp = &hpetp->hp_dev[2]; i < hdp->hd_nirqs; i++, devp++) { + struct hpet_timer __iomem *timer; + + timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; + + hpet_config = readq(&timer->hpet_config); + irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK) + >> Tn_INT_ROUTE_CAP_SHIFT; + if (!irq_bitmap) + irq = 0; /* No valid IRQ Assignable */ + else { + irq = find_first_bit(&irq_bitmap, 32); + do { + hpet_config |= irq << Tn_INT_ROUTE_CNF_SHIFT; + writeq(hpet_config, &timer->hpet_config); + + /* + * Verify whether we have written a valid + * IRQ number by reading it back again + */ + hpet_config = readq(&timer->hpet_config); + if (irq == (hpet_config & Tn_INT_ROUTE_CNF_MASK) + >> Tn_INT_ROUTE_CNF_SHIFT) + break; /* Success */ + } while ((irq = (find_next_bit(&irq_bitmap, 32, irq)))); + } + hpetp->hp_dev[i].hd_hdwirq = irq; + } cap = readq(&hpet->hpet_cap); @@ -875,7 +905,8 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_which, hdp->hd_phys_address, hpetp->hp_ntimer > 1 ? "s" : ""); for (i = 0; i < hpetp->hp_ntimer; i++) - printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); + printk("%s %d", i > 0 ? "," : "", + hpetp->hp_dev[i].hd_hdwirq); printk("\n"); printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", -- cgit v1.2.3 From 37a47db8d7f0f38dac5acf5a13abbc8f401707fa Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: x86: assign IRQs to HPET timers, fix Looks like IRQ 31 is assigned to timer 3, even without the patch! I wonder who wrote the number 31. But the manual says that it is zero by default. I think we should check whether the timer has been allocated an IRQ before proceeding to assign one to it. Here is a patch that does this. Signed-off-by: Balaji Rao Tested-by: Yinghai Lu Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/hpet.c | 10 +++++----- drivers/char/hpet.c | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 786aa227afdf..a3c56c9b8a02 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -117,7 +117,8 @@ int is_hpet_enabled(void) static void hpet_reserve_platform_timers(unsigned long id) { struct hpet __iomem *hpet = hpet_virt_address; - unsigned int nrtimers; + struct hpet_timer __iomem *timer = &hpet->hpet_timers[2]; + unsigned int nrtimers, i; struct hpet_data hd; nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; @@ -135,10 +136,9 @@ static void hpet_reserve_platform_timers(unsigned long id) hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; - /* - * IRQs for the other timers are assigned dynamically - * in hpet_alloc - */ + for (i = 2; i < nrtimers; timer++, i++) + hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >> + Tn_INT_ROUTE_CNF_SHIFT; hpet_alloc(&hd); } #else diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 593b32cfbc33..22f5fd02ea87 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -852,6 +852,12 @@ int hpet_alloc(struct hpet_data *hdp) timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; + /* Check if there's already an IRQ assigned to the timer */ + if (hdp->hd_irq[i]) { + hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; + continue; + } + hpet_config = readq(&timer->hpet_config); irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK) >> Tn_INT_ROUTE_CAP_SHIFT; -- cgit v1.2.3 From 02456c708eab4515121e5e581422fa3be14368d1 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:27 +0100 Subject: x86: nuke a ton of dead hpet code No users, just ballast Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- drivers/char/hpet.c | 75 ---------------------------------------------------- include/linux/hpet.h | 3 --- 2 files changed, 78 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 22f5fd02ea87..465ad35ed38f 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -600,63 +600,6 @@ static int hpet_is_known(struct hpet_data *hdp) return 0; } -EXPORT_SYMBOL(hpet_alloc); -EXPORT_SYMBOL(hpet_register); -EXPORT_SYMBOL(hpet_unregister); -EXPORT_SYMBOL(hpet_control); - -int hpet_register(struct hpet_task *tp, int periodic) -{ - unsigned int i; - u64 mask; - struct hpet_timer __iomem *timer; - struct hpet_dev *devp; - struct hpets *hpetp; - - switch (periodic) { - case 1: - mask = Tn_PER_INT_CAP_MASK; - break; - case 0: - mask = 0; - break; - default: - return -EINVAL; - } - - tp->ht_opaque = NULL; - - spin_lock_irq(&hpet_task_lock); - spin_lock(&hpet_lock); - - for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) - for (timer = hpetp->hp_hpet->hpet_timers, i = 0; - i < hpetp->hp_ntimer; i++, timer++) { - if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK) - != mask) - continue; - - devp = &hpetp->hp_dev[i]; - - if (devp->hd_flags & HPET_OPEN || devp->hd_task) { - devp = NULL; - continue; - } - - tp->ht_opaque = devp; - devp->hd_task = tp; - break; - } - - spin_unlock(&hpet_lock); - spin_unlock_irq(&hpet_task_lock); - - if (tp->ht_opaque) - return 0; - else - return -EBUSY; -} - static inline int hpet_tpcheck(struct hpet_task *tp) { struct hpet_dev *devp; @@ -706,24 +649,6 @@ int hpet_unregister(struct hpet_task *tp) return 0; } -int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) -{ - struct hpet_dev *devp; - int err; - - if ((err = hpet_tpcheck(tp))) - return err; - - spin_lock_irq(&hpet_lock); - devp = tp->ht_opaque; - if (devp->hd_task != tp) { - spin_unlock_irq(&hpet_lock); - return -ENXIO; - } - spin_unlock_irq(&hpet_lock); - return hpet_ioctl_common(devp, cmd, arg, 1); -} - static ctl_table hpet_table[] = { { .ctl_name = CTL_UNNUMBERED, diff --git a/include/linux/hpet.h b/include/linux/hpet.h index e3c0b2aa944c..9cd94bfd07e5 100644 --- a/include/linux/hpet.h +++ b/include/linux/hpet.h @@ -115,9 +115,6 @@ static inline void hpet_reserve_timer(struct hpet_data *hd, int timer) } int hpet_alloc(struct hpet_data *); -int hpet_register(struct hpet_task *, int); -int hpet_unregister(struct hpet_task *); -int hpet_control(struct hpet_task *, unsigned int, unsigned long); #endif /* __KERNEL__ */ -- cgit v1.2.3 From faca62273b602ab482fb7d3d940dbf41ef08b00e Mon Sep 17 00:00:00 2001 From: H. Peter Anvin Date: Wed, 30 Jan 2008 13:31:02 +0100 Subject: x86: use generic register name in the thread and tss structures This changes size-specific register names (eip/rip, esp/rsp, etc.) to generic names in the thread and tss structures. Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/asm-offsets_32.c | 4 ++-- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/doublefault_32.c | 15 ++++++++------- arch/x86/kernel/entry_32.S | 6 +++--- arch/x86/kernel/paravirt_32.c | 2 +- arch/x86/kernel/process_32.c | 12 ++++++------ arch/x86/kernel/process_64.c | 16 ++++++++-------- arch/x86/kernel/smpboot_32.c | 8 ++++---- arch/x86/kernel/smpboot_64.c | 6 +++--- arch/x86/kernel/traps_32.c | 6 +++--- arch/x86/kernel/traps_64.c | 4 ++-- arch/x86/kernel/vm86_32.c | 16 ++++++++-------- arch/x86/kernel/vmi_32.c | 10 +++++----- arch/x86/lguest/boot.c | 6 +++--- arch/x86/vdso/vdso32-setup.c | 4 ++-- arch/x86/xen/enlighten.c | 6 +++--- arch/x86/xen/smp.c | 4 ++-- drivers/lguest/x86/core.c | 4 ++-- include/asm-x86/paravirt.h | 6 +++--- include/asm-x86/processor_32.h | 37 +++++++++++++++++-------------------- include/asm-x86/processor_64.h | 20 ++++++++++---------- include/asm-x86/system_32.h | 4 ++-- include/asm-x86/system_64.h | 2 +- 23 files changed, 99 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 4fc24a61f431..415313556708 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -101,8 +101,8 @@ void foo(void) OFFSET(pbe_orig_address, pbe, orig_address); OFFSET(pbe_next, pbe, next); - /* Offset from the sysenter stack to tss.esp0 */ - DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, x86_tss.esp0) - + /* Offset from the sysenter stack to tss.sp0 */ + DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) - sizeof(struct tss_struct)); DEFINE(PAGE_SIZE_asm, PAGE_SIZE); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 5db2a163bf4b..235cd615b89d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -691,7 +691,7 @@ void __cpuinit cpu_init(void) BUG(); enter_lazy_tlb(&init_mm, curr); - load_esp0(t, thread); + load_sp0(t, thread); set_tss_desc(cpu,t); load_TR_desc(); load_LDT(&init_mm.context); diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index 40978af630e7..cc19a3ea403a 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c @@ -35,12 +35,13 @@ static void doublefault_fn(void) if (ptr_ok(tss)) { struct i386_hw_tss *t = (struct i386_hw_tss *)tss; - printk(KERN_EMERG "eip = %08lx, esp = %08lx\n", t->eip, t->esp); + printk(KERN_EMERG "eip = %08lx, esp = %08lx\n", + t->ip, t->sp); printk(KERN_EMERG "eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", - t->eax, t->ebx, t->ecx, t->edx); + t->ax, t->bx, t->cx, t->dx); printk(KERN_EMERG "esi = %08lx, edi = %08lx\n", - t->esi, t->edi); + t->si, t->di); } } @@ -50,15 +51,15 @@ static void doublefault_fn(void) struct tss_struct doublefault_tss __cacheline_aligned = { .x86_tss = { - .esp0 = STACK_START, + .sp0 = STACK_START, .ss0 = __KERNEL_DS, .ldt = 0, .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, - .eip = (unsigned long) doublefault_fn, + .ip = (unsigned long) doublefault_fn, /* 0x2 bit is always set */ - .eflags = X86_EFLAGS_SF | 0x2, - .esp = STACK_START, + .flags = X86_EFLAGS_SF | 0x2, + .sp = STACK_START, .es = __USER_DS, .cs = __KERNEL_CS, .ss = __KERNEL_DS, diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 153bb87a4eea..6a474e1028c7 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -288,7 +288,7 @@ ENTRY(ia32_sysenter_target) CFI_SIGNAL_FRAME CFI_DEF_CFA esp, 0 CFI_REGISTER esp, ebp - movl TSS_sysenter_esp0(%esp),%esp + movl TSS_sysenter_sp0(%esp),%esp sysenter_past_esp: /* * No need to follow this irqs on/off section: the syscall @@ -743,7 +743,7 @@ END(device_not_available) * that sets up the real kernel stack. Check here, since we can't * allow the wrong stack to be used. * - * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have + * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have * already pushed 3 words if it hits on the sysenter instruction: * eflags, cs and eip. * @@ -755,7 +755,7 @@ END(device_not_available) cmpw $__KERNEL_CS,4(%esp); \ jne ok; \ label: \ - movl TSS_sysenter_esp0+offset(%esp),%esp; \ + movl TSS_sysenter_sp0+offset(%esp),%esp; \ CFI_DEF_CFA esp, 0; \ CFI_UNDEFINED eip; \ pushfl; \ diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c index 706b0562ea40..f4e3a8e01cf2 100644 --- a/arch/x86/kernel/paravirt_32.c +++ b/arch/x86/kernel/paravirt_32.c @@ -382,7 +382,7 @@ struct pv_cpu_ops pv_cpu_ops = { .write_ldt_entry = write_dt_entry, .write_gdt_entry = write_dt_entry, .write_idt_entry = write_dt_entry, - .load_esp0 = native_load_esp0, + .load_sp0 = native_load_sp0, .irq_enable_syscall_ret = native_irq_enable_syscall_ret, .iret = native_iret, diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 3744cf63682c..add3bf34e205 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -75,7 +75,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_number); */ unsigned long thread_saved_pc(struct task_struct *tsk) { - return ((unsigned long *)tsk->thread.esp)[3]; + return ((unsigned long *)tsk->thread.sp)[3]; } /* @@ -488,10 +488,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, childregs->ax = 0; childregs->sp = sp; - p->thread.esp = (unsigned long) childregs; - p->thread.esp0 = (unsigned long) (childregs+1); + p->thread.sp = (unsigned long) childregs; + p->thread.sp0 = (unsigned long) (childregs+1); - p->thread.eip = (unsigned long) ret_from_fork; + p->thread.ip = (unsigned long) ret_from_fork; savesegment(gs,p->thread.gs); @@ -718,7 +718,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas /* * Reload esp0. */ - load_esp0(tss, next); + load_sp0(tss, next); /* * Save away %gs. No need to save %fs, as it was saved on the @@ -851,7 +851,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; stack_page = (unsigned long)task_stack_page(p); - sp = p->thread.esp; + sp = p->thread.sp; if (!stack_page || sp < stack_page || sp > top_esp+stack_page) return 0; /* include/asm-i386/system.h:switch_to() pushes bp last. */ diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index efbb1a2eab97..238193822e23 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -493,9 +493,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, if (sp == ~0UL) childregs->sp = (unsigned long)childregs; - p->thread.rsp = (unsigned long) childregs; - p->thread.rsp0 = (unsigned long) (childregs+1); - p->thread.userrsp = me->thread.userrsp; + p->thread.sp = (unsigned long) childregs; + p->thread.sp0 = (unsigned long) (childregs+1); + p->thread.usersp = me->thread.usersp; set_tsk_thread_flag(p, TIF_FORK); @@ -607,7 +607,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* * Reload esp0, LDT and the page table pointer: */ - tss->rsp0 = next->rsp0; + tss->sp0 = next->sp0; /* * Switch DS and ES. @@ -666,8 +666,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* * Switch the PDA and FPU contexts. */ - prev->userrsp = read_pda(oldrsp); - write_pda(oldrsp, next->userrsp); + prev->usersp = read_pda(oldrsp); + write_pda(oldrsp, next->usersp); write_pda(pcurrent, next_p); write_pda(kernelstack, @@ -769,9 +769,9 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state==TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); - if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE) + if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) return 0; - fp = *(u64 *)(p->thread.rsp); + fp = *(u64 *)(p->thread.sp); do { if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c index 3566191832b3..0f294d6e22cf 100644 --- a/arch/x86/kernel/smpboot_32.c +++ b/arch/x86/kernel/smpboot_32.c @@ -454,7 +454,7 @@ void __devinit initialize_secondary(void) "movl %0,%%esp\n\t" "jmp *%1" : - :"m" (current->thread.esp),"m" (current->thread.eip)); + :"m" (current->thread.sp),"m" (current->thread.ip)); } /* Static state in head.S used to set up a CPU */ @@ -753,7 +753,7 @@ static inline struct task_struct * __cpuinit alloc_idle_task(int cpu) /* initialize thread_struct. we really want to avoid destroy * idle tread */ - idle->thread.esp = (unsigned long)task_pt_regs(idle); + idle->thread.sp = (unsigned long)task_pt_regs(idle); init_idle(idle, cpu); return idle; } @@ -798,7 +798,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) per_cpu(current_task, cpu) = idle; early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); - idle->thread.eip = (unsigned long) start_secondary; + idle->thread.ip = (unsigned long) start_secondary; /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); @@ -808,7 +808,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) /* So we see what's up */ printk("Booting processor %d/%d ip %lx\n", cpu, apicid, start_eip); /* Stack for startup_32 can be just as for start_secondary onwards */ - stack_start.sp = (void *) idle->thread.esp; + stack_start.sp = (void *) idle->thread.sp; irq_ctx_init(cpu); diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index ac1089f2b917..c3f2736ba530 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c @@ -577,7 +577,7 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) c_idle.idle = get_idle_for_cpu(cpu); if (c_idle.idle) { - c_idle.idle->thread.rsp = (unsigned long) (((struct pt_regs *) + c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *) (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1); init_idle(c_idle.idle, cpu); goto do_rest; @@ -613,8 +613,8 @@ do_rest: start_rip = setup_trampoline(); - init_rsp = c_idle.idle->thread.rsp; - per_cpu(init_tss,cpu).rsp0 = init_rsp; + init_rsp = c_idle.idle->thread.sp; + per_cpu(init_tss,cpu).sp0 = init_rsp; initial_code = start_secondary; clear_tsk_thread_flag(c_idle.idle, TIF_FORK); diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 27713553cc59..57491942cc4e 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -163,7 +163,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, unsigned long dummy; stack = &dummy; if (task != current) - stack = (unsigned long *)task->thread.esp; + stack = (unsigned long *)task->thread.sp; } #ifdef CONFIG_FRAME_POINTER @@ -173,7 +173,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, asm ("movl %%ebp, %0" : "=r" (bp) : ); } else { /* bp is the last reg pushed by switch_to */ - bp = *(unsigned long *) task->thread.esp; + bp = *(unsigned long *) task->thread.sp; } } #endif @@ -253,7 +253,7 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, if (sp == NULL) { if (task) - sp = (unsigned long*)task->thread.esp; + sp = (unsigned long*)task->thread.sp; else sp = (unsigned long *)&sp; } diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index f7fecf9d47c3..965f2cc3a013 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -230,7 +230,7 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long dummy; stack = &dummy; if (tsk && tsk != current) - stack = (unsigned long *)tsk->thread.rsp; + stack = (unsigned long *)tsk->thread.sp; } /* @@ -366,7 +366,7 @@ _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *sp) if (sp == NULL) { if (tsk) - sp = (unsigned long *)tsk->thread.rsp; + sp = (unsigned long *)tsk->thread.sp; else sp = (unsigned long *)&sp; } diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 980e85b90091..e85bb44265cb 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -147,10 +147,10 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) } tss = &per_cpu(init_tss, get_cpu()); - current->thread.esp0 = current->thread.saved_esp0; + current->thread.sp0 = current->thread.saved_sp0; current->thread.sysenter_cs = __KERNEL_CS; - load_esp0(tss, ¤t->thread); - current->thread.saved_esp0 = 0; + load_sp0(tss, ¤t->thread); + current->thread.saved_sp0 = 0; put_cpu(); ret = KVM86->regs32; @@ -207,7 +207,7 @@ asmlinkage int sys_vm86old(struct pt_regs regs) int tmp, ret = -EPERM; tsk = current; - if (tsk->thread.saved_esp0) + if (tsk->thread.saved_sp0) goto out; tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, offsetof(struct kernel_vm86_struct, vm86plus) - @@ -256,7 +256,7 @@ asmlinkage int sys_vm86(struct pt_regs regs) /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */ ret = -EPERM; - if (tsk->thread.saved_esp0) + if (tsk->thread.saved_sp0) goto out; v86 = (struct vm86plus_struct __user *)regs.cx; tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, @@ -318,15 +318,15 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk * Save old state, set default return value (%ax) to 0 */ info->regs32->ax = 0; - tsk->thread.saved_esp0 = tsk->thread.esp0; + tsk->thread.saved_sp0 = tsk->thread.sp0; tsk->thread.saved_fs = info->regs32->fs; savesegment(gs, tsk->thread.saved_gs); tss = &per_cpu(init_tss, get_cpu()); - tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; + tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0; if (cpu_has_sep) tsk->thread.sysenter_cs = 0; - load_esp0(tss, &tsk->thread); + load_sp0(tss, &tsk->thread); put_cpu(); tsk->thread.screen_bitmap = info->screen_bitmap; diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 599b6f2ed562..4cfda7dbe90f 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -62,7 +62,7 @@ static struct { void (*cpuid)(void /* non-c */); void (*_set_ldt)(u32 selector); void (*set_tr)(u32 selector); - void (*set_kernel_stack)(u32 selector, u32 esp0); + void (*set_kernel_stack)(u32 selector, u32 sp0); void (*allocate_page)(u32, u32, u32, u32, u32); void (*release_page)(u32, u32); void (*set_pte)(pte_t, pte_t *, unsigned); @@ -214,17 +214,17 @@ static void vmi_set_tr(void) vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct)); } -static void vmi_load_esp0(struct tss_struct *tss, +static void vmi_load_sp0(struct tss_struct *tss, struct thread_struct *thread) { - tss->x86_tss.esp0 = thread->esp0; + tss->x86_tss.sp0 = thread->sp0; /* This can only happen when SEP is enabled, no need to test "SEP"arately */ if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) { tss->x86_tss.ss1 = thread->sysenter_cs; wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); } - vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.esp0); + vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.sp0); } static void vmi_flush_tlb_user(void) @@ -793,7 +793,7 @@ static inline int __init activate_vmi(void) para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry); para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry); para_fill(pv_cpu_ops.write_idt_entry, WriteIDTEntry); - para_wrap(pv_cpu_ops.load_esp0, vmi_load_esp0, set_kernel_stack, UpdateKernelStack); + para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack); para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask); para_fill(pv_cpu_ops.io_delay, IODelay); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index ea46d05853bb..c751e3c03e85 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -755,10 +755,10 @@ static void lguest_time_init(void) * segment), the privilege level (we're privilege level 1, the Host is 0 and * will not tolerate us trying to use that), the stack pointer, and the number * of pages in the stack. */ -static void lguest_load_esp0(struct tss_struct *tss, +static void lguest_load_sp0(struct tss_struct *tss, struct thread_struct *thread) { - lazy_hcall(LHCALL_SET_STACK, __KERNEL_DS|0x1, thread->esp0, + lazy_hcall(LHCALL_SET_STACK, __KERNEL_DS|0x1, thread->sp0, THREAD_SIZE/PAGE_SIZE); } @@ -957,7 +957,7 @@ __init void lguest_init(void) pv_cpu_ops.cpuid = lguest_cpuid; pv_cpu_ops.load_idt = lguest_load_idt; pv_cpu_ops.iret = lguest_iret; - pv_cpu_ops.load_esp0 = lguest_load_esp0; + pv_cpu_ops.load_sp0 = lguest_load_sp0; pv_cpu_ops.load_tr_desc = lguest_load_tr_desc; pv_cpu_ops.set_ldt = lguest_set_ldt; pv_cpu_ops.load_tls = lguest_load_tls; diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index d97a6d7d062b..e0feb66a2408 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -243,9 +243,9 @@ void enable_sep_cpu(void) } tss->x86_tss.ss1 = __KERNEL_CS; - tss->x86_tss.esp1 = sizeof(struct tss_struct) + (unsigned long) tss; + tss->x86_tss.sp1 = sizeof(struct tss_struct) + (unsigned long) tss; wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.esp1, 0); + wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.sp1, 0); wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0); put_cpu(); } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 29517faaa735..d81e8d709102 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -499,11 +499,11 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry, preempt_enable(); } -static void xen_load_esp0(struct tss_struct *tss, +static void xen_load_sp0(struct tss_struct *tss, struct thread_struct *thread) { struct multicall_space mcs = xen_mc_entry(0); - MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->esp0); + MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); xen_mc_issue(PARAVIRT_LAZY_CPU); } @@ -968,7 +968,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { .write_ldt_entry = xen_write_ldt_entry, .write_gdt_entry = xen_write_gdt_entry, .write_idt_entry = xen_write_idt_entry, - .load_esp0 = xen_load_esp0, + .load_sp0 = xen_load_sp0, .set_iopl_mask = xen_set_iopl_mask, .io_delay = xen_io_delay, diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 8e1234e14559..aafc54437403 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -239,10 +239,10 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) ctxt->gdt_ents = ARRAY_SIZE(gdt->gdt); ctxt->user_regs.cs = __KERNEL_CS; - ctxt->user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs); + ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs); ctxt->kernel_ss = __KERNEL_DS; - ctxt->kernel_sp = idle->thread.esp0; + ctxt->kernel_sp = idle->thread.sp0; ctxt->event_callback_cs = __KERNEL_CS; ctxt->event_callback_eip = (unsigned long)xen_hypervisor_callback; diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 96d0fd07c57d..44adb00e1490 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -94,7 +94,7 @@ static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages) /* Set up the two "TSS" members which tell the CPU what stack to use * for traps which do directly into the Guest (ie. traps at privilege * level 1). */ - pages->state.guest_tss.esp1 = lg->esp1; + pages->state.guest_tss.sp1 = lg->esp1; pages->state.guest_tss.ss1 = lg->ss1; /* Copy direct-to-Guest trap entries. */ @@ -416,7 +416,7 @@ void __init lguest_arch_host_init(void) /* We know where we want the stack to be when the Guest enters * the switcher: in pages->regs. The stack grows upwards, so * we start it at the end of that structure. */ - state->guest_tss.esp0 = (long)(&pages->regs + 1); + state->guest_tss.sp0 = (long)(&pages->regs + 1); /* And this is the GDT entry to use for the stack: we keep a * couple of special LGUEST entries. */ state->guest_tss.ss0 = LGUEST_DS; diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index be7b934f6c54..d1780e32722e 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -101,7 +101,7 @@ struct pv_cpu_ops { int entrynum, u32 low, u32 high); void (*write_idt_entry)(struct desc_struct *, int entrynum, u32 low, u32 high); - void (*load_esp0)(struct tss_struct *tss, struct thread_struct *t); + void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t); void (*set_iopl_mask)(unsigned mask); @@ -449,10 +449,10 @@ static inline int paravirt_enabled(void) return pv_info.paravirt_enabled; } -static inline void load_esp0(struct tss_struct *tss, +static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread) { - PVOP_VCALL2(pv_cpu_ops.load_esp0, tss, thread); + PVOP_VCALL2(pv_cpu_ops.load_sp0, tss, thread); } #define ARCH_SETUP pv_init_ops.arch_setup(); diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h index d50a4b48d441..6846cc346400 100644 --- a/include/asm-x86/processor_32.h +++ b/include/asm-x86/processor_32.h @@ -292,20 +292,17 @@ struct thread_struct; /* This is the TSS defined by the hardware. */ struct i386_hw_tss { unsigned short back_link,__blh; - unsigned long esp0; + unsigned long sp0; unsigned short ss0,__ss0h; - unsigned long esp1; + unsigned long sp1; unsigned short ss1,__ss1h; /* ss1 is used to cache MSR_IA32_SYSENTER_CS */ - unsigned long esp2; + unsigned long sp2; unsigned short ss2,__ss2h; unsigned long __cr3; - unsigned long eip; - unsigned long eflags; - unsigned long eax,ecx,edx,ebx; - unsigned long esp; - unsigned long ebp; - unsigned long esi; - unsigned long edi; + unsigned long ip; + unsigned long flags; + unsigned long ax, cx, dx, bx; + unsigned long sp, bp, si, di; unsigned short es, __esh; unsigned short cs, __csh; unsigned short ss, __ssh; @@ -346,10 +343,10 @@ struct tss_struct { struct thread_struct { /* cached TLS descriptors. */ struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; - unsigned long esp0; + unsigned long sp0; unsigned long sysenter_cs; - unsigned long eip; - unsigned long esp; + unsigned long ip; + unsigned long sp; unsigned long fs; unsigned long gs; /* Hardware debugging registers */ @@ -366,7 +363,7 @@ struct thread_struct { /* virtual 86 mode info */ struct vm86_struct __user * vm86_info; unsigned long screen_bitmap; - unsigned long v86flags, v86mask, saved_esp0; + unsigned long v86flags, v86mask, saved_sp0; unsigned int saved_fs, saved_gs; /* IO permissions */ unsigned long *io_bitmap_ptr; @@ -378,7 +375,7 @@ struct thread_struct { }; #define INIT_THREAD { \ - .esp0 = sizeof(init_stack) + (long)&init_stack, \ + .sp0 = sizeof(init_stack) + (long)&init_stack, \ .vm86_info = NULL, \ .sysenter_cs = __KERNEL_CS, \ .io_bitmap_ptr = NULL, \ @@ -393,7 +390,7 @@ struct thread_struct { */ #define INIT_TSS { \ .x86_tss = { \ - .esp0 = sizeof(init_stack) + (long)&init_stack, \ + .sp0 = sizeof(init_stack) + (long)&init_stack, \ .ss0 = __KERNEL_DS, \ .ss1 = __KERNEL_CS, \ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \ @@ -503,9 +500,9 @@ static inline void rep_nop(void) #define cpu_relax() rep_nop() -static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread) +static inline void native_load_sp0(struct tss_struct *tss, struct thread_struct *thread) { - tss->x86_tss.esp0 = thread->esp0; + tss->x86_tss.sp0 = thread->sp0; /* This can only happen when SEP is enabled, no need to test "SEP"arately */ if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) { tss->x86_tss.ss1 = thread->sysenter_cs; @@ -585,9 +582,9 @@ static inline void native_set_iopl_mask(unsigned mask) #define paravirt_enabled() 0 #define __cpuid native_cpuid -static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread) +static inline void load_sp0(struct tss_struct *tss, struct thread_struct *thread) { - native_load_esp0(tss, thread); + native_load_sp0(tss, thread); } /* diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h index 797770113e6d..0780f3e3fdfe 100644 --- a/include/asm-x86/processor_64.h +++ b/include/asm-x86/processor_64.h @@ -177,9 +177,9 @@ union i387_union { struct tss_struct { u32 reserved1; - u64 rsp0; - u64 rsp1; - u64 rsp2; + u64 sp0; + u64 sp1; + u64 sp2; u64 reserved2; u64 ist[7]; u32 reserved3; @@ -216,9 +216,9 @@ DECLARE_PER_CPU(struct orig_ist, orig_ist); #endif struct thread_struct { - unsigned long rsp0; - unsigned long rsp; - unsigned long userrsp; /* Copy from PDA */ + unsigned long sp0; + unsigned long sp; + unsigned long usersp; /* Copy from PDA */ unsigned long fs; unsigned long gs; unsigned short es, ds, fsindex, gsindex; @@ -245,11 +245,11 @@ struct thread_struct { } __attribute__((aligned(16))); #define INIT_THREAD { \ - .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \ + .sp0 = (unsigned long)&init_stack + sizeof(init_stack) \ } #define INIT_TSS { \ - .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \ + .sp0 = (unsigned long)&init_stack + sizeof(init_stack) \ } #define INIT_MMAP \ @@ -293,10 +293,10 @@ extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); * Return saved PC of a blocked thread. * What is this good for? it will be always the scheduler or ret_from_fork. */ -#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.rsp - 8)) +#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8)) extern unsigned long get_wchan(struct task_struct *p); -#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.rsp0 - 1) +#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1) #define KSTK_EIP(tsk) (task_pt_regs(tsk)->ip) #define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */ diff --git a/include/asm-x86/system_32.h b/include/asm-x86/system_32.h index db6283eb5e46..f5b3f77f5310 100644 --- a/include/asm-x86/system_32.h +++ b/include/asm-x86/system_32.h @@ -28,9 +28,9 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc "1:\t" \ "popl %%ebp\n\t" \ "popfl" \ - :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ + :"=m" (prev->thread.sp),"=m" (prev->thread.ip), \ "=a" (last),"=S" (esi),"=D" (edi) \ - :"m" (next->thread.esp),"m" (next->thread.eip), \ + :"m" (next->thread.sp),"m" (next->thread.ip), \ "2" (prev), "d" (next)); \ } while (0) diff --git a/include/asm-x86/system_64.h b/include/asm-x86/system_64.h index 6e9e4841a2da..3dcb217a7202 100644 --- a/include/asm-x86/system_64.h +++ b/include/asm-x86/system_64.h @@ -40,7 +40,7 @@ RESTORE_CONTEXT \ : "=a" (last) \ : [next] "S" (next), [prev] "D" (prev), \ - [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \ + [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \ [ti_flags] "i" (offsetof(struct thread_info, flags)),\ [tif_fork] "i" (TIF_FORK), \ [thread_info] "i" (offsetof(struct task_struct, stack)), \ -- cgit v1.2.3 From 5fd1fe9c582e00ca0a98f852cd693dc3caf607a0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:31:09 +0100 Subject: x86: clean up drivers/char/rtc.c tons of style cleanup in drivers/char/rtc.c - no code changed: text data bss dec hex filename 6400 384 32 6816 1aa0 rtc.o.before 6400 384 32 6816 1aa0 rtc.o.after since we seem to have a number of open breakages in this code we might as well start with making the code more readable and maintainable. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/char/rtc.c | 238 +++++++++++++++++++++++++++++------------------------ 1 file changed, 129 insertions(+), 109 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 0c66b802736a..3ac7952fe086 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -1,5 +1,5 @@ /* - * Real Time Clock interface for Linux + * Real Time Clock interface for Linux * * Copyright (C) 1996 Paul Gortmaker * @@ -17,7 +17,7 @@ * has been received. If a RTC interrupt has already happened, * it will output an unsigned long and then block. The output value * contains the interrupt status in the low byte and the number of - * interrupts since the last read in the remaining high bytes. The + * interrupts since the last read in the remaining high bytes. The * /dev/rtc interface can also be used with the select(2) call. * * This program is free software; you can redistribute it and/or @@ -104,12 +104,12 @@ static int rtc_has_irq = 1; #ifndef CONFIG_HPET_EMULATE_RTC #define is_hpet_enabled() 0 -#define hpet_set_alarm_time(hrs, min, sec) 0 -#define hpet_set_periodic_freq(arg) 0 -#define hpet_mask_rtc_irq_bit(arg) 0 -#define hpet_set_rtc_irq_bit(arg) 0 -#define hpet_rtc_timer_init() do { } while (0) -#define hpet_rtc_dropped_irq() 0 +#define hpet_set_alarm_time(hrs, min, sec) 0 +#define hpet_set_periodic_freq(arg) 0 +#define hpet_mask_rtc_irq_bit(arg) 0 +#define hpet_set_rtc_irq_bit(arg) 0 +#define hpet_rtc_timer_init() do { } while (0) +#define hpet_rtc_dropped_irq() 0 #ifdef RTC_IRQ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) { @@ -147,7 +147,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, static unsigned int rtc_poll(struct file *file, poll_table *wait); #endif -static void get_rtc_alm_time (struct rtc_time *alm_tm); +static void get_rtc_alm_time(struct rtc_time *alm_tm); #ifdef RTC_IRQ static void set_rtc_irq_bit_locked(unsigned char bit); static void mask_rtc_irq_bit_locked(unsigned char bit); @@ -185,9 +185,9 @@ static int rtc_proc_open(struct inode *inode, struct file *file); * rtc_status but before mod_timer is called, which would then reenable the * timer (but you would need to have an awful timing before you'd trip on it) */ -static unsigned long rtc_status = 0; /* bitmapped status byte. */ -static unsigned long rtc_freq = 0; /* Current periodic IRQ rate */ -static unsigned long rtc_irq_data = 0; /* our output to the world */ +static unsigned long rtc_status; /* bitmapped status byte. */ +static unsigned long rtc_freq; /* Current periodic IRQ rate */ +static unsigned long rtc_irq_data; /* our output to the world */ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ #ifdef RTC_IRQ @@ -195,7 +195,7 @@ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ * rtc_task_lock nests inside rtc_lock. */ static DEFINE_SPINLOCK(rtc_task_lock); -static rtc_task_t *rtc_callback = NULL; +static rtc_task_t *rtc_callback; #endif /* @@ -205,7 +205,7 @@ static rtc_task_t *rtc_callback = NULL; static unsigned long epoch = 1900; /* year corresponding to 0x00 */ -static const unsigned char days_in_mo[] = +static const unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* @@ -242,7 +242,7 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id) * the last read in the remainder of rtc_irq_data. */ - spin_lock (&rtc_lock); + spin_lock(&rtc_lock); rtc_irq_data += 0x100; rtc_irq_data &= ~0xff; if (is_hpet_enabled()) { @@ -259,16 +259,16 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id) if (rtc_status & RTC_TIMER_ON) mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100); - spin_unlock (&rtc_lock); + spin_unlock(&rtc_lock); /* Now do the rest of the actions */ spin_lock(&rtc_task_lock); if (rtc_callback) rtc_callback->func(rtc_callback->private_data); spin_unlock(&rtc_task_lock); - wake_up_interruptible(&rtc_wait); + wake_up_interruptible(&rtc_wait); - kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); + kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); return IRQ_HANDLED; } @@ -335,7 +335,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf, DECLARE_WAITQUEUE(wait, current); unsigned long data; ssize_t retval; - + if (rtc_has_irq == 0) return -EIO; @@ -358,11 +358,11 @@ static ssize_t rtc_read(struct file *file, char __user *buf, * confusing. And no, xchg() is not the answer. */ __set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irq (&rtc_lock); + + spin_lock_irq(&rtc_lock); data = rtc_irq_data; rtc_irq_data = 0; - spin_unlock_irq (&rtc_lock); + spin_unlock_irq(&rtc_lock); if (data != 0) break; @@ -378,10 +378,13 @@ static ssize_t rtc_read(struct file *file, char __user *buf, schedule(); } while (1); - if (count == sizeof(unsigned int)) - retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); - else - retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); + if (count == sizeof(unsigned int)) { + retval = put_user(data, + (unsigned int __user *)buf) ?: sizeof(int); + } else { + retval = put_user(data, + (unsigned long __user *)buf) ?: sizeof(long); + } if (!retval) retval = count; out: @@ -394,7 +397,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf, static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) { - struct rtc_time wtime; + struct rtc_time wtime; #ifdef RTC_IRQ if (rtc_has_irq == 0) { @@ -426,35 +429,41 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) } case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ { - unsigned long flags; /* can be called from isr via rtc_control() */ - spin_lock_irqsave (&rtc_lock, flags); + /* can be called from isr via rtc_control() */ + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); mask_rtc_irq_bit_locked(RTC_PIE); if (rtc_status & RTC_TIMER_ON) { rtc_status &= ~RTC_TIMER_ON; del_timer(&rtc_irq_timer); } - spin_unlock_irqrestore (&rtc_lock, flags); + spin_unlock_irqrestore(&rtc_lock, flags); + return 0; } case RTC_PIE_ON: /* Allow periodic ints */ { - unsigned long flags; /* can be called from isr via rtc_control() */ + /* can be called from isr via rtc_control() */ + unsigned long flags; + /* * We don't really want Joe User enabling more * than 64Hz of interrupts on a multi-user machine. */ if (!kernel && (rtc_freq > rtc_max_user_freq) && - (!capable(CAP_SYS_RESOURCE))) + (!capable(CAP_SYS_RESOURCE))) return -EACCES; - spin_lock_irqsave (&rtc_lock, flags); + spin_lock_irqsave(&rtc_lock, flags); if (!(rtc_status & RTC_TIMER_ON)) { mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100); rtc_status |= RTC_TIMER_ON; } set_rtc_irq_bit_locked(RTC_PIE); - spin_unlock_irqrestore (&rtc_lock, flags); + spin_unlock_irqrestore(&rtc_lock, flags); + return 0; } case RTC_UIE_OFF: /* Mask ints from RTC updates. */ @@ -477,7 +486,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) */ memset(&wtime, 0, sizeof(struct rtc_time)); get_rtc_alm_time(&wtime); - break; + break; } case RTC_ALM_SET: /* Store a time into the alarm */ { @@ -505,16 +514,21 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) */ } if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || - RTC_ALWAYS_BCD) - { - if (sec < 60) BIN_TO_BCD(sec); - else sec = 0xff; - - if (min < 60) BIN_TO_BCD(min); - else min = 0xff; - - if (hrs < 24) BIN_TO_BCD(hrs); - else hrs = 0xff; + RTC_ALWAYS_BCD) { + if (sec < 60) + BIN_TO_BCD(sec); + else + sec = 0xff; + + if (min < 60) + BIN_TO_BCD(min); + else + min = 0xff; + + if (hrs < 24) + BIN_TO_BCD(hrs); + else + hrs = 0xff; } CMOS_WRITE(hrs, RTC_HOURS_ALARM); CMOS_WRITE(min, RTC_MINUTES_ALARM); @@ -563,11 +577,12 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) return -EINVAL; - + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) return -EINVAL; - if ((yrs -= epoch) > 255) /* They are unsigned */ + yrs -= epoch; + if (yrs > 255) /* They are unsigned */ return -EINVAL; spin_lock_irq(&rtc_lock); @@ -635,9 +650,10 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) { int tmp = 0; unsigned char val; - unsigned long flags; /* can be called from isr via rtc_control() */ + /* can be called from isr via rtc_control() */ + unsigned long flags; - /* + /* * The max we can do is 8192Hz. */ if ((arg < 2) || (arg > 8192)) @@ -646,7 +662,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) * We don't really want Joe User generating more * than 64Hz of interrupts on a multi-user machine. */ - if (!kernel && (arg > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE))) + if (!kernel && (arg > rtc_max_user_freq) && + !capable(CAP_SYS_RESOURCE)) return -EACCES; while (arg > (1<f_flags & FASYNC) { - rtc_fasync (-1, file, 0); - } + if (file->f_flags & FASYNC) + rtc_fasync(-1, file, 0); no_irq: #endif - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); rtc_irq_data = 0; rtc_status &= ~RTC_IS_OPEN; - spin_unlock_irq (&rtc_lock); + spin_unlock_irq(&rtc_lock); + return 0; } @@ -786,9 +803,9 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait) poll_wait(file, &rtc_wait, wait); - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); l = rtc_irq_data; - spin_unlock_irq (&rtc_lock); + spin_unlock_irq(&rtc_lock); if (l != 0) return POLLIN | POLLRDNORM; @@ -796,14 +813,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait) } #endif -/* - * exported stuffs - */ - -EXPORT_SYMBOL(rtc_register); -EXPORT_SYMBOL(rtc_unregister); -EXPORT_SYMBOL(rtc_control); - int rtc_register(rtc_task_t *task) { #ifndef RTC_IRQ @@ -829,6 +838,7 @@ int rtc_register(rtc_task_t *task) return 0; #endif } +EXPORT_SYMBOL(rtc_register); int rtc_unregister(rtc_task_t *task) { @@ -845,7 +855,7 @@ int rtc_unregister(rtc_task_t *task) return -ENXIO; } rtc_callback = NULL; - + /* disable controls */ if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) { tmp = CMOS_READ(RTC_CONTROL); @@ -865,6 +875,7 @@ int rtc_unregister(rtc_task_t *task) return 0; #endif } +EXPORT_SYMBOL(rtc_unregister); int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) { @@ -883,7 +894,7 @@ int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) return rtc_do_ioctl(cmd, arg, 1); #endif } - +EXPORT_SYMBOL(rtc_control); /* * The various file operations we support. @@ -910,11 +921,11 @@ static struct miscdevice rtc_dev = { #ifdef CONFIG_PROC_FS static const struct file_operations rtc_proc_fops = { - .owner = THIS_MODULE, - .open = rtc_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, + .owner = THIS_MODULE, + .open = rtc_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; #endif @@ -965,7 +976,7 @@ static int __init rtc_init(void) #ifdef CONFIG_SPARC32 for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if(strcmp(edev->prom_node->name, "rtc") == 0) { + if (strcmp(edev->prom_node->name, "rtc") == 0) { rtc_port = edev->resource[0].start; rtc_irq = edev->irqs[0]; goto found; @@ -986,7 +997,8 @@ found: * XXX Interrupt pin #7 in Espresso is shared between RTC and * PCI Slot 2 INTA# (and some INTx# in Slot 1). */ - if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) { + if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", + (void *)&rtc_port)) { rtc_has_irq = 0; printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq); return -EIO; @@ -1020,11 +1032,13 @@ no_irq: rtc_int_handler_ptr = rtc_interrupt; } - if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { + if (request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, + "rtc", NULL)) { /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ rtc_has_irq = 0; printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); rtc_release_region(); + return -EIO; } hpet_rtc_timer_init(); @@ -1052,21 +1066,21 @@ no_irq: #if defined(__alpha__) || defined(__mips__) rtc_freq = HZ; - + /* Each operating system on an Alpha uses its own epoch. Let's try to guess which one we are using now. */ - + if (rtc_is_updating() != 0) msleep(20); - + spin_lock_irq(&rtc_lock); year = CMOS_READ(RTC_YEAR); ctrl = CMOS_READ(RTC_CONTROL); spin_unlock_irq(&rtc_lock); - + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) BCD_TO_BIN(year); /* This should never happen... */ - + if (year < 20) { epoch = 2000; guess = "SRM (post-2000)"; @@ -1087,7 +1101,8 @@ no_irq: #endif } if (guess) - printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", guess, epoch); + printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", + guess, epoch); #endif #ifdef RTC_IRQ if (rtc_has_irq == 0) @@ -1096,8 +1111,12 @@ no_irq: spin_lock_irq(&rtc_lock); rtc_freq = 1024; if (!hpet_set_periodic_freq(rtc_freq)) { - /* Initialize periodic freq. to CMOS reset default, which is 1024Hz */ - CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT); + /* + * Initialize periodic frequency to CMOS reset default, + * which is 1024Hz + */ + CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), + RTC_FREQ_SELECT); } spin_unlock_irq(&rtc_lock); no_irq2: @@ -1110,20 +1129,20 @@ no_irq2: return 0; } -static void __exit rtc_exit (void) +static void __exit rtc_exit(void) { cleanup_sysctl(); - remove_proc_entry ("driver/rtc", NULL); + remove_proc_entry("driver/rtc", NULL); misc_deregister(&rtc_dev); #ifdef CONFIG_SPARC32 if (rtc_has_irq) - free_irq (rtc_irq, &rtc_port); + free_irq(rtc_irq, &rtc_port); #else rtc_release_region(); #ifdef RTC_IRQ if (rtc_has_irq) - free_irq (RTC_IRQ, NULL); + free_irq(RTC_IRQ, NULL); #endif #endif /* CONFIG_SPARC32 */ } @@ -1133,14 +1152,14 @@ module_exit(rtc_exit); #ifdef RTC_IRQ /* - * At IRQ rates >= 4096Hz, an interrupt may get lost altogether. + * At IRQ rates >= 4096Hz, an interrupt may get lost altogether. * (usually during an IDE disk interrupt, with IRQ unmasking off) * Since the interrupt handler doesn't get called, the IRQ status * byte doesn't get read, and the RTC stops generating interrupts. * A timer is set, and will call this function if/when that happens. * To get it out of this stalled state, we just read the status. * At least a jiffy of interrupts (rtc_freq/HZ) will have been lost. - * (You *really* shouldn't be trying to use a non-realtime system + * (You *really* shouldn't be trying to use a non-realtime system * for something that requires a steady > 1KHz signal anyways.) */ @@ -1148,7 +1167,7 @@ static void rtc_dropped_irq(unsigned long data) { unsigned long freq; - spin_lock_irq (&rtc_lock); + spin_lock_irq(&rtc_lock); if (hpet_rtc_dropped_irq()) { spin_unlock_irq(&rtc_lock); @@ -1167,13 +1186,15 @@ static void rtc_dropped_irq(unsigned long data) spin_unlock_irq(&rtc_lock); - if (printk_ratelimit()) - printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); + if (printk_ratelimit()) { + printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", + freq); + } /* Now we have new data */ wake_up_interruptible(&rtc_wait); - kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); + kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); } #endif @@ -1277,7 +1298,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * can take just over 2ms. We wait 20ms. There is no need to * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. * If you need to know *exactly* when a second has started, enable - * periodic update complete interrupts, (via ioctl) and then + * periodic update complete interrupts, (via ioctl) and then * immediately read /dev/rtc which will block until you get the IRQ. * Once the read clears, read the RTC time (again via ioctl). Easy. */ @@ -1307,8 +1328,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) ctrl = CMOS_READ(RTC_CONTROL); spin_unlock_irqrestore(&rtc_lock, flags); - if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(rtc_tm->tm_sec); BCD_TO_BIN(rtc_tm->tm_min); BCD_TO_BIN(rtc_tm->tm_hour); @@ -1326,7 +1346,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * Account for differences between how the RTC uses the values * and how they are defined in a struct rtc_time; */ - if ((rtc_tm->tm_year += (epoch - 1900)) <= 69) + rtc_tm->tm_year += epoch - 1900; + if (rtc_tm->tm_year <= 69) rtc_tm->tm_year += 100; rtc_tm->tm_mon--; @@ -1347,8 +1368,7 @@ static void get_rtc_alm_time(struct rtc_time *alm_tm) ctrl = CMOS_READ(RTC_CONTROL); spin_unlock_irq(&rtc_lock); - if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(alm_tm->tm_sec); BCD_TO_BIN(alm_tm->tm_min); BCD_TO_BIN(alm_tm->tm_hour); -- cgit v1.2.3 From 6b68f01baa810e9f63fbf39e9d5c3ef1d94a966f Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Wed, 30 Jan 2008 13:31:12 +0100 Subject: x86: unify struct desc_ptr This patch unifies struct desc_ptr between i386 and x86_64. They can be expressed in the exact same way in C code, only having to change the name of one of them. As Xgt_desc_struct is ugly and big, this is the one that goes away. There's also a padding field in i386, but it is not really needed in the C structure definition. Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/asm-offsets_32.c | 5 ++--- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/doublefault_32.c | 2 +- arch/x86/kernel/efi_32.c | 4 ++-- arch/x86/kernel/machine_kexec_32.c | 4 ++-- arch/x86/kernel/reboot_32.c | 2 +- arch/x86/lguest/boot.c | 4 ++-- arch/x86/xen/enlighten.c | 10 +++++----- drivers/kvm/svm.c | 2 +- include/asm-x86/desc_32.h | 16 +++++----------- include/asm-x86/lguest.h | 8 ++++---- include/asm-x86/paravirt.h | 18 +++++++++--------- include/asm-x86/processor_32.h | 2 +- include/asm-x86/suspend_32.h | 4 ++-- 14 files changed, 38 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 415313556708..afd84463b712 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -70,9 +70,8 @@ void foo(void) OFFSET(TI_cpu, thread_info, cpu); BLANK(); - OFFSET(GDS_size, Xgt_desc_struct, size); - OFFSET(GDS_address, Xgt_desc_struct, address); - OFFSET(GDS_pad, Xgt_desc_struct, pad); + OFFSET(GDS_size, desc_ptr, size); + OFFSET(GDS_address, desc_ptr, address); BLANK(); OFFSET(PT_EBX, pt_regs, bx); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 4f9e31912a25..69507ae8a65b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -649,7 +649,7 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs) * it's on the real one. */ void switch_to_new_gdt(void) { - struct Xgt_desc_struct gdt_descr; + struct desc_ptr gdt_descr; gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); gdt_descr.size = GDT_SIZE - 1; diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index cc19a3ea403a..d16122a8e4eb 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c @@ -17,7 +17,7 @@ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; static void doublefault_fn(void) { - struct Xgt_desc_struct gdt_desc = {0, 0}; + struct desc_ptr gdt_desc = {0, 0}; unsigned long gdt, tss; store_gdt(&gdt_desc); diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c index e2be78f49399..863e8926f2bb 100644 --- a/arch/x86/kernel/efi_32.c +++ b/arch/x86/kernel/efi_32.c @@ -69,7 +69,7 @@ static void efi_call_phys_prelog(void) __acquires(efi_rt_lock) { unsigned long cr4; unsigned long temp; - struct Xgt_desc_struct gdt_descr; + struct desc_ptr gdt_descr; spin_lock(&efi_rt_lock); local_irq_save(efi_rt_eflags); @@ -111,7 +111,7 @@ static void efi_call_phys_prelog(void) __acquires(efi_rt_lock) static void efi_call_phys_epilog(void) __releases(efi_rt_lock) { unsigned long cr4; - struct Xgt_desc_struct gdt_descr; + struct desc_ptr gdt_descr; gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); gdt_descr.size = GDT_SIZE - 1; diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 11b935f4f886..c1cfd60639d4 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c @@ -32,7 +32,7 @@ static u32 kexec_pte1[1024] PAGE_ALIGNED; static void set_idt(void *newidt, __u16 limit) { - struct Xgt_desc_struct curidt; + struct desc_ptr curidt; /* ia32 supports unaliged loads & stores */ curidt.size = limit; @@ -44,7 +44,7 @@ static void set_idt(void *newidt, __u16 limit) static void set_gdt(void *newgdt, __u16 limit) { - struct Xgt_desc_struct curgdt; + struct desc_ptr curgdt; /* ia32 supports unaligned loads & stores */ curgdt.size = limit; diff --git a/arch/x86/kernel/reboot_32.c b/arch/x86/kernel/reboot_32.c index bb1a0f889c5e..c3376fae639d 100644 --- a/arch/x86/kernel/reboot_32.c +++ b/arch/x86/kernel/reboot_32.c @@ -161,7 +161,7 @@ real_mode_gdt_entries [3] = 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ }; -static struct Xgt_desc_struct +static struct desc_ptr real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries }, real_mode_idt = { 0x3ff, 0 }, no_idt = { 0, 0 }; diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index c751e3c03e85..aa0bdd5fc4bb 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -229,7 +229,7 @@ static void lguest_write_idt_entry(struct desc_struct *dt, /* Changing to a different IDT is very rare: we keep the IDT up-to-date every * time it is written, so we can simply loop through all entries and tell the * Host about them. */ -static void lguest_load_idt(const struct Xgt_desc_struct *desc) +static void lguest_load_idt(const struct desc_ptr *desc) { unsigned int i; struct desc_struct *idt = (void *)desc->address; @@ -252,7 +252,7 @@ static void lguest_load_idt(const struct Xgt_desc_struct *desc) * 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? */ -static void lguest_load_gdt(const struct Xgt_desc_struct *desc) +static void lguest_load_gdt(const struct desc_ptr *desc) { BUG_ON((desc->size+1)/8 != GDT_ENTRIES); hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index d81e8d709102..c32e0fd0f838 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -295,7 +295,7 @@ static void xen_set_ldt(const void *addr, unsigned entries) xen_mc_issue(PARAVIRT_LAZY_CPU); } -static void xen_load_gdt(const struct Xgt_desc_struct *dtr) +static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long *frames; unsigned long va = dtr->address; @@ -395,7 +395,7 @@ static int cvt_gate_to_trap(int vector, u32 low, u32 high, } /* Locations of each CPU's IDT */ -static DEFINE_PER_CPU(struct Xgt_desc_struct, idt_desc); +static DEFINE_PER_CPU(struct desc_ptr, idt_desc); /* Set an IDT entry. If the entry is part of the current IDT, then also update Xen. */ @@ -427,7 +427,7 @@ static void xen_write_idt_entry(struct desc_struct *dt, int entrynum, preempt_enable(); } -static void xen_convert_trap_info(const struct Xgt_desc_struct *desc, +static void xen_convert_trap_info(const struct desc_ptr *desc, struct trap_info *traps) { unsigned in, out, count; @@ -446,7 +446,7 @@ static void xen_convert_trap_info(const struct Xgt_desc_struct *desc, void xen_copy_trap_info(struct trap_info *traps) { - const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc); + const struct desc_ptr *desc = &__get_cpu_var(idt_desc); xen_convert_trap_info(desc, traps); } @@ -454,7 +454,7 @@ void xen_copy_trap_info(struct trap_info *traps) /* Load a new IDT into Xen. In principle this can be per-CPU, so we hold a spinlock to protect the static traps[] array (static because it avoids allocation, and saves stack space). */ -static void xen_load_idt(const struct Xgt_desc_struct *desc) +static void xen_load_idt(const struct desc_ptr *desc) { static DEFINE_SPINLOCK(lock); static struct trap_info traps[257]; diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 4e04e49a2f1c..ced4ac1955db 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -290,7 +290,7 @@ static void svm_hardware_enable(void *garbage) #ifdef CONFIG_X86_64 struct desc_ptr gdt_descr; #else - struct Xgt_desc_struct gdt_descr; + struct desc_ptr gdt_descr; #endif struct desc_struct *gdt; int me = raw_smp_processor_id(); diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h index c547403f341d..bc5ca3453466 100644 --- a/include/asm-x86/desc_32.h +++ b/include/asm-x86/desc_32.h @@ -12,12 +12,6 @@ #include -struct Xgt_desc_struct { - unsigned short size; - unsigned long address __attribute__((packed)); - unsigned short pad; -} __attribute__ ((packed)); - struct gdt_page { struct desc_struct gdt[GDT_ENTRIES]; @@ -29,7 +23,7 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) return per_cpu(gdt_page, cpu).gdt; } -extern struct Xgt_desc_struct idt_descr; +extern struct desc_ptr idt_descr; extern struct desc_struct idt_table[]; extern void set_intr_gate(unsigned int irq, void * addr); @@ -107,22 +101,22 @@ static inline void native_load_tr_desc(void) asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); } -static inline void native_load_gdt(const struct Xgt_desc_struct *dtr) +static inline void native_load_gdt(const struct desc_ptr *dtr) { asm volatile("lgdt %0"::"m" (*dtr)); } -static inline void native_load_idt(const struct Xgt_desc_struct *dtr) +static inline void native_load_idt(const struct desc_ptr *dtr) { asm volatile("lidt %0"::"m" (*dtr)); } -static inline void native_store_gdt(struct Xgt_desc_struct *dtr) +static inline void native_store_gdt(struct desc_ptr *dtr) { asm ("sgdt %0":"=m" (*dtr)); } -static inline void native_store_idt(struct Xgt_desc_struct *dtr) +static inline void native_store_idt(struct desc_ptr *dtr) { asm ("sidt %0":"=m" (*dtr)); } diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h index 17c908c0ef1c..3585a1628b59 100644 --- a/include/asm-x86/lguest.h +++ b/include/asm-x86/lguest.h @@ -44,13 +44,13 @@ struct lguest_ro_state { /* Host information we need to restore when we switch back. */ u32 host_cr3; - struct Xgt_desc_struct host_idt_desc; - struct Xgt_desc_struct host_gdt_desc; + struct desc_ptr host_idt_desc; + struct desc_ptr host_gdt_desc; u32 host_sp; /* Fields which are used when guest is running. */ - struct Xgt_desc_struct guest_idt_desc; - struct Xgt_desc_struct guest_gdt_desc; + struct desc_ptr guest_idt_desc; + struct desc_ptr guest_gdt_desc; struct i386_hw_tss guest_tss; struct desc_struct guest_idt[IDT_ENTRIES]; struct desc_struct guest_gdt[GDT_ENTRIES]; diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index e95c2a655165..0333fb6988b5 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -20,7 +20,7 @@ struct page; struct thread_struct; -struct Xgt_desc_struct; +struct desc_ptr; struct tss_struct; struct mm_struct; struct desc_struct; @@ -88,10 +88,10 @@ struct pv_cpu_ops { /* Segment descriptor handling */ void (*load_tr_desc)(void); - void (*load_gdt)(const struct Xgt_desc_struct *); - void (*load_idt)(const struct Xgt_desc_struct *); - void (*store_gdt)(struct Xgt_desc_struct *); - void (*store_idt)(struct Xgt_desc_struct *); + void (*load_gdt)(const struct desc_ptr *); + void (*load_idt)(const struct desc_ptr *); + void (*store_gdt)(struct desc_ptr *); + void (*store_idt)(struct desc_ptr *); void (*set_ldt)(const void *desc, unsigned entries); unsigned long (*store_tr)(void); void (*load_tls)(struct thread_struct *t, unsigned int cpu); @@ -630,11 +630,11 @@ static inline void load_TR_desc(void) { PVOP_VCALL0(pv_cpu_ops.load_tr_desc); } -static inline void load_gdt(const struct Xgt_desc_struct *dtr) +static inline void load_gdt(const struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.load_gdt, dtr); } -static inline void load_idt(const struct Xgt_desc_struct *dtr) +static inline void load_idt(const struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.load_idt, dtr); } @@ -642,11 +642,11 @@ static inline void set_ldt(const void *addr, unsigned entries) { PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries); } -static inline void store_gdt(struct Xgt_desc_struct *dtr) +static inline void store_gdt(struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr); } -static inline void store_idt(struct Xgt_desc_struct *dtr) +static inline void store_idt(struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.store_idt, dtr); } diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h index bc48ad64de47..e5056ab9dd9f 100644 --- a/include/asm-x86/processor_32.h +++ b/include/asm-x86/processor_32.h @@ -707,7 +707,7 @@ extern void enable_sep_cpu(void); extern int sysenter_setup(void); /* Defined in head.S */ -extern struct Xgt_desc_struct early_gdt_descr; +extern struct desc_ptr early_gdt_descr; extern void cpu_set_gdt(int); extern void switch_to_new_gdt(void); diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h index a2520732ffd6..1bbda3ad7796 100644 --- a/include/asm-x86/suspend_32.h +++ b/include/asm-x86/suspend_32.h @@ -12,8 +12,8 @@ static inline int arch_prepare_suspend(void) { return 0; } struct saved_context { u16 es, fs, gs, ss; unsigned long cr0, cr2, cr3, cr4; - struct Xgt_desc_struct gdt; - struct Xgt_desc_struct idt; + struct desc_ptr gdt; + struct desc_ptr idt; u16 ldt; u16 tss; unsigned long tr; -- cgit v1.2.3 From 41e191e85a122ad822deb7525a015410012e6c70 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:31:24 +0100 Subject: x86: replace outb_p() with udelay(2) in drivers/input/mouse/pc110pad.c replace outb_p() with udelay(2). This is a real ISA device so it likely needs this particular delay. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/input/mouse/pc110pad.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 8991ab0b4fe3..61cff8374e6c 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -62,8 +63,10 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr) int value = inb_p(pc110pad_io); int handshake = inb_p(pc110pad_io + 2); - outb_p(handshake | 1, pc110pad_io + 2); - outb_p(handshake & ~1, pc110pad_io + 2); + outb(handshake | 1, pc110pad_io + 2); + udelay(2); + outb(handshake & ~1, pc110pad_io + 2); + udelay(2); inb_p(0x64); pc110pad_data[pc110pad_count++] = value; -- cgit v1.2.3 From 053de044411111da00272d1b4e174e7dd743f499 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Wed, 30 Jan 2008 13:31:27 +0100 Subject: x86: get rid of _MASK flags There's no need for the *_MASK flags (TF_MASK, IF_MASK, etc), found in processor.h (both _32 and _64). They have a one-to-one mapping with the EFLAGS value. This patch removes the definitions, and use the already existent X86_EFLAGS_ version when applicable. [ roland@redhat.com: KVM build fixes. ] Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/ia32/ia32_signal.c | 4 ++-- arch/x86/kernel/kprobes.c | 18 +++++++++--------- arch/x86/kernel/signal_64.c | 4 ++-- arch/x86/kernel/traps_64.c | 2 +- drivers/kvm/vmx.c | 8 ++++---- include/asm-x86/kprobes.h | 2 +- include/asm-x86/processor.h | 2 ++ include/asm-x86/processor_32.h | 1 - include/asm-x86/processor_64.h | 11 ----------- 9 files changed, 21 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index d03d43f32f4c..0e24e3fda3d7 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -501,7 +501,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, regs->ss = __USER32_DS; set_fs(USER_DS); - regs->flags &= ~TF_MASK; + regs->flags &= ~X86_EFLAGS_TF; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); @@ -601,7 +601,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->ss = __USER32_DS; set_fs(USER_DS); - regs->flags &= ~TF_MASK; + regs->flags &= ~X86_EFLAGS_TF; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 9aadd4d4a229..8de82c8cedd6 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -387,9 +387,9 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, { __get_cpu_var(current_kprobe) = p; kcb->kprobe_saved_flags = kcb->kprobe_old_flags - = (regs->flags & (TF_MASK | IF_MASK)); + = (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF)); if (is_IF_modifier(p->ainsn.insn)) - kcb->kprobe_saved_flags &= ~IF_MASK; + kcb->kprobe_saved_flags &= ~X86_EFLAGS_IF; } static __always_inline void clear_btf(void) @@ -407,8 +407,8 @@ static __always_inline void restore_btf(void) static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { clear_btf(); - regs->flags |= TF_MASK; - regs->flags &= ~IF_MASK; + regs->flags |= X86_EFLAGS_TF; + regs->flags &= ~X86_EFLAGS_IF; /*single step inline if the instruction is an int3*/ if (p->opcode == BREAKPOINT_INSTRUCTION) regs->ip = (unsigned long)p->addr; @@ -454,7 +454,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) if (p) { if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { - regs->flags &= ~TF_MASK; + regs->flags &= ~X86_EFLAGS_TF; regs->flags |= kcb->kprobe_saved_flags; goto no_kprobe; #ifdef CONFIG_X86_64 @@ -749,10 +749,10 @@ static void __kprobes resume_execution(struct kprobe *p, insn++; #endif - regs->flags &= ~TF_MASK; + regs->flags &= ~X86_EFLAGS_TF; switch (*insn) { case 0x9c: /* pushfl */ - *tos &= ~(TF_MASK | IF_MASK); + *tos &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF); *tos |= kcb->kprobe_old_flags; break; case 0xc2: /* iret/ret/lret */ @@ -852,7 +852,7 @@ out: * will have TF set, in which case, continue the remaining processing * of do_debug, as if this is not a probe hit. */ - if (regs->flags & TF_MASK) + if (regs->flags & X86_EFLAGS_TF) return 0; return 1; @@ -982,7 +982,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) */ memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, MIN_STACK_SIZE(addr)); - regs->flags &= ~IF_MASK; + regs->flags &= ~X86_EFLAGS_IF; trace_hardirqs_off(); regs->ip = (unsigned long)(jp->entry); return 1; diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 1c9bca56fb55..4eb751c60390 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -295,7 +295,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, see include/asm-x86_64/uaccess.h for details. */ set_fs(USER_DS); - regs->flags &= ~TF_MASK; + regs->flags &= ~X86_EFLAGS_TF; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); #ifdef DEBUG_SIG @@ -463,7 +463,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) /* Pending single-step? */ if (thread_info_flags & _TIF_SINGLESTEP) { - regs->flags |= TF_MASK; + regs->flags |= X86_EFLAGS_TF; clear_thread_flag(TIF_SINGLESTEP); } diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index cf90ceb48f5f..7118fa0320ae 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -904,7 +904,7 @@ clear_dr7: clear_TF_reenable: set_tsk_thread_flag(tsk, TIF_SINGLESTEP); - regs->flags &= ~TF_MASK; + regs->flags &= ~X86_EFLAGS_TF; preempt_conditional_cli(regs); } diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index bb56ae3f89b6..5b397b6c9f93 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -524,7 +524,7 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu) static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) { if (vcpu->rmode.active) - rflags |= IOPL_MASK | X86_EFLAGS_VM; + rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM; vmcs_writel(GUEST_RFLAGS, rflags); } @@ -1050,7 +1050,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu) vmcs_write32(GUEST_TR_AR_BYTES, vcpu->rmode.tr.ar); flags = vmcs_readl(GUEST_RFLAGS); - flags &= ~(IOPL_MASK | X86_EFLAGS_VM); + flags &= ~(X86_EFLAGS_IOPL | X86_EFLAGS_VM); flags |= (vcpu->rmode.save_iopl << IOPL_SHIFT); vmcs_writel(GUEST_RFLAGS, flags); @@ -1107,9 +1107,9 @@ static void enter_rmode(struct kvm_vcpu *vcpu) vmcs_write32(GUEST_TR_AR_BYTES, 0x008b); flags = vmcs_readl(GUEST_RFLAGS); - vcpu->rmode.save_iopl = (flags & IOPL_MASK) >> IOPL_SHIFT; + vcpu->rmode.save_iopl = (flags & X86_EFLAGS_IOPL) >> IOPL_SHIFT; - flags |= IOPL_MASK | X86_EFLAGS_VM; + flags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM; vmcs_writel(GUEST_RFLAGS, flags); vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME); diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h index 6e6371a856e7..143476a3cb52 100644 --- a/include/asm-x86/kprobes.h +++ b/include/asm-x86/kprobes.h @@ -88,7 +88,7 @@ struct kprobe_ctlblk { */ static inline void restore_interrupts(struct pt_regs *regs) { - if (regs->flags & IF_MASK) + if (regs->flags & X86_EFLAGS_IF) local_irq_enable(); } diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index dea81b70895d..e8dd394c9f46 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -1,6 +1,8 @@ #ifndef __ASM_X86_PROCESSOR_H #define __ASM_X86_PROCESSOR_H +#include + static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h index 76cada930d22..b9dbe4668e75 100644 --- a/include/asm-x86/processor_32.h +++ b/include/asm-x86/processor_32.h @@ -19,7 +19,6 @@ #include #include #include -#include #include static inline int desc_empty(const void *ptr) diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h index a0a9e5515097..c49716a76644 100644 --- a/include/asm-x86/processor_64.h +++ b/include/asm-x86/processor_64.h @@ -18,19 +18,8 @@ #include #include #include -#include #include -#define TF_MASK 0x00000100 -#define IF_MASK 0x00000200 -#define IOPL_MASK 0x00003000 -#define NT_MASK 0x00004000 -#define VM_MASK 0x00020000 -#define AC_MASK 0x00040000 -#define VIF_MASK 0x00080000 /* virtual interrupt flag */ -#define VIP_MASK 0x00100000 /* virtual interrupt pending */ -#define ID_MASK 0x00200000 - static inline int desc_empty(const void *ptr) { const u32 *desc = ptr; -- cgit v1.2.3 From 79da4721117fcf188b4b007b775738a530f574da Mon Sep 17 00:00:00 2001 From: Parag Warudkar Date: Wed, 30 Jan 2008 13:31:59 +0100 Subject: x86: fix DMI out of memory problems People with HP Desktops (including me) encounter couple of DMI errors during boot - dmi_save_oem_strings_devices: out of memory and dmi_string: out of memory. On some HP desktops the DMI data include OEM strings (type 11) out of which only few are meaningful and most other are empty. DMI code religiously creates copies of these 27 strings (65 bytes each in my case) and goes OOM in dmi_string(). If DMI_MAX_DATA is bumped up a little then it goes and fails in dmi_save_oem_strings while allocating dmi_devices of sizeof(struct dmi_device) corresponding to these strings. On x86_64 since we cannot use alloc_bootmem this early, the code uses a static array of 2048 bytes (DMI_MAX_DATA) for allocating the memory DMI needs. It does not survive the creation of empty strings and devices. Fix this by detecting and not newly allocating empty strings and instead using a one statically defined dmi_empty_string. Also do not create a new struct dmi_device for each empty string - use one statically define dmi_device with .name=dmi_empty_string and add that to the dmi_devices list. On x64 this should stop the OOM with same current size of DMI_MAX_DATA and on x86 this should save a good amount of (27*65 bytes + 27*sizeof(struct dmi_device) bootmem. Compile and boot tested on both 32-bit and 64-bit x86. Signed-off-by: Parag Warudkar Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/firmware/dmi_scan.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 5e596a7e3601..0b24a1141009 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -8,6 +8,8 @@ #include #include +static char dmi_empty_string[] = " "; + static char * __init dmi_string(const struct dmi_header *dm, u8 s) { const u8 *bp = ((u8 *) dm) + dm->length; @@ -21,11 +23,16 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s) } if (*bp != 0) { - str = dmi_alloc(strlen(bp) + 1); + size_t len = strlen(bp)+1; + size_t cmp_len = len > 8 ? 8 : len; + + if (!memcmp(bp, dmi_empty_string, cmp_len)) + return dmi_empty_string; + str = dmi_alloc(len); if (str != NULL) strcpy(str, bp); else - printk(KERN_ERR "dmi_string: out of memory.\n"); + printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len); } } @@ -175,12 +182,23 @@ static void __init dmi_save_devices(const struct dmi_header *dm) } } +static struct dmi_device empty_oem_string_dev = { + .name = dmi_empty_string, +}; + static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm) { int i, count = *(u8 *)(dm + 1); struct dmi_device *dev; for (i = 1; i <= count; i++) { + char *devname = dmi_string(dm, i); + + if (!strcmp(devname, dmi_empty_string)) { + list_add(&empty_oem_string_dev.list, &dmi_devices); + continue; + } + dev = dmi_alloc(sizeof(*dev)); if (!dev) { printk(KERN_ERR @@ -189,7 +207,7 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm) } dev->type = DMI_DEV_TYPE_OEM_STRING; - dev->name = dmi_string(dm, i); + dev->name = devname; dev->device_data = NULL; list_add(&dev->list, &dmi_devices); -- cgit v1.2.3 From bde6f5f59c2b2b48a7a849c129d5b48838fe77ee Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Wed, 30 Jan 2008 13:32:01 +0100 Subject: x86: voluntary leave_mm before entering ACPI C3 Aviod TLB flush IPIs during C3 states by voluntary leave_mm() before entering C3. The performance impact of TLB flush on C3 should not be significant with respect to C3 wakeup latency. Also, CPUs tend to flush TLB in hardware while in C3 anyways. On a 8 logical CPU system, running make -j2, the number of tlbflush IPIs goes down from 40 per second to ~ 0. Total number of interrupts during the run of this workload was ~1200 per second, which makes it ~3% savings in wakeups. There was no measurable performance or power impact however. [ akpm@linux-foundation.org: symbol export fixes. ] Signed-off-by: Venkatesh Pallipadi Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/smp_32.c | 3 ++- arch/x86/kernel/smp_64.c | 3 ++- drivers/acpi/processor_idle.c | 2 ++ include/asm-ia64/acpi.h | 2 ++ include/asm-x86/acpi.h | 3 +++ include/asm-x86/mmu.h | 8 ++++++++ include/asm-x86/mmu_context_32.h | 2 -- 7 files changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/smp_32.c b/arch/x86/kernel/smp_32.c index 070816ac79e1..dc0cde9d16fb 100644 --- a/arch/x86/kernel/smp_32.c +++ b/arch/x86/kernel/smp_32.c @@ -256,13 +256,14 @@ static DEFINE_SPINLOCK(tlbstate_lock); * We need to reload %cr3 since the page tables may be going * away from under us.. */ -void leave_mm(unsigned long cpu) +void leave_mm(int cpu) { if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) BUG(); cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask); load_cr3(swapper_pg_dir); } +EXPORT_SYMBOL_GPL(leave_mm); /* * diff --git a/arch/x86/kernel/smp_64.c b/arch/x86/kernel/smp_64.c index 02a6533e8909..2fd74b06db67 100644 --- a/arch/x86/kernel/smp_64.c +++ b/arch/x86/kernel/smp_64.c @@ -69,13 +69,14 @@ static DEFINE_PER_CPU(union smp_flush_state, flush_state); * We cannot call mmdrop() because we are in interrupt context, * instead update mm->cpu_vm_mask. */ -static inline void leave_mm(int cpu) +void leave_mm(int cpu) { if (read_pda(mmu_state) == TLBSTATE_OK) BUG(); cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask); load_cr3(swapper_pg_dir); } +EXPORT_SYMBOL_GPL(leave_mm); /* * diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2235f4e02d26..0721a8183c89 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -534,6 +534,7 @@ static void acpi_processor_idle(void) break; case ACPI_STATE_C3: + acpi_unlazy_tlb(smp_processor_id()); /* * Must be done before busmaster disable as we might * need to access HPET ! @@ -1423,6 +1424,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, return 0; } + acpi_unlazy_tlb(smp_processor_id()); /* * Must be done before busmaster disable as we might need to * access HPET ! diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h index 81bcd5e51789..cd1cc39b5599 100644 --- a/include/asm-ia64/acpi.h +++ b/include/asm-ia64/acpi.h @@ -127,6 +127,8 @@ extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif +#define acpi_unlazy_tlb(x) + #endif /*__KERNEL__*/ #endif /*_ASM_ACPI_H*/ diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h index 2feb0c494be7..98a9ca266531 100644 --- a/include/asm-x86/acpi.h +++ b/include/asm-x86/acpi.h @@ -27,6 +27,7 @@ #include #include +#include #define COMPILER_DEPENDENT_INT64 long long #define COMPILER_DEPENDENT_UINT64 unsigned long long @@ -167,4 +168,6 @@ static inline void acpi_fake_nodes(const struct bootnode *fake_nodes, } #endif +#define acpi_unlazy_tlb(x) leave_mm(x) + #endif /*__X86_ASM_ACPI_H*/ diff --git a/include/asm-x86/mmu.h b/include/asm-x86/mmu.h index 3f922c8e1c88..efa962c38897 100644 --- a/include/asm-x86/mmu.h +++ b/include/asm-x86/mmu.h @@ -20,4 +20,12 @@ typedef struct { void *vdso; } mm_context_t; +#ifdef CONFIG_SMP +void leave_mm(int cpu); +#else +static inline void leave_mm(int cpu) +{ +} +#endif + #endif /* _ASM_X86_MMU_H */ diff --git a/include/asm-x86/mmu_context_32.h b/include/asm-x86/mmu_context_32.h index 7eb0b0b1fb3c..8198d1cca1f3 100644 --- a/include/asm-x86/mmu_context_32.h +++ b/include/asm-x86/mmu_context_32.h @@ -32,8 +32,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) #endif } -void leave_mm(unsigned long cpu); - static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) -- cgit v1.2.3 From 39657b6546558469734eb960f7c0c9492111096f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 30 Jan 2008 13:32:31 +0100 Subject: git-x86: drivers/pnp/pnpbios/bioscalls.c build fix drivers/pnp/pnpbios/bioscalls.c:64: warning: (near initialization for 'bad_bios_desc.') Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/pnp/pnpbios/bioscalls.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index 5dba68fe33f5..a8364d815222 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -61,7 +61,7 @@ set_base(gdt[(selname) >> 3], (u32)(address)); \ set_limit(gdt[(selname) >> 3], size); \ } while(0) -static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; +static struct desc_struct bad_bios_desc; /* * At some point we want to use this stack frame pointer to unwind @@ -477,6 +477,9 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment = PNP_CS16; + bad_bios_desc.a = 0; + bad_bios_desc.b = 0x00409200; + set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); for (i = 0; i < NR_CPUS; i++) { -- cgit v1.2.3 From ddb25f9ac1c4b4f9ba0bdacd7850a921a0c6886c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 30 Jan 2008 13:32:41 +0100 Subject: x86: don't disable TSC in any C states on AMD Fam10h The ACPI code currently disables TSC use in any C2 and C3 states. But the AMD Fam10h BKDG documents that the TSC will never stop in any C states when the CONSTANT_TSC bit is set. Make this disabling conditional on CONSTANT_TSC not set on AMD. I actually think this is true on Intel too for C2 states on CPUs with p-state invariant TSC, but this needs further discussions with Len to really confirm :-) So far it is only enabled on AMD. Cc: lenb@kernel.org Signed-off-by: Andi Kleen Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/acpi/processor_idle.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0721a8183c89..eb1f82f79153 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -357,6 +357,26 @@ int acpi_processor_resume(struct acpi_device * device) return 0; } +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) +static int tsc_halts_in_c(int state) +{ + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + /* + * AMD Fam10h TSC will tick in all + * C/P/S0/S1 states when this bit is set. + */ + if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) + return 0; + /*FALL THROUGH*/ + case X86_VENDOR_INTEL: + /* Several cases known where TSC halts in C2 too */ + default: + return state > ACPI_STATE_C1; + } +} +#endif + #ifndef CONFIG_CPU_IDLE static void acpi_processor_idle(void) { @@ -516,7 +536,8 @@ static void acpi_processor_idle(void) #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) /* TSC halts in C2, so notify users */ - mark_tsc_unstable("possible TSC halt in C2"); + if (tsc_halts_in_c(ACPI_STATE_C2)) + mark_tsc_unstable("possible TSC halt in C2"); #endif /* Compute time (ticks) that we were actually asleep */ sleep_ticks = ticks_elapsed(t1, t2); @@ -580,7 +601,8 @@ static void acpi_processor_idle(void) #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) /* TSC halts in C3, so notify users */ - mark_tsc_unstable("TSC halts in C3"); + if (tsc_halts_in_c(ACPI_STATE_C3)) + mark_tsc_unstable("TSC halts in C3"); #endif /* Compute time (ticks) that we were actually asleep */ sleep_ticks = ticks_elapsed(t1, t2); @@ -1445,7 +1467,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) /* TSC could halt in idle, so notify users */ - mark_tsc_unstable("TSC halts in idle");; + if (tsc_halts_in_c(cx->type)) + mark_tsc_unstable("TSC halts in idle");; #endif sleep_ticks = ticks_elapsed(t1, t2); @@ -1556,7 +1579,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) /* TSC could halt in idle, so notify users */ - mark_tsc_unstable("TSC halts in idle"); + if (tsc_halts_in_c(ACPI_STATE_C3)) + mark_tsc_unstable("TSC halts in idle"); #endif sleep_ticks = ticks_elapsed(t1, t2); /* Tell the scheduler how much we idled: */ -- cgit v1.2.3 From 0d64484f7ea12ca04211b497e94634c3d27cf3fb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:33:09 +0100 Subject: x86: fix DMI ioremap leak Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/firmware/dmi_scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 0b24a1141009..5f9d0bc839ba 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -349,6 +349,7 @@ void __init dmi_scan_machine(void) rc = dmi_present(q); if (!rc) { dmi_available = 1; + dmi_iounmap(p, 0x10000); return; } } -- cgit v1.2.3 From f8f76481bc2803aea03ff213c7e1405b53f7e488 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Wed, 30 Jan 2008 13:33:31 +0100 Subject: rtc: use the IRQ callback interface in (old) RTC driver the previous patch in the old RTC driver. It also removes the direct rtc_interrupt() call from arch/x86/kernel/hpetc.c so that there's finally no (code) dependency to CONFIG_RTC in arch/x86/kernel/hpet.c. Because of this, it's possible to compile the drivers/char/rtc.ko driver as module and still use the HPET emulation functionality. This is also expressed in Kconfig. Signed-off-by: Bernhard Walle Cc: Alessandro Zummo Cc: David Brownell Cc: Andi Kleen Cc: john stultz Cc: Robert Picco Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig | 2 +- arch/x86/kernel/hpet.c | 2 -- drivers/char/rtc.c | 15 ++++++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 81af31e5a9f1..4e911d0a4962 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -390,7 +390,7 @@ config HPET_TIMER config HPET_EMULATE_RTC def_bool y - depends on HPET_TIMER && RTC=y + depends on HPET_TIMER && (RTC=y || RTC=m) # Mark as embedded because too many people got it wrong. # The code disables itself when not needed. diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index d65ced59a18f..429d084e014d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -705,8 +705,6 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8)); if (irq_handler) irq_handler(rtc_int_flag, dev_id); - - rtc_interrupt(rtc_int_flag, dev_id); } return IRQ_HANDLED; } diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 3ac7952fe086..78b151c4d20f 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -110,6 +110,8 @@ static int rtc_has_irq = 1; #define hpet_set_rtc_irq_bit(arg) 0 #define hpet_rtc_timer_init() do { } while (0) #define hpet_rtc_dropped_irq() 0 +#define hpet_register_irq_handler(h) 0 +#define hpet_unregister_irq_handler(h) 0 #ifdef RTC_IRQ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) { @@ -1027,7 +1029,15 @@ no_irq: #ifdef RTC_IRQ if (is_hpet_enabled()) { + int err; + rtc_int_handler_ptr = hpet_rtc_interrupt; + err = hpet_register_irq_handler(rtc_interrupt); + if (err != 0) { + printk(KERN_WARNING "hpet_register_irq_handler failed " + "in rtc_init()."); + return err; + } } else { rtc_int_handler_ptr = rtc_interrupt; } @@ -1050,6 +1060,7 @@ no_irq: if (misc_register(&rtc_dev)) { #ifdef RTC_IRQ free_irq(RTC_IRQ, NULL); + hpet_unregister_irq_handler(rtc_interrupt); rtc_has_irq = 0; #endif rtc_release_region(); @@ -1141,8 +1152,10 @@ static void __exit rtc_exit(void) #else rtc_release_region(); #ifdef RTC_IRQ - if (rtc_has_irq) + if (rtc_has_irq) { free_irq(RTC_IRQ, NULL); + hpet_unregister_irq_handler(hpet_rtc_interrupt); + } #endif #endif /* CONFIG_SPARC32 */ } -- cgit v1.2.3 From 3212bff370c2f22e4987c6679ba485654cefb178 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 30 Jan 2008 13:33:32 +0100 Subject: x86: left over fix for leak of early_ioremp in dmi_scan Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/firmware/dmi_scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 5f9d0bc839ba..9008ed5ef4ce 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -353,6 +353,7 @@ void __init dmi_scan_machine(void) return; } } + dmi_iounmap(p, 0x10000); } out: printk(KERN_INFO "DMI not present or invalid.\n"); } -- cgit v1.2.3 From 53391fa20cab6df6b476a5a0ad6be653c9de0c46 Mon Sep 17 00:00:00 2001 From: Yi Yang Date: Wed, 30 Jan 2008 13:33:34 +0100 Subject: cpufreq: fix obvious condition statement error The function __cpufreq_set_policy in file drivers/cpufreq/cpufreq.c has a very obvious error: if (policy->min > data->min && policy->min > policy->max) { ret = -EINVAL; goto error_out; } This condtion statement is wrong because it returns -EINVAL only if policy->min is greater than policy->max (in this case, "policy->min > data->min" is true for ever.). In fact, it should return -EINVAL as well if policy->max is less than data->min. The correct condition should be: if (policy->min > data->max || policy->max < data->min) { The following test result testifies the above conclusion: Before applying this patch: [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 2394000 1596000 [root@yangyi-dev /]# echo 1596000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 1596000 [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 1596000 [root@yangyi-dev /]# echo "2000000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq -bash: echo: write error: Invalid argument [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 1596000 [root@yangyi-dev /]# echo "0" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 1596000 [root@yangyi-dev /]# echo "1595000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 1596000 [root@yangyi-dev /]# After applying this patch: [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 2394000 1596000 [root@yangyi-dev /]# echo 1596000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 1596000 [root@yangyi-dev /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 1596000 [root@localhost /]# echo "2000000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq -bash: echo: write error: Invalid argument [root@localhost /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 1596000 [root@localhost /]# echo "0" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq -bash: echo: write error: Invalid argument [root@localhost /]# echo "1595000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq -bash: echo: write error: Invalid argument [root@localhost /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 1596000 [root@localhost /]# echo "1596000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq [root@localhost /]# echo "2394000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq [root@localhost /]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 2394000 [root@localhost /] Signed-off-by: Yi Yang Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 5efd5550f4ca..b730d6709529 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1604,7 +1604,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); - if (policy->min > data->min && policy->min > policy->max) { + if (policy->min > data->max || policy->max < data->min) { ret = -EINVAL; goto error_out; } -- cgit v1.2.3 From 6d238cc4dc8a36a3915c26202fe49f58a0683fb9 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 30 Jan 2008 13:34:06 +0100 Subject: x86: convert CPA users to the new set_page_ API This patch converts various users of change_page_attr() to the new, more intent driven set_page_*/set_memory_* API set. Signed-off-by: Arjan van de Ven Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 8 ++++---- arch/x86/kernel/pci-gart_64.c | 3 +-- arch/x86/mm/init_32.c | 20 +++++++------------- arch/x86/mm/init_64.c | 10 ++++------ drivers/char/agp/intel-agp.c | 6 +++--- drivers/video/vermilion/vermilion.c | 9 +++------ include/asm-x86/agp.h | 4 ++-- sound/pci/intel8x0.c | 7 +++++-- 8 files changed, 29 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 57b57778bf60..a70fe77354b8 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -396,10 +396,10 @@ static void __init runtime_code_page_mkexec(void) md = p; end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); if (md->type == EFI_RUNTIME_SERVICES_CODE && - (end >> PAGE_SHIFT) <= max_pfn_mapped) - change_page_attr_addr(md->virt_addr, - md->num_pages, - PAGE_KERNEL_EXEC_NOCACHE); + (end >> PAGE_SHIFT) <= max_pfn_mapped) { + set_memory_x(md->virt_addr, md->num_pages); + set_memory_uc(md->virt_addr, md->num_pages); + } } __flush_tlb_all(); } diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 04ca5c5221d7..8860c6eba8ab 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -570,8 +570,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) gatt = (void *)__get_free_pages(GFP_KERNEL, get_order(gatt_size)); if (!gatt) panic("Cannot allocate GATT table"); - if (change_page_attr_addr((unsigned long)gatt, gatt_size >> PAGE_SHIFT, - PAGE_KERNEL_NOCACHE)) + if (set_memory_uc((unsigned long)gatt, gatt_size >> PAGE_SHIFT)) panic("Could not set GART PTEs to uncacheable pages"); global_flush_tlb(); diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 016c8ccd1d8d..7c9bb3076b8a 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -770,34 +770,30 @@ void mark_rodata_ro(void) if (num_possible_cpus() <= 1) #endif { - change_page_attr(virt_to_page(start), - size >> PAGE_SHIFT, PAGE_KERNEL_RX); + set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); printk("Write protecting the kernel text: %luk\n", size >> 10); #ifdef CONFIG_CPA_DEBUG global_flush_tlb(); printk("Testing CPA: Reverting %lx-%lx\n", start, start+size); - change_page_attr(virt_to_page(start), size>>PAGE_SHIFT, - PAGE_KERNEL_EXEC); + set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT); global_flush_tlb(); printk("Testing CPA: write protecting again\n"); - change_page_attr(virt_to_page(start), size>>PAGE_SHIFT, - PAGE_KERNEL_RX); + set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); global_flush_tlb(); #endif } #endif start += size; size = (unsigned long)__end_rodata - start; - change_page_attr(virt_to_page(start), - size >> PAGE_SHIFT, PAGE_KERNEL_RO); + set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); printk("Write protecting the kernel read-only data: %luk\n", size >> 10); /* - * change_page_attr() requires a global_flush_tlb() call after it. + * set_pages_*() requires a global_flush_tlb() call after it. * We do this after the printk so that if something went wrong in the * change, the printk gets out at least to give a better debug hint * of who is the culprit. @@ -806,13 +802,11 @@ void mark_rodata_ro(void) #ifdef CONFIG_CPA_DEBUG printk("Testing CPA: undo %lx-%lx\n", start, start + size); - change_page_attr(virt_to_page(start), size >> PAGE_SHIFT, - PAGE_KERNEL); + set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT); global_flush_tlb(); printk("Testing CPA: write protecting again\n"); - change_page_attr(virt_to_page(start), size >> PAGE_SHIFT, - PAGE_KERNEL_RO); + set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); global_flush_tlb(); #endif } diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index c250580a9432..05bb12db0b09 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -556,8 +556,6 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) init_page_count(virt_to_page(addr)); memset((void *)(addr & ~(PAGE_SIZE-1)), POISON_FREE_INITMEM, PAGE_SIZE); - if (addr >= __START_KERNEL_map) - change_page_attr_addr(addr, 1, __pgprot(0)); free_page(addr); totalram_pages++; } @@ -594,13 +592,13 @@ void mark_rodata_ro(void) if (end <= start) return; - change_page_attr_addr(start, (end - start) >> PAGE_SHIFT, PAGE_KERNEL_RO); + set_memory_ro(start, (end - start) >> PAGE_SHIFT); printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", (end - start) >> 10); /* - * change_page_attr_addr() requires a global_flush_tlb() call after it. + * set_memory_*() requires a global_flush_tlb() call after it. * We do this after the printk so that if something went wrong in the * change, the printk gets out at least to give a better debug hint * of who is the culprit. @@ -609,11 +607,11 @@ void mark_rodata_ro(void) #ifdef CONFIG_CPA_DEBUG printk("Testing CPA: undo %lx-%lx\n", start, end); - change_page_attr_addr(start, (end - start) >> PAGE_SHIFT, PAGE_KERNEL); + set_memory_rw(start, (end-start) >> PAGE_SHIFT); global_flush_tlb(); printk("Testing CPA: again\n"); - change_page_attr_addr(start, (end - start) >> PAGE_SHIFT, PAGE_KERNEL_RO); + set_memory_ro(start, (end-start) >> PAGE_SHIFT); global_flush_tlb(); #endif } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 03eac1eb8e0f..c03a7143928f 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -210,8 +210,8 @@ static void *i8xx_alloc_pages(void) if (page == NULL) return NULL; - if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { - change_page_attr(page, 4, PAGE_KERNEL); + if (set_pages_uc(page, 4) < 0) { + set_pages_wb(page, 4); global_flush_tlb(); __free_pages(page, 2); return NULL; @@ -230,7 +230,7 @@ static void i8xx_destroy_pages(void *addr) return; page = virt_to_page(addr); - change_page_attr(page, 4, PAGE_KERNEL); + set_pages_wb(page, 4); global_flush_tlb(); put_page(page); __free_pages(page, 2); diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index c31f549ebea0..fb72778dee48 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c @@ -88,9 +88,7 @@ static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order, { gfp_t flags; unsigned long i; - pgprot_t wc_pageprot; - wc_pageprot = PAGE_KERNEL_NOCACHE; max_order++; do { /* @@ -131,8 +129,7 @@ static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order, */ global_flush_tlb(); - change_page_attr(virt_to_page(va->logical), va->size >> PAGE_SHIFT, - wc_pageprot); + set_pages_uc(virt_to_page(va->logical), va->size >> PAGE_SHIFT); global_flush_tlb(); printk(KERN_DEBUG MODULE_NAME @@ -157,8 +154,8 @@ static void vmlfb_free_vram_area(struct vram_area *va) * Reset the linear kernel map caching policy. */ - change_page_attr(virt_to_page(va->logical), - va->size >> PAGE_SHIFT, PAGE_KERNEL); + set_pages_wb(virt_to_page(va->logical), + va->size >> PAGE_SHIFT); global_flush_tlb(); /* diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h index 62df2a9e7130..f6df72561832 100644 --- a/include/asm-x86/agp.h +++ b/include/asm-x86/agp.h @@ -16,8 +16,8 @@ * Caller's responsibility to call global_flush_tlb() for performance * reasons */ -#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE) -#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL) +#define map_page_into_agp(page) set_pages_uc(page, 1) +#define unmap_page_from_agp(page) set_pages_wb(page, 1) #define flush_agp_mappings() global_flush_tlb() /* diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index b4a38a3d855b..e5650905296e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -711,11 +711,14 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich static void fill_nocache(void *buf, int size, int nocache) { size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - change_page_attr(virt_to_page(buf), size, nocache ? PAGE_KERNEL_NOCACHE : PAGE_KERNEL); + if (nocache) + set_pages_uc(virt_to_page(buf), size); + else + set_pages_wb(virt_to_page(buf), size); global_flush_tlb(); } #else -#define fill_nocache(buf,size,nocache) +#define fill_nocache(buf, size, nocache) do { ; } while (0) #endif /* -- cgit v1.2.3 From d7c8f21a8cad0228c7c5ce2bb6dbd95d1ee49d13 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:34:07 +0100 Subject: x86: cpa: move flush to cpa The set_memory_* and set_pages_* family of API's currently requires the callers to do a global tlb flush after the function call; forgetting this is a very nasty deathtrap. This patch moves the global tlb flush into each of the callers Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/pci-gart_64.c | 1 - arch/x86/mm/init_32.c | 14 ---- arch/x86/mm/init_64.c | 10 --- arch/x86/mm/ioremap.c | 2 - arch/x86/mm/pageattr.c | 137 +++++++++++++++++++----------------- drivers/char/agp/ali-agp.c | 2 - drivers/char/agp/i460-agp.c | 2 - drivers/char/agp/intel-agp.c | 5 -- drivers/video/vermilion/vermilion.c | 6 -- include/asm-x86/agp.h | 6 +- include/asm-x86/cacheflush.h | 1 - sound/pci/intel8x0.c | 1 - 12 files changed, 72 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 8860c6eba8ab..4d5cc7181982 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -572,7 +572,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info) panic("Cannot allocate GATT table"); if (set_memory_uc((unsigned long)gatt, gatt_size >> PAGE_SHIFT)) panic("Could not set GART PTEs to uncacheable pages"); - global_flush_tlb(); memset(gatt, 0, gatt_size); agp_gatt_table = gatt; diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index f7b941c3b2c3..0d3369b900e9 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -752,15 +752,11 @@ void mark_rodata_ro(void) printk("Write protecting the kernel text: %luk\n", size >> 10); #ifdef CONFIG_CPA_DEBUG - global_flush_tlb(); - printk("Testing CPA: Reverting %lx-%lx\n", start, start+size); set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT); - global_flush_tlb(); printk("Testing CPA: write protecting again\n"); set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); - global_flush_tlb(); #endif } #endif @@ -770,22 +766,12 @@ void mark_rodata_ro(void) printk("Write protecting the kernel read-only data: %luk\n", size >> 10); - /* - * set_pages_*() requires a global_flush_tlb() call after it. - * We do this after the printk so that if something went wrong in the - * change, the printk gets out at least to give a better debug hint - * of who is the culprit. - */ - global_flush_tlb(); - #ifdef CONFIG_CPA_DEBUG printk("Testing CPA: undo %lx-%lx\n", start, start + size); set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT); - global_flush_tlb(); printk("Testing CPA: write protecting again\n"); set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); - global_flush_tlb(); #endif } #endif diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 4757be7b5e55..9b69fa54a831 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -610,22 +610,12 @@ void mark_rodata_ro(void) printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", (end - start) >> 10); - /* - * set_memory_*() requires a global_flush_tlb() call after it. - * We do this after the printk so that if something went wrong in the - * change, the printk gets out at least to give a better debug hint - * of who is the culprit. - */ - global_flush_tlb(); - #ifdef CONFIG_CPA_DEBUG printk("Testing CPA: undo %lx-%lx\n", start, end); set_memory_rw(start, (end-start) >> PAGE_SHIFT); - global_flush_tlb(); printk("Testing CPA: again\n"); set_memory_ro(start, (end-start) >> PAGE_SHIFT); - global_flush_tlb(); #endif } #endif diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index b86f66fa5185..6a9a1418bc98 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -96,8 +96,6 @@ static int ioremap_change_attr(unsigned long paddr, unsigned long size, err = set_memory_wb(vaddr, nrpages); break; } - if (!err) - global_flush_tlb(); return err; } diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index e4d2b6930e61..a2d747c06147 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -22,6 +22,36 @@ within(unsigned long addr, unsigned long start, unsigned long end) return addr >= start && addr < end; } +/* + * Flushing functions + */ +void clflush_cache_range(void *addr, int size) +{ + int i; + + for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size) + clflush(addr+i); +} + +static void flush_kernel_map(void *arg) +{ + /* + * Flush all to work around Errata in early athlons regarding + * large page flushing. + */ + __flush_tlb_all(); + + if (boot_cpu_data.x86_model >= 4) + wbinvd(); +} + +static void global_flush_tlb(void) +{ + BUG_ON(irqs_disabled()); + + on_each_cpu(flush_kernel_map, NULL, 1, 1); +} + /* * Certain areas of memory on x86 require very specific protection flags, * for example the BIOS area or kernel text. Callers don't always get this @@ -328,149 +358,124 @@ static int change_page_attr_clear(unsigned long addr, int numpages, int set_memory_uc(unsigned long addr, int numpages) { - pgprot_t uncached; + int err; - pgprot_val(uncached) = _PAGE_PCD | _PAGE_PWT; - return change_page_attr_set(addr, numpages, uncached); + err = change_page_attr_set(addr, numpages, + __pgprot(_PAGE_PCD | _PAGE_PWT)); + global_flush_tlb(); + return err; } EXPORT_SYMBOL(set_memory_uc); int set_memory_wb(unsigned long addr, int numpages) { - pgprot_t uncached; + int err; - pgprot_val(uncached) = _PAGE_PCD | _PAGE_PWT; - return change_page_attr_clear(addr, numpages, uncached); + err = change_page_attr_clear(addr, numpages, + __pgprot(_PAGE_PCD | _PAGE_PWT)); + global_flush_tlb(); + return err; } EXPORT_SYMBOL(set_memory_wb); int set_memory_x(unsigned long addr, int numpages) { - pgprot_t nx; + int err; - pgprot_val(nx) = _PAGE_NX; - return change_page_attr_clear(addr, numpages, nx); + err = change_page_attr_clear(addr, numpages, + __pgprot(_PAGE_NX)); + global_flush_tlb(); + return err; } EXPORT_SYMBOL(set_memory_x); int set_memory_nx(unsigned long addr, int numpages) { - pgprot_t nx; + int err; - pgprot_val(nx) = _PAGE_NX; - return change_page_attr_set(addr, numpages, nx); + err = change_page_attr_set(addr, numpages, + __pgprot(_PAGE_NX)); + global_flush_tlb(); + return err; } EXPORT_SYMBOL(set_memory_nx); int set_memory_ro(unsigned long addr, int numpages) { - pgprot_t rw; + int err; - pgprot_val(rw) = _PAGE_RW; - return change_page_attr_clear(addr, numpages, rw); + err = change_page_attr_clear(addr, numpages, + __pgprot(_PAGE_RW)); + global_flush_tlb(); + return err; } int set_memory_rw(unsigned long addr, int numpages) { - pgprot_t rw; + int err; - pgprot_val(rw) = _PAGE_RW; - return change_page_attr_set(addr, numpages, rw); + err = change_page_attr_set(addr, numpages, + __pgprot(_PAGE_RW)); + global_flush_tlb(); + return err; } int set_memory_np(unsigned long addr, int numpages) { - pgprot_t present; + int err; - pgprot_val(present) = _PAGE_PRESENT; - return change_page_attr_clear(addr, numpages, present); + err = change_page_attr_clear(addr, numpages, + __pgprot(_PAGE_PRESENT)); + global_flush_tlb(); + return err; } int set_pages_uc(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); - pgprot_t uncached; - pgprot_val(uncached) = _PAGE_PCD | _PAGE_PWT; - return change_page_attr_set(addr, numpages, uncached); + return set_memory_uc(addr, numpages); } EXPORT_SYMBOL(set_pages_uc); int set_pages_wb(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); - pgprot_t uncached; - pgprot_val(uncached) = _PAGE_PCD | _PAGE_PWT; - return change_page_attr_clear(addr, numpages, uncached); + return set_memory_wb(addr, numpages); } EXPORT_SYMBOL(set_pages_wb); int set_pages_x(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); - pgprot_t nx; - pgprot_val(nx) = _PAGE_NX; - return change_page_attr_clear(addr, numpages, nx); + return set_memory_x(addr, numpages); } EXPORT_SYMBOL(set_pages_x); int set_pages_nx(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); - pgprot_t nx; - pgprot_val(nx) = _PAGE_NX; - return change_page_attr_set(addr, numpages, nx); + return set_memory_nx(addr, numpages); } EXPORT_SYMBOL(set_pages_nx); int set_pages_ro(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); - pgprot_t rw; - pgprot_val(rw) = _PAGE_RW; - return change_page_attr_clear(addr, numpages, rw); + return set_memory_ro(addr, numpages); } int set_pages_rw(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); - pgprot_t rw; - - pgprot_val(rw) = _PAGE_RW; - return change_page_attr_set(addr, numpages, rw); -} - -void clflush_cache_range(void *addr, int size) -{ - int i; - - for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size) - clflush(addr+i); -} -static void flush_kernel_map(void *arg) -{ - /* - * Flush all to work around Errata in early athlons regarding - * large page flushing. - */ - __flush_tlb_all(); - - if (boot_cpu_data.x86_model >= 4) - wbinvd(); + return set_memory_rw(addr, numpages); } -void global_flush_tlb(void) -{ - BUG_ON(irqs_disabled()); - - on_each_cpu(flush_kernel_map, NULL, 1, 1); -} -EXPORT_SYMBOL(global_flush_tlb); #ifdef CONFIG_DEBUG_PAGEALLOC diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index aa5ddb716ffb..1ffb381130c3 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -145,7 +145,6 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) void *addr = agp_generic_alloc_page(agp_bridge); u32 temp; - global_flush_tlb(); if (!addr) return NULL; @@ -162,7 +161,6 @@ static void ali_destroy_page(void * addr, int flags) if (flags & AGP_PAGE_DESTROY_UNMAP) { global_cache_flush(); /* is this really needed? --hch */ agp_generic_destroy_page(addr, flags); - global_flush_tlb(); } else agp_generic_destroy_page(addr, flags); } diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index e72a83e2bad5..76f581c85a7d 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -527,7 +527,6 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge) if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { page = agp_generic_alloc_page(agp_bridge); - global_flush_tlb(); } else /* Returning NULL would cause problems */ /* AK: really dubious code. */ @@ -539,7 +538,6 @@ static void i460_destroy_page (void *page, int flags) { if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { agp_generic_destroy_page(page, flags); - global_flush_tlb(); } } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index c03a7143928f..189efb6ef970 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -212,11 +212,9 @@ static void *i8xx_alloc_pages(void) if (set_pages_uc(page, 4) < 0) { set_pages_wb(page, 4); - global_flush_tlb(); __free_pages(page, 2); return NULL; } - global_flush_tlb(); get_page(page); atomic_inc(&agp_bridge->current_memory_agp); return page_address(page); @@ -231,7 +229,6 @@ static void i8xx_destroy_pages(void *addr) page = virt_to_page(addr); set_pages_wb(page, 4); - global_flush_tlb(); put_page(page); __free_pages(page, 2); atomic_dec(&agp_bridge->current_memory_agp); @@ -341,7 +338,6 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) switch (pg_count) { case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); - global_flush_tlb(); break; case 4: /* kludge to get 4 physical pages for ARGB cursor */ @@ -404,7 +400,6 @@ static void intel_i810_free_by_type(struct agp_memory *curr) else { agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]), AGP_PAGE_DESTROY_UNMAP); - global_flush_tlb(); agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]), AGP_PAGE_DESTROY_FREE); } diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index fb72778dee48..1c656667b937 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c @@ -124,13 +124,8 @@ static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order, /* * Change caching policy of the linear kernel map to avoid * mapping type conflicts with user-space mappings. - * The first global_flush_tlb() is really only there to do a global - * wbinvd(). */ - - global_flush_tlb(); set_pages_uc(virt_to_page(va->logical), va->size >> PAGE_SHIFT); - global_flush_tlb(); printk(KERN_DEBUG MODULE_NAME ": Allocated %ld bytes vram area at 0x%08lx\n", @@ -156,7 +151,6 @@ static void vmlfb_free_vram_area(struct vram_area *va) set_pages_wb(virt_to_page(va->logical), va->size >> PAGE_SHIFT); - global_flush_tlb(); /* * Decrease the usage count on the pages we've used diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h index f6df72561832..0c309b9a5217 100644 --- a/include/asm-x86/agp.h +++ b/include/asm-x86/agp.h @@ -12,13 +12,9 @@ * page. This avoids data corruption on some CPUs. */ -/* - * Caller's responsibility to call global_flush_tlb() for performance - * reasons - */ #define map_page_into_agp(page) set_pages_uc(page, 1) #define unmap_page_from_agp(page) set_pages_wb(page, 1) -#define flush_agp_mappings() global_flush_tlb() +#define flush_agp_mappings() do { } while (0) /* * Could use CLFLUSH here if the cpu supports it. But then it would diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index d15ff359d3e3..157da0206ccc 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -24,7 +24,6 @@ #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ memcpy(dst, src, len) -void global_flush_tlb(void); int __deprecated_for_modules change_page_attr(struct page *page, int numpages, pgprot_t prot); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index e5650905296e..4bb97646a67a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -715,7 +715,6 @@ static void fill_nocache(void *buf, int size, int nocache) set_pages_uc(virt_to_page(buf), size); else set_pages_wb(virt_to_page(buf), size); - global_flush_tlb(); } #else #define fill_nocache(buf, size, nocache) do { ; } while (0) -- cgit v1.2.3 From 5398f9854f60d670e8ef1ea08c0e0310f253eeb1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:34:07 +0100 Subject: x86: remove flush_agp_mappings() Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/char/agp/backend.c | 3 --- drivers/char/agp/generic.c | 3 --- include/asm-alpha/agp.h | 1 - include/asm-ia64/agp.h | 1 - include/asm-parisc/agp.h | 1 - include/asm-powerpc/agp.h | 1 - include/asm-sparc64/agp.h | 1 - include/asm-x86/agp.h | 1 - 8 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 832ded20fe70..2720882e66fe 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -147,7 +147,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); return -ENOMEM; } - flush_agp_mappings(); bridge->scratch_page_real = virt_to_gart(addr); bridge->scratch_page = @@ -191,7 +190,6 @@ err_out: if (bridge->driver->needs_scratch_page) { bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), AGP_PAGE_DESTROY_UNMAP); - flush_agp_mappings(); bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), AGP_PAGE_DESTROY_FREE); } @@ -219,7 +217,6 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) bridge->driver->needs_scratch_page) { bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), AGP_PAGE_DESTROY_UNMAP); - flush_agp_mappings(); bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), AGP_PAGE_DESTROY_FREE); } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 64b2f6d7059d..1a4674ce0c71 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -197,7 +197,6 @@ void agp_free_memory(struct agp_memory *curr) for (i = 0; i < curr->page_count; i++) { curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_UNMAP); } - flush_agp_mappings(); for (i = 0; i < curr->page_count; i++) { curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_FREE); } @@ -267,8 +266,6 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, } new->bridge = bridge; - flush_agp_mappings(); - return new; } EXPORT_SYMBOL(agp_allocate_memory); diff --git a/include/asm-alpha/agp.h b/include/asm-alpha/agp.h index ef855a3bc0f5..26c179135293 100644 --- a/include/asm-alpha/agp.h +++ b/include/asm-alpha/agp.h @@ -7,7 +7,6 @@ #define map_page_into_agp(page) #define unmap_page_from_agp(page) -#define flush_agp_mappings() #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ diff --git a/include/asm-ia64/agp.h b/include/asm-ia64/agp.h index 4e517f0e6afa..c11fdd8ab4d7 100644 --- a/include/asm-ia64/agp.h +++ b/include/asm-ia64/agp.h @@ -15,7 +15,6 @@ */ #define map_page_into_agp(page) /* nothing */ #define unmap_page_from_agp(page) /* nothing */ -#define flush_agp_mappings() /* nothing */ #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ diff --git a/include/asm-parisc/agp.h b/include/asm-parisc/agp.h index 9f61d4eb6c01..9651660da639 100644 --- a/include/asm-parisc/agp.h +++ b/include/asm-parisc/agp.h @@ -9,7 +9,6 @@ #define map_page_into_agp(page) /* nothing */ #define unmap_page_from_agp(page) /* nothing */ -#define flush_agp_mappings() /* nothing */ #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ diff --git a/include/asm-powerpc/agp.h b/include/asm-powerpc/agp.h index e5ccaca2f5a4..86455c4c31ee 100644 --- a/include/asm-powerpc/agp.h +++ b/include/asm-powerpc/agp.h @@ -6,7 +6,6 @@ #define map_page_into_agp(page) #define unmap_page_from_agp(page) -#define flush_agp_mappings() #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ diff --git a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h index 58f8cb6ae767..e9fcf0e781ea 100644 --- a/include/asm-sparc64/agp.h +++ b/include/asm-sparc64/agp.h @@ -5,7 +5,6 @@ #define map_page_into_agp(page) #define unmap_page_from_agp(page) -#define flush_agp_mappings() #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h index 0c309b9a5217..e4004a9f6a9a 100644 --- a/include/asm-x86/agp.h +++ b/include/asm-x86/agp.h @@ -14,7 +14,6 @@ #define map_page_into_agp(page) set_pages_uc(page, 1) #define unmap_page_from_agp(page) set_pages_wb(page, 1) -#define flush_agp_mappings() do { } while (0) /* * Could use CLFLUSH here if the cpu supports it. But then it would -- cgit v1.2.3 From f212ec4b7b4d84290f12c9c0416cdea283bf5f40 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 30 Jan 2008 13:34:11 +0100 Subject: x86: early boot debugging via FireWire (ohci1394_dma=early) This patch adds a new configuration option, which adds support for a new early_param which gets checked in arch/x86/kernel/setup_{32,64}.c:setup_arch() to decide wether OHCI-1394 FireWire controllers should be initialized and enabled for physical DMA access to allow remote debugging of early problems like issues ACPI or other subsystems which are executed very early. If the config option is not enabled, no code is changed, and if the boot paramenter is not given, no new code is executed, and independent of that, all new code is freed after boot, so the config option can be even enabled in standard, non-debug kernels. With specialized tools, it is then possible to get debugging information from machines which have no serial ports (notebooks) such as the printk buffer contents, or any data which can be referenced from global pointers, if it is stored below the 4GB limit and even memory dumps of of the physical RAM region below the 4GB limit can be taken without any cooperation from the CPU of the host, so the machine can be crashed early, it does not matter. In the extreme, even kernel debuggers can be accessed in this way. I wrote a small kgdb module and an accompanying gdb stub for FireWire which allows to gdb to talk to kgdb using remote remory reads and writes over FireWire. An version of the gdb stub fore FireWire is able to read all global data from a system which is running a a normal kernel without any kernel debugger, without any interruption or support of the system's CPU. That way, e.g. the task struct and so on can be read and even manipulated when the physical DMA access is granted. A HOWTO is included in this patch, in Documentation/debugging-via-ohci1394.txt and I've put a copy online at ftp://ftp.suse.de/private/bk/firewire/docs/debugging-via-ohci1394.txt It also has links to all the tools which are available to make use of it another copy of it is online at: ftp://ftp.suse.de/private/bk/firewire/kernel/ohci1394_dma_early-v2.diff Signed-Off-By: Bernhard Kaindl Tested-By: Thomas Renninger Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/debugging-via-ohci1394.txt | 179 +++++++++++++++++++ arch/x86/kernel/setup_32.c | 11 ++ arch/x86/kernel/setup_64.c | 11 ++ drivers/Makefile | 2 +- drivers/ieee1394/Makefile | 1 + drivers/ieee1394/init_ohci1394_dma.c | 285 +++++++++++++++++++++++++++++++ include/asm-x86/fixmap_32.h | 3 + include/asm-x86/fixmap_64.h | 3 + include/linux/init_ohci1394_dma.h | 4 + lib/Kconfig.debug | 28 +++ 10 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 Documentation/debugging-via-ohci1394.txt create mode 100644 drivers/ieee1394/init_ohci1394_dma.c create mode 100644 include/linux/init_ohci1394_dma.h (limited to 'drivers') diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt new file mode 100644 index 000000000000..de4804e8b396 --- /dev/null +++ b/Documentation/debugging-via-ohci1394.txt @@ -0,0 +1,179 @@ + + Using physical DMA provided by OHCI-1394 FireWire controllers for debugging + --------------------------------------------------------------------------- + +Introduction +------------ + +Basically all FireWire controllers which are in use today are compliant +to the OHCI-1394 specification which defines the controller to be a PCI +bus master which uses DMA to offload data transfers from the CPU and has +a "Physical Response Unit" which executes specific requests by employing +PCI-Bus master DMA after applying filters defined by the OHCI-1394 driver. + +Once properly configured, remote machines can send these requests to +ask the OHCI-1394 controller to perform read and write requests on +physical system memory and, for read requests, send the result of +the physical memory read back to the requester. + +With that, it is possible to debug issues by reading interesting memory +locations such as buffers like the printk buffer or the process table. + +Retrieving a full system memory dump is also possible over the FireWire, +using data transfer rates in the order of 10MB/s or more. + +Memory access is currently limited to the low 4G of physical address +space which can be a problem on IA64 machines where memory is located +mostly above that limit, but it is rarely a problem on more common +hardware such as hardware based on x86, x86-64 and PowerPC. + +Together with a early initialization of the OHCI-1394 controller for debugging, +this facility proved most useful for examining long debugs logs in the printk +buffer on to debug early boot problems in areas like ACPI where the system +fails to boot and other means for debugging (serial port) are either not +available (notebooks) or too slow for extensive debug information (like ACPI). + +Drivers +------- + +The OHCI-1394 drivers in drivers/firewire and drivers/ieee1394 initialize +the OHCI-1394 controllers to a working state and can be used to enable +physical DMA. By default you only have to load the driver, and physical +DMA access will be granted to all remote nodes, but it can be turned off +when using the ohci1394 driver. + +Because these drivers depend on the PCI enumeration to be completed, an +initialization routine which can runs pretty early (long before console_init(), +which makes the printk buffer appear on the console can be called) was written. + +To activate it, enable CONFIG_PROVIDE_OHCI1394_DMA_INIT (Kernel hacking menu: +Provide code for enabling DMA over FireWire early on boot) and pass the +parameter "ohci1394_dma=early" to the recompiled kernel on boot. + +Tools +----- + +firescope - Originally developed by Benjamin Herrenschmidt, Andi Kleen ported +it from PowerPC to x86 and x86_64 and added functionality, firescope can now +be used to view the printk buffer of a remote machine, even with live update. + +Bernhard Kaindl enhanced firescope to support accessing 64-bit machines +from 32-bit firescope and vice versa: +- ftp://ftp.suse.de/private/bk/firewire/tools/firescope-0.2.2.tar.bz2 + +and he implemented fast system dump (alpha version - read README.txt): +- ftp://ftp.suse.de/private/bk/firewire/tools/firedump-0.1.tar.bz2 + +There is also a gdb proxy for firewire which allows to use gdb to access +data which can be referenced from symbols found by gdb in vmlinux: +- ftp://ftp.suse.de/private/bk/firewire/tools/fireproxy-0.33.tar.bz2 + +The latest version of this gdb proxy (fireproxy-0.34) can communicate (not +yet stable) with kgdb over an memory-based communication module (kgdbom). + +Getting Started +--------------- + +The OHCI-1394 specification regulates that the OHCI-1394 controller must +disable all physical DMA on each bus reset. + +This means that if you want to debug an issue in a system state where +interrupts are disabled and where no polling of the OHCI-1394 controller +for bus resets takes place, you have to establish any FireWire cable +connections and fully initialize all FireWire hardware __before__ the +system enters such state. + +Step-by-step instructions for using firescope with early OHCI initialization: + +1) Verify that your hardware is supported: + + Load the ohci1394 or the fw-ohci module and check your kernel logs. + You should see a line similar to + + ohci1394: fw-host0: OHCI-1394 1.1 (PCI): IRQ=[18] MMIO=[fe9ff800-fe9fffff] + ... Max Packet=[2048] IR/IT contexts=[4/8] + + when loading the driver. If you have no supported controller, many PCI, + CardBus and even some Express cards which are fully compliant to OHCI-1394 + specification are available. If it requires no driver for Windows operating + systems, it most likely is. Only specialized shops have cards which are not + compliant, they are based on TI PCILynx chips and require drivers for Win- + dows operating systems. + +2) Establish a working FireWire cable connection: + + Any FireWire cable, as long at it provides electrically and mechanically + stable connection and has matching connectors (there are small 4-pin and + large 6-pin FireWire ports) will do. + + If an driver is running on both machines you should see a line like + + ieee1394: Node added: ID:BUS[0-01:1023] GUID[0090270001b84bba] + + on both machines in the kernel log when the cable is plugged in + and connects the two machines. + +3) Test physical DMA using firescope: + + On the debug host, + - load the raw1394 module, + - make sure that /dev/raw1394 is accessible, + then start firescope: + + $ firescope + Port 0 (ohci1394) opened, 2 nodes detected + + FireScope + --------- + Target : + Gen : 1 + [Ctrl-T] choose target + [Ctrl-H] this menu + [Ctrl-Q] quit + + ------> Press Ctrl-T now, the output should be similar to: + + 2 nodes available, local node is: 0 + 0: ffc0, uuid: 00000000 00000000 [LOCAL] + 1: ffc1, uuid: 00279000 ba4bb801 + + Besides the [LOCAL] node, it must show another node without error message. + +4) Prepare for debugging with early OHCI-1394 initialization: + + 4.1) Kernel compilation and installation on debug target + + Compile the kernel to be debugged with CONFIG_PROVIDE_OHCI1394_DMA_INIT + (Kernel hacking: Provide code for enabling DMA over FireWire early on boot) + enabled and install it on the machine to be debugged (debug target). + + 4.2) Transfer the System.map of the debugged kernel to the debug host + + Copy the System.map of the kernel be debugged to the debug host (the host + which is connected to the debugged machine over the FireWire cable). + +5) Retrieving the printk buffer contents: + + With the FireWire cable connected, the OHCI-1394 driver on the debugging + host loaded, reboot the debugged machine, booting the kernel which has + CONFIG_PROVIDE_OHCI1394_DMA_INIT enabled, with the option ohci1394_dma=early. + + Then, on the debugging host, run firescope, for example by using -A: + + firescope -A System.map-of-debug-target-kernel + + Note: -A automatically attaches to the first non-local node. It only works + reliably if only connected two machines are connected using FireWire. + + After having attached to the debug target, press Ctrl-D to view the + complete printk buffer or Ctrl-U to enter auto update mode and get an + updated live view of recent kernel messages logged on the debug target. + + Call "firescope -h" to get more information on firescope's options. + +Notes +----- +Documentation and specifications: ftp://ftp.suse.de/private/bk/firewire/docs + +FireWire is a trademark of Apple Inc. - for more information please refer to: +http://en.wikipedia.org/wiki/FireWire diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 9c0ef4945a58..62adc5f20be5 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -45,6 +45,7 @@ #include #include #include +#include #include