aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel')
-rw-r--r--arch/x86_64/kernel/apic.c12
-rw-r--r--arch/x86_64/kernel/entry.S8
-rw-r--r--arch/x86_64/kernel/irq.c7
-rw-r--r--arch/x86_64/kernel/pci-calgary.c36
-rw-r--r--arch/x86_64/kernel/process.c7
-rw-r--r--arch/x86_64/kernel/time.c20
-rw-r--r--arch/x86_64/kernel/traps.c2
7 files changed, 57 insertions, 35 deletions
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 6472e32..af4a1c7 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -885,14 +885,14 @@ void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
* value into /proc/profile.
*/
-void smp_local_timer_interrupt(struct pt_regs *regs)
+void smp_local_timer_interrupt(void)
{
- profile_tick(CPU_PROFILING, regs);
+ profile_tick(CPU_PROFILING);
#ifdef CONFIG_SMP
- update_process_times(user_mode(regs));
+ update_process_times(user_mode(get_irq_regs()));
#endif
if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id)
- main_timer_handler(regs);
+ main_timer_handler();
/*
* We take the 'long' return path, and there every subsystem
* grabs the appropriate locks (kernel lock/ irq lock).
@@ -913,7 +913,7 @@ void smp_local_timer_interrupt(struct pt_regs *regs)
* [ if a single-CPU system runs an SMP kernel then we call the local
* interrupt as well. Thus we cannot inline the local irq ... ]
*/
-void smp_apic_timer_interrupt(struct pt_regs *regs)
+void smp_apic_timer_interrupt(void)
{
/*
* the NMI deadlock-detector uses this.
@@ -932,7 +932,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
*/
exit_idle();
irq_enter();
- smp_local_timer_interrupt(regs);
+ smp_local_timer_interrupt();
irq_exit();
}
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index b8285cf..38a7b2d 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -535,6 +535,8 @@ END(stub_rt_sigreturn)
1: incl %gs:pda_irqcount
cmoveq %gs:pda_irqstackptr,%rsp
push %rbp # backlink for old unwinder
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rbp,0
/*
* We entered an interrupt context - irqs are off:
*/
@@ -978,6 +980,11 @@ ENTRY(kernel_thread)
call do_fork
movq %rax,RAX(%rsp)
xorl %edi,%edi
+ test %rax,%rax
+ jnz 1f
+ /* terminate stack in child */
+ movq %rdi,RIP(%rsp)
+1:
/*
* It isn't worth to check for reschedule here,
@@ -1169,6 +1176,7 @@ ENTRY(call_softirq)
incl %gs:pda_irqcount
cmove %gs:pda_irqstackptr,%rsp
push %rbp # backlink for old unwinder
+ CFI_ADJUST_CFA_OFFSET 8
call __do_softirq
leaveq
CFI_DEF_CFA_REGISTER rsp
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 506f27c..b8a407f 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -103,7 +103,9 @@ skip:
* handlers).
*/
asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
-{
+{
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
/* high bit used in ret_from_ code */
unsigned vector = ~regs->orig_rax;
unsigned irq;
@@ -121,9 +123,10 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
#ifdef CONFIG_DEBUG_STACKOVERFLOW
stack_overflow_check(regs);
#endif
- generic_handle_irq(irq, regs);
+ generic_handle_irq(irq);
irq_exit();
+ set_irq_regs(old_regs);
return 1;
}
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index f760045..b3296cc 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -2,8 +2,9 @@
* Derived from arch/powerpc/kernel/iommu.c
*
* Copyright (C) IBM Corporation, 2006
+ * Copyright (C) 2006 Jon Mason <jdmason@kudzu.us>
*
- * Author: Jon Mason <jdmason@us.ibm.com>
+ * Author: Jon Mason <jdmason@kudzu.us>
* Author: Muli Ben-Yehuda <muli@il.ibm.com>
* This program is free software; you can redistribute it and/or modify
@@ -714,7 +715,7 @@ static void calgary_watchdog(unsigned long data)
/* If no error, the agent ID in the CSR is not valid */
if (val32 & CSR_AGENT_MASK) {
- printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, "
+ printk(KERN_EMERG "calgary_watchdog: DMA error on PHB %#x, "
"CSR = %#x\n", dev->bus->number, val32);
writel(0, target);
@@ -748,7 +749,7 @@ static void __init calgary_enable_translation(struct pci_dev *dev)
val32 = be32_to_cpu(readl(target));
val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE;
- printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum);
+ printk(KERN_INFO "Calgary: enabling translation on PHB %#x\n", busnum);
printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this "
"bus.\n");
@@ -778,7 +779,7 @@ static void __init calgary_disable_translation(struct pci_dev *dev)
val32 = be32_to_cpu(readl(target));
val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE);
- printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum);
+ printk(KERN_INFO "Calgary: disabling translation on PHB %#x!\n", busnum);
writel(cpu_to_be32(val32), target);
readl(target); /* flush */
@@ -790,7 +791,16 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
int rionodeid;
u32 address;
- rionodeid = (dev->bus->number % 15 > 4) ? 3 : 2;
+ /*
+ * Each Calgary has four busses. The first four busses (first Calgary)
+ * have RIO node ID 2, then the next four (second Calgary) have RIO
+ * node ID 3, the next four (third Calgary) have node ID 2 again, etc.
+ * We use a gross hack - relying on the dev->bus->number ordering,
+ * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1,
+ * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the
+ * second (id 3), and then it repeats modulo 14.
+ */
+ rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2;
/*
* register space address calculation as follows:
* FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
@@ -798,7 +808,7 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
* RioNodeId is 2 for first Calgary, 3 for second Calgary
*/
address = START_ADDRESS -
- (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 15)) +
+ (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) +
(0x100000) * (rionodeid - CHASSIS_BASE);
return address;
}
@@ -816,6 +826,8 @@ static int __init calgary_init_one(struct pci_dev *dev)
void __iomem *bbar;
int ret;
+ BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
+
address = locate_register_space(dev);
/* map entire 1MB of Calgary config space */
bbar = ioremap_nocache(address, 1024 * 1024);
@@ -842,10 +854,10 @@ done:
static int __init calgary_init(void)
{
- int i, ret = -ENODEV;
+ int ret = -ENODEV;
struct pci_dev *dev = NULL;
- for (i = 0; i < MAX_PHB_BUS_NUM; i++) {
+ do {
dev = pci_get_device(PCI_VENDOR_ID_IBM,
PCI_DEVICE_ID_IBM_CALGARY,
dev);
@@ -861,12 +873,12 @@ static int __init calgary_init(void)
ret = calgary_init_one(dev);
if (ret)
goto error;
- }
+ } while (1);
return ret;
error:
- for (i--; i >= 0; i--) {
+ do {
dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
PCI_DEVICE_ID_IBM_CALGARY,
dev);
@@ -882,7 +894,7 @@ error:
calgary_disable_translation(dev);
calgary_free_bus(dev);
pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
- }
+ } while (1);
return ret;
}
@@ -1052,7 +1064,7 @@ static int __init calgary_parse_options(char *p)
if (bridge < MAX_PHB_BUS_NUM) {
printk(KERN_INFO "Calgary: disabling "
- "translation for PHB 0x%x\n", bridge);
+ "translation for PHB %#x\n", bridge);
bus_info[bridge].translation_disabled = 1;
}
}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index de10cb8..5e95b25 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -615,6 +615,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
prev->gsindex = gsindex;
}
+ /* Must be after DS reload */
+ unlazy_fpu(prev_p);
+
/*
* Switch the PDA and FPU contexts.
*/
@@ -622,10 +625,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
write_pda(oldrsp, next->userrsp);
write_pda(pcurrent, next_p);
- /* This must be here to ensure both math_state_restore() and
- kernel_fpu_begin() work consistently.
- And the AMD workaround requires it to be after DS reload. */
- unlazy_fpu(prev_p);
write_pda(kernelstack,
(unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
#ifdef CONFIG_CC_STACKPROTECTOR
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 557e92a..1ba5a44 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -302,20 +302,20 @@ unsigned long long monotonic_clock(void)
}
EXPORT_SYMBOL(monotonic_clock);
-static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
+static noinline void handle_lost_ticks(int lost)
{
static long lost_count;
static int warned;
if (report_lost_ticks) {
printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
- print_symbol("rip %s)\n", regs->rip);
+ print_symbol("rip %s)\n", get_irq_regs()->rip);
}
if (lost_count == 1000 && !warned) {
printk(KERN_WARNING "warning: many lost ticks.\n"
KERN_WARNING "Your time source seems to be instable or "
"some driver is hogging interupts\n");
- print_symbol("rip %s\n", regs->rip);
+ print_symbol("rip %s\n", get_irq_regs()->rip);
if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
printk(KERN_WARNING "Falling back to HPET\n");
if (hpet_use_timer)
@@ -339,7 +339,7 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
#endif
}
-void main_timer_handler(struct pt_regs *regs)
+void main_timer_handler(void)
{
static unsigned long rtc_update = 0;
unsigned long tsc;
@@ -411,7 +411,7 @@ void main_timer_handler(struct pt_regs *regs)
}
if (lost > 0)
- handle_lost_ticks(lost, regs);
+ handle_lost_ticks(lost);
else
lost = 0;
@@ -421,7 +421,7 @@ void main_timer_handler(struct pt_regs *regs)
do_timer(lost + 1);
#ifndef CONFIG_SMP
- update_process_times(user_mode(regs));
+ update_process_times(user_mode(get_irq_regs()));
#endif
/*
@@ -431,7 +431,7 @@ void main_timer_handler(struct pt_regs *regs)
*/
if (!using_apic_timer)
- smp_local_timer_interrupt(regs);
+ smp_local_timer_interrupt();
/*
* If we have an externally synchronized Linux clock, then update CMOS clock
@@ -450,11 +450,11 @@ void main_timer_handler(struct pt_regs *regs)
write_sequnlock(&xtime_lock);
}
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
if (apic_runs_main_timer > 1)
return IRQ_HANDLED;
- main_timer_handler(regs);
+ main_timer_handler();
if (using_apic_timer)
smp_send_timer_broadcast_ipi();
return IRQ_HANDLED;
@@ -1337,7 +1337,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (call_rtc_interrupt) {
rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
- rtc_interrupt(rtc_int_flag, dev_id, regs);
+ rtc_interrupt(rtc_int_flag, dev_id);
}
return IRQ_HANDLED;
}
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 01f2a8d..7819022 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/nmi.h>
@@ -115,7 +116,6 @@ static int call_trace = 1;
#endif
#ifdef CONFIG_KALLSYMS
-# include <linux/kallsyms.h>
void printk_address(unsigned long address)
{
unsigned long offset = 0, symsize;