aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-10-05 15:51:43 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-05 15:54:07 -0700
commite03508b43fd93410c1abda2eeabe021de8461f95 (patch)
tree4e06ae2ce0e6a0c5c93a8ad79322ff53a11fc874 /arch/x86_64/kernel
parentd7a297baa6edea94167163bed808c6a8933bd5aa (diff)
parent88271e9e43e65537c6390af3718a60c45c787e8f (diff)
Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: [PATCH] i386: fix rwsem build bug on CONFIG_M386=y [PATCH] x86-64: Annotate interrupt frame backlink in interrupt handlers [PATCH] x86-64: Fix FPU corruption [PATCH] x86: Terminate the kernel stacks for the unwinder [PATCH] i386: Fix PCI BIOS config space access [PATCH] x86-64: Calgary IOMMU: print PCI bus numbers in hex [PATCH] x86-64: Calgary IOMMU: Update Jon's contact info [PATCH] x86-64: Calgary IOMMU: Fix off by one when calculating register space location [PATCH] x86-64: Calgary IOMMU: deobfuscate calgary_init [PATCH] i386: Update defconfig [PATCH] x86-64: Update defconfig [ Manually skipped commits that incorrectly ignored AC in kernel space. The alignment fault is defined to only happen for CPL3 anyway - Linus ]
Diffstat (limited to 'arch/x86_64/kernel')
-rw-r--r--arch/x86_64/kernel/entry.S8
-rw-r--r--arch/x86_64/kernel/pci-calgary.c36
-rw-r--r--arch/x86_64/kernel/process.c7
3 files changed, 35 insertions, 16 deletions
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index b8285cf1a9c..38a7b2d528e 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/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index f760045d6d3..b3296cc2f2f 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 de10cb8a2c9..5e95b257ee2 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