diff options
Diffstat (limited to 'arch')
184 files changed, 2902 insertions, 11789 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3df7cbd924a1..70b007e66926 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -702,6 +702,8 @@ menu "Device Drivers" | |||
702 | 702 | ||
703 | source "drivers/base/Kconfig" | 703 | source "drivers/base/Kconfig" |
704 | 704 | ||
705 | source "drivers/connector/Kconfig" | ||
706 | |||
705 | if ALIGNMENT_TRAP | 707 | if ALIGNMENT_TRAP |
706 | source "drivers/mtd/Kconfig" | 708 | source "drivers/mtd/Kconfig" |
707 | endif | 709 | endif |
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 557e52c1c869..1b7eaab02b9e 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -623,8 +623,6 @@ static int locomo_resume(struct platform_device *dev) | |||
623 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); | 623 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); |
624 | 624 | ||
625 | spin_unlock_irqrestore(&lchip->lock, flags); | 625 | spin_unlock_irqrestore(&lchip->lock, flags); |
626 | |||
627 | dev->power.saved_state = NULL; | ||
628 | kfree(save); | 626 | kfree(save); |
629 | 627 | ||
630 | return 0; | 628 | return 0; |
@@ -775,7 +773,7 @@ static int locomo_probe(struct platform_device *dev) | |||
775 | 773 | ||
776 | static int locomo_remove(struct platform_device *dev) | 774 | static int locomo_remove(struct platform_device *dev) |
777 | { | 775 | { |
778 | struct locomo *lchip = platform__get_drvdata(dev); | 776 | struct locomo *lchip = platform_get_drvdata(dev); |
779 | 777 | ||
780 | if (lchip) { | 778 | if (lchip) { |
781 | __locomo_remove(lchip); | 779 | __locomo_remove(lchip); |
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index 32924c6714fe..0c3cbd9a388b 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c | |||
@@ -153,7 +153,7 @@ int __init scoop_probe(struct platform_device *pdev) | |||
153 | printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); | 153 | printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); |
154 | 154 | ||
155 | SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; | 155 | SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; |
156 | reset_scoop(dev); | 156 | reset_scoop(&pdev->dev); |
157 | SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; | 157 | SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; |
158 | SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; | 158 | SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; |
159 | 159 | ||
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index b0bbd1e62ebb..a2843be05557 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/apm_bios.h> | 20 | #include <linux/apm_bios.h> |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
23 | #include <linux/pm_legacy.h> | ||
23 | #include <linux/device.h> | 24 | #include <linux/device.h> |
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/list.h> | 26 | #include <linux/list.h> |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e55ea952f7aa..373c0959bc2f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -256,9 +256,7 @@ void __cpuexit cpu_die(void) | |||
256 | asmlinkage void __cpuinit secondary_start_kernel(void) | 256 | asmlinkage void __cpuinit secondary_start_kernel(void) |
257 | { | 257 | { |
258 | struct mm_struct *mm = &init_mm; | 258 | struct mm_struct *mm = &init_mm; |
259 | unsigned int cpu; | 259 | unsigned int cpu = smp_processor_id(); |
260 | |||
261 | cpu = smp_processor_id(); | ||
262 | 260 | ||
263 | printk("CPU%u: Booted secondary processor\n", cpu); | 261 | printk("CPU%u: Booted secondary processor\n", cpu); |
264 | 262 | ||
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index dc09fd200c16..bbe6e4a0bf6a 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c | |||
@@ -132,14 +132,14 @@ void __init footbridge_init_irq(void) | |||
132 | static struct map_desc fb_common_io_desc[] __initdata = { | 132 | static struct map_desc fb_common_io_desc[] __initdata = { |
133 | { | 133 | { |
134 | .virtual = ARMCSR_BASE, | 134 | .virtual = ARMCSR_BASE, |
135 | .pfn = DC21285_ARMCSR_BASE, | 135 | .pfn = __phys_to_pfn(DC21285_ARMCSR_BASE), |
136 | .length = ARMCSR_SIZE, | 136 | .length = ARMCSR_SIZE, |
137 | .type = MT_DEVICE | 137 | .type = MT_DEVICE, |
138 | }, { | 138 | }, { |
139 | .virtual = XBUS_BASE, | 139 | .virtual = XBUS_BASE, |
140 | .pfn = __phys_to_pfn(0x40000000), | 140 | .pfn = __phys_to_pfn(0x40000000), |
141 | .length = XBUS_SIZE, | 141 | .length = XBUS_SIZE, |
142 | .type = MT_DEVICE | 142 | .type = MT_DEVICE, |
143 | } | 143 | } |
144 | }; | 144 | }; |
145 | 145 | ||
@@ -153,28 +153,28 @@ static struct map_desc ebsa285_host_io_desc[] __initdata = { | |||
153 | .virtual = PCIMEM_BASE, | 153 | .virtual = PCIMEM_BASE, |
154 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), | 154 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), |
155 | .length = PCIMEM_SIZE, | 155 | .length = PCIMEM_SIZE, |
156 | .type = MT_DEVICE | 156 | .type = MT_DEVICE, |
157 | }, { | 157 | }, { |
158 | .virtual = PCICFG0_BASE, | 158 | .virtual = PCICFG0_BASE, |
159 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG), | 159 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG), |
160 | .length = PCICFG0_SIZE, | 160 | .length = PCICFG0_SIZE, |
161 | .type = MT_DEVICE | 161 | .type = MT_DEVICE, |
162 | }, { | 162 | }, { |
163 | .virtual = PCICFG1_BASE, | 163 | .virtual = PCICFG1_BASE, |
164 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG), | 164 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG), |
165 | .length = PCICFG1_SIZE, | 165 | .length = PCICFG1_SIZE, |
166 | .type = MT_DEVICE | 166 | .type = MT_DEVICE, |
167 | }, { | 167 | }, { |
168 | .virtual = PCIIACK_BASE, | 168 | .virtual = PCIIACK_BASE, |
169 | .pfn = __phys_to_pfn(DC21285_PCI_IACK), | 169 | .pfn = __phys_to_pfn(DC21285_PCI_IACK), |
170 | .length = PCIIACK_SIZE, | 170 | .length = PCIIACK_SIZE, |
171 | .type = MT_DEVICE | 171 | .type = MT_DEVICE, |
172 | }, { | 172 | }, { |
173 | .virtual = PCIO_BASE, | 173 | .virtual = PCIO_BASE, |
174 | .pfn = __phys_to_pfn(DC21285_PCI_IO), | 174 | .pfn = __phys_to_pfn(DC21285_PCI_IO), |
175 | .length = PCIO_SIZE, | 175 | .length = PCIO_SIZE, |
176 | .type = MT_DEVICE | 176 | .type = MT_DEVICE, |
177 | } | 177 | }, |
178 | #endif | 178 | #endif |
179 | }; | 179 | }; |
180 | 180 | ||
@@ -187,13 +187,13 @@ static struct map_desc co285_io_desc[] __initdata = { | |||
187 | .virtual = PCIO_BASE, | 187 | .virtual = PCIO_BASE, |
188 | .pfn = __phys_to_pfn(DC21285_PCI_IO), | 188 | .pfn = __phys_to_pfn(DC21285_PCI_IO), |
189 | .length = PCIO_SIZE, | 189 | .length = PCIO_SIZE, |
190 | .type = MT_DEVICE | 190 | .type = MT_DEVICE, |
191 | }, { | 191 | }, { |
192 | .virtual = PCIMEM_BASE, | 192 | .virtual = PCIMEM_BASE, |
193 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), | 193 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), |
194 | .length = PCIMEM_SIZE, | 194 | .length = PCIMEM_SIZE, |
195 | .type = MT_DEVICE | 195 | .type = MT_DEVICE, |
196 | } | 196 | }, |
197 | #endif | 197 | #endif |
198 | }; | 198 | }; |
199 | 199 | ||
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index e201aa9765b9..cd506646801a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -72,6 +72,12 @@ config MACH_HUSKY | |||
72 | depends PXA_SHARPSL_25x | 72 | depends PXA_SHARPSL_25x |
73 | select PXA_SHARP_C7xx | 73 | select PXA_SHARP_C7xx |
74 | 74 | ||
75 | config MACH_AKITA | ||
76 | bool "Enable Sharp SL-1000 (Akita) Support" | ||
77 | depends PXA_SHARPSL_27x | ||
78 | select PXA_SHARP_Cxx00 | ||
79 | select MACH_SPITZ | ||
80 | |||
75 | config MACH_SPITZ | 81 | config MACH_SPITZ |
76 | bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" | 82 | bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" |
77 | depends PXA_SHARPSL_27x | 83 | depends PXA_SHARPSL_27x |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index d210bd5032ce..32526a0a6f86 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
@@ -11,8 +11,9 @@ obj-$(CONFIG_PXA27x) += pxa27x.o | |||
11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o | 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o |
12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o | 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o |
13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o | 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o |
14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o | 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o |
15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o | 15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o |
16 | obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o | ||
16 | obj-$(CONFIG_MACH_POODLE) += poodle.o | 17 | obj-$(CONFIG_MACH_POODLE) += poodle.o |
17 | obj-$(CONFIG_MACH_TOSA) += tosa.o | 18 | obj-$(CONFIG_MACH_TOSA) += tosa.o |
18 | 19 | ||
diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c new file mode 100644 index 000000000000..f6d73cc01f78 --- /dev/null +++ b/arch/arm/mach-pxa/akita-ioexp.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Support for the Extra GPIOs on the Sharp SL-C1000 (Akita) | ||
3 | * (uses a Maxim MAX7310 8 Port IO Expander) | ||
4 | * | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * | ||
7 | * Author: Richard Purdie <richard@openedhand.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <asm/arch/akita.h> | ||
23 | |||
24 | /* MAX7310 Regiser Map */ | ||
25 | #define MAX7310_INPUT 0x00 | ||
26 | #define MAX7310_OUTPUT 0x01 | ||
27 | #define MAX7310_POLINV 0x02 | ||
28 | #define MAX7310_IODIR 0x03 /* 1 = Input, 0 = Output */ | ||
29 | #define MAX7310_TIMEOUT 0x04 | ||
30 | |||
31 | /* Addresses to scan */ | ||
32 | static unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END }; | ||
33 | |||
34 | /* I2C Magic */ | ||
35 | I2C_CLIENT_INSMOD; | ||
36 | |||
37 | static int max7310_write(struct i2c_client *client, int address, int data); | ||
38 | static struct i2c_client max7310_template; | ||
39 | static void akita_ioexp_work(void *private_); | ||
40 | |||
41 | static struct device *akita_ioexp_device; | ||
42 | static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT; | ||
43 | DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL); | ||
44 | |||
45 | |||
46 | /* | ||
47 | * MAX7310 Access | ||
48 | */ | ||
49 | static int max7310_config(struct device *dev, int iomode, int polarity) | ||
50 | { | ||
51 | int ret; | ||
52 | struct i2c_client *client = to_i2c_client(dev); | ||
53 | |||
54 | ret = max7310_write(client, MAX7310_POLINV, polarity); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | ret = max7310_write(client, MAX7310_IODIR, iomode); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static int max7310_set_ouputs(struct device *dev, int outputs) | ||
62 | { | ||
63 | struct i2c_client *client = to_i2c_client(dev); | ||
64 | |||
65 | return max7310_write(client, MAX7310_OUTPUT, outputs); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * I2C Functions | ||
70 | */ | ||
71 | static int max7310_write(struct i2c_client *client, int address, int value) | ||
72 | { | ||
73 | u8 data[2]; | ||
74 | |||
75 | data[0] = address & 0xff; | ||
76 | data[1] = value & 0xff; | ||
77 | |||
78 | if (i2c_master_send(client, data, 2) == 2) | ||
79 | return 0; | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | static int max7310_detect(struct i2c_adapter *adapter, int address, int kind) | ||
84 | { | ||
85 | struct i2c_client *new_client; | ||
86 | int err; | ||
87 | |||
88 | if (!(new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | max7310_template.adapter = adapter; | ||
92 | max7310_template.addr = address; | ||
93 | |||
94 | memcpy(new_client, &max7310_template, sizeof(struct i2c_client)); | ||
95 | |||
96 | if ((err = i2c_attach_client(new_client))) { | ||
97 | kfree(new_client); | ||
98 | return err; | ||
99 | } | ||
100 | |||
101 | max7310_config(&new_client->dev, AKITA_IOEXP_IO_DIR, 0); | ||
102 | akita_ioexp_device = &new_client->dev; | ||
103 | schedule_work(&akita_ioexp); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int max7310_attach_adapter(struct i2c_adapter *adapter) | ||
109 | { | ||
110 | return i2c_probe(adapter, &addr_data, max7310_detect); | ||
111 | } | ||
112 | |||
113 | static int max7310_detach_client(struct i2c_client *client) | ||
114 | { | ||
115 | int err; | ||
116 | |||
117 | akita_ioexp_device = NULL; | ||
118 | |||
119 | if ((err = i2c_detach_client(client))) | ||
120 | return err; | ||
121 | |||
122 | kfree(client); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static struct i2c_driver max7310_i2c_driver = { | ||
127 | .owner = THIS_MODULE, | ||
128 | .name = "akita-max7310", | ||
129 | .id = I2C_DRIVERID_AKITAIOEXP, | ||
130 | .flags = I2C_DF_NOTIFY, | ||
131 | .attach_adapter = max7310_attach_adapter, | ||
132 | .detach_client = max7310_detach_client, | ||
133 | }; | ||
134 | |||
135 | static struct i2c_client max7310_template = { | ||
136 | name: "akita-max7310", | ||
137 | flags: I2C_CLIENT_ALLOW_USE, | ||
138 | driver: &max7310_i2c_driver, | ||
139 | }; | ||
140 | |||
141 | void akita_set_ioexp(struct device *dev, unsigned char bit) | ||
142 | { | ||
143 | ioexp_output_value |= bit; | ||
144 | |||
145 | if (akita_ioexp_device) | ||
146 | schedule_work(&akita_ioexp); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | void akita_reset_ioexp(struct device *dev, unsigned char bit) | ||
151 | { | ||
152 | ioexp_output_value &= ~bit; | ||
153 | |||
154 | if (akita_ioexp_device) | ||
155 | schedule_work(&akita_ioexp); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | EXPORT_SYMBOL(akita_set_ioexp); | ||
160 | EXPORT_SYMBOL(akita_reset_ioexp); | ||
161 | |||
162 | static void akita_ioexp_work(void *private_) | ||
163 | { | ||
164 | if (akita_ioexp_device) | ||
165 | max7310_set_ouputs(akita_ioexp_device, ioexp_output_value); | ||
166 | } | ||
167 | |||
168 | |||
169 | #ifdef CONFIG_PM | ||
170 | static int akita_ioexp_suspend(struct platform_device *pdev, pm_message_t state) | ||
171 | { | ||
172 | flush_scheduled_work(); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int akita_ioexp_resume(struct platform_device *pdev) | ||
177 | { | ||
178 | schedule_work(&akita_ioexp); | ||
179 | return 0; | ||
180 | } | ||
181 | #else | ||
182 | #define akita_ioexp_suspend NULL | ||
183 | #define akita_ioexp_resume NULL | ||
184 | #endif | ||
185 | |||
186 | static int __init akita_ioexp_probe(struct platform_device *pdev) | ||
187 | { | ||
188 | return i2c_add_driver(&max7310_i2c_driver); | ||
189 | } | ||
190 | |||
191 | static int akita_ioexp_remove(struct platform_device *pdev) | ||
192 | { | ||
193 | i2c_del_driver(&max7310_i2c_driver); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static struct platform_driver akita_ioexp_driver = { | ||
198 | .probe = akita_ioexp_probe, | ||
199 | .remove = akita_ioexp_remove, | ||
200 | .suspend = akita_ioexp_suspend, | ||
201 | .resume = akita_ioexp_resume, | ||
202 | .driver = { | ||
203 | .name = "akita-ioexp", | ||
204 | }, | ||
205 | }; | ||
206 | |||
207 | static int __init akita_ioexp_init(void) | ||
208 | { | ||
209 | return platform_driver_register(&akita_ioexp_driver); | ||
210 | } | ||
211 | |||
212 | static void __exit akita_ioexp_exit(void) | ||
213 | { | ||
214 | platform_driver_unregister(&akita_ioexp_driver); | ||
215 | } | ||
216 | |||
217 | MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); | ||
218 | MODULE_DESCRIPTION("Akita IO-Expander driver"); | ||
219 | MODULE_LICENSE("GPL"); | ||
220 | |||
221 | fs_initcall(akita_ioexp_init); | ||
222 | module_exit(akita_ioexp_exit); | ||
223 | |||
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c new file mode 100644 index 000000000000..599be14754f9 --- /dev/null +++ b/arch/arm/mach-pxa/corgi_pm.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-C7xx | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/apm.h> | ||
20 | #include <asm/irq.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/hardware/scoop.h> | ||
24 | |||
25 | #include <asm/arch/sharpsl.h> | ||
26 | #include <asm/arch/corgi.h> | ||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include "sharpsl.h" | ||
29 | |||
30 | static void corgi_charger_init(void) | ||
31 | { | ||
32 | pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT); | ||
33 | pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT); | ||
34 | pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT); | ||
35 | pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN); | ||
36 | } | ||
37 | |||
38 | static void corgi_charge_led(int val) | ||
39 | { | ||
40 | if (val == SHARPSL_LED_ERROR) { | ||
41 | dev_dbg(sharpsl_pm.dev, "Charge LED Error\n"); | ||
42 | } else if (val == SHARPSL_LED_ON) { | ||
43 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | ||
44 | GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
45 | } else { | ||
46 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | ||
47 | GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void corgi_measure_temp(int on) | ||
52 | { | ||
53 | if (on) | ||
54 | GPSR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); | ||
55 | else | ||
56 | GPCR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); | ||
57 | } | ||
58 | |||
59 | static void corgi_charge(int on) | ||
60 | { | ||
61 | if (on) { | ||
62 | if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) { | ||
63 | GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
64 | GPSR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
65 | } else { | ||
66 | GPSR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
67 | GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
68 | } | ||
69 | } else { | ||
70 | GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
71 | GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static void corgi_discharge(int on) | ||
76 | { | ||
77 | if (on) | ||
78 | GPSR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); | ||
79 | else | ||
80 | GPCR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); | ||
81 | } | ||
82 | |||
83 | static void corgi_presuspend(void) | ||
84 | { | ||
85 | int i; | ||
86 | unsigned long wakeup_mask; | ||
87 | |||
88 | /* charging , so CHARGE_ON bit is HIGH during OFF. */ | ||
89 | if (READ_GPIO_BIT(CORGI_GPIO_CHRG_ON)) | ||
90 | PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
91 | else | ||
92 | PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
93 | |||
94 | if (READ_GPIO_BIT(CORGI_GPIO_LED_ORANGE)) | ||
95 | PGSR0 |= GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
96 | else | ||
97 | PGSR0 &= ~GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
98 | |||
99 | if (READ_GPIO_BIT(CORGI_GPIO_CHRG_UKN)) | ||
100 | PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
101 | else | ||
102 | PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
103 | |||
104 | /* Resume on keyboard power key */ | ||
105 | PGSR2 = (PGSR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(0); | ||
106 | |||
107 | wakeup_mask = GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) | GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_CHRG_FULL); | ||
108 | |||
109 | if (!machine_is_corgi()) | ||
110 | wakeup_mask |= GPIO_bit(CORGI_GPIO_MAIN_BAT_LOW); | ||
111 | |||
112 | PWER = wakeup_mask | PWER_RTC; | ||
113 | PRER = wakeup_mask; | ||
114 | PFER = wakeup_mask; | ||
115 | |||
116 | for (i = 0; i <=15; i++) { | ||
117 | if (PRER & PFER & GPIO_bit(i)) { | ||
118 | if (GPLR0 & GPIO_bit(i) ) | ||
119 | PRER &= ~GPIO_bit(i); | ||
120 | else | ||
121 | PFER &= ~GPIO_bit(i); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void corgi_postsuspend(void) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Check what brought us out of the suspend. | ||
132 | * Return: 0 to sleep, otherwise wake | ||
133 | */ | ||
134 | static int corgi_should_wakeup(unsigned int resume_on_alarm) | ||
135 | { | ||
136 | int is_resume = 0; | ||
137 | |||
138 | dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR); | ||
139 | |||
140 | if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) { | ||
141 | if (STATUS_AC_IN()) { | ||
142 | /* charge on */ | ||
143 | dev_dbg(sharpsl_pm.dev, "ac insert\n"); | ||
144 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
145 | } else { | ||
146 | /* charge off */ | ||
147 | dev_dbg(sharpsl_pm.dev, "ac remove\n"); | ||
148 | CHARGE_LED_OFF(); | ||
149 | CHARGE_OFF(); | ||
150 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | if ((PEDR & GPIO_bit(CORGI_GPIO_CHRG_FULL))) | ||
155 | dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n"); | ||
156 | |||
157 | if (PEDR & GPIO_bit(CORGI_GPIO_KEY_INT)) | ||
158 | is_resume |= GPIO_bit(CORGI_GPIO_KEY_INT); | ||
159 | |||
160 | if (PEDR & GPIO_bit(CORGI_GPIO_WAKEUP)) | ||
161 | is_resume |= GPIO_bit(CORGI_GPIO_WAKEUP); | ||
162 | |||
163 | if (resume_on_alarm && (PEDR & PWER_RTC)) | ||
164 | is_resume |= PWER_RTC; | ||
165 | |||
166 | dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); | ||
167 | return is_resume; | ||
168 | } | ||
169 | |||
170 | static unsigned long corgi_charger_wakeup(void) | ||
171 | { | ||
172 | return ~GPLR0 & ( GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) ); | ||
173 | } | ||
174 | |||
175 | static int corgi_acin_status(void) | ||
176 | { | ||
177 | return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0); | ||
178 | } | ||
179 | |||
180 | static struct sharpsl_charger_machinfo corgi_pm_machinfo = { | ||
181 | .init = corgi_charger_init, | ||
182 | .gpio_batlock = CORGI_GPIO_BAT_COVER, | ||
183 | .gpio_acin = CORGI_GPIO_AC_IN, | ||
184 | .gpio_batfull = CORGI_GPIO_CHRG_FULL, | ||
185 | .status_acin = corgi_acin_status, | ||
186 | .discharge = corgi_discharge, | ||
187 | .charge = corgi_charge, | ||
188 | .chargeled = corgi_charge_led, | ||
189 | .measure_temp = corgi_measure_temp, | ||
190 | .presuspend = corgi_presuspend, | ||
191 | .postsuspend = corgi_postsuspend, | ||
192 | .charger_wakeup = corgi_charger_wakeup, | ||
193 | .should_wakeup = corgi_should_wakeup, | ||
194 | .bat_levels = 40, | ||
195 | .bat_levels_noac = spitz_battery_levels_noac, | ||
196 | .bat_levels_acin = spitz_battery_levels_acin, | ||
197 | .status_high_acin = 188, | ||
198 | .status_low_acin = 178, | ||
199 | .status_high_noac = 185, | ||
200 | .status_low_noac = 175, | ||
201 | }; | ||
202 | |||
203 | static struct platform_device *corgipm_device; | ||
204 | |||
205 | static int __devinit corgipm_init(void) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | corgipm_device = platform_device_alloc("sharpsl-pm", -1); | ||
210 | if (!corgipm_device) | ||
211 | return -ENOMEM; | ||
212 | |||
213 | corgipm_device->dev.platform_data = &corgi_pm_machinfo; | ||
214 | ret = platform_device_add(corgipm_device); | ||
215 | |||
216 | if (ret) | ||
217 | platform_device_put(corgipm_device); | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static void corgipm_exit(void) | ||
223 | { | ||
224 | platform_device_unregister(corgipm_device); | ||
225 | } | ||
226 | |||
227 | module_init(corgipm_init); | ||
228 | module_exit(corgipm_exit); | ||
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h index 4879c0f7da72..b0c40a1d6671 100644 --- a/arch/arm/mach-pxa/sharpsl.h +++ b/arch/arm/mach-pxa/sharpsl.h | |||
@@ -115,7 +115,7 @@ extern struct battery_thresh spitz_battery_levels_noac[]; | |||
115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) | 115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) |
116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) | 116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) |
117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) | 117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) |
118 | #define STATUS_AC_IN sharpsl_pm.machinfo->status_acin() | 118 | #define STATUS_AC_IN() sharpsl_pm.machinfo->status_acin() |
119 | #define STATUS_BATT_LOCKED READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) | 119 | #define STATUS_BATT_LOCKED() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) |
120 | #define STATUS_CHRG_FULL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) | 120 | #define STATUS_CHRG_FULL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) |
121 | #define STATUS_FATAL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) | 121 | #define STATUS_FATAL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) |
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 6c9e871c53d8..c10be00fb526 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/apm_bios.h> | 21 | #include <linux/apm_bios.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/hardware.h> | 26 | #include <asm/hardware.h> |
27 | #include <asm/hardware/scoop.h> | 27 | #include <asm/hardware/scoop.h> |
@@ -45,15 +45,15 @@ | |||
45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ | 45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ |
46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ | 46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ |
47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ | 47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ |
48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD 10 /* 10 msec */ | 48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */ |
49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ | 49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ |
50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ | 50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ |
51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ | 51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ |
52 | 52 | ||
53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ | 53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ |
54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ | 54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ |
55 | #define SHARPSL_CHARGE_ON_JKVAD_HIGH 0x9b /* 6V */ | 55 | #define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ |
56 | #define SHARPSL_CHARGE_ON_JKVAD_LOW 0x34 /* 2V */ | 56 | #define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ |
57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ | 57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ |
58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ | 58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ |
59 | 59 | ||
@@ -160,9 +160,10 @@ struct battery_thresh spitz_battery_levels_noac[] = { | |||
160 | /* | 160 | /* |
161 | * Prototypes | 161 | * Prototypes |
162 | */ | 162 | */ |
163 | static int sharpsl_read_MainBattery(void); | 163 | static int sharpsl_read_main_battery(void); |
164 | static int sharpsl_off_charge_battery(void); | 164 | static int sharpsl_off_charge_battery(void); |
165 | static int sharpsl_check_battery(int mode); | 165 | static int sharpsl_check_battery_temp(void); |
166 | static int sharpsl_check_battery_voltage(void); | ||
166 | static int sharpsl_ac_check(void); | 167 | static int sharpsl_ac_check(void); |
167 | static int sharpsl_fatal_check(void); | 168 | static int sharpsl_fatal_check(void); |
168 | static int sharpsl_average_value(int ad); | 169 | static int sharpsl_average_value(int ad); |
@@ -228,7 +229,7 @@ static void sharpsl_battery_thread(void *private_) | |||
228 | if (!sharpsl_pm.machinfo) | 229 | if (!sharpsl_pm.machinfo) |
229 | return; | 230 | return; |
230 | 231 | ||
231 | sharpsl_pm.battstat.ac_status = (!(STATUS_AC_IN) ? APM_AC_OFFLINE : APM_AC_ONLINE); | 232 | sharpsl_pm.battstat.ac_status = (STATUS_AC_IN() ? APM_AC_ONLINE : APM_AC_OFFLINE); |
232 | 233 | ||
233 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ | 234 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ |
234 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) | 235 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) |
@@ -236,7 +237,7 @@ static void sharpsl_battery_thread(void *private_) | |||
236 | schedule_work(&toggle_charger); | 237 | schedule_work(&toggle_charger); |
237 | 238 | ||
238 | while(1) { | 239 | while(1) { |
239 | voltage = sharpsl_read_MainBattery(); | 240 | voltage = sharpsl_read_main_battery(); |
240 | if (voltage > 0) break; | 241 | if (voltage > 0) break; |
241 | if (i++ > 5) { | 242 | if (i++ > 5) { |
242 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; | 243 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; |
@@ -317,10 +318,10 @@ static void sharpsl_charge_toggle(void *private_) | |||
317 | { | 318 | { |
318 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); | 319 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); |
319 | 320 | ||
320 | if (STATUS_AC_IN == 0) { | 321 | if (STATUS_AC_IN() == 0) { |
321 | sharpsl_charge_off(); | 322 | sharpsl_charge_off(); |
322 | return; | 323 | return; |
323 | } else if ((sharpsl_check_battery(1) < 0) || (sharpsl_ac_check() < 0)) { | 324 | } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) { |
324 | sharpsl_charge_error(); | 325 | sharpsl_charge_error(); |
325 | return; | 326 | return; |
326 | } | 327 | } |
@@ -335,7 +336,7 @@ static void sharpsl_charge_toggle(void *private_) | |||
335 | 336 | ||
336 | static void sharpsl_ac_timer(unsigned long data) | 337 | static void sharpsl_ac_timer(unsigned long data) |
337 | { | 338 | { |
338 | int acin = STATUS_AC_IN; | 339 | int acin = STATUS_AC_IN(); |
339 | 340 | ||
340 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); | 341 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); |
341 | 342 | ||
@@ -364,7 +365,7 @@ static void sharpsl_chrg_full_timer(unsigned long data) | |||
364 | 365 | ||
365 | sharpsl_pm.full_count++; | 366 | sharpsl_pm.full_count++; |
366 | 367 | ||
367 | if (STATUS_AC_IN == 0) { | 368 | if (STATUS_AC_IN() == 0) { |
368 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); | 369 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); |
369 | if (sharpsl_pm.charge_mode == CHRG_ON) | 370 | if (sharpsl_pm.charge_mode == CHRG_ON) |
370 | sharpsl_charge_off(); | 371 | sharpsl_charge_off(); |
@@ -399,12 +400,12 @@ static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp) | |||
399 | { | 400 | { |
400 | int is_fatal = 0; | 401 | int is_fatal = 0; |
401 | 402 | ||
402 | if (STATUS_BATT_LOCKED == 0) { | 403 | if (STATUS_BATT_LOCKED() == 0) { |
403 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); | 404 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); |
404 | is_fatal = 1; | 405 | is_fatal = 1; |
405 | } | 406 | } |
406 | 407 | ||
407 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL == 0)) { | 408 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL() == 0)) { |
408 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); | 409 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); |
409 | is_fatal = 1; | 410 | is_fatal = 1; |
410 | } | 411 | } |
@@ -461,12 +462,12 @@ static int read_max1111(int channel) | |||
461 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); | 462 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); |
462 | } | 463 | } |
463 | 464 | ||
464 | static int sharpsl_read_MainBattery(void) | 465 | static int sharpsl_read_main_battery(void) |
465 | { | 466 | { |
466 | return read_max1111(BATT_AD); | 467 | return read_max1111(BATT_AD); |
467 | } | 468 | } |
468 | 469 | ||
469 | static int sharpsl_read_Temp(void) | 470 | static int sharpsl_read_temp(void) |
470 | { | 471 | { |
471 | int temp; | 472 | int temp; |
472 | 473 | ||
@@ -480,7 +481,7 @@ static int sharpsl_read_Temp(void) | |||
480 | return temp; | 481 | return temp; |
481 | } | 482 | } |
482 | 483 | ||
483 | static int sharpsl_read_jkvad(void) | 484 | static int sharpsl_read_acin(void) |
484 | { | 485 | { |
485 | return read_max1111(JK_VAD); | 486 | return read_max1111(JK_VAD); |
486 | } | 487 | } |
@@ -522,16 +523,14 @@ static int get_select_val(int *val) | |||
522 | return (sum/3); | 523 | return (sum/3); |
523 | } | 524 | } |
524 | 525 | ||
525 | /* mode 0 - Check temperature and voltage | 526 | static int sharpsl_check_battery_temp(void) |
526 | * 1 - Check temperature only */ | ||
527 | static int sharpsl_check_battery(int mode) | ||
528 | { | 527 | { |
529 | int val, i, buff[5]; | 528 | int val, i, buff[5]; |
530 | 529 | ||
531 | /* Check battery temperature */ | 530 | /* Check battery temperature */ |
532 | for (i=0; i<5; i++) { | 531 | for (i=0; i<5; i++) { |
533 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); | 532 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); |
534 | buff[i] = sharpsl_read_Temp(); | 533 | buff[i] = sharpsl_read_temp(); |
535 | } | 534 | } |
536 | 535 | ||
537 | val = get_select_val(buff); | 536 | val = get_select_val(buff); |
@@ -539,8 +538,13 @@ static int sharpsl_check_battery(int mode) | |||
539 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); | 538 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); |
540 | if (val > SHARPSL_CHARGE_ON_TEMP) | 539 | if (val > SHARPSL_CHARGE_ON_TEMP) |
541 | return -1; | 540 | return -1; |
542 | if (mode == 1) | 541 | |
543 | return 0; | 542 | return 0; |
543 | } | ||
544 | |||
545 | static int sharpsl_check_battery_voltage(void) | ||
546 | { | ||
547 | int val, i, buff[5]; | ||
544 | 548 | ||
545 | /* disable charge, enable discharge */ | 549 | /* disable charge, enable discharge */ |
546 | CHARGE_OFF(); | 550 | CHARGE_OFF(); |
@@ -552,7 +556,7 @@ static int sharpsl_check_battery(int mode) | |||
552 | 556 | ||
553 | /* Check battery voltage */ | 557 | /* Check battery voltage */ |
554 | for (i=0; i<5; i++) { | 558 | for (i=0; i<5; i++) { |
555 | buff[i] = sharpsl_read_MainBattery(); | 559 | buff[i] = sharpsl_read_main_battery(); |
556 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | 560 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); |
557 | } | 561 | } |
558 | 562 | ||
@@ -575,14 +579,14 @@ static int sharpsl_ac_check(void) | |||
575 | int temp, i, buff[5]; | 579 | int temp, i, buff[5]; |
576 | 580 | ||
577 | for (i=0; i<5; i++) { | 581 | for (i=0; i<5; i++) { |
578 | buff[i] = sharpsl_read_jkvad(); | 582 | buff[i] = sharpsl_read_acin(); |
579 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD); | 583 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); |
580 | } | 584 | } |
581 | 585 | ||
582 | temp = get_select_val(buff); | 586 | temp = get_select_val(buff); |
583 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); | 587 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); |
584 | 588 | ||
585 | if ((temp > SHARPSL_CHARGE_ON_JKVAD_HIGH) || (temp < SHARPSL_CHARGE_ON_JKVAD_LOW)) { | 589 | if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) { |
586 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); | 590 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); |
587 | return -1; | 591 | return -1; |
588 | } | 592 | } |
@@ -591,7 +595,7 @@ static int sharpsl_ac_check(void) | |||
591 | } | 595 | } |
592 | 596 | ||
593 | #ifdef CONFIG_PM | 597 | #ifdef CONFIG_PM |
594 | static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | 598 | static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) |
595 | { | 599 | { |
596 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; | 600 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; |
597 | flush_scheduled_work(); | 601 | flush_scheduled_work(); |
@@ -604,7 +608,7 @@ static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | |||
604 | return 0; | 608 | return 0; |
605 | } | 609 | } |
606 | 610 | ||
607 | static int sharpsl_pm_resume(struct device *dev) | 611 | static int sharpsl_pm_resume(struct platform_device *pdev) |
608 | { | 612 | { |
609 | /* Clear the reset source indicators as they break the bootloader upon reboot */ | 613 | /* Clear the reset source indicators as they break the bootloader upon reboot */ |
610 | RCSR = 0x0f; | 614 | RCSR = 0x0f; |
@@ -622,7 +626,7 @@ static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable | |||
622 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); | 626 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); |
623 | /* not charging and AC-IN! */ | 627 | /* not charging and AC-IN! */ |
624 | 628 | ||
625 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN != 0)) { | 629 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN() != 0)) { |
626 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); | 630 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); |
627 | sharpsl_pm.charge_mode = CHRG_OFF; | 631 | sharpsl_pm.charge_mode = CHRG_OFF; |
628 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; | 632 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; |
@@ -671,7 +675,7 @@ static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enab | |||
671 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); | 675 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); |
672 | } | 676 | } |
673 | 677 | ||
674 | if ((STATUS_BATT_LOCKED == 0) || (sharpsl_fatal_check() < 0) ) | 678 | if ((STATUS_BATT_LOCKED() == 0) || (sharpsl_fatal_check() < 0) ) |
675 | { | 679 | { |
676 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); | 680 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); |
677 | corgi_goto_sleep(alarm_time, alarm_enable, state); | 681 | corgi_goto_sleep(alarm_time, alarm_enable, state); |
@@ -711,7 +715,7 @@ static int sharpsl_fatal_check(void) | |||
711 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); | 715 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); |
712 | 716 | ||
713 | /* Check AC-Adapter */ | 717 | /* Check AC-Adapter */ |
714 | acin = STATUS_AC_IN; | 718 | acin = STATUS_AC_IN(); |
715 | 719 | ||
716 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { | 720 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { |
717 | CHARGE_OFF(); | 721 | CHARGE_OFF(); |
@@ -725,7 +729,7 @@ static int sharpsl_fatal_check(void) | |||
725 | 729 | ||
726 | /* Check battery : check inserting battery ? */ | 730 | /* Check battery : check inserting battery ? */ |
727 | for (i=0; i<5; i++) { | 731 | for (i=0; i<5; i++) { |
728 | buff[i] = sharpsl_read_MainBattery(); | 732 | buff[i] = sharpsl_read_main_battery(); |
729 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | 733 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); |
730 | } | 734 | } |
731 | 735 | ||
@@ -739,7 +743,7 @@ static int sharpsl_fatal_check(void) | |||
739 | } | 743 | } |
740 | 744 | ||
741 | temp = get_select_val(buff); | 745 | temp = get_select_val(buff); |
742 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_MainBattery()); | 746 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_main_battery()); |
743 | 747 | ||
744 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || | 748 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || |
745 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) | 749 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) |
@@ -771,7 +775,7 @@ static int sharpsl_off_charge_battery(void) | |||
771 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); | 775 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); |
772 | 776 | ||
773 | /* AC Check */ | 777 | /* AC Check */ |
774 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery(1) < 0)) | 778 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) |
775 | return sharpsl_off_charge_error(); | 779 | return sharpsl_off_charge_error(); |
776 | 780 | ||
777 | /* Start Charging */ | 781 | /* Start Charging */ |
@@ -793,7 +797,7 @@ static int sharpsl_off_charge_battery(void) | |||
793 | 797 | ||
794 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); | 798 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); |
795 | 799 | ||
796 | if (sharpsl_check_battery(0) < 0) | 800 | if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) |
797 | return sharpsl_off_charge_error(); | 801 | return sharpsl_off_charge_error(); |
798 | 802 | ||
799 | CHARGE_OFF(); | 803 | CHARGE_OFF(); |
@@ -811,7 +815,7 @@ static int sharpsl_off_charge_battery(void) | |||
811 | /* Check for timeout */ | 815 | /* Check for timeout */ |
812 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) | 816 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) |
813 | return 1; | 817 | return 1; |
814 | if (STATUS_CHRG_FULL) { | 818 | if (STATUS_CHRG_FULL()) { |
815 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); | 819 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); |
816 | sharpsl_pm.full_count++; | 820 | sharpsl_pm.full_count++; |
817 | CHARGE_OFF(); | 821 | CHARGE_OFF(); |
@@ -840,7 +844,7 @@ static int sharpsl_off_charge_battery(void) | |||
840 | sharpsl_pm.full_count++; | 844 | sharpsl_pm.full_count++; |
841 | return 1; | 845 | return 1; |
842 | } | 846 | } |
843 | if (STATUS_CHRG_FULL) { | 847 | if (STATUS_CHRG_FULL()) { |
844 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); | 848 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); |
845 | CHARGE_LED_OFF(); | 849 | CHARGE_LED_OFF(); |
846 | CHARGE_OFF(); | 850 | CHARGE_OFF(); |
@@ -886,13 +890,13 @@ static struct pm_ops sharpsl_pm_ops = { | |||
886 | .finish = pxa_pm_finish, | 890 | .finish = pxa_pm_finish, |
887 | }; | 891 | }; |
888 | 892 | ||
889 | static int __init sharpsl_pm_probe(struct device *dev) | 893 | static int __init sharpsl_pm_probe(struct platform_device *pdev) |
890 | { | 894 | { |
891 | if (!dev->platform_data) | 895 | if (!pdev->dev.platform_data) |
892 | return -EINVAL; | 896 | return -EINVAL; |
893 | 897 | ||
894 | sharpsl_pm.dev = dev; | 898 | sharpsl_pm.dev = &pdev->dev; |
895 | sharpsl_pm.machinfo = dev->platform_data; | 899 | sharpsl_pm.machinfo = pdev->dev.platform_data; |
896 | sharpsl_pm.charge_mode = CHRG_OFF; | 900 | sharpsl_pm.charge_mode = CHRG_OFF; |
897 | sharpsl_pm.flags = 0; | 901 | sharpsl_pm.flags = 0; |
898 | 902 | ||
@@ -935,8 +939,8 @@ static int __init sharpsl_pm_probe(struct device *dev) | |||
935 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); | 939 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); |
936 | } | 940 | } |
937 | 941 | ||
938 | device_create_file(dev, &dev_attr_battery_percentage); | 942 | device_create_file(&pdev->dev, &dev_attr_battery_percentage); |
939 | device_create_file(dev, &dev_attr_battery_voltage); | 943 | device_create_file(&pdev->dev, &dev_attr_battery_voltage); |
940 | 944 | ||
941 | apm_get_power_status = sharpsl_apm_get_power_status; | 945 | apm_get_power_status = sharpsl_apm_get_power_status; |
942 | 946 | ||
@@ -947,12 +951,12 @@ static int __init sharpsl_pm_probe(struct device *dev) | |||
947 | return 0; | 951 | return 0; |
948 | } | 952 | } |
949 | 953 | ||
950 | static int sharpsl_pm_remove(struct device *dev) | 954 | static int sharpsl_pm_remove(struct platform_device *pdev) |
951 | { | 955 | { |
952 | pm_set_ops(NULL); | 956 | pm_set_ops(NULL); |
953 | 957 | ||
954 | device_remove_file(dev, &dev_attr_battery_percentage); | 958 | device_remove_file(&pdev->dev, &dev_attr_battery_percentage); |
955 | device_remove_file(dev, &dev_attr_battery_voltage); | 959 | device_remove_file(&pdev->dev, &dev_attr_battery_voltage); |
956 | 960 | ||
957 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); | 961 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); |
958 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); | 962 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); |
@@ -969,23 +973,24 @@ static int sharpsl_pm_remove(struct device *dev) | |||
969 | return 0; | 973 | return 0; |
970 | } | 974 | } |
971 | 975 | ||
972 | static struct device_driver sharpsl_pm_driver = { | 976 | static struct platform_driver sharpsl_pm_driver = { |
973 | .name = "sharpsl-pm", | ||
974 | .bus = &platform_bus_type, | ||
975 | .probe = sharpsl_pm_probe, | 977 | .probe = sharpsl_pm_probe, |
976 | .remove = sharpsl_pm_remove, | 978 | .remove = sharpsl_pm_remove, |
977 | .suspend = sharpsl_pm_suspend, | 979 | .suspend = sharpsl_pm_suspend, |
978 | .resume = sharpsl_pm_resume, | 980 | .resume = sharpsl_pm_resume, |
981 | .driver = { | ||
982 | .name = "sharpsl-pm", | ||
983 | }, | ||
979 | }; | 984 | }; |
980 | 985 | ||
981 | static int __devinit sharpsl_pm_init(void) | 986 | static int __devinit sharpsl_pm_init(void) |
982 | { | 987 | { |
983 | return driver_register(&sharpsl_pm_driver); | 988 | return platform_driver_register(&sharpsl_pm_driver); |
984 | } | 989 | } |
985 | 990 | ||
986 | static void sharpsl_pm_exit(void) | 991 | static void sharpsl_pm_exit(void) |
987 | { | 992 | { |
988 | driver_unregister(&sharpsl_pm_driver); | 993 | platform_driver_unregister(&sharpsl_pm_driver); |
989 | } | 994 | } |
990 | 995 | ||
991 | late_initcall(sharpsl_pm_init); | 996 | late_initcall(sharpsl_pm_init); |
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 4e9a699ee428..2df1b56615b1 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c | |||
@@ -345,6 +345,16 @@ static void spitz_irda_transceiver_mode(struct device *dev, int mode) | |||
345 | reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); | 345 | reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); |
346 | } | 346 | } |
347 | 347 | ||
348 | #ifdef CONFIG_MACH_AKITA | ||
349 | static void akita_irda_transceiver_mode(struct device *dev, int mode) | ||
350 | { | ||
351 | if (mode & IR_OFF) | ||
352 | akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON); | ||
353 | else | ||
354 | akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON); | ||
355 | } | ||
356 | #endif | ||
357 | |||
348 | static struct pxaficp_platform_data spitz_ficp_platform_data = { | 358 | static struct pxaficp_platform_data spitz_ficp_platform_data = { |
349 | .transceiver_cap = IR_SIRMODE | IR_OFF, | 359 | .transceiver_cap = IR_SIRMODE | IR_OFF, |
350 | .transceiver_mode = spitz_irda_transceiver_mode, | 360 | .transceiver_mode = spitz_irda_transceiver_mode, |
@@ -417,6 +427,32 @@ static void __init spitz_init(void) | |||
417 | platform_device_register(&spitzscoop2_device); | 427 | platform_device_register(&spitzscoop2_device); |
418 | } | 428 | } |
419 | 429 | ||
430 | #ifdef CONFIG_MACH_AKITA | ||
431 | /* | ||
432 | * Akita IO Expander | ||
433 | */ | ||
434 | struct platform_device akitaioexp_device = { | ||
435 | .name = "akita-ioexp", | ||
436 | .id = -1, | ||
437 | }; | ||
438 | |||
439 | static void __init akita_init(void) | ||
440 | { | ||
441 | spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode; | ||
442 | |||
443 | /* We just pretend the second element of the array doesn't exist */ | ||
444 | spitz_pcmcia_config.num_devs = 1; | ||
445 | platform_scoop_config = &spitz_pcmcia_config; | ||
446 | spitz_bl_machinfo.set_bl_intensity = akita_bl_set_intensity; | ||
447 | |||
448 | platform_device_register(&akitaioexp_device); | ||
449 | |||
450 | spitzscoop_device.dev.parent = &akitaioexp_device.dev; | ||
451 | common_init(); | ||
452 | } | ||
453 | #endif | ||
454 | |||
455 | |||
420 | static void __init fixup_spitz(struct machine_desc *desc, | 456 | static void __init fixup_spitz(struct machine_desc *desc, |
421 | struct tag *tags, char **cmdline, struct meminfo *mi) | 457 | struct tag *tags, char **cmdline, struct meminfo *mi) |
422 | { | 458 | { |
@@ -452,3 +488,16 @@ MACHINE_START(BORZOI, "SHARP Borzoi") | |||
452 | .timer = &pxa_timer, | 488 | .timer = &pxa_timer, |
453 | MACHINE_END | 489 | MACHINE_END |
454 | #endif | 490 | #endif |
491 | |||
492 | #ifdef CONFIG_MACH_AKITA | ||
493 | MACHINE_START(AKITA, "SHARP Akita") | ||
494 | .phys_ram = 0xa0000000, | ||
495 | .phys_io = 0x40000000, | ||
496 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | ||
497 | .fixup = fixup_spitz, | ||
498 | .map_io = pxa_map_io, | ||
499 | .init_irq = pxa_init_irq, | ||
500 | .init_machine = akita_init, | ||
501 | .timer = &pxa_timer, | ||
502 | MACHINE_END | ||
503 | #endif | ||
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c new file mode 100644 index 000000000000..3ce7486daa51 --- /dev/null +++ b/arch/arm/mach-pxa/spitz_pm.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-Cxx00 | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/apm.h> | ||
20 | #include <asm/irq.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/hardware/scoop.h> | ||
24 | |||
25 | #include <asm/arch/sharpsl.h> | ||
26 | #include <asm/arch/spitz.h> | ||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include "sharpsl.h" | ||
29 | |||
30 | static int spitz_last_ac_status; | ||
31 | |||
32 | static void spitz_charger_init(void) | ||
33 | { | ||
34 | pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN); | ||
35 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
36 | } | ||
37 | |||
38 | static void spitz_charge_led(int val) | ||
39 | { | ||
40 | if (val == SHARPSL_LED_ERROR) { | ||
41 | dev_dbg(sharpsl_pm.dev, "Charge LED Error\n"); | ||
42 | } else if (val == SHARPSL_LED_ON) { | ||
43 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | ||
44 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); | ||
45 | } else { | ||
46 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | ||
47 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void spitz_measure_temp(int on) | ||
52 | { | ||
53 | if (on) | ||
54 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_ADC_TEMP_ON); | ||
55 | else | ||
56 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_ADC_TEMP_ON); | ||
57 | } | ||
58 | |||
59 | static void spitz_charge(int on) | ||
60 | { | ||
61 | if (on) { | ||
62 | if (sharpsl_pm.flags & SHARPSL_SUSPENDED) { | ||
63 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
64 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
65 | } else { | ||
66 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
67 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
68 | } | ||
69 | } else { | ||
70 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
71 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static void spitz_discharge(int on) | ||
76 | { | ||
77 | if (on) | ||
78 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_A); | ||
79 | else | ||
80 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_A); | ||
81 | } | ||
82 | |||
83 | /* HACK - For unknown reasons, accurate voltage readings are only made with a load | ||
84 | on the power bus which the green led on spitz provides */ | ||
85 | static void spitz_discharge1(int on) | ||
86 | { | ||
87 | if (on) | ||
88 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); | ||
89 | else | ||
90 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); | ||
91 | } | ||
92 | |||
93 | static void spitz_presuspend(void) | ||
94 | { | ||
95 | spitz_last_ac_status = STATUS_AC_IN(); | ||
96 | |||
97 | /* GPIO Sleep Register */ | ||
98 | PGSR0 = 0x00144018; | ||
99 | PGSR1 = 0x00EF0000; | ||
100 | if (machine_is_akita()) { | ||
101 | PGSR2 = 0x2121C000; | ||
102 | PGSR3 = 0x00600400; | ||
103 | } else { | ||
104 | PGSR2 = 0x0121C000; | ||
105 | PGSR3 = 0x00600000; | ||
106 | } | ||
107 | |||
108 | PGSR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
109 | PGSR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
110 | PGSR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
111 | PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
112 | PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0); | ||
113 | |||
114 | pxa_gpio_mode(GPIO18_RDY|GPIO_OUT | GPIO_DFLT_HIGH); | ||
115 | |||
116 | PRER = GPIO_bit(SPITZ_GPIO_KEY_INT); | ||
117 | PFER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); | ||
118 | PWER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET) | PWER_RTC; | ||
119 | PKWR = GPIO_bit(SPITZ_GPIO_SYNC) | GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); | ||
120 | PKSR = 0xffffffff; // clear | ||
121 | |||
122 | /* nRESET_OUT Disable */ | ||
123 | PSLR |= PSLR_SL_ROD; | ||
124 | |||
125 | /* Clear reset status */ | ||
126 | RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; | ||
127 | |||
128 | /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ | ||
129 | PCFR = PCFR_GPR_EN | PCFR_OPDE; | ||
130 | } | ||
131 | |||
132 | static void spitz_postsuspend(void) | ||
133 | { | ||
134 | pxa_gpio_mode(GPIO18_RDY_MD); | ||
135 | pxa_gpio_mode(10 | GPIO_IN); | ||
136 | } | ||
137 | |||
138 | static int spitz_should_wakeup(unsigned int resume_on_alarm) | ||
139 | { | ||
140 | int is_resume = 0; | ||
141 | int acin = STATUS_AC_IN(); | ||
142 | |||
143 | if (spitz_last_ac_status != acin) { | ||
144 | if (acin) { | ||
145 | /* charge on */ | ||
146 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
147 | dev_dbg(sharpsl_pm.dev, "AC Inserted\n"); | ||
148 | } else { | ||
149 | /* charge off */ | ||
150 | dev_dbg(sharpsl_pm.dev, "AC Removed\n"); | ||
151 | CHARGE_LED_OFF(); | ||
152 | CHARGE_OFF(); | ||
153 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
154 | } | ||
155 | spitz_last_ac_status = acin; | ||
156 | /* Return to suspend as this must be what we were woken for */ | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | if (PEDR & GPIO_bit(SPITZ_GPIO_KEY_INT)) | ||
161 | is_resume |= GPIO_bit(SPITZ_GPIO_KEY_INT); | ||
162 | |||
163 | if (PKSR & GPIO_bit(SPITZ_GPIO_SYNC)) | ||
164 | is_resume |= GPIO_bit(SPITZ_GPIO_SYNC); | ||
165 | |||
166 | if (resume_on_alarm && (PEDR & PWER_RTC)) | ||
167 | is_resume |= PWER_RTC; | ||
168 | |||
169 | dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); | ||
170 | return is_resume; | ||
171 | } | ||
172 | |||
173 | static unsigned long spitz_charger_wakeup(void) | ||
174 | { | ||
175 | return (~GPLR0 & GPIO_bit(SPITZ_GPIO_KEY_INT)) | (GPLR0 & GPIO_bit(SPITZ_GPIO_SYNC)); | ||
176 | } | ||
177 | |||
178 | static int spitz_acin_status(void) | ||
179 | { | ||
180 | return (((~GPLR(SPITZ_GPIO_AC_IN)) & GPIO_bit(SPITZ_GPIO_AC_IN)) != 0); | ||
181 | } | ||
182 | |||
183 | struct sharpsl_charger_machinfo spitz_pm_machinfo = { | ||
184 | .init = spitz_charger_init, | ||
185 | .gpio_batlock = SPITZ_GPIO_BAT_COVER, | ||
186 | .gpio_acin = SPITZ_GPIO_AC_IN, | ||
187 | .gpio_batfull = SPITZ_GPIO_CHRG_FULL, | ||
188 | .gpio_fatal = SPITZ_GPIO_FATAL_BAT, | ||
189 | .status_acin = spitz_acin_status, | ||
190 | .discharge = spitz_discharge, | ||
191 | .discharge1 = spitz_discharge1, | ||
192 | .charge = spitz_charge, | ||
193 | .chargeled = spitz_charge_led, | ||
194 | .measure_temp = spitz_measure_temp, | ||
195 | .presuspend = spitz_presuspend, | ||
196 | .postsuspend = spitz_postsuspend, | ||
197 | .charger_wakeup = spitz_charger_wakeup, | ||
198 | .should_wakeup = spitz_should_wakeup, | ||
199 | .bat_levels = 40, | ||
200 | .bat_levels_noac = spitz_battery_levels_noac, | ||
201 | .bat_levels_acin = spitz_battery_levels_acin, | ||
202 | .status_high_acin = 188, | ||
203 | .status_low_acin = 178, | ||
204 | .status_high_noac = 185, | ||
205 | .status_low_noac = 175, | ||
206 | }; | ||
207 | |||
208 | static struct platform_device *spitzpm_device; | ||
209 | |||
210 | static int __devinit spitzpm_init(void) | ||
211 | { | ||
212 | int ret; | ||
213 | |||
214 | spitzpm_device = platform_device_alloc("sharpsl-pm", -1); | ||
215 | if (!spitzpm_device) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | spitzpm_device->dev.platform_data = &spitz_pm_machinfo; | ||
219 | ret = platform_device_add(spitzpm_device); | ||
220 | |||
221 | if (ret) | ||
222 | platform_device_put(spitzpm_device); | ||
223 | |||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | static void spitzpm_exit(void) | ||
228 | { | ||
229 | platform_device_unregister(spitzpm_device); | ||
230 | } | ||
231 | |||
232 | module_init(spitzpm_init); | ||
233 | module_exit(spitzpm_exit); | ||
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index 1a1e8a119c3d..712c3c24c954 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/pm_legacy.h> | ||
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <linux/sysctl.h> | 20 | #include <linux/sysctl.h> |
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index dbf90ad6eac3..6004bb0795e0 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -699,7 +699,7 @@ depends on PM && !X86_VISWS | |||
699 | 699 | ||
700 | config APM | 700 | config APM |
701 | tristate "APM (Advanced Power Management) BIOS support" | 701 | tristate "APM (Advanced Power Management) BIOS support" |
702 | depends on PM | 702 | depends on PM && PM_LEGACY |
703 | ---help--- | 703 | ---help--- |
704 | APM is a BIOS specification for saving power using several different | 704 | APM is a BIOS specification for saving power using several different |
705 | techniques. This is mostly useful for battery powered laptops with | 705 | techniques. This is mostly useful for battery powered laptops with |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index b66c13c0cc0f..f36677241ecd 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -39,17 +39,14 @@ | |||
39 | 39 | ||
40 | #ifdef CONFIG_X86_64 | 40 | #ifdef CONFIG_X86_64 |
41 | 41 | ||
42 | static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) | ||
43 | { | ||
44 | } | ||
45 | extern void __init clustered_apic_check(void); | 42 | extern void __init clustered_apic_check(void); |
46 | static inline int ioapic_setup_disabled(void) | ||
47 | { | ||
48 | return 0; | ||
49 | } | ||
50 | 43 | ||
44 | extern int gsi_irq_sharing(int gsi); | ||
51 | #include <asm/proto.h> | 45 | #include <asm/proto.h> |
52 | 46 | ||
47 | static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } | ||
48 | |||
49 | |||
53 | #else /* X86 */ | 50 | #else /* X86 */ |
54 | 51 | ||
55 | #ifdef CONFIG_X86_LOCAL_APIC | 52 | #ifdef CONFIG_X86_LOCAL_APIC |
@@ -57,6 +54,8 @@ static inline int ioapic_setup_disabled(void) | |||
57 | #include <mach_mpparse.h> | 54 | #include <mach_mpparse.h> |
58 | #endif /* CONFIG_X86_LOCAL_APIC */ | 55 | #endif /* CONFIG_X86_LOCAL_APIC */ |
59 | 56 | ||
57 | static inline int gsi_irq_sharing(int gsi) { return gsi; } | ||
58 | |||
60 | #endif /* X86 */ | 59 | #endif /* X86 */ |
61 | 60 | ||
62 | #define BAD_MADT_ENTRY(entry, end) ( \ | 61 | #define BAD_MADT_ENTRY(entry, end) ( \ |
@@ -459,7 +458,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | |||
459 | *irq = IO_APIC_VECTOR(gsi); | 458 | *irq = IO_APIC_VECTOR(gsi); |
460 | else | 459 | else |
461 | #endif | 460 | #endif |
462 | *irq = gsi; | 461 | *irq = gsi_irq_sharing(gsi); |
463 | return 0; | 462 | return 0; |
464 | } | 463 | } |
465 | 464 | ||
@@ -543,7 +542,7 @@ acpi_scan_rsdp(unsigned long start, unsigned long length) | |||
543 | * RSDP signature. | 542 | * RSDP signature. |
544 | */ | 543 | */ |
545 | for (offset = 0; offset < length; offset += 16) { | 544 | for (offset = 0; offset < length; offset += 16) { |
546 | if (strncmp((char *)(start + offset), "RSD PTR ", sig_len)) | 545 | if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len)) |
547 | continue; | 546 | continue; |
548 | return (start + offset); | 547 | return (start + offset); |
549 | } | 548 | } |
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 003548b8735f..1e60acbed3c1 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -218,6 +218,7 @@ | |||
218 | #include <linux/time.h> | 218 | #include <linux/time.h> |
219 | #include <linux/sched.h> | 219 | #include <linux/sched.h> |
220 | #include <linux/pm.h> | 220 | #include <linux/pm.h> |
221 | #include <linux/pm_legacy.h> | ||
221 | #include <linux/device.h> | 222 | #include <linux/device.h> |
222 | #include <linux/kernel.h> | 223 | #include <linux/kernel.h> |
223 | #include <linux/smp.h> | 224 | #include <linux/smp.h> |
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 53a1681cd964..e344ef88cfcd 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c | |||
@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuinfo_x86 *c) | |||
206 | display_cacheinfo(c); | 206 | display_cacheinfo(c); |
207 | 207 | ||
208 | if (cpuid_eax(0x80000000) >= 0x80000008) { | 208 | if (cpuid_eax(0x80000000) >= 0x80000008) { |
209 | c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; | 209 | c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; |
210 | if (c->x86_num_cores & (c->x86_num_cores - 1)) | 210 | if (c->x86_max_cores & (c->x86_max_cores - 1)) |
211 | c->x86_num_cores = 1; | 211 | c->x86_max_cores = 1; |
212 | } | 212 | } |
213 | 213 | ||
214 | #ifdef CONFIG_X86_HT | 214 | #ifdef CONFIG_X86_HT |
@@ -217,15 +217,15 @@ static void __init init_amd(struct cpuinfo_x86 *c) | |||
217 | * distingush the cores. Assumes number of cores is a power | 217 | * distingush the cores. Assumes number of cores is a power |
218 | * of two. | 218 | * of two. |
219 | */ | 219 | */ |
220 | if (c->x86_num_cores > 1) { | 220 | if (c->x86_max_cores > 1) { |
221 | int cpu = smp_processor_id(); | 221 | int cpu = smp_processor_id(); |
222 | unsigned bits = 0; | 222 | unsigned bits = 0; |
223 | while ((1 << bits) < c->x86_num_cores) | 223 | while ((1 << bits) < c->x86_max_cores) |
224 | bits++; | 224 | bits++; |
225 | cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); | 225 | cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); |
226 | phys_proc_id[cpu] >>= bits; | 226 | phys_proc_id[cpu] >>= bits; |
227 | printk(KERN_INFO "CPU %d(%d) -> Core %d\n", | 227 | printk(KERN_INFO "CPU %d(%d) -> Core %d\n", |
228 | cpu, c->x86_num_cores, cpu_core_id[cpu]); | 228 | cpu, c->x86_max_cores, cpu_core_id[cpu]); |
229 | } | 229 | } |
230 | #endif | 230 | #endif |
231 | } | 231 | } |
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index c145fb30002e..31e344b26bae 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
@@ -231,10 +231,10 @@ static void __init early_cpu_detect(void) | |||
231 | cpuid(0x00000001, &tfms, &misc, &junk, &cap0); | 231 | cpuid(0x00000001, &tfms, &misc, &junk, &cap0); |
232 | c->x86 = (tfms >> 8) & 15; | 232 | c->x86 = (tfms >> 8) & 15; |
233 | c->x86_model = (tfms >> 4) & 15; | 233 | c->x86_model = (tfms >> 4) & 15; |
234 | if (c->x86 == 0xf) { | 234 | if (c->x86 == 0xf) |
235 | c->x86 += (tfms >> 20) & 0xff; | 235 | c->x86 += (tfms >> 20) & 0xff; |
236 | if (c->x86 >= 0x6) | ||
236 | c->x86_model += ((tfms >> 16) & 0xF) << 4; | 237 | c->x86_model += ((tfms >> 16) & 0xF) << 4; |
237 | } | ||
238 | c->x86_mask = tfms & 15; | 238 | c->x86_mask = tfms & 15; |
239 | if (cap0 & (1<<19)) | 239 | if (cap0 & (1<<19)) |
240 | c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; | 240 | c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; |
@@ -333,7 +333,7 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) | |||
333 | c->x86_model = c->x86_mask = 0; /* So far unknown... */ | 333 | c->x86_model = c->x86_mask = 0; /* So far unknown... */ |
334 | c->x86_vendor_id[0] = '\0'; /* Unset */ | 334 | c->x86_vendor_id[0] = '\0'; /* Unset */ |
335 | c->x86_model_id[0] = '\0'; /* Unset */ | 335 | c->x86_model_id[0] = '\0'; /* Unset */ |
336 | c->x86_num_cores = 1; | 336 | c->x86_max_cores = 1; |
337 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 337 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
338 | 338 | ||
339 | if (!have_cpuid_p()) { | 339 | if (!have_cpuid_p()) { |
@@ -443,52 +443,44 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) | |||
443 | void __devinit detect_ht(struct cpuinfo_x86 *c) | 443 | void __devinit detect_ht(struct cpuinfo_x86 *c) |
444 | { | 444 | { |
445 | u32 eax, ebx, ecx, edx; | 445 | u32 eax, ebx, ecx, edx; |
446 | int index_msb, tmp; | 446 | int index_msb, core_bits; |
447 | int cpu = smp_processor_id(); | 447 | int cpu = smp_processor_id(); |
448 | 448 | ||
449 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
450 | |||
451 | c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); | ||
452 | |||
449 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 453 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
450 | return; | 454 | return; |
451 | 455 | ||
452 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
453 | smp_num_siblings = (ebx & 0xff0000) >> 16; | 456 | smp_num_siblings = (ebx & 0xff0000) >> 16; |
454 | 457 | ||
455 | if (smp_num_siblings == 1) { | 458 | if (smp_num_siblings == 1) { |
456 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); | 459 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); |
457 | } else if (smp_num_siblings > 1 ) { | 460 | } else if (smp_num_siblings > 1 ) { |
458 | index_msb = 31; | ||
459 | 461 | ||
460 | if (smp_num_siblings > NR_CPUS) { | 462 | if (smp_num_siblings > NR_CPUS) { |
461 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); | 463 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); |
462 | smp_num_siblings = 1; | 464 | smp_num_siblings = 1; |
463 | return; | 465 | return; |
464 | } | 466 | } |
465 | tmp = smp_num_siblings; | 467 | |
466 | while ((tmp & 0x80000000 ) == 0) { | 468 | index_msb = get_count_order(smp_num_siblings); |
467 | tmp <<=1 ; | ||
468 | index_msb--; | ||
469 | } | ||
470 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
471 | index_msb++; | ||
472 | phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); | 469 | phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); |
473 | 470 | ||
474 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | 471 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", |
475 | phys_proc_id[cpu]); | 472 | phys_proc_id[cpu]); |
476 | 473 | ||
477 | smp_num_siblings = smp_num_siblings / c->x86_num_cores; | 474 | smp_num_siblings = smp_num_siblings / c->x86_max_cores; |
478 | 475 | ||
479 | tmp = smp_num_siblings; | 476 | index_msb = get_count_order(smp_num_siblings) ; |
480 | index_msb = 31; | ||
481 | while ((tmp & 0x80000000) == 0) { | ||
482 | tmp <<=1 ; | ||
483 | index_msb--; | ||
484 | } | ||
485 | 477 | ||
486 | if (smp_num_siblings & (smp_num_siblings - 1)) | 478 | core_bits = get_count_order(c->x86_max_cores); |
487 | index_msb++; | ||
488 | 479 | ||
489 | cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); | 480 | cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & |
481 | ((1 << core_bits) - 1); | ||
490 | 482 | ||
491 | if (c->x86_num_cores > 1) | 483 | if (c->x86_max_cores > 1) |
492 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | 484 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", |
493 | cpu_core_id[cpu]); | 485 | cpu_core_id[cpu]); |
494 | } | 486 | } |
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 43601de0f633..5e2da704f0fa 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/bitops.h> | 6 | #include <linux/bitops.h> |
7 | #include <linux/smp.h> | 7 | #include <linux/smp.h> |
8 | #include <linux/thread_info.h> | 8 | #include <linux/thread_info.h> |
9 | #include <linux/module.h> | ||
9 | 10 | ||
10 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
11 | #include <asm/msr.h> | 12 | #include <asm/msr.h> |
@@ -157,7 +158,7 @@ static void __devinit init_intel(struct cpuinfo_x86 *c) | |||
157 | if ( p ) | 158 | if ( p ) |
158 | strcpy(c->x86_model_id, p); | 159 | strcpy(c->x86_model_id, p); |
159 | 160 | ||
160 | c->x86_num_cores = num_cpu_cores(c); | 161 | c->x86_max_cores = num_cpu_cores(c); |
161 | 162 | ||
162 | detect_ht(c); | 163 | detect_ht(c); |
163 | 164 | ||
@@ -264,5 +265,52 @@ __init int intel_cpu_init(void) | |||
264 | return 0; | 265 | return 0; |
265 | } | 266 | } |
266 | 267 | ||
268 | #ifndef CONFIG_X86_CMPXCHG | ||
269 | unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) | ||
270 | { | ||
271 | u8 prev; | ||
272 | unsigned long flags; | ||
273 | |||
274 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
275 | local_irq_save(flags); | ||
276 | prev = *(u8 *)ptr; | ||
277 | if (prev == old) | ||
278 | *(u8 *)ptr = new; | ||
279 | local_irq_restore(flags); | ||
280 | return prev; | ||
281 | } | ||
282 | EXPORT_SYMBOL(cmpxchg_386_u8); | ||
283 | |||
284 | unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) | ||
285 | { | ||
286 | u16 prev; | ||
287 | unsigned long flags; | ||
288 | |||
289 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
290 | local_irq_save(flags); | ||
291 | prev = *(u16 *)ptr; | ||
292 | if (prev == old) | ||
293 | *(u16 *)ptr = new; | ||
294 | local_irq_restore(flags); | ||
295 | return prev; | ||
296 | } | ||
297 | EXPORT_SYMBOL(cmpxchg_386_u16); | ||
298 | |||
299 | unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) | ||
300 | { | ||
301 | u32 prev; | ||
302 | unsigned long flags; | ||
303 | |||
304 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
305 | local_irq_save(flags); | ||
306 | prev = *(u32 *)ptr; | ||
307 | if (prev == old) | ||
308 | *(u32 *)ptr = new; | ||
309 | local_irq_restore(flags); | ||
310 | return prev; | ||
311 | } | ||
312 | EXPORT_SYMBOL(cmpxchg_386_u32); | ||
313 | #endif | ||
314 | |||
267 | // arch_initcall(intel_cpu_init); | 315 | // arch_initcall(intel_cpu_init); |
268 | 316 | ||
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index 4dc42a189ae5..fbfd374aa336 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c | |||
@@ -293,29 +293,45 @@ static struct _cpuid4_info *cpuid4_info[NR_CPUS]; | |||
293 | #ifdef CONFIG_SMP | 293 | #ifdef CONFIG_SMP |
294 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) | 294 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) |
295 | { | 295 | { |
296 | struct _cpuid4_info *this_leaf; | 296 | struct _cpuid4_info *this_leaf, *sibling_leaf; |
297 | unsigned long num_threads_sharing; | 297 | unsigned long num_threads_sharing; |
298 | #ifdef CONFIG_X86_HT | 298 | int index_msb, i; |
299 | struct cpuinfo_x86 *c = cpu_data + cpu; | 299 | struct cpuinfo_x86 *c = cpu_data; |
300 | #endif | ||
301 | 300 | ||
302 | this_leaf = CPUID4_INFO_IDX(cpu, index); | 301 | this_leaf = CPUID4_INFO_IDX(cpu, index); |
303 | num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; | 302 | num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; |
304 | 303 | ||
305 | if (num_threads_sharing == 1) | 304 | if (num_threads_sharing == 1) |
306 | cpu_set(cpu, this_leaf->shared_cpu_map); | 305 | cpu_set(cpu, this_leaf->shared_cpu_map); |
307 | #ifdef CONFIG_X86_HT | 306 | else { |
308 | else if (num_threads_sharing == smp_num_siblings) | 307 | index_msb = get_count_order(num_threads_sharing); |
309 | this_leaf->shared_cpu_map = cpu_sibling_map[cpu]; | 308 | |
310 | else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings)) | 309 | for_each_online_cpu(i) { |
311 | this_leaf->shared_cpu_map = cpu_core_map[cpu]; | 310 | if (c[i].apicid >> index_msb == |
312 | else | 311 | c[cpu].apicid >> index_msb) { |
313 | printk(KERN_DEBUG "Number of CPUs sharing cache didn't match " | 312 | cpu_set(i, this_leaf->shared_cpu_map); |
314 | "any known set of CPUs\n"); | 313 | if (i != cpu && cpuid4_info[i]) { |
315 | #endif | 314 | sibling_leaf = CPUID4_INFO_IDX(i, index); |
315 | cpu_set(cpu, sibling_leaf->shared_cpu_map); | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | static void __devinit cache_remove_shared_cpu_map(unsigned int cpu, int index) | ||
322 | { | ||
323 | struct _cpuid4_info *this_leaf, *sibling_leaf; | ||
324 | int sibling; | ||
325 | |||
326 | this_leaf = CPUID4_INFO_IDX(cpu, index); | ||
327 | for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) { | ||
328 | sibling_leaf = CPUID4_INFO_IDX(sibling, index); | ||
329 | cpu_clear(cpu, sibling_leaf->shared_cpu_map); | ||
330 | } | ||
316 | } | 331 | } |
317 | #else | 332 | #else |
318 | static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {} | 333 | static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {} |
334 | static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {} | ||
319 | #endif | 335 | #endif |
320 | 336 | ||
321 | static void free_cache_attributes(unsigned int cpu) | 337 | static void free_cache_attributes(unsigned int cpu) |
@@ -574,8 +590,10 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev) | |||
574 | unsigned int cpu = sys_dev->id; | 590 | unsigned int cpu = sys_dev->id; |
575 | unsigned long i; | 591 | unsigned long i; |
576 | 592 | ||
577 | for (i = 0; i < num_cache_leaves; i++) | 593 | for (i = 0; i < num_cache_leaves; i++) { |
594 | cache_remove_shared_cpu_map(cpu, i); | ||
578 | kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); | 595 | kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); |
596 | } | ||
579 | kobject_unregister(cache_kobject[cpu]); | 597 | kobject_unregister(cache_kobject[cpu]); |
580 | cpuid4_cache_sysfs_exit(cpu); | 598 | cpuid4_cache_sysfs_exit(cpu); |
581 | return; | 599 | return; |
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index dd4ebd6af7e4..1e9db198c440 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c | |||
@@ -626,6 +626,14 @@ void __init mtrr_bp_init(void) | |||
626 | if (cpuid_eax(0x80000000) >= 0x80000008) { | 626 | if (cpuid_eax(0x80000000) >= 0x80000008) { |
627 | u32 phys_addr; | 627 | u32 phys_addr; |
628 | phys_addr = cpuid_eax(0x80000008) & 0xff; | 628 | phys_addr = cpuid_eax(0x80000008) & 0xff; |
629 | /* CPUID workaround for Intel 0F33/0F34 CPU */ | ||
630 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | ||
631 | boot_cpu_data.x86 == 0xF && | ||
632 | boot_cpu_data.x86_model == 0x3 && | ||
633 | (boot_cpu_data.x86_mask == 0x3 || | ||
634 | boot_cpu_data.x86_mask == 0x4)) | ||
635 | phys_addr = 36; | ||
636 | |||
629 | size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1); | 637 | size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1); |
630 | size_and_mask = ~size_or_mask & 0xfff00000; | 638 | size_and_mask = ~size_or_mask & 0xfff00000; |
631 | } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && | 639 | } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && |
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 41b871ecf4b3..e7921315ae9d 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c | |||
@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
94 | if (c->x86_cache_size >= 0) | 94 | if (c->x86_cache_size >= 0) |
95 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); | 95 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); |
96 | #ifdef CONFIG_X86_HT | 96 | #ifdef CONFIG_X86_HT |
97 | if (c->x86_num_cores * smp_num_siblings > 1) { | 97 | if (c->x86_max_cores * smp_num_siblings > 1) { |
98 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); | 98 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); |
99 | seq_printf(m, "siblings\t: %d\n", | 99 | seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n])); |
100 | c->x86_num_cores * smp_num_siblings); | ||
101 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); | 100 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); |
102 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | 101 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); |
103 | } | 102 | } |
104 | #endif | 103 | #endif |
105 | 104 | ||
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index af809ccf5fbe..0248e084017c 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/hardirq.h> | 21 | #include <asm/hardirq.h> |
22 | #include <asm/nmi.h> | 22 | #include <asm/nmi.h> |
23 | #include <asm/hw_irq.h> | 23 | #include <asm/hw_irq.h> |
24 | #include <asm/apic.h> | ||
24 | #include <mach_ipi.h> | 25 | #include <mach_ipi.h> |
25 | 26 | ||
26 | 27 | ||
@@ -147,6 +148,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu) | |||
147 | regs = &fixed_regs; | 148 | regs = &fixed_regs; |
148 | } | 149 | } |
149 | crash_save_this_cpu(regs, cpu); | 150 | crash_save_this_cpu(regs, cpu); |
151 | disable_local_APIC(); | ||
150 | atomic_dec(&waiting_for_crash_ipi); | 152 | atomic_dec(&waiting_for_crash_ipi); |
151 | /* Assume hlt works */ | 153 | /* Assume hlt works */ |
152 | halt(); | 154 | halt(); |
@@ -186,6 +188,7 @@ static void nmi_shootdown_cpus(void) | |||
186 | } | 188 | } |
187 | 189 | ||
188 | /* Leave the nmi callback set */ | 190 | /* Leave the nmi callback set */ |
191 | disable_local_APIC(); | ||
189 | } | 192 | } |
190 | #else | 193 | #else |
191 | static void nmi_shootdown_cpus(void) | 194 | static void nmi_shootdown_cpus(void) |
@@ -210,5 +213,9 @@ void machine_crash_shutdown(struct pt_regs *regs) | |||
210 | /* Make a note of crashing cpu. Will be used in NMI callback.*/ | 213 | /* Make a note of crashing cpu. Will be used in NMI callback.*/ |
211 | crashing_cpu = smp_processor_id(); | 214 | crashing_cpu = smp_processor_id(); |
212 | nmi_shootdown_cpus(); | 215 | nmi_shootdown_cpus(); |
216 | lapic_shutdown(); | ||
217 | #if defined(CONFIG_X86_IO_APIC) | ||
218 | disable_IO_APIC(); | ||
219 | #endif | ||
213 | crash_save_self(regs); | 220 | crash_save_self(regs); |
214 | } | 221 | } |
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 9e24f7b207ee..e50b93155249 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -560,11 +560,10 @@ nmi_stack_fixup: | |||
560 | nmi_debug_stack_check: | 560 | nmi_debug_stack_check: |
561 | cmpw $__KERNEL_CS,16(%esp) | 561 | cmpw $__KERNEL_CS,16(%esp) |
562 | jne nmi_stack_correct | 562 | jne nmi_stack_correct |
563 | cmpl $debug - 1,(%esp) | 563 | cmpl $debug,(%esp) |
564 | jle nmi_stack_correct | 564 | jb nmi_stack_correct |
565 | cmpl $debug_esp_fix_insn,(%esp) | 565 | cmpl $debug_esp_fix_insn,(%esp) |
566 | jle nmi_debug_stack_fixup | 566 | ja nmi_stack_correct |
567 | nmi_debug_stack_fixup: | ||
568 | FIX_STACK(24,nmi_stack_correct, 1) | 567 | FIX_STACK(24,nmi_stack_correct, 1) |
569 | jmp nmi_stack_correct | 568 | jmp nmi_stack_correct |
570 | 569 | ||
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index bc5a9d97466b..d16520da4550 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -72,9 +72,11 @@ int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | |||
72 | /* Core ID of each logical CPU */ | 72 | /* Core ID of each logical CPU */ |
73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | 73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; |
74 | 74 | ||
75 | /* representing HT siblings of each logical CPU */ | ||
75 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 76 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
76 | EXPORT_SYMBOL(cpu_sibling_map); | 77 | EXPORT_SYMBOL(cpu_sibling_map); |
77 | 78 | ||
79 | /* representing HT and core siblings of each logical CPU */ | ||
78 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 80 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
79 | EXPORT_SYMBOL(cpu_core_map); | 81 | EXPORT_SYMBOL(cpu_core_map); |
80 | 82 | ||
@@ -442,35 +444,60 @@ static void __devinit smp_callin(void) | |||
442 | 444 | ||
443 | static int cpucount; | 445 | static int cpucount; |
444 | 446 | ||
447 | /* representing cpus for which sibling maps can be computed */ | ||
448 | static cpumask_t cpu_sibling_setup_map; | ||
449 | |||
445 | static inline void | 450 | static inline void |
446 | set_cpu_sibling_map(int cpu) | 451 | set_cpu_sibling_map(int cpu) |
447 | { | 452 | { |
448 | int i; | 453 | int i; |
454 | struct cpuinfo_x86 *c = cpu_data; | ||
455 | |||
456 | cpu_set(cpu, cpu_sibling_setup_map); | ||
449 | 457 | ||
450 | if (smp_num_siblings > 1) { | 458 | if (smp_num_siblings > 1) { |
451 | for (i = 0; i < NR_CPUS; i++) { | 459 | for_each_cpu_mask(i, cpu_sibling_setup_map) { |
452 | if (!cpu_isset(i, cpu_callout_map)) | 460 | if (phys_proc_id[cpu] == phys_proc_id[i] && |
453 | continue; | 461 | cpu_core_id[cpu] == cpu_core_id[i]) { |
454 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | ||
455 | cpu_set(i, cpu_sibling_map[cpu]); | 462 | cpu_set(i, cpu_sibling_map[cpu]); |
456 | cpu_set(cpu, cpu_sibling_map[i]); | 463 | cpu_set(cpu, cpu_sibling_map[i]); |
464 | cpu_set(i, cpu_core_map[cpu]); | ||
465 | cpu_set(cpu, cpu_core_map[i]); | ||
457 | } | 466 | } |
458 | } | 467 | } |
459 | } else { | 468 | } else { |
460 | cpu_set(cpu, cpu_sibling_map[cpu]); | 469 | cpu_set(cpu, cpu_sibling_map[cpu]); |
461 | } | 470 | } |
462 | 471 | ||
463 | if (current_cpu_data.x86_num_cores > 1) { | 472 | if (current_cpu_data.x86_max_cores == 1) { |
464 | for (i = 0; i < NR_CPUS; i++) { | ||
465 | if (!cpu_isset(i, cpu_callout_map)) | ||
466 | continue; | ||
467 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
468 | cpu_set(i, cpu_core_map[cpu]); | ||
469 | cpu_set(cpu, cpu_core_map[i]); | ||
470 | } | ||
471 | } | ||
472 | } else { | ||
473 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 473 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
474 | c[cpu].booted_cores = 1; | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | ||
479 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
480 | cpu_set(i, cpu_core_map[cpu]); | ||
481 | cpu_set(cpu, cpu_core_map[i]); | ||
482 | /* | ||
483 | * Does this new cpu bringup a new core? | ||
484 | */ | ||
485 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) { | ||
486 | /* | ||
487 | * for each core in package, increment | ||
488 | * the booted_cores for this new cpu | ||
489 | */ | ||
490 | if (first_cpu(cpu_sibling_map[i]) == i) | ||
491 | c[cpu].booted_cores++; | ||
492 | /* | ||
493 | * increment the core count for all | ||
494 | * the other cpus in this package | ||
495 | */ | ||
496 | if (i != cpu) | ||
497 | c[i].booted_cores++; | ||
498 | } else if (i != cpu && !c[cpu].booted_cores) | ||
499 | c[cpu].booted_cores = c[i].booted_cores; | ||
500 | } | ||
474 | } | 501 | } |
475 | } | 502 | } |
476 | 503 | ||
@@ -1095,11 +1122,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1095 | 1122 | ||
1096 | current_thread_info()->cpu = 0; | 1123 | current_thread_info()->cpu = 0; |
1097 | smp_tune_scheduling(); | 1124 | smp_tune_scheduling(); |
1098 | cpus_clear(cpu_sibling_map[0]); | ||
1099 | cpu_set(0, cpu_sibling_map[0]); | ||
1100 | 1125 | ||
1101 | cpus_clear(cpu_core_map[0]); | 1126 | set_cpu_sibling_map(0); |
1102 | cpu_set(0, cpu_core_map[0]); | ||
1103 | 1127 | ||
1104 | /* | 1128 | /* |
1105 | * If we couldn't find an SMP configuration at boot time, | 1129 | * If we couldn't find an SMP configuration at boot time, |
@@ -1278,15 +1302,24 @@ static void | |||
1278 | remove_siblinginfo(int cpu) | 1302 | remove_siblinginfo(int cpu) |
1279 | { | 1303 | { |
1280 | int sibling; | 1304 | int sibling; |
1305 | struct cpuinfo_x86 *c = cpu_data; | ||
1281 | 1306 | ||
1307 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) { | ||
1308 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1309 | /* | ||
1310 | * last thread sibling in this cpu core going down | ||
1311 | */ | ||
1312 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) | ||
1313 | c[sibling].booted_cores--; | ||
1314 | } | ||
1315 | |||
1282 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) | 1316 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) |
1283 | cpu_clear(cpu, cpu_sibling_map[sibling]); | 1317 | cpu_clear(cpu, cpu_sibling_map[sibling]); |
1284 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) | ||
1285 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1286 | cpus_clear(cpu_sibling_map[cpu]); | 1318 | cpus_clear(cpu_sibling_map[cpu]); |
1287 | cpus_clear(cpu_core_map[cpu]); | 1319 | cpus_clear(cpu_core_map[cpu]); |
1288 | phys_proc_id[cpu] = BAD_APICID; | 1320 | phys_proc_id[cpu] = BAD_APICID; |
1289 | cpu_core_id[cpu] = BAD_APICID; | 1321 | cpu_core_id[cpu] = BAD_APICID; |
1322 | cpu_clear(cpu, cpu_sibling_setup_map); | ||
1290 | } | 1323 | } |
1291 | 1324 | ||
1292 | int __cpu_disable(void) | 1325 | int __cpu_disable(void) |
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index 8de658db8146..52b3ed5d2cb5 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c | |||
@@ -137,8 +137,8 @@ static void __init parse_memory_affinity_structure (char *sratp) | |||
137 | "enabled and removable" : "enabled" ) ); | 137 | "enabled and removable" : "enabled" ) ); |
138 | } | 138 | } |
139 | 139 | ||
140 | #if MAX_NR_ZONES != 3 | 140 | #if MAX_NR_ZONES != 4 |
141 | #error "MAX_NR_ZONES != 3, chunk_to_zone requires review" | 141 | #error "MAX_NR_ZONES != 4, chunk_to_zone requires review" |
142 | #endif | 142 | #endif |
143 | /* Take a chunk of pages from page frame cstart to cend and count the number | 143 | /* Take a chunk of pages from page frame cstart to cend and count the number |
144 | * of pages in each zone, returned via zones[]. | 144 | * of pages in each zone, returned via zones[]. |
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c index e42e46d35159..b9b6bd56b9ba 100644 --- a/arch/i386/kernel/timers/timer_pit.c +++ b/arch/i386/kernel/timers/timer_pit.c | |||
@@ -25,8 +25,9 @@ static int __init init_pit(char* override) | |||
25 | { | 25 | { |
26 | /* check clock override */ | 26 | /* check clock override */ |
27 | if (override[0] && strncmp(override,"pit",3)) | 27 | if (override[0] && strncmp(override,"pit",3)) |
28 | printk(KERN_ERR "Warning: clock= override failed. Defaulting to PIT\n"); | 28 | printk(KERN_ERR "Warning: clock= override failed. Defaulting " |
29 | 29 | "to PIT\n"); | |
30 | init_cpu_khz(); | ||
30 | count_p = LATCH; | 31 | count_p = LATCH; |
31 | return 0; | 32 | return 0; |
32 | } | 33 | } |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 542d9298da5e..06e26f006238 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
29 | #include <linux/efi.h> | 29 | #include <linux/efi.h> |
30 | #include <linux/memory_hotplug.h> | 30 | #include <linux/memory_hotplug.h> |
31 | #include <linux/initrd.h> | ||
31 | 32 | ||
32 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
33 | #include <asm/system.h> | 34 | #include <asm/system.h> |
@@ -267,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) | |||
267 | pkmap_page_table = pte; | 268 | pkmap_page_table = pte; |
268 | } | 269 | } |
269 | 270 | ||
270 | void __devinit free_new_highpage(struct page *page) | 271 | static void __devinit free_new_highpage(struct page *page) |
271 | { | 272 | { |
272 | set_page_count(page, 1); | 273 | set_page_count(page, 1); |
273 | __free_page(page); | 274 | __free_page(page); |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 8796e12c56f3..b76ce1fe2e7f 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -58,6 +58,10 @@ config IA64_UNCACHED_ALLOCATOR | |||
58 | bool | 58 | bool |
59 | select GENERIC_ALLOCATOR | 59 | select GENERIC_ALLOCATOR |
60 | 60 | ||
61 | config ZONE_DMA_IS_DMA32 | ||
62 | bool | ||
63 | default y | ||
64 | |||
61 | choice | 65 | choice |
62 | prompt "System type" | 66 | prompt "System type" |
63 | default IA64_GENERIC | 67 | default IA64_GENERIC |
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S index 9571a21d6ad4..a1629194e3fd 100644 --- a/arch/m68k/fpsp040/skeleton.S +++ b/arch/m68k/fpsp040/skeleton.S | |||
@@ -381,10 +381,8 @@ fpsp_done: | |||
381 | .Lnotkern: | 381 | .Lnotkern: |
382 | SAVE_ALL_INT | 382 | SAVE_ALL_INT |
383 | GET_CURRENT(%d0) | 383 | GET_CURRENT(%d0) |
384 | tstb %curptr@(TASK_NEEDRESCHED) | 384 | | deliver signals, reschedule etc.. |
385 | jne ret_from_exception | deliver signals, | 385 | jra ret_from_exception |
386 | | reschedule etc.. | ||
387 | RESTORE_ALL | ||
388 | 386 | ||
389 | | | 387 | | |
390 | | mem_write --- write to user or supervisor address space | 388 | | mem_write --- write to user or supervisor address space |
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S index 4ba2c74da93d..b2dbdf5ee309 100644 --- a/arch/m68k/ifpsp060/iskeleton.S +++ b/arch/m68k/ifpsp060/iskeleton.S | |||
@@ -75,10 +75,8 @@ _060_isp_done: | |||
75 | .Lnotkern: | 75 | .Lnotkern: |
76 | SAVE_ALL_INT | 76 | SAVE_ALL_INT |
77 | GET_CURRENT(%d0) | 77 | GET_CURRENT(%d0) |
78 | tstb %curptr@(TASK_NEEDRESCHED) | 78 | | deliver signals, reschedule etc.. |
79 | jne ret_from_exception | deliver signals, | 79 | jra ret_from_exception |
80 | | reschedule etc.. | ||
81 | RESTORE_ALL | ||
82 | 80 | ||
83 | | | 81 | | |
84 | | _060_real_chk(): | 82 | | _060_real_chk(): |
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index cee3317b8665..c787c5ba9513 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c | |||
@@ -25,12 +25,8 @@ int main(void) | |||
25 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); | 25 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); |
26 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); | 26 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); |
27 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); | 27 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); |
28 | DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work)); | ||
29 | DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched)); | ||
30 | DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace)); | ||
31 | DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending)); | ||
32 | DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume)); | ||
33 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); | 28 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); |
29 | DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); | ||
34 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); | 30 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); |
35 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | 31 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); |
36 | 32 | ||
@@ -45,6 +41,10 @@ int main(void) | |||
45 | DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); | 41 | DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); |
46 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); | 42 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); |
47 | 43 | ||
44 | /* offsets into the thread_info struct */ | ||
45 | DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
46 | DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); | ||
47 | |||
48 | /* offsets into the pt_regs */ | 48 | /* offsets into the pt_regs */ |
49 | DEFINE(PT_D0, offsetof(struct pt_regs, d0)); | 49 | DEFINE(PT_D0, offsetof(struct pt_regs, d0)); |
50 | DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); | 50 | DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 23ca60a45552..320fde05dc63 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -44,9 +44,7 @@ | |||
44 | 44 | ||
45 | #include <asm/asm-offsets.h> | 45 | #include <asm/asm-offsets.h> |
46 | 46 | ||
47 | .globl system_call, buserr, trap | 47 | .globl system_call, buserr, trap, resume |
48 | .globl resume, ret_from_exception | ||
49 | .globl ret_from_signal | ||
50 | .globl inthandler, sys_call_table | 48 | .globl inthandler, sys_call_table |
51 | .globl sys_fork, sys_clone, sys_vfork | 49 | .globl sys_fork, sys_clone, sys_vfork |
52 | .globl ret_from_interrupt, bad_interrupt | 50 | .globl ret_from_interrupt, bad_interrupt |
@@ -58,7 +56,7 @@ ENTRY(buserr) | |||
58 | movel %sp,%sp@- | stack frame pointer argument | 56 | movel %sp,%sp@- | stack frame pointer argument |
59 | bsrl buserr_c | 57 | bsrl buserr_c |
60 | addql #4,%sp | 58 | addql #4,%sp |
61 | jra ret_from_exception | 59 | jra .Lret_from_exception |
62 | 60 | ||
63 | ENTRY(trap) | 61 | ENTRY(trap) |
64 | SAVE_ALL_INT | 62 | SAVE_ALL_INT |
@@ -66,7 +64,7 @@ ENTRY(trap) | |||
66 | movel %sp,%sp@- | stack frame pointer argument | 64 | movel %sp,%sp@- | stack frame pointer argument |
67 | bsrl trap_c | 65 | bsrl trap_c |
68 | addql #4,%sp | 66 | addql #4,%sp |
69 | jra ret_from_exception | 67 | jra .Lret_from_exception |
70 | 68 | ||
71 | | After a fork we jump here directly from resume, | 69 | | After a fork we jump here directly from resume, |
72 | | so that %d1 contains the previous task | 70 | | so that %d1 contains the previous task |
@@ -75,30 +73,31 @@ ENTRY(ret_from_fork) | |||
75 | movel %d1,%sp@- | 73 | movel %d1,%sp@- |
76 | jsr schedule_tail | 74 | jsr schedule_tail |
77 | addql #4,%sp | 75 | addql #4,%sp |
78 | jra ret_from_exception | 76 | jra .Lret_from_exception |
79 | 77 | ||
80 | badsys: | 78 | do_trace_entry: |
81 | movel #-ENOSYS,%sp@(PT_D0) | ||
82 | jra ret_from_exception | ||
83 | |||
84 | do_trace: | ||
85 | movel #-ENOSYS,%sp@(PT_D0) | needed for strace | 79 | movel #-ENOSYS,%sp@(PT_D0) | needed for strace |
86 | subql #4,%sp | 80 | subql #4,%sp |
87 | SAVE_SWITCH_STACK | 81 | SAVE_SWITCH_STACK |
88 | jbsr syscall_trace | 82 | jbsr syscall_trace |
89 | RESTORE_SWITCH_STACK | 83 | RESTORE_SWITCH_STACK |
90 | addql #4,%sp | 84 | addql #4,%sp |
91 | movel %sp@(PT_ORIG_D0),%d1 | 85 | movel %sp@(PT_ORIG_D0),%d0 |
92 | movel #-ENOSYS,%d0 | 86 | cmpl #NR_syscalls,%d0 |
93 | cmpl #NR_syscalls,%d1 | 87 | jcs syscall |
94 | jcc 1f | 88 | badsys: |
95 | jbsr @(sys_call_table,%d1:l:4)@(0) | 89 | movel #-ENOSYS,%sp@(PT_D0) |
96 | 1: movel %d0,%sp@(PT_D0) | save the return value | 90 | jra ret_from_syscall |
97 | subql #4,%sp | dummy return address | 91 | |
92 | do_trace_exit: | ||
93 | subql #4,%sp | ||
98 | SAVE_SWITCH_STACK | 94 | SAVE_SWITCH_STACK |
99 | jbsr syscall_trace | 95 | jbsr syscall_trace |
96 | RESTORE_SWITCH_STACK | ||
97 | addql #4,%sp | ||
98 | jra .Lret_from_exception | ||
100 | 99 | ||
101 | ret_from_signal: | 100 | ENTRY(ret_from_signal) |
102 | RESTORE_SWITCH_STACK | 101 | RESTORE_SWITCH_STACK |
103 | addql #4,%sp | 102 | addql #4,%sp |
104 | /* on 68040 complete pending writebacks if any */ | 103 | /* on 68040 complete pending writebacks if any */ |
@@ -111,7 +110,7 @@ ret_from_signal: | |||
111 | addql #4,%sp | 110 | addql #4,%sp |
112 | 1: | 111 | 1: |
113 | #endif | 112 | #endif |
114 | jra ret_from_exception | 113 | jra .Lret_from_exception |
115 | 114 | ||
116 | ENTRY(system_call) | 115 | ENTRY(system_call) |
117 | SAVE_ALL_SYS | 116 | SAVE_ALL_SYS |
@@ -120,30 +119,34 @@ ENTRY(system_call) | |||
120 | | save top of frame | 119 | | save top of frame |
121 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 120 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
122 | 121 | ||
123 | tstb %curptr@(TASK_SYSCALL_TRACE) | 122 | | syscall trace? |
124 | jne do_trace | 123 | tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) |
124 | jmi do_trace_entry | ||
125 | cmpl #NR_syscalls,%d0 | 125 | cmpl #NR_syscalls,%d0 |
126 | jcc badsys | 126 | jcc badsys |
127 | syscall: | ||
127 | jbsr @(sys_call_table,%d0:l:4)@(0) | 128 | jbsr @(sys_call_table,%d0:l:4)@(0) |
128 | movel %d0,%sp@(PT_D0) | save the return value | 129 | movel %d0,%sp@(PT_D0) | save the return value |
129 | 130 | ret_from_syscall: | |
130 | |oriw #0x0700,%sr | 131 | |oriw #0x0700,%sr |
131 | movel %curptr@(TASK_WORK),%d0 | 132 | movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 |
132 | jne syscall_exit_work | 133 | jne syscall_exit_work |
133 | 1: RESTORE_ALL | 134 | 1: RESTORE_ALL |
134 | 135 | ||
135 | syscall_exit_work: | 136 | syscall_exit_work: |
136 | btst #5,%sp@(PT_SR) | check if returning to kernel | 137 | btst #5,%sp@(PT_SR) | check if returning to kernel |
137 | bnes 1b | if so, skip resched, signals | 138 | bnes 1b | if so, skip resched, signals |
138 | tstw %d0 | 139 | lslw #1,%d0 |
139 | jeq do_signal_return | 140 | jcs do_trace_exit |
140 | tstb %d0 | 141 | jmi do_delayed_trace |
141 | jne do_delayed_trace | 142 | lslw #8,%d0 |
142 | 143 | jmi do_signal_return | |
143 | pea resume_userspace | 144 | pea resume_userspace |
144 | jmp schedule | 145 | jra schedule |
146 | |||
145 | 147 | ||
146 | ret_from_exception: | 148 | ENTRY(ret_from_exception) |
149 | .Lret_from_exception: | ||
147 | btst #5,%sp@(PT_SR) | check if returning to kernel | 150 | btst #5,%sp@(PT_SR) | check if returning to kernel |
148 | bnes 1f | if so, skip resched, signals | 151 | bnes 1f | if so, skip resched, signals |
149 | | only allow interrupts when we are really the last one on the | 152 | | only allow interrupts when we are really the last one on the |
@@ -152,19 +155,18 @@ ret_from_exception: | |||
152 | andw #ALLOWINT,%sr | 155 | andw #ALLOWINT,%sr |
153 | 156 | ||
154 | resume_userspace: | 157 | resume_userspace: |
155 | movel %curptr@(TASK_WORK),%d0 | 158 | moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 |
156 | lsrl #8,%d0 | ||
157 | jne exit_work | 159 | jne exit_work |
158 | 1: RESTORE_ALL | 160 | 1: RESTORE_ALL |
159 | 161 | ||
160 | exit_work: | 162 | exit_work: |
161 | | save top of frame | 163 | | save top of frame |
162 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 164 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
163 | tstb %d0 | 165 | lslb #1,%d0 |
164 | jeq do_signal_return | 166 | jmi do_signal_return |
165 | |||
166 | pea resume_userspace | 167 | pea resume_userspace |
167 | jmp schedule | 168 | jra schedule |
169 | |||
168 | 170 | ||
169 | do_signal_return: | 171 | do_signal_return: |
170 | |andw #ALLOWINT,%sr | 172 | |andw #ALLOWINT,%sr |
@@ -254,7 +256,7 @@ ret_from_interrupt: | |||
254 | 256 | ||
255 | /* check if we need to do software interrupts */ | 257 | /* check if we need to do software interrupts */ |
256 | tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING | 258 | tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING |
257 | jeq ret_from_exception | 259 | jeq .Lret_from_exception |
258 | pea ret_from_exception | 260 | pea ret_from_exception |
259 | jra do_softirq | 261 | jra do_softirq |
260 | 262 | ||
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 7e54422685cf..540638ca81f9 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -109,7 +109,7 @@ static inline void singlestep_disable(struct task_struct *child) | |||
109 | { | 109 | { |
110 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | 110 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); |
111 | put_reg(child, PT_SR, tmp); | 111 | put_reg(child, PT_SR, tmp); |
112 | child->thread.work.delayed_trace = 0; | 112 | clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | /* |
@@ -118,7 +118,7 @@ static inline void singlestep_disable(struct task_struct *child) | |||
118 | void ptrace_disable(struct task_struct *child) | 118 | void ptrace_disable(struct task_struct *child) |
119 | { | 119 | { |
120 | singlestep_disable(child); | 120 | singlestep_disable(child); |
121 | child->thread.work.syscall_trace = 0; | 121 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
122 | } | 122 | } |
123 | 123 | ||
124 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 124 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -198,9 +198,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
198 | goto out_eio; | 198 | goto out_eio; |
199 | 199 | ||
200 | if (request == PTRACE_SYSCALL) | 200 | if (request == PTRACE_SYSCALL) |
201 | child->thread.work.syscall_trace = ~0; | 201 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
202 | else | 202 | else |
203 | child->thread.work.syscall_trace = 0; | 203 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
204 | child->exit_code = data; | 204 | child->exit_code = data; |
205 | singlestep_disable(child); | 205 | singlestep_disable(child); |
206 | wake_up_process(child); | 206 | wake_up_process(child); |
@@ -223,10 +223,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
223 | if (!valid_signal(data)) | 223 | if (!valid_signal(data)) |
224 | goto out_eio; | 224 | goto out_eio; |
225 | 225 | ||
226 | child->thread.work.syscall_trace = 0; | 226 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
227 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); | 227 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); |
228 | put_reg(child, PT_SR, tmp); | 228 | put_reg(child, PT_SR, tmp); |
229 | child->thread.work.delayed_trace = 1; | 229 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); |
230 | 230 | ||
231 | child->exit_code = data; | 231 | child->exit_code = data; |
232 | /* give it a chance to run. */ | 232 | /* give it a chance to run. */ |
@@ -288,9 +288,6 @@ out_eio: | |||
288 | 288 | ||
289 | asmlinkage void syscall_trace(void) | 289 | asmlinkage void syscall_trace(void) |
290 | { | 290 | { |
291 | if (!current->thread.work.delayed_trace && | ||
292 | !current->thread.work.syscall_trace) | ||
293 | return; | ||
294 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | 291 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) |
295 | ? 0x80 : 0)); | 292 | ? 0x80 : 0)); |
296 | /* | 293 | /* |
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c index f85093b8d54d..f4926315fb68 100644 --- a/arch/mips/au1000/common/power.c +++ b/arch/mips/au1000/common/power.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/config.h> | 32 | #include <linux/config.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/pm.h> | 34 | #include <linux/pm.h> |
35 | #include <linux/pm_legacy.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | #include <linux/sysctl.h> | 37 | #include <linux/sysctl.h> |
37 | #include <linux/jiffies.h> | 38 | #include <linux/jiffies.h> |
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c index 0b21bed7ee55..2cab7629702c 100644 --- a/arch/mips/au1000/common/usbdev.c +++ b/arch/mips/au1000/common/usbdev.c | |||
@@ -348,7 +348,7 @@ endpoint_stall(endpoint_t * ep) | |||
348 | { | 348 | { |
349 | u32 cs; | 349 | u32 cs; |
350 | 350 | ||
351 | warn(__FUNCTION__); | 351 | warn("%s", __FUNCTION__); |
352 | 352 | ||
353 | cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; | 353 | cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; |
354 | au_writel(cs, ep->reg->ctrl_stat); | 354 | au_writel(cs, ep->reg->ctrl_stat); |
@@ -360,7 +360,7 @@ endpoint_unstall(endpoint_t * ep) | |||
360 | { | 360 | { |
361 | u32 cs; | 361 | u32 cs; |
362 | 362 | ||
363 | warn(__FUNCTION__); | 363 | warn("%s", __FUNCTION__); |
364 | 364 | ||
365 | cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; | 365 | cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; |
366 | au_writel(cs, ep->reg->ctrl_stat); | 366 | au_writel(cs, ep->reg->ctrl_stat); |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c523029674e6..94df74bcc0ee 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -261,7 +261,7 @@ config PPC_ISERIES | |||
261 | 261 | ||
262 | config EMBEDDED6xx | 262 | config EMBEDDED6xx |
263 | bool "Embedded 6xx/7xx/7xxx-based board" | 263 | bool "Embedded 6xx/7xx/7xxx-based board" |
264 | depends on PPC32 | 264 | depends on PPC32 && BROKEN |
265 | 265 | ||
266 | config APUS | 266 | config APUS |
267 | bool "Amiga-APUS" | 267 | bool "Amiga-APUS" |
@@ -305,7 +305,7 @@ config PPC_PMAC64 | |||
305 | 305 | ||
306 | config PPC_PREP | 306 | config PPC_PREP |
307 | bool " PowerPC Reference Platform (PReP) based machines" | 307 | bool " PowerPC Reference Platform (PReP) based machines" |
308 | depends on PPC_MULTIPLATFORM && PPC32 | 308 | depends on PPC_MULTIPLATFORM && PPC32 && BROKEN |
309 | select PPC_I8259 | 309 | select PPC_I8259 |
310 | select PPC_INDIRECT_PCI | 310 | select PPC_INDIRECT_PCI |
311 | default y | 311 | default y |
@@ -932,6 +932,7 @@ source "arch/powerpc/oprofile/Kconfig" | |||
932 | 932 | ||
933 | config KPROBES | 933 | config KPROBES |
934 | bool "Kprobes (EXPERIMENTAL)" | 934 | bool "Kprobes (EXPERIMENTAL)" |
935 | depends on PPC64 | ||
935 | help | 936 | help |
936 | Kprobes allows you to trap at almost any kernel address and | 937 | Kprobes allows you to trap at almost any kernel address and |
937 | execute a callback function. register_kprobe() establishes | 938 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 5bc11bd36c1f..d41ad2e675db 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -187,7 +187,7 @@ archprepare: checkbin | |||
187 | 187 | ||
188 | # Temporary hack until we have migrated to asm-powerpc | 188 | # Temporary hack until we have migrated to asm-powerpc |
189 | include/asm: arch/$(ARCH)/include/asm | 189 | include/asm: arch/$(ARCH)/include/asm |
190 | arch/$(ARCH)/include/asm: | 190 | arch/$(ARCH)/include/asm: FORCE |
191 | $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi | 191 | $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi |
192 | $(Q)ln -fsn $(srctree)/include/asm-$(OLDARCH) arch/$(ARCH)/include/asm | 192 | $(Q)ln -fsn $(srctree)/include/asm-$(OLDARCH) arch/$(ARCH)/include/asm |
193 | 193 | ||
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 9f09dff9e11a..913962c1dae0 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -1,18 +1,33 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.14-rc4 | 3 | # Linux kernel version: 2.6.15-rc1 |
4 | # Thu Oct 20 08:32:17 2005 | 4 | # Mon Nov 14 15:27:00 2005 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | ||
6 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
8 | CONFIG_PPC_MERGE=y | ||
7 | CONFIG_MMU=y | 9 | CONFIG_MMU=y |
10 | CONFIG_GENERIC_HARDIRQS=y | ||
8 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | 11 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y |
9 | CONFIG_GENERIC_CALIBRATE_DELAY=y | 12 | CONFIG_GENERIC_CALIBRATE_DELAY=y |
10 | CONFIG_GENERIC_ISA_DMA=y | 13 | CONFIG_PPC=y |
11 | CONFIG_EARLY_PRINTK=y | 14 | CONFIG_EARLY_PRINTK=y |
12 | CONFIG_COMPAT=y | 15 | CONFIG_COMPAT=y |
16 | CONFIG_SYSVIPC_COMPAT=y | ||
13 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y |
14 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y |
15 | CONFIG_FORCE_MAX_ZONEORDER=13 | 19 | |
20 | # | ||
21 | # Processor support | ||
22 | # | ||
23 | # CONFIG_POWER4_ONLY is not set | ||
24 | CONFIG_POWER3=y | ||
25 | CONFIG_POWER4=y | ||
26 | CONFIG_PPC_FPU=y | ||
27 | CONFIG_ALTIVEC=y | ||
28 | CONFIG_PPC_STD_MMU=y | ||
29 | CONFIG_SMP=y | ||
30 | CONFIG_NR_CPUS=128 | ||
16 | 31 | ||
17 | # | 32 | # |
18 | # Code maturity level options | 33 | # Code maturity level options |
@@ -68,75 +83,103 @@ CONFIG_MODVERSIONS=y | |||
68 | CONFIG_MODULE_SRCVERSION_ALL=y | 83 | CONFIG_MODULE_SRCVERSION_ALL=y |
69 | CONFIG_KMOD=y | 84 | CONFIG_KMOD=y |
70 | CONFIG_STOP_MACHINE=y | 85 | CONFIG_STOP_MACHINE=y |
71 | CONFIG_SYSVIPC_COMPAT=y | 86 | |
87 | # | ||
88 | # Block layer | ||
89 | # | ||
90 | |||
91 | # | ||
92 | # IO Schedulers | ||
93 | # | ||
94 | CONFIG_IOSCHED_NOOP=y | ||
95 | CONFIG_IOSCHED_AS=y | ||
96 | CONFIG_IOSCHED_DEADLINE=y | ||
97 | CONFIG_IOSCHED_CFQ=y | ||
98 | CONFIG_DEFAULT_AS=y | ||
99 | # CONFIG_DEFAULT_DEADLINE is not set | ||
100 | # CONFIG_DEFAULT_CFQ is not set | ||
101 | # CONFIG_DEFAULT_NOOP is not set | ||
102 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
72 | 103 | ||
73 | # | 104 | # |
74 | # Platform support | 105 | # Platform support |
75 | # | 106 | # |
76 | # CONFIG_PPC_ISERIES is not set | ||
77 | CONFIG_PPC_MULTIPLATFORM=y | 107 | CONFIG_PPC_MULTIPLATFORM=y |
108 | # CONFIG_PPC_ISERIES is not set | ||
109 | # CONFIG_EMBEDDED6xx is not set | ||
110 | # CONFIG_APUS is not set | ||
78 | CONFIG_PPC_PSERIES=y | 111 | CONFIG_PPC_PSERIES=y |
79 | # CONFIG_PPC_BPA is not set | ||
80 | # CONFIG_PPC_PMAC is not set | 112 | # CONFIG_PPC_PMAC is not set |
81 | # CONFIG_PPC_MAPLE is not set | 113 | # CONFIG_PPC_MAPLE is not set |
82 | CONFIG_PPC=y | 114 | # CONFIG_PPC_CELL is not set |
83 | CONFIG_PPC64=y | ||
84 | CONFIG_PPC_OF=y | 115 | CONFIG_PPC_OF=y |
85 | CONFIG_XICS=y | 116 | CONFIG_XICS=y |
117 | # CONFIG_U3_DART is not set | ||
86 | CONFIG_MPIC=y | 118 | CONFIG_MPIC=y |
87 | CONFIG_ALTIVEC=y | 119 | CONFIG_PPC_RTAS=y |
88 | CONFIG_PPC_SPLPAR=y | 120 | CONFIG_RTAS_ERROR_LOGGING=y |
89 | CONFIG_KEXEC=y | 121 | CONFIG_RTAS_PROC=y |
122 | CONFIG_RTAS_FLASH=m | ||
123 | # CONFIG_MMIO_NVRAM is not set | ||
90 | CONFIG_IBMVIO=y | 124 | CONFIG_IBMVIO=y |
91 | # CONFIG_U3_DART is not set | 125 | # CONFIG_PPC_MPC106 is not set |
92 | # CONFIG_BOOTX_TEXT is not set | 126 | # CONFIG_GENERIC_TBSYNC is not set |
93 | # CONFIG_POWER4_ONLY is not set | 127 | # CONFIG_CPU_FREQ is not set |
128 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
129 | |||
130 | # | ||
131 | # Kernel options | ||
132 | # | ||
133 | # CONFIG_HZ_100 is not set | ||
134 | CONFIG_HZ_250=y | ||
135 | # CONFIG_HZ_1000 is not set | ||
136 | CONFIG_HZ=250 | ||
137 | CONFIG_PREEMPT_NONE=y | ||
138 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
139 | # CONFIG_PREEMPT is not set | ||
140 | # CONFIG_PREEMPT_BKL is not set | ||
141 | CONFIG_BINFMT_ELF=y | ||
142 | # CONFIG_BINFMT_MISC is not set | ||
143 | CONFIG_FORCE_MAX_ZONEORDER=13 | ||
94 | CONFIG_IOMMU_VMERGE=y | 144 | CONFIG_IOMMU_VMERGE=y |
95 | CONFIG_SMP=y | 145 | CONFIG_HOTPLUG_CPU=y |
96 | CONFIG_NR_CPUS=128 | 146 | CONFIG_KEXEC=y |
147 | # CONFIG_IRQ_ALL_CPUS is not set | ||
148 | CONFIG_PPC_SPLPAR=y | ||
149 | CONFIG_EEH=y | ||
150 | CONFIG_SCANLOG=m | ||
151 | CONFIG_LPARCFG=y | ||
152 | CONFIG_NUMA=y | ||
97 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | 153 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y |
98 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
99 | CONFIG_ARCH_DISCONTIGMEM_ENABLE=y | ||
100 | CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y | ||
101 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | 154 | CONFIG_ARCH_SPARSEMEM_ENABLE=y |
155 | CONFIG_ARCH_SPARSEMEM_DEFAULT=y | ||
102 | CONFIG_SELECT_MEMORY_MODEL=y | 156 | CONFIG_SELECT_MEMORY_MODEL=y |
103 | # CONFIG_FLATMEM_MANUAL is not set | 157 | # CONFIG_FLATMEM_MANUAL is not set |
104 | CONFIG_DISCONTIGMEM_MANUAL=y | 158 | # CONFIG_DISCONTIGMEM_MANUAL is not set |
105 | # CONFIG_SPARSEMEM_MANUAL is not set | 159 | CONFIG_SPARSEMEM_MANUAL=y |
106 | CONFIG_DISCONTIGMEM=y | 160 | CONFIG_SPARSEMEM=y |
107 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
108 | CONFIG_NEED_MULTIPLE_NODES=y | 161 | CONFIG_NEED_MULTIPLE_NODES=y |
162 | CONFIG_HAVE_MEMORY_PRESENT=y | ||
109 | # CONFIG_SPARSEMEM_STATIC is not set | 163 | # CONFIG_SPARSEMEM_STATIC is not set |
164 | CONFIG_SPARSEMEM_EXTREME=y | ||
165 | # CONFIG_MEMORY_HOTPLUG is not set | ||
166 | CONFIG_SPLIT_PTLOCK_CPUS=4096 | ||
110 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y | 167 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y |
111 | CONFIG_NODES_SPAN_OTHER_NODES=y | 168 | CONFIG_NODES_SPAN_OTHER_NODES=y |
112 | CONFIG_NUMA=y | 169 | # CONFIG_PPC_64K_PAGES is not set |
113 | CONFIG_SCHED_SMT=y | 170 | CONFIG_SCHED_SMT=y |
114 | CONFIG_PREEMPT_NONE=y | ||
115 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
116 | # CONFIG_PREEMPT is not set | ||
117 | # CONFIG_PREEMPT_BKL is not set | ||
118 | # CONFIG_HZ_100 is not set | ||
119 | CONFIG_HZ_250=y | ||
120 | # CONFIG_HZ_1000 is not set | ||
121 | CONFIG_HZ=250 | ||
122 | CONFIG_EEH=y | ||
123 | CONFIG_GENERIC_HARDIRQS=y | ||
124 | CONFIG_PPC_RTAS=y | ||
125 | CONFIG_RTAS_PROC=y | ||
126 | CONFIG_RTAS_FLASH=m | ||
127 | CONFIG_SCANLOG=m | ||
128 | CONFIG_LPARCFG=y | ||
129 | CONFIG_SECCOMP=y | ||
130 | CONFIG_BINFMT_ELF=y | ||
131 | # CONFIG_BINFMT_MISC is not set | ||
132 | CONFIG_HOTPLUG_CPU=y | ||
133 | CONFIG_PROC_DEVICETREE=y | 171 | CONFIG_PROC_DEVICETREE=y |
134 | # CONFIG_CMDLINE_BOOL is not set | 172 | # CONFIG_CMDLINE_BOOL is not set |
173 | # CONFIG_PM is not set | ||
174 | CONFIG_SECCOMP=y | ||
135 | CONFIG_ISA_DMA_API=y | 175 | CONFIG_ISA_DMA_API=y |
136 | 176 | ||
137 | # | 177 | # |
138 | # Bus Options | 178 | # Bus options |
139 | # | 179 | # |
180 | CONFIG_GENERIC_ISA_DMA=y | ||
181 | CONFIG_PPC_I8259=y | ||
182 | # CONFIG_PPC_INDIRECT_PCI is not set | ||
140 | CONFIG_PCI=y | 183 | CONFIG_PCI=y |
141 | CONFIG_PCI_DOMAINS=y | 184 | CONFIG_PCI_DOMAINS=y |
142 | CONFIG_PCI_LEGACY_PROC=y | 185 | CONFIG_PCI_LEGACY_PROC=y |
@@ -156,6 +199,7 @@ CONFIG_HOTPLUG_PCI=m | |||
156 | # CONFIG_HOTPLUG_PCI_SHPC is not set | 199 | # CONFIG_HOTPLUG_PCI_SHPC is not set |
157 | CONFIG_HOTPLUG_PCI_RPA=m | 200 | CONFIG_HOTPLUG_PCI_RPA=m |
158 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m | 201 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m |
202 | CONFIG_KERNEL_START=0xc000000000000000 | ||
159 | 203 | ||
160 | # | 204 | # |
161 | # Networking | 205 | # Networking |
@@ -197,6 +241,10 @@ CONFIG_TCP_CONG_BIC=y | |||
197 | # CONFIG_IPV6 is not set | 241 | # CONFIG_IPV6 is not set |
198 | CONFIG_NETFILTER=y | 242 | CONFIG_NETFILTER=y |
199 | # CONFIG_NETFILTER_DEBUG is not set | 243 | # CONFIG_NETFILTER_DEBUG is not set |
244 | |||
245 | # | ||
246 | # Core Netfilter Configuration | ||
247 | # | ||
200 | CONFIG_NETFILTER_NETLINK=y | 248 | CONFIG_NETFILTER_NETLINK=y |
201 | CONFIG_NETFILTER_NETLINK_QUEUE=m | 249 | CONFIG_NETFILTER_NETLINK_QUEUE=m |
202 | CONFIG_NETFILTER_NETLINK_LOG=m | 250 | CONFIG_NETFILTER_NETLINK_LOG=m |
@@ -299,6 +347,10 @@ CONFIG_LLC=y | |||
299 | # CONFIG_NET_DIVERT is not set | 347 | # CONFIG_NET_DIVERT is not set |
300 | # CONFIG_ECONET is not set | 348 | # CONFIG_ECONET is not set |
301 | # CONFIG_WAN_ROUTER is not set | 349 | # CONFIG_WAN_ROUTER is not set |
350 | |||
351 | # | ||
352 | # QoS and/or fair queueing | ||
353 | # | ||
302 | # CONFIG_NET_SCHED is not set | 354 | # CONFIG_NET_SCHED is not set |
303 | CONFIG_NET_CLS_ROUTE=y | 355 | CONFIG_NET_CLS_ROUTE=y |
304 | 356 | ||
@@ -368,14 +420,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16 | |||
368 | CONFIG_BLK_DEV_RAM_SIZE=65536 | 420 | CONFIG_BLK_DEV_RAM_SIZE=65536 |
369 | CONFIG_BLK_DEV_INITRD=y | 421 | CONFIG_BLK_DEV_INITRD=y |
370 | # CONFIG_CDROM_PKTCDVD is not set | 422 | # CONFIG_CDROM_PKTCDVD is not set |
371 | |||
372 | # | ||
373 | # IO Schedulers | ||
374 | # | ||
375 | CONFIG_IOSCHED_NOOP=y | ||
376 | CONFIG_IOSCHED_AS=y | ||
377 | CONFIG_IOSCHED_DEADLINE=y | ||
378 | CONFIG_IOSCHED_CFQ=y | ||
379 | # CONFIG_ATA_OVER_ETH is not set | 423 | # CONFIG_ATA_OVER_ETH is not set |
380 | 424 | ||
381 | # | 425 | # |
@@ -473,6 +517,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m | |||
473 | # | 517 | # |
474 | # SCSI low-level drivers | 518 | # SCSI low-level drivers |
475 | # | 519 | # |
520 | # CONFIG_ISCSI_TCP is not set | ||
476 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set | 521 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set |
477 | # CONFIG_SCSI_3W_9XXX is not set | 522 | # CONFIG_SCSI_3W_9XXX is not set |
478 | # CONFIG_SCSI_ACARD is not set | 523 | # CONFIG_SCSI_ACARD is not set |
@@ -559,6 +604,7 @@ CONFIG_DM_MULTIPATH_EMC=m | |||
559 | # | 604 | # |
560 | # Macintosh device drivers | 605 | # Macintosh device drivers |
561 | # | 606 | # |
607 | # CONFIG_WINDFARM is not set | ||
562 | 608 | ||
563 | # | 609 | # |
564 | # Network device support | 610 | # Network device support |
@@ -645,7 +691,6 @@ CONFIG_IXGB=m | |||
645 | # CONFIG_IXGB_NAPI is not set | 691 | # CONFIG_IXGB_NAPI is not set |
646 | CONFIG_S2IO=m | 692 | CONFIG_S2IO=m |
647 | # CONFIG_S2IO_NAPI is not set | 693 | # CONFIG_S2IO_NAPI is not set |
648 | # CONFIG_2BUFF_MODE is not set | ||
649 | 694 | ||
650 | # | 695 | # |
651 | # Token Ring devices | 696 | # Token Ring devices |
@@ -674,6 +719,7 @@ CONFIG_PPP_ASYNC=m | |||
674 | CONFIG_PPP_SYNC_TTY=m | 719 | CONFIG_PPP_SYNC_TTY=m |
675 | CONFIG_PPP_DEFLATE=m | 720 | CONFIG_PPP_DEFLATE=m |
676 | CONFIG_PPP_BSDCOMP=m | 721 | CONFIG_PPP_BSDCOMP=m |
722 | # CONFIG_PPP_MPPE is not set | ||
677 | CONFIG_PPPOE=m | 723 | CONFIG_PPPOE=m |
678 | # CONFIG_SLIP is not set | 724 | # CONFIG_SLIP is not set |
679 | # CONFIG_NET_FC is not set | 725 | # CONFIG_NET_FC is not set |
@@ -784,6 +830,8 @@ CONFIG_HVCS=m | |||
784 | # | 830 | # |
785 | # CONFIG_WATCHDOG is not set | 831 | # CONFIG_WATCHDOG is not set |
786 | # CONFIG_RTC is not set | 832 | # CONFIG_RTC is not set |
833 | CONFIG_GEN_RTC=y | ||
834 | # CONFIG_GEN_RTC_X is not set | ||
787 | # CONFIG_DTLK is not set | 835 | # CONFIG_DTLK is not set |
788 | # CONFIG_R3964 is not set | 836 | # CONFIG_R3964 is not set |
789 | # CONFIG_APPLICOM is not set | 837 | # CONFIG_APPLICOM is not set |
@@ -801,6 +849,7 @@ CONFIG_MAX_RAW_DEVS=1024 | |||
801 | # TPM devices | 849 | # TPM devices |
802 | # | 850 | # |
803 | # CONFIG_TCG_TPM is not set | 851 | # CONFIG_TCG_TPM is not set |
852 | # CONFIG_TELCLOCK is not set | ||
804 | 853 | ||
805 | # | 854 | # |
806 | # I2C support | 855 | # I2C support |
@@ -852,6 +901,7 @@ CONFIG_I2C_ALGOBIT=y | |||
852 | # CONFIG_SENSORS_PCF8591 is not set | 901 | # CONFIG_SENSORS_PCF8591 is not set |
853 | # CONFIG_SENSORS_RTC8564 is not set | 902 | # CONFIG_SENSORS_RTC8564 is not set |
854 | # CONFIG_SENSORS_MAX6875 is not set | 903 | # CONFIG_SENSORS_MAX6875 is not set |
904 | # CONFIG_RTC_X1205_I2C is not set | ||
855 | # CONFIG_I2C_DEBUG_CORE is not set | 905 | # CONFIG_I2C_DEBUG_CORE is not set |
856 | # CONFIG_I2C_DEBUG_ALGO is not set | 906 | # CONFIG_I2C_DEBUG_ALGO is not set |
857 | # CONFIG_I2C_DEBUG_BUS is not set | 907 | # CONFIG_I2C_DEBUG_BUS is not set |
@@ -893,7 +943,6 @@ CONFIG_FB=y | |||
893 | CONFIG_FB_CFB_FILLRECT=y | 943 | CONFIG_FB_CFB_FILLRECT=y |
894 | CONFIG_FB_CFB_COPYAREA=y | 944 | CONFIG_FB_CFB_COPYAREA=y |
895 | CONFIG_FB_CFB_IMAGEBLIT=y | 945 | CONFIG_FB_CFB_IMAGEBLIT=y |
896 | CONFIG_FB_SOFT_CURSOR=y | ||
897 | CONFIG_FB_MACMODES=y | 946 | CONFIG_FB_MACMODES=y |
898 | CONFIG_FB_MODE_HELPERS=y | 947 | CONFIG_FB_MODE_HELPERS=y |
899 | CONFIG_FB_TILEBLITTING=y | 948 | CONFIG_FB_TILEBLITTING=y |
@@ -905,6 +954,7 @@ CONFIG_FB_OF=y | |||
905 | # CONFIG_FB_ASILIANT is not set | 954 | # CONFIG_FB_ASILIANT is not set |
906 | # CONFIG_FB_IMSTT is not set | 955 | # CONFIG_FB_IMSTT is not set |
907 | # CONFIG_FB_VGA16 is not set | 956 | # CONFIG_FB_VGA16 is not set |
957 | # CONFIG_FB_S1D13XXX is not set | ||
908 | # CONFIG_FB_NVIDIA is not set | 958 | # CONFIG_FB_NVIDIA is not set |
909 | # CONFIG_FB_RIVA is not set | 959 | # CONFIG_FB_RIVA is not set |
910 | CONFIG_FB_MATROX=y | 960 | CONFIG_FB_MATROX=y |
@@ -927,7 +977,6 @@ CONFIG_FB_RADEON_I2C=y | |||
927 | # CONFIG_FB_VOODOO1 is not set | 977 | # CONFIG_FB_VOODOO1 is not set |
928 | # CONFIG_FB_CYBLA is not set | 978 | # CONFIG_FB_CYBLA is not set |
929 | # CONFIG_FB_TRIDENT is not set | 979 | # CONFIG_FB_TRIDENT is not set |
930 | # CONFIG_FB_S1D13XXX is not set | ||
931 | # CONFIG_FB_VIRTUAL is not set | 980 | # CONFIG_FB_VIRTUAL is not set |
932 | 981 | ||
933 | # | 982 | # |
@@ -936,6 +985,7 @@ CONFIG_FB_RADEON_I2C=y | |||
936 | # CONFIG_VGA_CONSOLE is not set | 985 | # CONFIG_VGA_CONSOLE is not set |
937 | CONFIG_DUMMY_CONSOLE=y | 986 | CONFIG_DUMMY_CONSOLE=y |
938 | CONFIG_FRAMEBUFFER_CONSOLE=y | 987 | CONFIG_FRAMEBUFFER_CONSOLE=y |
988 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
939 | # CONFIG_FONTS is not set | 989 | # CONFIG_FONTS is not set |
940 | CONFIG_FONT_8x8=y | 990 | CONFIG_FONT_8x8=y |
941 | CONFIG_FONT_8x16=y | 991 | CONFIG_FONT_8x16=y |
@@ -990,12 +1040,15 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y | |||
990 | # | 1040 | # |
991 | # USB Device Class drivers | 1041 | # USB Device Class drivers |
992 | # | 1042 | # |
993 | # CONFIG_USB_BLUETOOTH_TTY is not set | ||
994 | # CONFIG_USB_ACM is not set | 1043 | # CONFIG_USB_ACM is not set |
995 | # CONFIG_USB_PRINTER is not set | 1044 | # CONFIG_USB_PRINTER is not set |
996 | 1045 | ||
997 | # | 1046 | # |
998 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information | 1047 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' |
1048 | # | ||
1049 | |||
1050 | # | ||
1051 | # may also be needed; see USB_STORAGE Help for more information | ||
999 | # | 1052 | # |
1000 | CONFIG_USB_STORAGE=y | 1053 | CONFIG_USB_STORAGE=y |
1001 | # CONFIG_USB_STORAGE_DEBUG is not set | 1054 | # CONFIG_USB_STORAGE_DEBUG is not set |
@@ -1106,6 +1159,7 @@ CONFIG_INFINIBAND_MTHCA=m | |||
1106 | # CONFIG_INFINIBAND_MTHCA_DEBUG is not set | 1159 | # CONFIG_INFINIBAND_MTHCA_DEBUG is not set |
1107 | CONFIG_INFINIBAND_IPOIB=m | 1160 | CONFIG_INFINIBAND_IPOIB=m |
1108 | # CONFIG_INFINIBAND_IPOIB_DEBUG is not set | 1161 | # CONFIG_INFINIBAND_IPOIB_DEBUG is not set |
1162 | # CONFIG_INFINIBAND_SRP is not set | ||
1109 | 1163 | ||
1110 | # | 1164 | # |
1111 | # SN Devices | 1165 | # SN Devices |
@@ -1288,10 +1342,25 @@ CONFIG_NLS_ISO8859_1=y | |||
1288 | # CONFIG_NLS_UTF8 is not set | 1342 | # CONFIG_NLS_UTF8 is not set |
1289 | 1343 | ||
1290 | # | 1344 | # |
1291 | # Profiling support | 1345 | # Library routines |
1346 | # | ||
1347 | CONFIG_CRC_CCITT=m | ||
1348 | # CONFIG_CRC16 is not set | ||
1349 | CONFIG_CRC32=y | ||
1350 | CONFIG_LIBCRC32C=m | ||
1351 | CONFIG_ZLIB_INFLATE=y | ||
1352 | CONFIG_ZLIB_DEFLATE=m | ||
1353 | CONFIG_TEXTSEARCH=y | ||
1354 | CONFIG_TEXTSEARCH_KMP=m | ||
1355 | CONFIG_TEXTSEARCH_BM=m | ||
1356 | CONFIG_TEXTSEARCH_FSM=m | ||
1357 | |||
1358 | # | ||
1359 | # Instrumentation Support | ||
1292 | # | 1360 | # |
1293 | CONFIG_PROFILING=y | 1361 | CONFIG_PROFILING=y |
1294 | CONFIG_OPROFILE=y | 1362 | CONFIG_OPROFILE=y |
1363 | # CONFIG_KPROBES is not set | ||
1295 | 1364 | ||
1296 | # | 1365 | # |
1297 | # Kernel hacking | 1366 | # Kernel hacking |
@@ -1308,14 +1377,15 @@ CONFIG_DETECT_SOFTLOCKUP=y | |||
1308 | # CONFIG_DEBUG_KOBJECT is not set | 1377 | # CONFIG_DEBUG_KOBJECT is not set |
1309 | # CONFIG_DEBUG_INFO is not set | 1378 | # CONFIG_DEBUG_INFO is not set |
1310 | CONFIG_DEBUG_FS=y | 1379 | CONFIG_DEBUG_FS=y |
1380 | # CONFIG_DEBUG_VM is not set | ||
1381 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1311 | CONFIG_DEBUG_STACKOVERFLOW=y | 1382 | CONFIG_DEBUG_STACKOVERFLOW=y |
1312 | # CONFIG_KPROBES is not set | ||
1313 | CONFIG_DEBUG_STACK_USAGE=y | 1383 | CONFIG_DEBUG_STACK_USAGE=y |
1314 | CONFIG_DEBUGGER=y | 1384 | CONFIG_DEBUGGER=y |
1315 | CONFIG_XMON=y | 1385 | CONFIG_XMON=y |
1316 | CONFIG_XMON_DEFAULT=y | 1386 | CONFIG_XMON_DEFAULT=y |
1317 | # CONFIG_PPCDBG is not set | ||
1318 | CONFIG_IRQSTACKS=y | 1387 | CONFIG_IRQSTACKS=y |
1388 | # CONFIG_BOOTX_TEXT is not set | ||
1319 | 1389 | ||
1320 | # | 1390 | # |
1321 | # Security options | 1391 | # Security options |
@@ -1355,17 +1425,3 @@ CONFIG_CRYPTO_TEST=m | |||
1355 | # | 1425 | # |
1356 | # Hardware crypto devices | 1426 | # Hardware crypto devices |
1357 | # | 1427 | # |
1358 | |||
1359 | # | ||
1360 | # Library routines | ||
1361 | # | ||
1362 | CONFIG_CRC_CCITT=m | ||
1363 | # CONFIG_CRC16 is not set | ||
1364 | CONFIG_CRC32=y | ||
1365 | CONFIG_LIBCRC32C=m | ||
1366 | CONFIG_ZLIB_INFLATE=y | ||
1367 | CONFIG_ZLIB_DEFLATE=m | ||
1368 | CONFIG_TEXTSEARCH=y | ||
1369 | CONFIG_TEXTSEARCH_KMP=m | ||
1370 | CONFIG_TEXTSEARCH_BM=m | ||
1371 | CONFIG_TEXTSEARCH_FSM=m | ||
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9a74b7ab03a4..4970e3721a84 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -25,7 +25,7 @@ obj-$(CONFIG_PPC_OF) += of_device.o | |||
25 | procfs-$(CONFIG_PPC64) := proc_ppc64.o | 25 | procfs-$(CONFIG_PPC64) := proc_ppc64.o |
26 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 26 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
27 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o | 27 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o |
28 | obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y) | 28 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y) |
29 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 29 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
30 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 30 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
31 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 31 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
@@ -49,12 +49,23 @@ extra-y += vmlinux.lds | |||
49 | obj-y += process.o init_task.o time.o \ | 49 | obj-y += process.o init_task.o time.o \ |
50 | prom.o traps.o setup-common.o | 50 | prom.o traps.o setup-common.o |
51 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o | 51 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o |
52 | obj-$(CONFIG_PPC64) += misc_64.o | 52 | obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o |
53 | obj-$(CONFIG_PPC_OF) += prom_init.o | 53 | obj-$(CONFIG_PPC_OF) += prom_init.o |
54 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 54 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
55 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 55 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
56 | obj-$(CONFIG_6xx) += idle_6xx.o | 56 | obj-$(CONFIG_6xx) += idle_6xx.o |
57 | obj-$(CONFIG_SMP) += smp.o | 57 | obj-$(CONFIG_SMP) += smp.o |
58 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
59 | |||
60 | module-$(CONFIG_PPC64) += module_64.o | ||
61 | obj-$(CONFIG_MODULES) += $(module-y) | ||
62 | |||
63 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | ||
64 | pci_direct_iommu.o iomap.o | ||
65 | obj-$(CONFIG_PCI) += $(pci64-y) | ||
66 | |||
67 | kexec64-$(CONFIG_PPC64) += machine_kexec_64.o | ||
68 | obj-$(CONFIG_KEXEC) += $(kexec64-y) | ||
58 | 69 | ||
59 | ifeq ($(CONFIG_PPC_ISERIES),y) | 70 | ifeq ($(CONFIG_PPC_ISERIES),y) |
60 | $(obj)/head_64.o: $(obj)/lparmap.s | 71 | $(obj)/head_64.o: $(obj)/lparmap.s |
@@ -62,11 +73,8 @@ AFLAGS_head_64.o += -I$(obj) | |||
62 | endif | 73 | endif |
63 | 74 | ||
64 | else | 75 | else |
65 | # stuff used from here for ARCH=ppc or ARCH=ppc64 | 76 | # stuff used from here for ARCH=ppc |
66 | smpobj-$(CONFIG_SMP) += smp.o | 77 | smpobj-$(CONFIG_SMP) += smp.o |
67 | obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o \ | ||
68 | setup-common.o $(smpobj-y) | ||
69 | |||
70 | 78 | ||
71 | endif | 79 | endif |
72 | 80 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 4550eb4f4fbd..91538d2445bf 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -270,13 +270,15 @@ int main(void) | |||
270 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); | 270 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); |
271 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); | 271 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); |
272 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); | 272 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); |
273 | DEFINE(TSPC64_TV_SEC, offsetof(struct timespec, tv_sec)); | ||
274 | DEFINE(TSPC64_TV_NSEC, offsetof(struct timespec, tv_nsec)); | ||
273 | DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); | 275 | DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); |
274 | DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); | 276 | DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); |
275 | #else | 277 | #else |
276 | DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); | 278 | DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); |
277 | DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); | 279 | DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); |
278 | DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec)); | 280 | DEFINE(TSPC32_TV_SEC, offsetof(struct timespec, tv_sec)); |
279 | DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); | 281 | DEFINE(TSPC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); |
280 | #endif | 282 | #endif |
281 | /* timeval/timezone offsets for use by vdso */ | 283 | /* timeval/timezone offsets for use by vdso */ |
282 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | 284 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); |
diff --git a/arch/ppc64/kernel/dma.c b/arch/powerpc/kernel/dma_64.c index 7c3419656ccc..7c3419656ccc 100644 --- a/arch/ppc64/kernel/dma.c +++ b/arch/powerpc/kernel/dma_64.c | |||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 5063c603fad4..8d60fa99fc4b 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -24,7 +24,7 @@ | |||
24 | * Copyright 2002-2004 MontaVista Software, Inc. | 24 | * Copyright 2002-2004 MontaVista Software, Inc. |
25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> | 25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> |
26 | * Copyright 2004 Freescale Semiconductor, Inc | 26 | * Copyright 2004 Freescale Semiconductor, Inc |
27 | * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> | 27 | * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org> |
28 | * | 28 | * |
29 | * This program is free software; you can redistribute it and/or modify it | 29 | * This program is free software; you can redistribute it and/or modify it |
30 | * under the terms of the GNU General Public License as published by the | 30 | * under the terms of the GNU General Public License as published by the |
diff --git a/arch/ppc64/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..6160c8dbb7c5 100644 --- a/arch/ppc64/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
diff --git a/arch/ppc64/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4d9b4388918b..4d9b4388918b 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 4b7940693f3d..5a71ed9612fe 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -71,6 +71,11 @@ | |||
71 | #include <asm/paca.h> | 71 | #include <asm/paca.h> |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | int __irq_offset_value; | ||
75 | #ifdef CONFIG_PPC32 | ||
76 | EXPORT_SYMBOL(__irq_offset_value); | ||
77 | #endif | ||
78 | |||
74 | static int ppc_spurious_interrupts; | 79 | static int ppc_spurious_interrupts; |
75 | 80 | ||
76 | #if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) | 81 | #if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) |
@@ -98,7 +103,6 @@ extern atomic_t ipi_sent; | |||
98 | EXPORT_SYMBOL(irq_desc); | 103 | EXPORT_SYMBOL(irq_desc); |
99 | 104 | ||
100 | int distribute_irqs = 1; | 105 | int distribute_irqs = 1; |
101 | int __irq_offset_value; | ||
102 | u64 ppc64_interrupt_controller; | 106 | u64 ppc64_interrupt_controller; |
103 | #endif /* CONFIG_PPC64 */ | 107 | #endif /* CONFIG_PPC64 */ |
104 | 108 | ||
@@ -311,7 +315,6 @@ void __init init_IRQ(void) | |||
311 | } | 315 | } |
312 | 316 | ||
313 | #ifdef CONFIG_PPC64 | 317 | #ifdef CONFIG_PPC64 |
314 | #ifndef CONFIG_PPC_ISERIES | ||
315 | /* | 318 | /* |
316 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. | 319 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. |
317 | */ | 320 | */ |
@@ -420,8 +423,6 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
420 | 423 | ||
421 | } | 424 | } |
422 | 425 | ||
423 | #endif /* CONFIG_PPC_ISERIES */ | ||
424 | |||
425 | #ifdef CONFIG_IRQSTACKS | 426 | #ifdef CONFIG_IRQSTACKS |
426 | struct thread_info *softirq_ctx[NR_CPUS]; | 427 | struct thread_info *softirq_ctx[NR_CPUS]; |
427 | struct thread_info *hardirq_ctx[NR_CPUS]; | 428 | struct thread_info *hardirq_ctx[NR_CPUS]; |
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 511af54e6230..511af54e6230 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 1b3ba8a440a6..9dda16ccde78 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -42,32 +42,6 @@ | |||
42 | 42 | ||
43 | /* #define LPARCFG_DEBUG */ | 43 | /* #define LPARCFG_DEBUG */ |
44 | 44 | ||
45 | /* find a better place for this function... */ | ||
46 | static void log_plpar_hcall_return(unsigned long rc, char *tag) | ||
47 | { | ||
48 | if (rc == 0) /* success, return */ | ||
49 | return; | ||
50 | /* check for null tag ? */ | ||
51 | if (rc == H_Hardware) | ||
52 | printk(KERN_INFO | ||
53 | "plpar-hcall (%s) failed with hardware fault\n", tag); | ||
54 | else if (rc == H_Function) | ||
55 | printk(KERN_INFO | ||
56 | "plpar-hcall (%s) failed; function not allowed\n", tag); | ||
57 | else if (rc == H_Authority) | ||
58 | printk(KERN_INFO | ||
59 | "plpar-hcall (%s) failed; not authorized to this function\n", | ||
60 | tag); | ||
61 | else if (rc == H_Parameter) | ||
62 | printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", | ||
63 | tag); | ||
64 | else | ||
65 | printk(KERN_INFO | ||
66 | "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", | ||
67 | tag, rc); | ||
68 | |||
69 | } | ||
70 | |||
71 | static struct proc_dir_entry *proc_ppc64_lparcfg; | 45 | static struct proc_dir_entry *proc_ppc64_lparcfg; |
72 | #define LPARCFG_BUFF_SIZE 4096 | 46 | #define LPARCFG_BUFF_SIZE 4096 |
73 | 47 | ||
@@ -172,6 +146,31 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
172 | /* | 146 | /* |
173 | * Methods used to fetch LPAR data when running on a pSeries platform. | 147 | * Methods used to fetch LPAR data when running on a pSeries platform. |
174 | */ | 148 | */ |
149 | /* find a better place for this function... */ | ||
150 | static void log_plpar_hcall_return(unsigned long rc, char *tag) | ||
151 | { | ||
152 | if (rc == 0) /* success, return */ | ||
153 | return; | ||
154 | /* check for null tag ? */ | ||
155 | if (rc == H_Hardware) | ||
156 | printk(KERN_INFO | ||
157 | "plpar-hcall (%s) failed with hardware fault\n", tag); | ||
158 | else if (rc == H_Function) | ||
159 | printk(KERN_INFO | ||
160 | "plpar-hcall (%s) failed; function not allowed\n", tag); | ||
161 | else if (rc == H_Authority) | ||
162 | printk(KERN_INFO | ||
163 | "plpar-hcall (%s) failed; not authorized to this function\n", | ||
164 | tag); | ||
165 | else if (rc == H_Parameter) | ||
166 | printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", | ||
167 | tag); | ||
168 | else | ||
169 | printk(KERN_INFO | ||
170 | "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", | ||
171 | tag, rc); | ||
172 | |||
173 | } | ||
175 | 174 | ||
176 | /* | 175 | /* |
177 | * H_GET_PPP hcall returns info in 4 parms. | 176 | * H_GET_PPP hcall returns info in 4 parms. |
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec_64.c index 07ea03598c00..97c51e452be7 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -185,8 +185,8 @@ void kexec_copy_flush(struct kimage *image) | |||
185 | */ | 185 | */ |
186 | void kexec_smp_down(void *arg) | 186 | void kexec_smp_down(void *arg) |
187 | { | 187 | { |
188 | if (ppc_md.cpu_irq_down) | 188 | if (ppc_md.kexec_cpu_down) |
189 | ppc_md.cpu_irq_down(1); | 189 | ppc_md.kexec_cpu_down(0, 1); |
190 | 190 | ||
191 | local_irq_disable(); | 191 | local_irq_disable(); |
192 | kexec_smp_wait(); | 192 | kexec_smp_wait(); |
@@ -233,8 +233,8 @@ static void kexec_prepare_cpus(void) | |||
233 | } | 233 | } |
234 | 234 | ||
235 | /* after we tell the others to go down */ | 235 | /* after we tell the others to go down */ |
236 | if (ppc_md.cpu_irq_down) | 236 | if (ppc_md.kexec_cpu_down) |
237 | ppc_md.cpu_irq_down(0); | 237 | ppc_md.kexec_cpu_down(0, 0); |
238 | 238 | ||
239 | put_cpu(); | 239 | put_cpu(); |
240 | 240 | ||
@@ -255,8 +255,8 @@ static void kexec_prepare_cpus(void) | |||
255 | * UP to an SMP kernel. | 255 | * UP to an SMP kernel. |
256 | */ | 256 | */ |
257 | smp_release_cpus(); | 257 | smp_release_cpus(); |
258 | if (ppc_md.cpu_irq_down) | 258 | if (ppc_md.kexec_cpu_down) |
259 | ppc_md.cpu_irq_down(0); | 259 | ppc_md.kexec_cpu_down(0, 0); |
260 | local_irq_disable(); | 260 | local_irq_disable(); |
261 | } | 261 | } |
262 | 262 | ||
@@ -305,3 +305,54 @@ void machine_kexec(struct kimage *image) | |||
305 | ppc_md.hpte_clear_all); | 305 | ppc_md.hpte_clear_all); |
306 | /* NOTREACHED */ | 306 | /* NOTREACHED */ |
307 | } | 307 | } |
308 | |||
309 | /* Values we need to export to the second kernel via the device tree. */ | ||
310 | static unsigned long htab_base, htab_size, kernel_end; | ||
311 | |||
312 | static struct property htab_base_prop = { | ||
313 | .name = "linux,htab-base", | ||
314 | .length = sizeof(unsigned long), | ||
315 | .value = (unsigned char *)&htab_base, | ||
316 | }; | ||
317 | |||
318 | static struct property htab_size_prop = { | ||
319 | .name = "linux,htab-size", | ||
320 | .length = sizeof(unsigned long), | ||
321 | .value = (unsigned char *)&htab_size, | ||
322 | }; | ||
323 | |||
324 | static struct property kernel_end_prop = { | ||
325 | .name = "linux,kernel-end", | ||
326 | .length = sizeof(unsigned long), | ||
327 | .value = (unsigned char *)&kernel_end, | ||
328 | }; | ||
329 | |||
330 | static void __init export_htab_values(void) | ||
331 | { | ||
332 | struct device_node *node; | ||
333 | |||
334 | node = of_find_node_by_path("/chosen"); | ||
335 | if (!node) | ||
336 | return; | ||
337 | |||
338 | kernel_end = __pa(_end); | ||
339 | prom_add_property(node, &kernel_end_prop); | ||
340 | |||
341 | /* On machines with no htab htab_address is NULL */ | ||
342 | if (NULL == htab_address) | ||
343 | goto out; | ||
344 | |||
345 | htab_base = __pa(htab_address); | ||
346 | prom_add_property(node, &htab_base_prop); | ||
347 | |||
348 | htab_size = 1UL << ppc64_pft_size; | ||
349 | prom_add_property(node, &htab_size_prop); | ||
350 | |||
351 | out: | ||
352 | of_node_put(node); | ||
353 | } | ||
354 | |||
355 | void __init kexec_setup(void) | ||
356 | { | ||
357 | export_htab_values(); | ||
358 | } | ||
diff --git a/arch/ppc64/kernel/module.c b/arch/powerpc/kernel/module_64.c index 928b8581fcb0..928b8581fcb0 100644 --- a/arch/ppc64/kernel/module.c +++ b/arch/powerpc/kernel/module_64.c | |||
diff --git a/arch/ppc64/kernel/pci.c b/arch/powerpc/kernel/pci_64.c index 3cef1b8f57f0..3cef1b8f57f0 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/powerpc/kernel/pci_64.c | |||
diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c index e1a32f802c0b..e1a32f802c0b 100644 --- a/arch/ppc64/kernel/pci_direct_iommu.c +++ b/arch/powerpc/kernel/pci_direct_iommu.c | |||
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 12c4c9e9bbc7..12c4c9e9bbc7 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..bdf15dbbf4f0 100644 --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c | |||
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 5dcf4ba05ee8..59846b40d521 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -105,6 +105,13 @@ EXPORT_SYMBOL(__clear_user); | |||
105 | EXPORT_SYMBOL(__strncpy_from_user); | 105 | EXPORT_SYMBOL(__strncpy_from_user); |
106 | EXPORT_SYMBOL(__strnlen_user); | 106 | EXPORT_SYMBOL(__strnlen_user); |
107 | 107 | ||
108 | #ifndef __powerpc64__ | ||
109 | EXPORT_SYMBOL(__ide_mm_insl); | ||
110 | EXPORT_SYMBOL(__ide_mm_outsw); | ||
111 | EXPORT_SYMBOL(__ide_mm_insw); | ||
112 | EXPORT_SYMBOL(__ide_mm_outsl); | ||
113 | #endif | ||
114 | |||
108 | EXPORT_SYMBOL(_insb); | 115 | EXPORT_SYMBOL(_insb); |
109 | EXPORT_SYMBOL(_outsb); | 116 | EXPORT_SYMBOL(_outsb); |
110 | EXPORT_SYMBOL(_insw); | 117 | EXPORT_SYMBOL(_insw); |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6a5b468edb4d..3bf968e74095 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -1368,6 +1368,7 @@ prom_n_addr_cells(struct device_node* np) | |||
1368 | /* No #address-cells property for the root node, default to 1 */ | 1368 | /* No #address-cells property for the root node, default to 1 */ |
1369 | return 1; | 1369 | return 1; |
1370 | } | 1370 | } |
1371 | EXPORT_SYMBOL(prom_n_addr_cells); | ||
1371 | 1372 | ||
1372 | int | 1373 | int |
1373 | prom_n_size_cells(struct device_node* np) | 1374 | prom_n_size_cells(struct device_node* np) |
@@ -1383,6 +1384,7 @@ prom_n_size_cells(struct device_node* np) | |||
1383 | /* No #size-cells property for the root node, default to 1 */ | 1384 | /* No #size-cells property for the root node, default to 1 */ |
1384 | return 1; | 1385 | return 1; |
1385 | } | 1386 | } |
1387 | EXPORT_SYMBOL(prom_n_size_cells); | ||
1386 | 1388 | ||
1387 | /** | 1389 | /** |
1388 | * Work out the sense (active-low level / active-high edge) | 1390 | * Work out the sense (active-low level / active-high edge) |
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c new file mode 100644 index 000000000000..7b948662704c --- /dev/null +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -0,0 +1,105 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/time.h> | ||
3 | #include <linux/timer.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/rtc.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <asm/prom.h> | ||
8 | #include <asm/rtas.h> | ||
9 | #include <asm/time.h> | ||
10 | |||
11 | |||
12 | #define MAX_RTC_WAIT 5000 /* 5 sec */ | ||
13 | #define RTAS_CLOCK_BUSY (-2) | ||
14 | unsigned long __init rtas_get_boot_time(void) | ||
15 | { | ||
16 | int ret[8]; | ||
17 | int error, wait_time; | ||
18 | unsigned long max_wait_tb; | ||
19 | |||
20 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
21 | do { | ||
22 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
23 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
24 | wait_time = rtas_extended_busy_delay_time(error); | ||
25 | /* This is boot time so we spin. */ | ||
26 | udelay(wait_time*1000); | ||
27 | error = RTAS_CLOCK_BUSY; | ||
28 | } | ||
29 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
30 | |||
31 | if (error != 0 && printk_ratelimit()) { | ||
32 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
33 | error); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); | ||
38 | } | ||
39 | |||
40 | /* NOTE: get_rtc_time will get an error if executed in interrupt context | ||
41 | * and if a delay is needed to read the clock. In this case we just | ||
42 | * silently return without updating rtc_tm. | ||
43 | */ | ||
44 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | ||
45 | { | ||
46 | int ret[8]; | ||
47 | int error, wait_time; | ||
48 | unsigned long max_wait_tb; | ||
49 | |||
50 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
51 | do { | ||
52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
54 | if (in_interrupt() && printk_ratelimit()) { | ||
55 | memset(&rtc_tm, 0, sizeof(struct rtc_time)); | ||
56 | printk(KERN_WARNING "error: reading clock" | ||
57 | " would delay interrupt\n"); | ||
58 | return; /* delay not allowed */ | ||
59 | } | ||
60 | wait_time = rtas_extended_busy_delay_time(error); | ||
61 | msleep(wait_time); | ||
62 | error = RTAS_CLOCK_BUSY; | ||
63 | } | ||
64 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
65 | |||
66 | if (error != 0 && printk_ratelimit()) { | ||
67 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
68 | error); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | rtc_tm->tm_sec = ret[5]; | ||
73 | rtc_tm->tm_min = ret[4]; | ||
74 | rtc_tm->tm_hour = ret[3]; | ||
75 | rtc_tm->tm_mday = ret[2]; | ||
76 | rtc_tm->tm_mon = ret[1] - 1; | ||
77 | rtc_tm->tm_year = ret[0] - 1900; | ||
78 | } | ||
79 | |||
80 | int rtas_set_rtc_time(struct rtc_time *tm) | ||
81 | { | ||
82 | int error, wait_time; | ||
83 | unsigned long max_wait_tb; | ||
84 | |||
85 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
86 | do { | ||
87 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, | ||
88 | tm->tm_year + 1900, tm->tm_mon + 1, | ||
89 | tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
90 | tm->tm_sec, 0); | ||
91 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
92 | if (in_interrupt()) | ||
93 | return 1; /* probably decrementer */ | ||
94 | wait_time = rtas_extended_busy_delay_time(error); | ||
95 | msleep(wait_time); | ||
96 | error = RTAS_CLOCK_BUSY; | ||
97 | } | ||
98 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
99 | |||
100 | if (error != 0 && printk_ratelimit()) | ||
101 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | ||
102 | error); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index c98cfcc9cd9a..e5694335bf10 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -57,10 +57,6 @@ extern void power4_idle(void); | |||
57 | boot_infos_t *boot_infos; | 57 | boot_infos_t *boot_infos; |
58 | struct ide_machdep_calls ppc_ide_md; | 58 | struct ide_machdep_calls ppc_ide_md; |
59 | 59 | ||
60 | /* XXX should go elsewhere */ | ||
61 | int __irq_offset_value; | ||
62 | EXPORT_SYMBOL(__irq_offset_value); | ||
63 | |||
64 | int boot_cpuid; | 60 | int boot_cpuid; |
65 | EXPORT_SYMBOL_GPL(boot_cpuid); | 61 | EXPORT_SYMBOL_GPL(boot_cpuid); |
66 | int boot_cpuid_phys; | 62 | int boot_cpuid_phys; |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index fdbd9f9122f2..608fee7c7e20 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/firmware.h> | 59 | #include <asm/firmware.h> |
60 | #include <asm/xmon.h> | 60 | #include <asm/xmon.h> |
61 | #include <asm/udbg.h> | 61 | #include <asm/udbg.h> |
62 | #include <asm/kexec.h> | ||
62 | 63 | ||
63 | #include "setup.h" | 64 | #include "setup.h" |
64 | 65 | ||
@@ -415,6 +416,10 @@ void __init setup_system(void) | |||
415 | */ | 416 | */ |
416 | unflatten_device_tree(); | 417 | unflatten_device_tree(); |
417 | 418 | ||
419 | #ifdef CONFIG_KEXEC | ||
420 | kexec_setup(); /* requires unflattened device tree. */ | ||
421 | #endif | ||
422 | |||
418 | /* | 423 | /* |
419 | * Fill the ppc64_caches & systemcfg structures with informations | 424 | * Fill the ppc64_caches & systemcfg structures with informations |
420 | * retreived from the device-tree. Need to be called before | 425 | * retreived from the device-tree. Need to be called before |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 8bdf95b7e420..5a2eba60dd39 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -403,8 +403,6 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | |||
403 | ELF_NFPREG * sizeof(double))) | 403 | ELF_NFPREG * sizeof(double))) |
404 | return 1; | 404 | return 1; |
405 | 405 | ||
406 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | ||
407 | |||
408 | #ifdef CONFIG_ALTIVEC | 406 | #ifdef CONFIG_ALTIVEC |
409 | /* save altivec registers */ | 407 | /* save altivec registers */ |
410 | if (current->thread.used_vr) { | 408 | if (current->thread.used_vr) { |
@@ -818,6 +816,9 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
818 | goto badframe; | 816 | goto badframe; |
819 | regs->link = (unsigned long) frame->tramp; | 817 | regs->link = (unsigned long) frame->tramp; |
820 | } | 818 | } |
819 | |||
820 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | ||
821 | |||
821 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 822 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
822 | goto badframe; | 823 | goto badframe; |
823 | regs->gpr[1] = newsp; | 824 | regs->gpr[1] = newsp; |
@@ -1097,6 +1098,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1097 | regs->link = (unsigned long) frame->mctx.tramp; | 1098 | regs->link = (unsigned long) frame->mctx.tramp; |
1098 | } | 1099 | } |
1099 | 1100 | ||
1101 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | ||
1102 | |||
1100 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 1103 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
1101 | goto badframe; | 1104 | goto badframe; |
1102 | regs->gpr[1] = newsp; | 1105 | regs->gpr[1] = newsp; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 58194e150711..1decf2785530 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -131,9 +131,6 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
131 | 131 | ||
132 | flush_fp_to_thread(current); | 132 | flush_fp_to_thread(current); |
133 | 133 | ||
134 | /* Make sure signal doesn't get spurrious FP exceptions */ | ||
135 | current->thread.fpscr.val = 0; | ||
136 | |||
137 | #ifdef CONFIG_ALTIVEC | 134 | #ifdef CONFIG_ALTIVEC |
138 | err |= __put_user(v_regs, &sc->v_regs); | 135 | err |= __put_user(v_regs, &sc->v_regs); |
139 | 136 | ||
@@ -423,6 +420,9 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
423 | if (err) | 420 | if (err) |
424 | goto badframe; | 421 | goto badframe; |
425 | 422 | ||
423 | /* Make sure signal handler doesn't get spurious FP exceptions */ | ||
424 | current->thread.fpscr.val = 0; | ||
425 | |||
426 | /* Set up to return from userspace. */ | 426 | /* Set up to return from userspace. */ |
427 | if (vdso64_rt_sigtramp && current->thread.vdso_base) { | 427 | if (vdso64_rt_sigtramp && current->thread.vdso_base) { |
428 | regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; | 428 | regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; |
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S index a08c26e87835..f6b38472318d 100644 --- a/arch/powerpc/kernel/vdso32/datapage.S +++ b/arch/powerpc/kernel/vdso32/datapage.S | |||
@@ -77,8 +77,9 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq) | |||
77 | mflr r12 | 77 | mflr r12 |
78 | .cfi_register lr,r12 | 78 | .cfi_register lr,r12 |
79 | bl __get_datapage@local | 79 | bl __get_datapage@local |
80 | lwz r3,CFG_TB_TICKS_PER_SEC(r3) | ||
81 | lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) | 80 | lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) |
81 | lwz r3,CFG_TB_TICKS_PER_SEC(r3) | ||
82 | mtlr r12 | 82 | mtlr r12 |
83 | blr | ||
83 | .cfi_endproc | 84 | .cfi_endproc |
84 | V_FUNCTION_END(__kernel_get_tbfreq) | 85 | V_FUNCTION_END(__kernel_get_tbfreq) |
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index aeb5fc9b87b3..0a32a41d50b0 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S | |||
@@ -83,7 +83,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
83 | /* Check for supported clock IDs */ | 83 | /* Check for supported clock IDs */ |
84 | cmpli cr0,r3,CLOCK_REALTIME | 84 | cmpli cr0,r3,CLOCK_REALTIME |
85 | cmpli cr1,r3,CLOCK_MONOTONIC | 85 | cmpli cr1,r3,CLOCK_MONOTONIC |
86 | cror cr0,cr0,cr1 | 86 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
87 | bne cr0,99f | 87 | bne cr0,99f |
88 | 88 | ||
89 | mflr r12 /* r12 saves lr */ | 89 | mflr r12 /* r12 saves lr */ |
@@ -91,7 +91,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
91 | mr r10,r3 /* r10 saves id */ | 91 | mr r10,r3 /* r10 saves id */ |
92 | mr r11,r4 /* r11 saves tp */ | 92 | mr r11,r4 /* r11 saves tp */ |
93 | bl __get_datapage@local /* get data page */ | 93 | bl __get_datapage@local /* get data page */ |
94 | mr r9, r3 /* datapage ptr in r9 */ | 94 | mr r9,r3 /* datapage ptr in r9 */ |
95 | beq cr1,50f /* if monotonic -> jump there */ | 95 | beq cr1,50f /* if monotonic -> jump there */ |
96 | 96 | ||
97 | /* | 97 | /* |
@@ -173,10 +173,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
173 | add r4,r4,r7 | 173 | add r4,r4,r7 |
174 | lis r5,NSEC_PER_SEC@h | 174 | lis r5,NSEC_PER_SEC@h |
175 | ori r5,r5,NSEC_PER_SEC@l | 175 | ori r5,r5,NSEC_PER_SEC@l |
176 | cmpli cr0,r4,r5 | 176 | cmpl cr0,r4,r5 |
177 | cmpli cr1,r4,0 | ||
177 | blt 1f | 178 | blt 1f |
178 | subf r4,r5,r4 | 179 | subf r4,r5,r4 |
179 | addi r3,r3,1 | 180 | addi r3,r3,1 |
181 | 1: bge cr1,1f | ||
182 | addi r3,r3,-1 | ||
183 | add r4,r4,r5 | ||
180 | 1: stw r3,TSPC32_TV_SEC(r11) | 184 | 1: stw r3,TSPC32_TV_SEC(r11) |
181 | stw r4,TSPC32_TV_NSEC(r11) | 185 | stw r4,TSPC32_TV_NSEC(r11) |
182 | 186 | ||
@@ -210,7 +214,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres) | |||
210 | /* Check for supported clock IDs */ | 214 | /* Check for supported clock IDs */ |
211 | cmpwi cr0,r3,CLOCK_REALTIME | 215 | cmpwi cr0,r3,CLOCK_REALTIME |
212 | cmpwi cr1,r3,CLOCK_MONOTONIC | 216 | cmpwi cr1,r3,CLOCK_MONOTONIC |
213 | cror cr0,cr0,cr1 | 217 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
214 | bne cr0,99f | 218 | bne cr0,99f |
215 | 219 | ||
216 | li r3,0 | 220 | li r3,0 |
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S index e67eda0f8cda..6393e4137bc7 100644 --- a/arch/powerpc/kernel/vdso64/datapage.S +++ b/arch/powerpc/kernel/vdso64/datapage.S | |||
@@ -80,5 +80,6 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq) | |||
80 | bl V_LOCAL_FUNC(__get_datapage) | 80 | bl V_LOCAL_FUNC(__get_datapage) |
81 | ld r3,CFG_TB_TICKS_PER_SEC(r3) | 81 | ld r3,CFG_TB_TICKS_PER_SEC(r3) |
82 | mtlr r12 | 82 | mtlr r12 |
83 | blr | ||
83 | .cfi_endproc | 84 | .cfi_endproc |
84 | V_FUNCTION_END(__kernel_get_tbfreq) | 85 | V_FUNCTION_END(__kernel_get_tbfreq) |
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index d371c02a8c0e..1a89094715cc 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | |
2 | /* | ||
2 | * Userland implementation of gettimeofday() for 64 bits processes in a | 3 | * Userland implementation of gettimeofday() for 64 bits processes in a |
3 | * ppc64 kernel for use in the vDSO | 4 | * ppc64 kernel for use in the vDSO |
4 | * | 5 | * |
@@ -68,7 +69,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
68 | /* Check for supported clock IDs */ | 69 | /* Check for supported clock IDs */ |
69 | cmpwi cr0,r3,CLOCK_REALTIME | 70 | cmpwi cr0,r3,CLOCK_REALTIME |
70 | cmpwi cr1,r3,CLOCK_MONOTONIC | 71 | cmpwi cr1,r3,CLOCK_MONOTONIC |
71 | cror cr0,cr0,cr1 | 72 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
72 | bne cr0,99f | 73 | bne cr0,99f |
73 | 74 | ||
74 | mflr r12 /* r12 saves lr */ | 75 | mflr r12 /* r12 saves lr */ |
@@ -84,16 +85,17 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
84 | 85 | ||
85 | bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ | 86 | bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ |
86 | 87 | ||
87 | lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ | 88 | lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ |
88 | ori r7,r7,0xca00 | 89 | ori r7,r7,16960 |
89 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ | 90 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ |
90 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ | 91 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ |
91 | std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ | 92 | std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ |
92 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ | 93 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ |
93 | mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / | 94 | mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / |
94 | * XSEC_PER_SEC | 95 | * XSEC_PER_SEC |
95 | */ | 96 | */ |
96 | rldicl r0,r0,44,20 | 97 | rldicl r0,r0,44,20 |
98 | mulli r0,r0,1000 /* nsec = usec * 1000 */ | ||
97 | std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ | 99 | std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ |
98 | 100 | ||
99 | mtlr r12 | 101 | mtlr r12 |
@@ -106,15 +108,16 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
106 | 108 | ||
107 | 50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ | 109 | 50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ |
108 | 110 | ||
109 | lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ | 111 | lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ |
110 | ori r7,r7,0xca00 | 112 | ori r7,r7,16960 |
111 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ | 113 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ |
112 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ | 114 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ |
113 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ | 115 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ |
114 | mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / | 116 | mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / |
115 | * XSEC_PER_SEC | 117 | * XSEC_PER_SEC |
116 | */ | 118 | */ |
117 | rldicl r6,r0,44,20 | 119 | rldicl r6,r0,44,20 |
120 | mulli r6,r6,1000 /* nsec = usec * 1000 */ | ||
118 | 121 | ||
119 | /* now we must fixup using wall to monotonic. We need to snapshot | 122 | /* now we must fixup using wall to monotonic. We need to snapshot |
120 | * that value and do the counter trick again. Fortunately, we still | 123 | * that value and do the counter trick again. Fortunately, we still |
@@ -123,8 +126,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
123 | * can be used | 126 | * can be used |
124 | */ | 127 | */ |
125 | 128 | ||
126 | lwz r4,WTOM_CLOCK_SEC(r9) | 129 | lwa r4,WTOM_CLOCK_SEC(r3) |
127 | lwz r7,WTOM_CLOCK_NSEC(r9) | 130 | lwa r7,WTOM_CLOCK_NSEC(r3) |
128 | 131 | ||
129 | /* We now have our result in r4,r7. We create a fake dependency | 132 | /* We now have our result in r4,r7. We create a fake dependency |
130 | * on that result and re-check the counter | 133 | * on that result and re-check the counter |
@@ -144,10 +147,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
144 | add r7,r7,r6 | 147 | add r7,r7,r6 |
145 | lis r9,NSEC_PER_SEC@h | 148 | lis r9,NSEC_PER_SEC@h |
146 | ori r9,r9,NSEC_PER_SEC@l | 149 | ori r9,r9,NSEC_PER_SEC@l |
147 | cmpli cr0,r7,r9 | 150 | cmpl cr0,r7,r9 |
151 | cmpli cr1,r7,0 | ||
148 | blt 1f | 152 | blt 1f |
149 | subf r7,r9,r7 | 153 | subf r7,r9,r7 |
150 | addi r4,r4,1 | 154 | addi r4,r4,1 |
155 | 1: bge cr1,1f | ||
156 | addi r4,r4,-1 | ||
157 | add r7,r7,r9 | ||
151 | 1: std r4,TSPC64_TV_SEC(r11) | 158 | 1: std r4,TSPC64_TV_SEC(r11) |
152 | std r7,TSPC64_TV_NSEC(r11) | 159 | std r7,TSPC64_TV_NSEC(r11) |
153 | 160 | ||
@@ -181,7 +188,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres) | |||
181 | /* Check for supported clock IDs */ | 188 | /* Check for supported clock IDs */ |
182 | cmpwi cr0,r3,CLOCK_REALTIME | 189 | cmpwi cr0,r3,CLOCK_REALTIME |
183 | cmpwi cr1,r3,CLOCK_MONOTONIC | 190 | cmpwi cr1,r3,CLOCK_MONOTONIC |
184 | cror cr0,cr0,cr1 | 191 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
185 | bne cr0,99f | 192 | bne cr0,99f |
186 | 193 | ||
187 | li r3,0 | 194 | li r3,0 |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index af9ca0eb6d55..5d581bb3aa12 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Modifications by Kumar Gala (kumar.gala@freescale.com) to support | 2 | * Modifications by Kumar Gala (galak@kernel.crashing.org) to support |
3 | * E500 Book E processors. | 3 | * E500 Book E processors. |
4 | * | 4 | * |
5 | * Copyright 2004 Freescale Semiconductor, Inc | 5 | * Copyright 2004 Freescale Semiconductor, Inc |
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index 86124a94c9af..26539cda6023 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (c) 2004 Freescale Semiconductor, Inc | 7 | * Copyright (c) 2004 Freescale Semiconductor, Inc |
8 | * | 8 | * |
9 | * Author: Andy Fleming | 9 | * Author: Andy Fleming |
10 | * Maintainer: Kumar Gala <Kumar.Gala@freescale.com> | 10 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 01090e9ce0cf..a58daa153686 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -42,13 +42,6 @@ | |||
42 | #include "irq.h" | 42 | #include "irq.h" |
43 | #include "call_pci.h" | 43 | #include "call_pci.h" |
44 | 44 | ||
45 | /* This maps virtual irq numbers to real irqs */ | ||
46 | unsigned int virt_irq_to_real_map[NR_IRQS]; | ||
47 | |||
48 | /* The next available virtual irq number */ | ||
49 | /* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ | ||
50 | static int next_virtual_irq = 2; | ||
51 | |||
52 | static long Pci_Interrupt_Count; | 45 | static long Pci_Interrupt_Count; |
53 | static long Pci_Event_Count; | 46 | static long Pci_Event_Count; |
54 | 47 | ||
@@ -350,26 +343,14 @@ static hw_irq_controller iSeries_IRQ_handler = { | |||
350 | int __init iSeries_allocate_IRQ(HvBusNumber busNumber, | 343 | int __init iSeries_allocate_IRQ(HvBusNumber busNumber, |
351 | HvSubBusNumber subBusNumber, HvAgentId deviceId) | 344 | HvSubBusNumber subBusNumber, HvAgentId deviceId) |
352 | { | 345 | { |
353 | unsigned int realirq, virtirq; | 346 | int virtirq; |
347 | unsigned int realirq; | ||
354 | u8 idsel = (deviceId >> 4); | 348 | u8 idsel = (deviceId >> 4); |
355 | u8 function = deviceId & 7; | 349 | u8 function = deviceId & 7; |
356 | 350 | ||
357 | virtirq = next_virtual_irq++; | ||
358 | realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; | 351 | realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; |
359 | virt_irq_to_real_map[virtirq] = realirq; | 352 | virtirq = virt_irq_create_mapping(realirq); |
360 | 353 | ||
361 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; | 354 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; |
362 | return virtirq; | 355 | return virtirq; |
363 | } | 356 | } |
364 | |||
365 | int virt_irq_create_mapping(unsigned int real_irq) | ||
366 | { | ||
367 | BUG(); /* Don't call this on iSeries, yet */ | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | void virt_irq_init(void) | ||
373 | { | ||
374 | return; | ||
375 | } | ||
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 6a29f301436b..da26639190db 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
41 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
42 | #include <asm/systemcfg.h> | ||
43 | #include <asm/system.h> | 42 | #include <asm/system.h> |
44 | #include <asm/time.h> | 43 | #include <asm/time.h> |
45 | #include <asm/paca.h> | 44 | #include <asm/paca.h> |
@@ -548,8 +547,6 @@ static unsigned long __init build_iSeries_Memory_Map(void) | |||
548 | */ | 547 | */ |
549 | static void __init iSeries_setup_arch(void) | 548 | static void __init iSeries_setup_arch(void) |
550 | { | 549 | { |
551 | unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index; | ||
552 | |||
553 | if (get_paca()->lppaca.shared_proc) { | 550 | if (get_paca()->lppaca.shared_proc) { |
554 | ppc_md.idle_loop = iseries_shared_idle; | 551 | ppc_md.idle_loop = iseries_shared_idle; |
555 | printk(KERN_INFO "Using shared processor idle loop\n"); | 552 | printk(KERN_INFO "Using shared processor idle loop\n"); |
@@ -565,9 +562,6 @@ static void __init iSeries_setup_arch(void) | |||
565 | itVpdAreas.xSlicMaxLogicalProcs); | 562 | itVpdAreas.xSlicMaxLogicalProcs); |
566 | printk("Max physical processors = %d\n", | 563 | printk("Max physical processors = %d\n", |
567 | itVpdAreas.xSlicMaxPhysicalProcs); | 564 | itVpdAreas.xSlicMaxPhysicalProcs); |
568 | |||
569 | _systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; | ||
570 | printk("Processor version = %x\n", _systemcfg->processor); | ||
571 | } | 565 | } |
572 | 566 | ||
573 | static void iSeries_show_cpuinfo(struct seq_file *m) | 567 | static void iSeries_show_cpuinfo(struct seq_file *m) |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 5947b21a8588..feb0a94e7819 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -102,7 +102,7 @@ static unsigned long from_rtc_time(struct rtc_time *tm) | |||
102 | static unsigned long cuda_get_time(void) | 102 | static unsigned long cuda_get_time(void) |
103 | { | 103 | { |
104 | struct adb_request req; | 104 | struct adb_request req; |
105 | unsigned long now; | 105 | unsigned int now; |
106 | 106 | ||
107 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | 107 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) |
108 | return 0; | 108 | return 0; |
@@ -113,7 +113,7 @@ static unsigned long cuda_get_time(void) | |||
113 | req.reply_len); | 113 | req.reply_len); |
114 | now = (req.reply[3] << 24) + (req.reply[4] << 16) | 114 | now = (req.reply[3] << 24) + (req.reply[4] << 16) |
115 | + (req.reply[5] << 8) + req.reply[6]; | 115 | + (req.reply[5] << 8) + req.reply[6]; |
116 | return now - RTC_OFFSET; | 116 | return ((unsigned long)now) - RTC_OFFSET; |
117 | } | 117 | } |
118 | 118 | ||
119 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) | 119 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) |
@@ -146,7 +146,7 @@ static int cuda_set_rtc_time(struct rtc_time *tm) | |||
146 | static unsigned long pmu_get_time(void) | 146 | static unsigned long pmu_get_time(void) |
147 | { | 147 | { |
148 | struct adb_request req; | 148 | struct adb_request req; |
149 | unsigned long now; | 149 | unsigned int now; |
150 | 150 | ||
151 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | 151 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) |
152 | return 0; | 152 | return 0; |
@@ -156,7 +156,7 @@ static unsigned long pmu_get_time(void) | |||
156 | req.reply_len); | 156 | req.reply_len); |
157 | now = (req.reply[0] << 24) + (req.reply[1] << 16) | 157 | now = (req.reply[0] << 24) + (req.reply[1] << 16) |
158 | + (req.reply[2] << 8) + req.reply[3]; | 158 | + (req.reply[2] << 8) + req.reply[3]; |
159 | return now - RTC_OFFSET; | 159 | return ((unsigned long)now) - RTC_OFFSET; |
160 | } | 160 | } |
161 | 161 | ||
162 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) | 162 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) |
@@ -199,6 +199,7 @@ static unsigned long smu_get_time(void) | |||
199 | #define smu_set_rtc_time(tm, spin) 0 | 199 | #define smu_set_rtc_time(tm, spin) 0 |
200 | #endif | 200 | #endif |
201 | 201 | ||
202 | /* Can't be __init, it's called when suspending and resuming */ | ||
202 | unsigned long pmac_get_boot_time(void) | 203 | unsigned long pmac_get_boot_time(void) |
203 | { | 204 | { |
204 | /* Get the time from the RTC, used only at boot time */ | 205 | /* Get the time from the RTC, used only at boot time */ |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index e7ca5b1f591e..06d5ef501218 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -4,4 +4,7 @@ obj-$(CONFIG_SMP) += smp.o | |||
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
6 | obj-$(CONFIG_SCANLOG) += scanlog.o | 6 | obj-$(CONFIG_SCANLOG) += scanlog.o |
7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o | 7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o |
8 | |||
9 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
10 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 138e128a3886..138e128a3886 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c | |||
diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index 4d584172055a..4d584172055a 100644 --- a/arch/ppc64/kernel/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c | |||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 31990829310c..b9d9732b2e06 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -200,14 +200,12 @@ static void __init pSeries_setup_arch(void) | |||
200 | if (ppc64_interrupt_controller == IC_OPEN_PIC) { | 200 | if (ppc64_interrupt_controller == IC_OPEN_PIC) { |
201 | ppc_md.init_IRQ = pSeries_init_mpic; | 201 | ppc_md.init_IRQ = pSeries_init_mpic; |
202 | ppc_md.get_irq = mpic_get_irq; | 202 | ppc_md.get_irq = mpic_get_irq; |
203 | ppc_md.cpu_irq_down = mpic_teardown_this_cpu; | ||
204 | /* Allocate the mpic now, so that find_and_init_phbs() can | 203 | /* Allocate the mpic now, so that find_and_init_phbs() can |
205 | * fill the ISUs */ | 204 | * fill the ISUs */ |
206 | pSeries_setup_mpic(); | 205 | pSeries_setup_mpic(); |
207 | } else { | 206 | } else { |
208 | ppc_md.init_IRQ = xics_init_IRQ; | 207 | ppc_md.init_IRQ = xics_init_IRQ; |
209 | ppc_md.get_irq = xics_get_irq; | 208 | ppc_md.get_irq = xics_get_irq; |
210 | ppc_md.cpu_irq_down = xics_teardown_cpu; | ||
211 | } | 209 | } |
212 | 210 | ||
213 | #ifdef CONFIG_SMP | 211 | #ifdef CONFIG_SMP |
@@ -595,6 +593,27 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
595 | return PCI_PROBE_NORMAL; | 593 | return PCI_PROBE_NORMAL; |
596 | } | 594 | } |
597 | 595 | ||
596 | #ifdef CONFIG_KEXEC | ||
597 | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | ||
598 | { | ||
599 | /* Don't risk a hypervisor call if we're crashing */ | ||
600 | if (!crash_shutdown) { | ||
601 | unsigned long vpa = __pa(&get_paca()->lppaca); | ||
602 | |||
603 | if (unregister_vpa(hard_smp_processor_id(), vpa)) { | ||
604 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | ||
605 | "failed\n", smp_processor_id(), | ||
606 | hard_smp_processor_id()); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | if (ppc64_interrupt_controller == IC_OPEN_PIC) | ||
611 | mpic_teardown_this_cpu(secondary); | ||
612 | else | ||
613 | xics_teardown_cpu(secondary); | ||
614 | } | ||
615 | #endif | ||
616 | |||
598 | struct machdep_calls __initdata pSeries_md = { | 617 | struct machdep_calls __initdata pSeries_md = { |
599 | .probe = pSeries_probe, | 618 | .probe = pSeries_probe, |
600 | .setup_arch = pSeries_setup_arch, | 619 | .setup_arch = pSeries_setup_arch, |
@@ -617,4 +636,7 @@ struct machdep_calls __initdata pSeries_md = { | |||
617 | .check_legacy_ioport = pSeries_check_legacy_ioport, | 636 | .check_legacy_ioport = pSeries_check_legacy_ioport, |
618 | .system_reset_exception = pSeries_system_reset_exception, | 637 | .system_reset_exception = pSeries_system_reset_exception, |
619 | .machine_check_exception = pSeries_machine_check_exception, | 638 | .machine_check_exception = pSeries_machine_check_exception, |
639 | #ifdef CONFIG_KEXEC | ||
640 | .kexec_cpu_down = pseries_kexec_cpu_down, | ||
641 | #endif | ||
620 | }; | 642 | }; |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index ef4356b29a97..c45a6ad5f3b7 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/sysrq.h> | 21 | #include <linux/sysrq.h> |
22 | #include <linux/interrupt.h> | ||
22 | 23 | ||
23 | #include <asm/ptrace.h> | 24 | #include <asm/ptrace.h> |
24 | #include <asm/string.h> | 25 | #include <asm/string.h> |
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index 5063c603fad4..8d60fa99fc4b 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S | |||
@@ -24,7 +24,7 @@ | |||
24 | * Copyright 2002-2004 MontaVista Software, Inc. | 24 | * Copyright 2002-2004 MontaVista Software, Inc. |
25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> | 25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> |
26 | * Copyright 2004 Freescale Semiconductor, Inc | 26 | * Copyright 2004 Freescale Semiconductor, Inc |
27 | * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> | 27 | * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org> |
28 | * | 28 | * |
29 | * This program is free software; you can redistribute it and/or modify it | 29 | * This program is free software; you can redistribute it and/or modify it |
30 | * under the terms of the GNU General Public License as published by the | 30 | * under the terms of the GNU General Public License as published by the |
diff --git a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c index af9ca0eb6d55..5d581bb3aa12 100644 --- a/arch/ppc/mm/fsl_booke_mmu.c +++ b/arch/ppc/mm/fsl_booke_mmu.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Modifications by Kumar Gala (kumar.gala@freescale.com) to support | 2 | * Modifications by Kumar Gala (galak@kernel.crashing.org) to support |
3 | * E500 Book E processors. | 3 | * E500 Book E processors. |
4 | * | 4 | * |
5 | * Copyright 2004 Freescale Semiconductor, Inc | 5 | * Copyright 2004 Freescale Semiconductor, Inc |
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 98edc75f4105..04bdc39bf47b 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC834x SYS board specific routines | 4 | * MPC834x SYS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
@@ -73,12 +73,19 @@ mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | |||
73 | * A B C D | 73 | * A B C D |
74 | */ | 74 | */ |
75 | { | 75 | { |
76 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ | 76 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ |
77 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ | 77 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ |
78 | {PIRQD, PIRQA, PIRQB, PIRQC} /* idsel 0x13 */ | 78 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ |
79 | {0, 0, 0, 0}, | ||
80 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ | ||
81 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ | ||
82 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ | ||
83 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ | ||
84 | {0, 0, 0, 0}, /* idsel 0x19 */ | ||
85 | {0, 0, 0, 0}, /* idsel 0x20 */ | ||
79 | }; | 86 | }; |
80 | 87 | ||
81 | const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4; | 88 | const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; |
82 | return PCI_IRQ_TABLE_LOOKUP; | 89 | return PCI_IRQ_TABLE_LOOKUP; |
83 | } | 90 | } |
84 | 91 | ||
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index 58e44c042535..2e514d316fb8 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC834X SYS common board definitions | 4 | * MPC834X SYS common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc. | 8 | * Copyright 2005 Freescale Semiconductor, Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 7e952c1228cb..c5cde97c6ef0 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board specific routines | 4 | * MPC8540ADS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h index 3d05d7c4a938..e48ca3a97397 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.h +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board definitions | 4 | * MPC8540ADS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h index e0e75568bc57..1a8e6c67355d 100644 --- a/arch/ppc/platforms/85xx/mpc8555_cds.h +++ b/arch/ppc/platforms/85xx/mpc8555_cds.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8555CDS board definitions | 4 | * MPC8555CDS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 208433f1e93a..8e39a5517092 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8560ADS board specific routines | 4 | * MPC8560ADS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h index 7df885d73e9d..143ae7eefa7c 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.h +++ b/arch/ppc/platforms/85xx/mpc8560_ads.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board definitions | 4 | * MPC8540ADS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 16ad092d8a06..17ce48fe3503 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx ADS board common routines | 4 | * MPC85xx ADS board common routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h index 84acf6e8d45e..7b26bcc5d10d 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX ADS common board definitions | 4 | * MPC85XX ADS common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index a21156967a5e..d8991b88dc9c 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx CDS board specific routines | 4 | * MPC85xx CDS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h index 12b292c6ae32..5b588cfd0e41 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx CDS board definitions | 4 | * MPC85xx CDS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index b4ee1707a836..45a5b81b4ed1 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Wind River SBC8560 board specific routines | 4 | * Wind River SBC8560 board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 58884a63ebdb..1e69b0593162 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c | |||
@@ -2317,6 +2317,14 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2317 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2317 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2318 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2318 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
2319 | }, | 2319 | }, |
2320 | { "PowerBook5,8", "PowerBook G4 15\"", | ||
2321 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2322 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2323 | }, | ||
2324 | { "PowerBook5,9", "PowerBook G4 17\"", | ||
2325 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2326 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2327 | }, | ||
2320 | { "PowerBook6,1", "PowerBook G4 12\"", | 2328 | { "PowerBook6,1", "PowerBook G4 12\"", |
2321 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2329 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2322 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2330 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c index 6a1475c1e128..71c9fca1fe9b 100644 --- a/arch/ppc/platforms/pq2ads.c +++ b/arch/ppc/platforms/pq2ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2ADS platform support | 4 | * PQ2ADS platform support |
5 | * | 5 | * |
6 | * Author: Kumar Gala <kumar.gala@freescale.com> | 6 | * Author: Kumar Gala <galak@kernel.crashing.org> |
7 | * Derived from: est8260_setup.c by Allen Curtis | 7 | * Derived from: est8260_setup.c by Allen Curtis |
8 | * | 8 | * |
9 | * Copyright 2004 Freescale Semiconductor, Inc. | 9 | * Copyright 2004 Freescale Semiconductor, Inc. |
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h index 2b56a4fcf373..a7ce7da8785c 100644 --- a/arch/ppc/syslib/ipic.h +++ b/arch/ppc/syslib/ipic.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * IPIC private definitions and structure. | 4 | * IPIC private definitions and structure. |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index f43fbf9a9389..847df4409982 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx Device descriptions | 4 | * MPC83xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index da743446789b..a1523989aff4 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx System descriptions | 4 | * MPC83xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 2ede677a0a53..69949d255658 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx Device descriptions | 4 | * MPC85xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c index cb68d8c58348..397cfbcce5ea 100644 --- a/arch/ppc/syslib/mpc85xx_sys.c +++ b/arch/ppc/syslib/mpc85xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx System descriptions | 4 | * MPC85xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index 2b5f0e701687..92dc98b36bde 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8xx Device descriptions | 4 | * MPC8xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> | 8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c index 3cc27d29e3af..d3c617521603 100644 --- a/arch/ppc/syslib/mpc8xx_sys.c +++ b/arch/ppc/syslib/mpc8xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8xx System descriptions | 4 | * MPC8xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index 4da168a6ad03..1b5fe9e398d4 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83XX common board code | 4 | * MPC83XX common board code |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h index c766c1a5f786..a122a7322e5e 100644 --- a/arch/ppc/syslib/ppc83xx_setup.h +++ b/arch/ppc/syslib/ppc83xx_setup.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83XX common board definitions | 4 | * MPC83XX common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c index da841dacdc13..19ad537225e4 100644 --- a/arch/ppc/syslib/ppc85xx_common.c +++ b/arch/ppc/syslib/ppc85xx_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx support routines | 4 | * MPC85xx support routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h index 2c8f304441bf..94edf32151dd 100644 --- a/arch/ppc/syslib/ppc85xx_common.h +++ b/arch/ppc/syslib/ppc85xx_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx support routines | 4 | * MPC85xx support routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index de2f90576577..1a47ff4b831d 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX common board code | 4 | * MPC85XX common board code |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h index 6e6cfe162faf..e340b0545fb5 100644 --- a/arch/ppc/syslib/ppc85xx_setup.h +++ b/arch/ppc/syslib/ppc85xx_setup.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX common board definitions | 4 | * MPC85XX common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 603f01190816..c0b93c4191ee 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PPC System library functions | 4 | * PPC System library functions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c index e960fe935325..6ff3aab82fc3 100644 --- a/arch/ppc/syslib/pq2_devices.c +++ b/arch/ppc/syslib/pq2_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2 Device descriptions | 4 | * PQ2 Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c index 7b6c9ebdb9e3..36d6e2179940 100644 --- a/arch/ppc/syslib/pq2_sys.c +++ b/arch/ppc/syslib/pq2_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2 System descriptions | 4 | * PQ2 System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig deleted file mode 100644 index 9d10c12e87fe..000000000000 --- a/arch/ppc64/Kconfig +++ /dev/null | |||
@@ -1,520 +0,0 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see Documentation/kbuild/kconfig-language.txt. | ||
4 | # | ||
5 | |||
6 | config 64BIT | ||
7 | def_bool y | ||
8 | |||
9 | config MMU | ||
10 | bool | ||
11 | default y | ||
12 | |||
13 | config PPC_STD_MMU | ||
14 | def_bool y | ||
15 | |||
16 | config UID16 | ||
17 | bool | ||
18 | |||
19 | config RWSEM_GENERIC_SPINLOCK | ||
20 | bool | ||
21 | |||
22 | config RWSEM_XCHGADD_ALGORITHM | ||
23 | bool | ||
24 | default y | ||
25 | |||
26 | config GENERIC_CALIBRATE_DELAY | ||
27 | bool | ||
28 | default y | ||
29 | |||
30 | config GENERIC_ISA_DMA | ||
31 | bool | ||
32 | default y | ||
33 | |||
34 | config EARLY_PRINTK | ||
35 | bool | ||
36 | default y | ||
37 | |||
38 | config COMPAT | ||
39 | bool | ||
40 | default y | ||
41 | |||
42 | config SCHED_NO_NO_OMIT_FRAME_POINTER | ||
43 | bool | ||
44 | default y | ||
45 | |||
46 | config ARCH_MAY_HAVE_PC_FDC | ||
47 | bool | ||
48 | default y | ||
49 | |||
50 | config PPC_STD_MMU | ||
51 | bool | ||
52 | default y | ||
53 | |||
54 | # We optimistically allocate largepages from the VM, so make the limit | ||
55 | # large enough (16MB). This badly named config option is actually | ||
56 | # max order + 1 | ||
57 | config FORCE_MAX_ZONEORDER | ||
58 | int | ||
59 | default "9" if PPC_64K_PAGES | ||
60 | default "13" | ||
61 | |||
62 | source "init/Kconfig" | ||
63 | |||
64 | config SYSVIPC_COMPAT | ||
65 | bool | ||
66 | depends on COMPAT && SYSVIPC | ||
67 | default y | ||
68 | |||
69 | menu "Platform support" | ||
70 | |||
71 | choice | ||
72 | prompt "Platform Type" | ||
73 | default PPC_MULTIPLATFORM | ||
74 | |||
75 | config PPC_ISERIES | ||
76 | bool "IBM Legacy iSeries" | ||
77 | |||
78 | config PPC_MULTIPLATFORM | ||
79 | bool "Generic" | ||
80 | |||
81 | endchoice | ||
82 | |||
83 | config PPC_PSERIES | ||
84 | depends on PPC_MULTIPLATFORM | ||
85 | bool " IBM pSeries & new iSeries" | ||
86 | default y | ||
87 | |||
88 | config PPC_BPA | ||
89 | bool " Broadband Processor Architecture" | ||
90 | depends on PPC_MULTIPLATFORM | ||
91 | |||
92 | config PPC_PMAC | ||
93 | depends on PPC_MULTIPLATFORM | ||
94 | bool " Apple G5 based machines" | ||
95 | default y | ||
96 | select U3_DART | ||
97 | select GENERIC_TBSYNC | ||
98 | |||
99 | config PPC_MAPLE | ||
100 | depends on PPC_MULTIPLATFORM | ||
101 | bool " Maple 970FX Evaluation Board" | ||
102 | select U3_DART | ||
103 | select MPIC_BROKEN_U3 | ||
104 | select GENERIC_TBSYNC | ||
105 | default n | ||
106 | help | ||
107 | This option enables support for the Maple 970FX Evaluation Board. | ||
108 | For more informations, refer to <http://www.970eval.com> | ||
109 | |||
110 | config PPC | ||
111 | bool | ||
112 | default y | ||
113 | |||
114 | config PPC64 | ||
115 | bool | ||
116 | default y | ||
117 | |||
118 | config PPC_OF | ||
119 | depends on PPC_MULTIPLATFORM | ||
120 | bool | ||
121 | default y | ||
122 | |||
123 | config XICS | ||
124 | depends on PPC_PSERIES | ||
125 | bool | ||
126 | default y | ||
127 | |||
128 | config MPIC | ||
129 | depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE | ||
130 | bool | ||
131 | default y | ||
132 | |||
133 | config PPC_I8259 | ||
134 | depends on PPC_PSERIES | ||
135 | bool | ||
136 | default y | ||
137 | |||
138 | config BPA_IIC | ||
139 | depends on PPC_BPA | ||
140 | bool | ||
141 | default y | ||
142 | |||
143 | # VMX is pSeries only for now until somebody writes the iSeries | ||
144 | # exception vectors for it | ||
145 | config ALTIVEC | ||
146 | bool "Support for VMX (Altivec) vector unit" | ||
147 | depends on PPC_MULTIPLATFORM | ||
148 | default y | ||
149 | |||
150 | config PPC_SPLPAR | ||
151 | depends on PPC_PSERIES | ||
152 | bool "Support for shared-processor logical partitions" | ||
153 | default n | ||
154 | help | ||
155 | Enabling this option will make the kernel run more efficiently | ||
156 | on logically-partitioned pSeries systems which use shared | ||
157 | processors, that is, which share physical processors between | ||
158 | two or more partitions. | ||
159 | |||
160 | config KEXEC | ||
161 | bool "kexec system call (EXPERIMENTAL)" | ||
162 | depends on PPC_MULTIPLATFORM && EXPERIMENTAL | ||
163 | help | ||
164 | kexec is a system call that implements the ability to shutdown your | ||
165 | current kernel, and to start another kernel. It is like a reboot | ||
166 | but it is indepedent of the system firmware. And like a reboot | ||
167 | you can start any kernel with it, not just Linux. | ||
168 | |||
169 | The name comes from the similiarity to the exec system call. | ||
170 | |||
171 | It is an ongoing process to be certain the hardware in a machine | ||
172 | is properly shutdown, so do not be surprised if this code does not | ||
173 | initially work for you. It may help to enable device hotplugging | ||
174 | support. As of this writing the exact hardware interface is | ||
175 | strongly in flux, so no good recommendation can be made. | ||
176 | |||
177 | source "drivers/cpufreq/Kconfig" | ||
178 | |||
179 | config CPU_FREQ_PMAC64 | ||
180 | bool "Support for some Apple G5s" | ||
181 | depends on CPU_FREQ && PMAC_SMU && PPC64 | ||
182 | select CPU_FREQ_TABLE | ||
183 | help | ||
184 | This adds support for frequency switching on Apple iMac G5, | ||
185 | and some of the more recent desktop G5 machines as well. | ||
186 | |||
187 | config IBMVIO | ||
188 | depends on PPC_PSERIES || PPC_ISERIES | ||
189 | bool | ||
190 | default y | ||
191 | |||
192 | config U3_DART | ||
193 | bool | ||
194 | depends on PPC_MULTIPLATFORM | ||
195 | default n | ||
196 | |||
197 | config MPIC_BROKEN_U3 | ||
198 | bool | ||
199 | depends on PPC_MAPLE | ||
200 | default y | ||
201 | |||
202 | config GENERIC_TBSYNC | ||
203 | def_bool n | ||
204 | |||
205 | config PPC_PMAC64 | ||
206 | bool | ||
207 | depends on PPC_PMAC | ||
208 | default y | ||
209 | |||
210 | config BOOTX_TEXT | ||
211 | bool "Support for early boot text console" | ||
212 | depends PPC_OF | ||
213 | help | ||
214 | Say Y here to see progress messages from the boot firmware in text | ||
215 | mode. Requires an Open Firmware compatible video card. | ||
216 | |||
217 | config POWER4 | ||
218 | def_bool y | ||
219 | |||
220 | config PPC_FPU | ||
221 | def_bool y | ||
222 | |||
223 | config POWER4_ONLY | ||
224 | bool "Optimize for POWER4" | ||
225 | default n | ||
226 | ---help--- | ||
227 | Cause the compiler to optimize for POWER4 processors. The resulting | ||
228 | binary will not work on POWER3 or RS64 processors when compiled with | ||
229 | binutils 2.15 or later. | ||
230 | |||
231 | config IOMMU_VMERGE | ||
232 | bool "Enable IOMMU virtual merging (EXPERIMENTAL)" | ||
233 | depends on EXPERIMENTAL | ||
234 | default n | ||
235 | help | ||
236 | Cause IO segments sent to a device for DMA to be merged virtually | ||
237 | by the IOMMU when they happen to have been allocated contiguously. | ||
238 | This doesn't add pressure to the IOMMU allocator. However, some | ||
239 | drivers don't support getting large merged segments coming back | ||
240 | from *_map_sg(). Say Y if you know the drivers you are using are | ||
241 | properly handling this case. | ||
242 | |||
243 | config SMP | ||
244 | bool "Symmetric multi-processing support" | ||
245 | ---help--- | ||
246 | This enables support for systems with more than one CPU. If you have | ||
247 | a system with only one CPU, say N. If you have a system with more | ||
248 | than one CPU, say Y. | ||
249 | |||
250 | If you say N here, the kernel will run on single and multiprocessor | ||
251 | machines, but will use only one CPU of a multiprocessor machine. If | ||
252 | you say Y here, the kernel will run on single-processor machines. | ||
253 | On a single-processor machine, the kernel will run faster if you say | ||
254 | N here. | ||
255 | |||
256 | If you don't know what to do here, say Y. | ||
257 | |||
258 | config NR_CPUS | ||
259 | int "Maximum number of CPUs (2-128)" | ||
260 | range 2 128 | ||
261 | depends on SMP | ||
262 | default "32" | ||
263 | |||
264 | config HMT | ||
265 | bool "Hardware multithreading" | ||
266 | depends on SMP && PPC_PSERIES && BROKEN | ||
267 | help | ||
268 | This option enables hardware multithreading on RS64 cpus. | ||
269 | pSeries systems p620 and p660 have such a cpu type. | ||
270 | |||
271 | config NUMA | ||
272 | bool "NUMA support" | ||
273 | default y if SMP && PPC_PSERIES | ||
274 | |||
275 | config ARCH_SELECT_MEMORY_MODEL | ||
276 | def_bool y | ||
277 | |||
278 | config ARCH_FLATMEM_ENABLE | ||
279 | def_bool y | ||
280 | depends on !NUMA | ||
281 | |||
282 | config ARCH_SPARSEMEM_ENABLE | ||
283 | def_bool y | ||
284 | |||
285 | config ARCH_SPARSEMEM_DEFAULT | ||
286 | def_bool y | ||
287 | depends on NUMA | ||
288 | |||
289 | source "mm/Kconfig" | ||
290 | |||
291 | config HAVE_ARCH_EARLY_PFN_TO_NID | ||
292 | def_bool y | ||
293 | depends on NEED_MULTIPLE_NODES | ||
294 | |||
295 | config ARCH_MEMORY_PROBE | ||
296 | def_bool y | ||
297 | depends on MEMORY_HOTPLUG | ||
298 | |||
299 | # Some NUMA nodes have memory ranges that span | ||
300 | # other nodes. Even though a pfn is valid and | ||
301 | # between a node's start and end pfns, it may not | ||
302 | # reside on that node. | ||
303 | # | ||
304 | # This is a relatively temporary hack that should | ||
305 | # be able to go away when sparsemem is fully in | ||
306 | # place | ||
307 | config NODES_SPAN_OTHER_NODES | ||
308 | def_bool y | ||
309 | depends on NEED_MULTIPLE_NODES | ||
310 | |||
311 | config PPC_64K_PAGES | ||
312 | bool "64k page size" | ||
313 | help | ||
314 | This option changes the kernel logical page size to 64k. On machines | ||
315 | without processor support for 64k pages, the kernel will simulate | ||
316 | them by loading each individual 4k page on demand transparently, | ||
317 | while on hardware with such support, it will be used to map | ||
318 | normal application pages. | ||
319 | |||
320 | config SCHED_SMT | ||
321 | bool "SMT (Hyperthreading) scheduler support" | ||
322 | depends on SMP | ||
323 | default off | ||
324 | help | ||
325 | SMT scheduler support improves the CPU scheduler's decision making | ||
326 | when dealing with POWER5 cpus at a cost of slightly increased | ||
327 | overhead in some places. If unsure say N here. | ||
328 | |||
329 | source "kernel/Kconfig.preempt" | ||
330 | source kernel/Kconfig.hz | ||
331 | |||
332 | config EEH | ||
333 | bool "PCI Extended Error Handling (EEH)" if EMBEDDED | ||
334 | depends on PPC_PSERIES | ||
335 | default y if !EMBEDDED | ||
336 | |||
337 | # | ||
338 | # Use the generic interrupt handling code in kernel/irq/: | ||
339 | # | ||
340 | config GENERIC_HARDIRQS | ||
341 | bool | ||
342 | default y | ||
343 | |||
344 | config PPC_RTAS | ||
345 | bool | ||
346 | depends on PPC_PSERIES || PPC_BPA | ||
347 | default y | ||
348 | |||
349 | config RTAS_ERROR_LOGGING | ||
350 | bool | ||
351 | depends on PPC_RTAS | ||
352 | default y | ||
353 | |||
354 | config RTAS_PROC | ||
355 | bool "Proc interface to RTAS" | ||
356 | depends on PPC_RTAS | ||
357 | default y | ||
358 | |||
359 | config RTAS_FLASH | ||
360 | tristate "Firmware flash interface" | ||
361 | depends on RTAS_PROC | ||
362 | |||
363 | config SCANLOG | ||
364 | tristate "Scanlog dump interface" | ||
365 | depends on RTAS_PROC && PPC_PSERIES | ||
366 | |||
367 | config LPARCFG | ||
368 | tristate "LPAR Configuration Data" | ||
369 | depends on PPC_PSERIES || PPC_ISERIES | ||
370 | help | ||
371 | Provide system capacity information via human readable | ||
372 | <key word>=<value> pairs through a /proc/ppc64/lparcfg interface. | ||
373 | |||
374 | config SECCOMP | ||
375 | bool "Enable seccomp to safely compute untrusted bytecode" | ||
376 | depends on PROC_FS | ||
377 | default y | ||
378 | help | ||
379 | This kernel feature is useful for number crunching applications | ||
380 | that may need to compute untrusted bytecode during their | ||
381 | execution. By using pipes or other transports made available to | ||
382 | the process as file descriptors supporting the read/write | ||
383 | syscalls, it's possible to isolate those applications in | ||
384 | their own address space using seccomp. Once seccomp is | ||
385 | enabled via /proc/<pid>/seccomp, it cannot be disabled | ||
386 | and the task is only allowed to execute a few safe syscalls | ||
387 | defined by each seccomp mode. | ||
388 | |||
389 | If unsure, say Y. Only embedded should say N here. | ||
390 | |||
391 | source "fs/Kconfig.binfmt" | ||
392 | |||
393 | config HOTPLUG_CPU | ||
394 | bool "Support for hot-pluggable CPUs" | ||
395 | depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC) | ||
396 | select HOTPLUG | ||
397 | ---help--- | ||
398 | Say Y here to be able to turn CPUs off and on. | ||
399 | |||
400 | Say N if you are unsure. | ||
401 | |||
402 | config PROC_DEVICETREE | ||
403 | bool "Support for Open Firmware device tree in /proc" | ||
404 | help | ||
405 | This option adds a device-tree directory under /proc which contains | ||
406 | an image of the device tree that the kernel copies from Open | ||
407 | Firmware. If unsure, say Y here. | ||
408 | |||
409 | config CMDLINE_BOOL | ||
410 | bool "Default bootloader kernel arguments" | ||
411 | depends on !PPC_ISERIES | ||
412 | |||
413 | config CMDLINE | ||
414 | string "Initial kernel command string" | ||
415 | depends on CMDLINE_BOOL | ||
416 | default "console=ttyS0,9600 console=tty0 root=/dev/sda2" | ||
417 | help | ||
418 | On some platforms, there is currently no way for the boot loader to | ||
419 | pass arguments to the kernel. For these platforms, you can supply | ||
420 | some command-line options at build time by entering them here. In | ||
421 | most cases you will need to specify the root device here. | ||
422 | |||
423 | endmenu | ||
424 | |||
425 | config ISA_DMA_API | ||
426 | bool | ||
427 | default y | ||
428 | |||
429 | menu "Bus Options" | ||
430 | |||
431 | config ISA | ||
432 | bool | ||
433 | help | ||
434 | Find out whether you have ISA slots on your motherboard. ISA is the | ||
435 | name of a bus system, i.e. the way the CPU talks to the other stuff | ||
436 | inside your box. If you have an Apple machine, say N here; if you | ||
437 | have an IBM RS/6000 or pSeries machine or a PReP machine, say Y. If | ||
438 | you have an embedded board, consult your board documentation. | ||
439 | |||
440 | config SBUS | ||
441 | bool | ||
442 | |||
443 | config MCA | ||
444 | bool | ||
445 | |||
446 | config EISA | ||
447 | bool | ||
448 | |||
449 | config PCI | ||
450 | bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES) | ||
451 | default y | ||
452 | help | ||
453 | Find out whether your system includes a PCI bus. PCI is the name of | ||
454 | a bus system, i.e. the way the CPU talks to the other stuff inside | ||
455 | your box. If you say Y here, the kernel will include drivers and | ||
456 | infrastructure code to support PCI bus devices. | ||
457 | |||
458 | config PCI_DOMAINS | ||
459 | bool | ||
460 | default PCI | ||
461 | |||
462 | source "drivers/pci/Kconfig" | ||
463 | |||
464 | source "drivers/pcmcia/Kconfig" | ||
465 | |||
466 | source "drivers/pci/hotplug/Kconfig" | ||
467 | |||
468 | endmenu | ||
469 | |||
470 | source "net/Kconfig" | ||
471 | |||
472 | source "drivers/Kconfig" | ||
473 | |||
474 | source "fs/Kconfig" | ||
475 | |||
476 | menu "iSeries device drivers" | ||
477 | depends on PPC_ISERIES | ||
478 | |||
479 | config VIOCONS | ||
480 | tristate "iSeries Virtual Console Support" | ||
481 | |||
482 | config VIODASD | ||
483 | tristate "iSeries Virtual I/O disk support" | ||
484 | help | ||
485 | If you are running on an iSeries system and you want to use | ||
486 | virtual disks created and managed by OS/400, say Y. | ||
487 | |||
488 | config VIOCD | ||
489 | tristate "iSeries Virtual I/O CD support" | ||
490 | help | ||
491 | If you are running Linux on an IBM iSeries system and you want to | ||
492 | read a CD drive owned by OS/400, say Y here. | ||
493 | |||
494 | config VIOTAPE | ||
495 | tristate "iSeries Virtual Tape Support" | ||
496 | help | ||
497 | If you are running Linux on an iSeries system and you want Linux | ||
498 | to read and/or write a tape drive owned by OS/400, say Y here. | ||
499 | |||
500 | endmenu | ||
501 | |||
502 | config VIOPATH | ||
503 | bool | ||
504 | depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH | ||
505 | default y | ||
506 | |||
507 | source "arch/powerpc/oprofile/Kconfig" | ||
508 | |||
509 | source "arch/ppc64/Kconfig.debug" | ||
510 | |||
511 | source "security/Kconfig" | ||
512 | |||
513 | config KEYS_COMPAT | ||
514 | bool | ||
515 | depends on COMPAT && KEYS | ||
516 | default y | ||
517 | |||
518 | source "crypto/Kconfig" | ||
519 | |||
520 | source "lib/Kconfig" | ||
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index dac4cc20fa93..e876c213f5ce 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -2,45 +2,6 @@ | |||
2 | # Makefile for the linux ppc64 kernel. | 2 | # Makefile for the linux ppc64 kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifneq ($(CONFIG_PPC_MERGE),y) | 5 | obj-y += idle.o align.o |
6 | |||
7 | EXTRA_CFLAGS += -mno-minimal-toc | ||
8 | extra-y := head.o vmlinux.lds | ||
9 | |||
10 | obj-y := misc.o prom.o | ||
11 | |||
12 | endif | ||
13 | |||
14 | obj-y += idle.o dma.o \ | ||
15 | align.o \ | ||
16 | rtc.o \ | ||
17 | iommu.o | ||
18 | |||
19 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o | ||
20 | |||
21 | obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) | ||
22 | 6 | ||
23 | obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o | 7 | obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o |
24 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
25 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o | ||
26 | endif | ||
27 | |||
28 | obj-$(CONFIG_KEXEC) += machine_kexec.o | ||
29 | obj-$(CONFIG_MODULES) += module.o | ||
30 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
31 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | ||
32 | endif | ||
33 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
34 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
35 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | ||
36 | endif | ||
37 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
38 | |||
39 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
40 | |||
41 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
42 | ifeq ($(CONFIG_PPC_ISERIES),y) | ||
43 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s | ||
44 | AFLAGS_head.o += -Iarch/powerpc/kernel | ||
45 | endif | ||
46 | endif | ||
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c deleted file mode 100644 index 84ab5c18ef52..000000000000 --- a/arch/ppc64/kernel/asm-offsets.c +++ /dev/null | |||
@@ -1,195 +0,0 @@ | |||
1 | /* | ||
2 | * This program is used to generate definitions needed by | ||
3 | * assembly language modules. | ||
4 | * | ||
5 | * We use the technique used in the OSF Mach kernel code: | ||
6 | * generate asm statements containing #defines, | ||
7 | * compile this file to assembler, and then extract the | ||
8 | * #defines from the assembly-language output. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/signal.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/mman.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/time.h> | ||
26 | #include <linux/hardirq.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/processor.h> | ||
31 | |||
32 | #include <asm/paca.h> | ||
33 | #include <asm/lppaca.h> | ||
34 | #include <asm/iseries/hv_lp_event.h> | ||
35 | #include <asm/rtas.h> | ||
36 | #include <asm/cputable.h> | ||
37 | #include <asm/cache.h> | ||
38 | #include <asm/systemcfg.h> | ||
39 | #include <asm/compat.h> | ||
40 | |||
41 | #define DEFINE(sym, val) \ | ||
42 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | ||
43 | |||
44 | #define BLANK() asm volatile("\n->" : : ) | ||
45 | |||
46 | int main(void) | ||
47 | { | ||
48 | /* thread struct on stack */ | ||
49 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | ||
50 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
51 | DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); | ||
52 | |||
53 | /* task_struct->thread */ | ||
54 | DEFINE(THREAD, offsetof(struct task_struct, thread)); | ||
55 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); | ||
56 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); | ||
57 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); | ||
58 | DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); | ||
59 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); | ||
60 | DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); | ||
61 | |||
62 | #ifdef CONFIG_ALTIVEC | ||
63 | DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); | ||
64 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); | ||
65 | DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); | ||
66 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); | ||
67 | #endif /* CONFIG_ALTIVEC */ | ||
68 | DEFINE(MM, offsetof(struct task_struct, mm)); | ||
69 | DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); | ||
70 | |||
71 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); | ||
72 | DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); | ||
73 | DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page)); | ||
74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | ||
75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | ||
76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | ||
77 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | ||
78 | |||
79 | /* paca */ | ||
80 | DEFINE(PACA_SIZE, sizeof(struct paca_struct)); | ||
81 | DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); | ||
82 | DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start)); | ||
83 | DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack)); | ||
84 | DEFINE(PACACURRENT, offsetof(struct paca_struct, __current)); | ||
85 | DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr)); | ||
86 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); | ||
87 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); | ||
88 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); | ||
89 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); | ||
90 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); | ||
91 | DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); | ||
92 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | ||
93 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | ||
94 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | ||
95 | #ifdef CONFIG_PPC_64K_PAGES | ||
96 | DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); | ||
97 | #endif | ||
98 | #ifdef CONFIG_HUGETLB_PAGE | ||
99 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); | ||
100 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); | ||
101 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
102 | DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); | ||
103 | DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); | ||
104 | DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); | ||
105 | DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); | ||
106 | DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); | ||
107 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | ||
108 | DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); | ||
109 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | ||
110 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | ||
111 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | ||
112 | DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); | ||
113 | DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); | ||
114 | |||
115 | /* RTAS */ | ||
116 | DEFINE(RTASBASE, offsetof(struct rtas_t, base)); | ||
117 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); | ||
118 | |||
119 | /* Interrupt register frame */ | ||
120 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); | ||
121 | |||
122 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | ||
123 | |||
124 | /* 288 = # of volatile regs, int & fp, for leaf routines */ | ||
125 | /* which do not stack a frame. See the PPC64 ABI. */ | ||
126 | DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288); | ||
127 | /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ | ||
128 | DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
129 | DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
130 | DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0])); | ||
131 | DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1])); | ||
132 | DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2])); | ||
133 | DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3])); | ||
134 | DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4])); | ||
135 | DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5])); | ||
136 | DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6])); | ||
137 | DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7])); | ||
138 | DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8])); | ||
139 | DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9])); | ||
140 | DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10])); | ||
141 | DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11])); | ||
142 | DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12])); | ||
143 | DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13])); | ||
144 | /* | ||
145 | * Note: these symbols include _ because they overlap with special | ||
146 | * register names | ||
147 | */ | ||
148 | DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip)); | ||
149 | DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr)); | ||
150 | DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr)); | ||
151 | DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link)); | ||
152 | DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr)); | ||
153 | DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer)); | ||
154 | DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); | ||
155 | DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); | ||
156 | DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); | ||
157 | DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); | ||
158 | DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); | ||
159 | DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); | ||
160 | |||
161 | /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ | ||
162 | DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); | ||
163 | DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); | ||
164 | |||
165 | DEFINE(CLONE_VM, CLONE_VM); | ||
166 | DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); | ||
167 | |||
168 | /* About the CPU features table */ | ||
169 | DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); | ||
170 | DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); | ||
171 | DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); | ||
172 | DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); | ||
173 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); | ||
174 | |||
175 | /* systemcfg offsets for use by vdso */ | ||
176 | DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp)); | ||
177 | DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec)); | ||
178 | DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs)); | ||
179 | DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec)); | ||
180 | DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count)); | ||
181 | DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest)); | ||
182 | DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime)); | ||
183 | DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32)); | ||
184 | DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64)); | ||
185 | |||
186 | /* timeval/timezone offsets for use by vdso */ | ||
187 | DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec)); | ||
188 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); | ||
189 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); | ||
190 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); | ||
191 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | ||
192 | DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c deleted file mode 100644 index 506a37885c5c..000000000000 --- a/arch/ppc64/kernel/btext.c +++ /dev/null | |||
@@ -1,792 +0,0 @@ | |||
1 | /* | ||
2 | * Procedures for drawing on the screen early on in the boot process. | ||
3 | * | ||
4 | * Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | */ | ||
6 | #include <linux/config.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/string.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include <asm/sections.h> | ||
12 | #include <asm/prom.h> | ||
13 | #include <asm/btext.h> | ||
14 | #include <asm/prom.h> | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/mmu.h> | ||
17 | #include <asm/pgtable.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/lmb.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/udbg.h> | ||
22 | |||
23 | #undef NO_SCROLL | ||
24 | |||
25 | #ifndef NO_SCROLL | ||
26 | static void scrollscreen(void); | ||
27 | #endif | ||
28 | |||
29 | static void draw_byte(unsigned char c, long locX, long locY); | ||
30 | static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); | ||
31 | static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); | ||
32 | static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); | ||
33 | |||
34 | static int g_loc_X; | ||
35 | static int g_loc_Y; | ||
36 | static int g_max_loc_X; | ||
37 | static int g_max_loc_Y; | ||
38 | |||
39 | static int dispDeviceRowBytes; | ||
40 | static int dispDeviceDepth; | ||
41 | static int dispDeviceRect[4]; | ||
42 | static unsigned char *dispDeviceBase, *logicalDisplayBase; | ||
43 | |||
44 | unsigned long disp_BAT[2] __initdata = {0, 0}; | ||
45 | |||
46 | #define cmapsz (16*256) | ||
47 | |||
48 | static unsigned char vga_font[cmapsz]; | ||
49 | |||
50 | int boot_text_mapped; | ||
51 | int force_printk_to_btext = 0; | ||
52 | |||
53 | |||
54 | /* Here's a small text engine to use during early boot | ||
55 | * or for debugging purposes | ||
56 | * | ||
57 | * todo: | ||
58 | * | ||
59 | * - build some kind of vgacon with it to enable early printk | ||
60 | * - move to a separate file | ||
61 | * - add a few video driver hooks to keep in sync with display | ||
62 | * changes. | ||
63 | */ | ||
64 | |||
65 | void map_boot_text(void) | ||
66 | { | ||
67 | unsigned long base, offset, size; | ||
68 | unsigned char *vbase; | ||
69 | |||
70 | /* By default, we are no longer mapped */ | ||
71 | boot_text_mapped = 0; | ||
72 | if (dispDeviceBase == 0) | ||
73 | return; | ||
74 | base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL; | ||
75 | offset = ((unsigned long) dispDeviceBase) - base; | ||
76 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset | ||
77 | + dispDeviceRect[0]; | ||
78 | vbase = __ioremap(base, size, _PAGE_NO_CACHE); | ||
79 | if (vbase == 0) | ||
80 | return; | ||
81 | logicalDisplayBase = vbase + offset; | ||
82 | boot_text_mapped = 1; | ||
83 | } | ||
84 | |||
85 | int btext_initialize(struct device_node *np) | ||
86 | { | ||
87 | unsigned int width, height, depth, pitch; | ||
88 | unsigned long address = 0; | ||
89 | u32 *prop; | ||
90 | |||
91 | prop = (u32 *)get_property(np, "width", NULL); | ||
92 | if (prop == NULL) | ||
93 | return -EINVAL; | ||
94 | width = *prop; | ||
95 | prop = (u32 *)get_property(np, "height", NULL); | ||
96 | if (prop == NULL) | ||
97 | return -EINVAL; | ||
98 | height = *prop; | ||
99 | prop = (u32 *)get_property(np, "depth", NULL); | ||
100 | if (prop == NULL) | ||
101 | return -EINVAL; | ||
102 | depth = *prop; | ||
103 | pitch = width * ((depth + 7) / 8); | ||
104 | prop = (u32 *)get_property(np, "linebytes", NULL); | ||
105 | if (prop) | ||
106 | pitch = *prop; | ||
107 | if (pitch == 1) | ||
108 | pitch = 0x1000; | ||
109 | prop = (u32 *)get_property(np, "address", NULL); | ||
110 | if (prop) | ||
111 | address = *prop; | ||
112 | |||
113 | /* FIXME: Add support for PCI reg properties */ | ||
114 | |||
115 | if (address == 0) | ||
116 | return -EINVAL; | ||
117 | |||
118 | g_loc_X = 0; | ||
119 | g_loc_Y = 0; | ||
120 | g_max_loc_X = width / 8; | ||
121 | g_max_loc_Y = height / 16; | ||
122 | logicalDisplayBase = (unsigned char *)address; | ||
123 | dispDeviceBase = (unsigned char *)address; | ||
124 | dispDeviceRowBytes = pitch; | ||
125 | dispDeviceDepth = depth; | ||
126 | dispDeviceRect[0] = dispDeviceRect[1] = 0; | ||
127 | dispDeviceRect[2] = width; | ||
128 | dispDeviceRect[3] = height; | ||
129 | |||
130 | map_boot_text(); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static void btext_putc(unsigned char c) | ||
136 | { | ||
137 | btext_drawchar(c); | ||
138 | } | ||
139 | |||
140 | void __init init_boot_display(void) | ||
141 | { | ||
142 | char *name; | ||
143 | struct device_node *np = NULL; | ||
144 | int rc = -ENODEV; | ||
145 | |||
146 | printk("trying to initialize btext ...\n"); | ||
147 | |||
148 | name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); | ||
149 | if (name != NULL) { | ||
150 | np = of_find_node_by_path(name); | ||
151 | if (np != NULL) { | ||
152 | if (strcmp(np->type, "display") != 0) { | ||
153 | printk("boot stdout isn't a display !\n"); | ||
154 | of_node_put(np); | ||
155 | np = NULL; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | if (np) | ||
160 | rc = btext_initialize(np); | ||
161 | if (rc) { | ||
162 | for (np = NULL; (np = of_find_node_by_type(np, "display"));) { | ||
163 | if (get_property(np, "linux,opened", NULL)) { | ||
164 | printk("trying %s ...\n", np->full_name); | ||
165 | rc = btext_initialize(np); | ||
166 | printk("result: %d\n", rc); | ||
167 | } | ||
168 | if (rc == 0) | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | if (rc == 0 && udbg_putc == NULL) | ||
173 | udbg_putc = btext_putc; | ||
174 | } | ||
175 | |||
176 | |||
177 | /* Calc the base address of a given point (x,y) */ | ||
178 | static unsigned char * calc_base(int x, int y) | ||
179 | { | ||
180 | unsigned char *base; | ||
181 | |||
182 | base = logicalDisplayBase; | ||
183 | if (base == 0) | ||
184 | base = dispDeviceBase; | ||
185 | base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); | ||
186 | base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; | ||
187 | return base; | ||
188 | } | ||
189 | |||
190 | /* Adjust the display to a new resolution */ | ||
191 | void btext_update_display(unsigned long phys, int width, int height, | ||
192 | int depth, int pitch) | ||
193 | { | ||
194 | if (dispDeviceBase == 0) | ||
195 | return; | ||
196 | |||
197 | /* check it's the same frame buffer (within 256MB) */ | ||
198 | if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000) | ||
199 | return; | ||
200 | |||
201 | dispDeviceBase = (__u8 *) phys; | ||
202 | dispDeviceRect[0] = 0; | ||
203 | dispDeviceRect[1] = 0; | ||
204 | dispDeviceRect[2] = width; | ||
205 | dispDeviceRect[3] = height; | ||
206 | dispDeviceDepth = depth; | ||
207 | dispDeviceRowBytes = pitch; | ||
208 | if (boot_text_mapped) { | ||
209 | iounmap(logicalDisplayBase); | ||
210 | boot_text_mapped = 0; | ||
211 | } | ||
212 | map_boot_text(); | ||
213 | g_loc_X = 0; | ||
214 | g_loc_Y = 0; | ||
215 | g_max_loc_X = width / 8; | ||
216 | g_max_loc_Y = height / 16; | ||
217 | } | ||
218 | |||
219 | void btext_clearscreen(void) | ||
220 | { | ||
221 | unsigned long *base = (unsigned long *)calc_base(0, 0); | ||
222 | unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * | ||
223 | (dispDeviceDepth >> 3)) >> 3; | ||
224 | int i,j; | ||
225 | |||
226 | for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) | ||
227 | { | ||
228 | unsigned long *ptr = base; | ||
229 | for(j=width; j; --j) | ||
230 | *(ptr++) = 0; | ||
231 | base += (dispDeviceRowBytes >> 3); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | #ifndef NO_SCROLL | ||
236 | static void scrollscreen(void) | ||
237 | { | ||
238 | unsigned long *src = (unsigned long *)calc_base(0,16); | ||
239 | unsigned long *dst = (unsigned long *)calc_base(0,0); | ||
240 | unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * | ||
241 | (dispDeviceDepth >> 3)) >> 3; | ||
242 | int i,j; | ||
243 | |||
244 | for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) | ||
245 | { | ||
246 | unsigned long *src_ptr = src; | ||
247 | unsigned long *dst_ptr = dst; | ||
248 | for(j=width; j; --j) | ||
249 | *(dst_ptr++) = *(src_ptr++); | ||
250 | src += (dispDeviceRowBytes >> 3); | ||
251 | dst += (dispDeviceRowBytes >> 3); | ||
252 | } | ||
253 | for (i=0; i<16; i++) | ||
254 | { | ||
255 | unsigned long *dst_ptr = dst; | ||
256 | for(j=width; j; --j) | ||
257 | *(dst_ptr++) = 0; | ||
258 | dst += (dispDeviceRowBytes >> 3); | ||
259 | } | ||
260 | } | ||
261 | #endif /* ndef NO_SCROLL */ | ||
262 | |||
263 | void btext_drawchar(char c) | ||
264 | { | ||
265 | int cline = 0; | ||
266 | #ifdef NO_SCROLL | ||
267 | int x; | ||
268 | #endif | ||
269 | if (!boot_text_mapped) | ||
270 | return; | ||
271 | |||
272 | switch (c) { | ||
273 | case '\b': | ||
274 | if (g_loc_X > 0) | ||
275 | --g_loc_X; | ||
276 | break; | ||
277 | case '\t': | ||
278 | g_loc_X = (g_loc_X & -8) + 8; | ||
279 | break; | ||
280 | case '\r': | ||
281 | g_loc_X = 0; | ||
282 | break; | ||
283 | case '\n': | ||
284 | g_loc_X = 0; | ||
285 | g_loc_Y++; | ||
286 | cline = 1; | ||
287 | break; | ||
288 | default: | ||
289 | draw_byte(c, g_loc_X++, g_loc_Y); | ||
290 | } | ||
291 | if (g_loc_X >= g_max_loc_X) { | ||
292 | g_loc_X = 0; | ||
293 | g_loc_Y++; | ||
294 | cline = 1; | ||
295 | } | ||
296 | #ifndef NO_SCROLL | ||
297 | while (g_loc_Y >= g_max_loc_Y) { | ||
298 | scrollscreen(); | ||
299 | g_loc_Y--; | ||
300 | } | ||
301 | #else | ||
302 | /* wrap around from bottom to top of screen so we don't | ||
303 | waste time scrolling each line. -- paulus. */ | ||
304 | if (g_loc_Y >= g_max_loc_Y) | ||
305 | g_loc_Y = 0; | ||
306 | if (cline) { | ||
307 | for (x = 0; x < g_max_loc_X; ++x) | ||
308 | draw_byte(' ', x, g_loc_Y); | ||
309 | } | ||
310 | #endif | ||
311 | } | ||
312 | |||
313 | void btext_drawstring(const char *c) | ||
314 | { | ||
315 | if (!boot_text_mapped) | ||
316 | return; | ||
317 | while (*c) | ||
318 | btext_drawchar(*c++); | ||
319 | } | ||
320 | |||
321 | void btext_drawhex(unsigned long v) | ||
322 | { | ||
323 | char *hex_table = "0123456789abcdef"; | ||
324 | |||
325 | if (!boot_text_mapped) | ||
326 | return; | ||
327 | btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); | ||
328 | btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]); | ||
329 | btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]); | ||
330 | btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]); | ||
331 | btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]); | ||
332 | btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]); | ||
333 | btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]); | ||
334 | btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]); | ||
335 | btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]); | ||
336 | btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]); | ||
337 | btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]); | ||
338 | btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]); | ||
339 | btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]); | ||
340 | btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]); | ||
341 | btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]); | ||
342 | btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]); | ||
343 | btext_drawchar(' '); | ||
344 | } | ||
345 | |||
346 | static void draw_byte(unsigned char c, long locX, long locY) | ||
347 | { | ||
348 | unsigned char *base = calc_base(locX << 3, locY << 4); | ||
349 | unsigned char *font = &vga_font[((unsigned int)c) * 16]; | ||
350 | int rb = dispDeviceRowBytes; | ||
351 | |||
352 | switch(dispDeviceDepth) { | ||
353 | case 24: | ||
354 | case 32: | ||
355 | draw_byte_32(font, (unsigned int *)base, rb); | ||
356 | break; | ||
357 | case 15: | ||
358 | case 16: | ||
359 | draw_byte_16(font, (unsigned int *)base, rb); | ||
360 | break; | ||
361 | case 8: | ||
362 | draw_byte_8(font, (unsigned int *)base, rb); | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static unsigned int expand_bits_8[16] = { | ||
368 | 0x00000000, | ||
369 | 0x000000ff, | ||
370 | 0x0000ff00, | ||
371 | 0x0000ffff, | ||
372 | 0x00ff0000, | ||
373 | 0x00ff00ff, | ||
374 | 0x00ffff00, | ||
375 | 0x00ffffff, | ||
376 | 0xff000000, | ||
377 | 0xff0000ff, | ||
378 | 0xff00ff00, | ||
379 | 0xff00ffff, | ||
380 | 0xffff0000, | ||
381 | 0xffff00ff, | ||
382 | 0xffffff00, | ||
383 | 0xffffffff | ||
384 | }; | ||
385 | |||
386 | static unsigned int expand_bits_16[4] = { | ||
387 | 0x00000000, | ||
388 | 0x0000ffff, | ||
389 | 0xffff0000, | ||
390 | 0xffffffff | ||
391 | }; | ||
392 | |||
393 | |||
394 | static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) | ||
395 | { | ||
396 | int l, bits; | ||
397 | int fg = 0xFFFFFFFFUL; | ||
398 | int bg = 0x00000000UL; | ||
399 | |||
400 | for (l = 0; l < 16; ++l) | ||
401 | { | ||
402 | bits = *font++; | ||
403 | base[0] = (-(bits >> 7) & fg) ^ bg; | ||
404 | base[1] = (-((bits >> 6) & 1) & fg) ^ bg; | ||
405 | base[2] = (-((bits >> 5) & 1) & fg) ^ bg; | ||
406 | base[3] = (-((bits >> 4) & 1) & fg) ^ bg; | ||
407 | base[4] = (-((bits >> 3) & 1) & fg) ^ bg; | ||
408 | base[5] = (-((bits >> 2) & 1) & fg) ^ bg; | ||
409 | base[6] = (-((bits >> 1) & 1) & fg) ^ bg; | ||
410 | base[7] = (-(bits & 1) & fg) ^ bg; | ||
411 | base = (unsigned int *) ((char *)base + rb); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static void draw_byte_16(unsigned char *font, unsigned int *base, int rb) | ||
416 | { | ||
417 | int l, bits; | ||
418 | int fg = 0xFFFFFFFFUL; | ||
419 | int bg = 0x00000000UL; | ||
420 | unsigned int *eb = (int *)expand_bits_16; | ||
421 | |||
422 | for (l = 0; l < 16; ++l) | ||
423 | { | ||
424 | bits = *font++; | ||
425 | base[0] = (eb[bits >> 6] & fg) ^ bg; | ||
426 | base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; | ||
427 | base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; | ||
428 | base[3] = (eb[bits & 3] & fg) ^ bg; | ||
429 | base = (unsigned int *) ((char *)base + rb); | ||
430 | } | ||
431 | } | ||
432 | |||
433 | static void draw_byte_8(unsigned char *font, unsigned int *base, int rb) | ||
434 | { | ||
435 | int l, bits; | ||
436 | int fg = 0x0F0F0F0FUL; | ||
437 | int bg = 0x00000000UL; | ||
438 | unsigned int *eb = (int *)expand_bits_8; | ||
439 | |||
440 | for (l = 0; l < 16; ++l) | ||
441 | { | ||
442 | bits = *font++; | ||
443 | base[0] = (eb[bits >> 4] & fg) ^ bg; | ||
444 | base[1] = (eb[bits & 0xf] & fg) ^ bg; | ||
445 | base = (unsigned int *) ((char *)base + rb); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | static unsigned char vga_font[cmapsz] = { | ||
450 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
451 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, | ||
452 | 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, | ||
453 | 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
454 | 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, | ||
455 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, | ||
456 | 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, | ||
457 | 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
458 | 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, | ||
459 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, | ||
460 | 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | ||
461 | 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
462 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, | ||
463 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, | ||
464 | 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, | ||
465 | 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, | ||
466 | 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, | ||
467 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, | ||
468 | 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, | ||
469 | 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, | ||
470 | 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, | ||
471 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, | ||
472 | 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, | ||
473 | 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
474 | 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, | ||
475 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, | ||
476 | 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, | ||
477 | 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, | ||
478 | 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, | ||
479 | 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
480 | 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, | ||
481 | 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
482 | 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
483 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
484 | 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
485 | 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
486 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, | ||
487 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, | ||
488 | 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
489 | 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
490 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, | ||
491 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, | ||
492 | 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
493 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
494 | 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | ||
495 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, | ||
496 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, | ||
497 | 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, | ||
498 | 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, | ||
499 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, | ||
500 | 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, | ||
501 | 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
502 | 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
503 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, | ||
504 | 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, | ||
505 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | ||
506 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, | ||
507 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, | ||
508 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
509 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, | ||
510 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
511 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
512 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
513 | 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, | ||
514 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, | ||
515 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, | ||
516 | 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
517 | 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
518 | 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, | ||
519 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, | ||
520 | 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, | ||
521 | 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
522 | 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
523 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, | ||
524 | 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
525 | 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
526 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, | ||
527 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, | ||
528 | 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
529 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | ||
530 | 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, | ||
531 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, | ||
532 | 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, | ||
533 | 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, | ||
534 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | ||
535 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, | ||
536 | 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, | ||
537 | 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
538 | 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, | ||
539 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, | ||
540 | 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, | ||
541 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, | ||
542 | 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, | ||
543 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, | ||
544 | 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, | ||
545 | 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, | ||
546 | 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
547 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
548 | 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, | ||
549 | 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, | ||
550 | 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, | ||
551 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, | ||
552 | 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, | ||
553 | 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, | ||
554 | 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, | ||
555 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
556 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, | ||
557 | 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, | ||
558 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, | ||
559 | 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, | ||
560 | 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
561 | 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
562 | 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
563 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
564 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, | ||
565 | 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
566 | 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, | ||
567 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, | ||
568 | 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, | ||
569 | 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
570 | 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, | ||
571 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, | ||
572 | 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
573 | 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
574 | 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, | ||
575 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
576 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
577 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, | ||
578 | 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
579 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, | ||
580 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
581 | 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
582 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, | ||
583 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, | ||
584 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
585 | 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
586 | 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, | ||
587 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, | ||
588 | 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
589 | 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, | ||
590 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
591 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, | ||
592 | 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
593 | 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, | ||
594 | 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
595 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, | ||
596 | 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
597 | 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
598 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
599 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, | ||
600 | 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
601 | 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, | ||
602 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, | ||
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, | ||
604 | 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, | ||
605 | 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, | ||
606 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
607 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, | ||
608 | 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
609 | 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
610 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, | ||
611 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, | ||
612 | 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
613 | 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
614 | 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, | ||
615 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, | ||
616 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, | ||
617 | 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
618 | 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
619 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, | ||
620 | 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, | ||
621 | 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, | ||
622 | 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
623 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, | ||
624 | 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, | ||
625 | 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
626 | 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, | ||
627 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, | ||
628 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, | ||
629 | 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
630 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, | ||
631 | 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, | ||
632 | 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, | ||
633 | 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
634 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, | ||
635 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, | ||
636 | 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, | ||
637 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
638 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
639 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, | ||
640 | 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, | ||
641 | 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
642 | 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, | ||
643 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, | ||
644 | 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, | ||
645 | 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, | ||
646 | 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, | ||
648 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, | ||
649 | 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
650 | 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, | ||
652 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, | ||
653 | 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, | ||
654 | 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
655 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
656 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, | ||
657 | 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
658 | 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, | ||
659 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, | ||
660 | 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, | ||
661 | 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, | ||
662 | 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
663 | 0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, | ||
664 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, | ||
665 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
666 | 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
667 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, | ||
668 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, | ||
669 | 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
670 | 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, | ||
671 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, | ||
672 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, | ||
673 | 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
674 | 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, | ||
675 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, | ||
676 | 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
677 | 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
678 | 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, | ||
679 | 0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, | ||
680 | 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, | ||
681 | 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
682 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, | ||
683 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, | ||
684 | 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, | ||
685 | 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, | ||
686 | 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, | ||
687 | 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, | ||
688 | 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, | ||
689 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
690 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, | ||
691 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, | ||
692 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, | ||
693 | 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
694 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, | ||
695 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, | ||
696 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, | ||
697 | 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
698 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
699 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, | ||
700 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
701 | 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
702 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
703 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, | ||
704 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
705 | 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
706 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, | ||
707 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, | ||
708 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
709 | 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
710 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
711 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
712 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, | ||
713 | 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
714 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
715 | 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, | ||
716 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
717 | 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
718 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, | ||
719 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, | ||
720 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
721 | 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
722 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, | ||
723 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, | ||
724 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, | ||
725 | 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
726 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, | ||
727 | 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, | ||
728 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
729 | 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
730 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, | ||
731 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, | ||
732 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, | ||
733 | 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
734 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
735 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, | ||
736 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
737 | 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
738 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, | ||
739 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, | ||
740 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
741 | 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
742 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
743 | 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
744 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, | ||
745 | 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, | ||
746 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
747 | 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, | ||
748 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
749 | 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
750 | 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, | ||
751 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, | ||
752 | 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
753 | 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, | ||
754 | 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, | ||
755 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, | ||
756 | 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
757 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, | ||
758 | 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
759 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, | ||
760 | 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, | ||
761 | 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, | ||
762 | 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, | ||
763 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, | ||
764 | 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
765 | 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
766 | 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, | ||
767 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, | ||
768 | 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, | ||
769 | 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
770 | 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, | ||
771 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, | ||
772 | 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, | ||
773 | 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
774 | 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, | ||
775 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, | ||
776 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
777 | 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
778 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, | ||
779 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, | ||
780 | 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, | ||
781 | 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
782 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, | ||
783 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
784 | 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, | ||
785 | 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, | ||
786 | 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
787 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, | ||
788 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
789 | 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
790 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
791 | 0x00, 0x00, 0x00, 0x00, | ||
792 | }; | ||
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S deleted file mode 100644 index 1c869ea72d28..000000000000 --- a/arch/ppc64/kernel/head.S +++ /dev/null | |||
@@ -1,2007 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc64/kernel/head.S | ||
3 | * | ||
4 | * PowerPC version | ||
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
6 | * | ||
7 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | ||
8 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> | ||
9 | * Adapted for Power Macintosh by Paul Mackerras. | ||
10 | * Low-level exception handlers and MMU support | ||
11 | * rewritten by Paul Mackerras. | ||
12 | * Copyright (C) 1996 Paul Mackerras. | ||
13 | * | ||
14 | * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and | ||
15 | * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com | ||
16 | * | ||
17 | * This file contains the low-level support and setup for the | ||
18 | * PowerPC-64 platform, including trap and interrupt dispatch. | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or | ||
21 | * modify it under the terms of the GNU General Public License | ||
22 | * as published by the Free Software Foundation; either version | ||
23 | * 2 of the License, or (at your option) any later version. | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/threads.h> | ||
28 | #include <asm/processor.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/mmu.h> | ||
31 | #include <asm/ppc_asm.h> | ||
32 | #include <asm/asm-offsets.h> | ||
33 | #include <asm/bug.h> | ||
34 | #include <asm/cputable.h> | ||
35 | #include <asm/setup.h> | ||
36 | #include <asm/hvcall.h> | ||
37 | #include <asm/iseries/lpar_map.h> | ||
38 | #include <asm/thread_info.h> | ||
39 | |||
40 | #ifdef CONFIG_PPC_ISERIES | ||
41 | #define DO_SOFT_DISABLE | ||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * We layout physical memory as follows: | ||
46 | * 0x0000 - 0x00ff : Secondary processor spin code | ||
47 | * 0x0100 - 0x2fff : pSeries Interrupt prologs | ||
48 | * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs | ||
49 | * 0x6000 - 0x6fff : Initial (CPU0) segment table | ||
50 | * 0x7000 - 0x7fff : FWNMI data area | ||
51 | * 0x8000 - : Early init and support code | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * SPRG Usage | ||
56 | * | ||
57 | * Register Definition | ||
58 | * | ||
59 | * SPRG0 reserved for hypervisor | ||
60 | * SPRG1 temp - used to save gpr | ||
61 | * SPRG2 temp - used to save gpr | ||
62 | * SPRG3 virt addr of paca | ||
63 | */ | ||
64 | |||
65 | /* | ||
66 | * Entering into this code we make the following assumptions: | ||
67 | * For pSeries: | ||
68 | * 1. The MMU is off & open firmware is running in real mode. | ||
69 | * 2. The kernel is entered at __start | ||
70 | * | ||
71 | * For iSeries: | ||
72 | * 1. The MMU is on (as it always is for iSeries) | ||
73 | * 2. The kernel is entered at system_reset_iSeries | ||
74 | */ | ||
75 | |||
76 | .text | ||
77 | .globl _stext | ||
78 | _stext: | ||
79 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
80 | _GLOBAL(__start) | ||
81 | /* NOP this out unconditionally */ | ||
82 | BEGIN_FTR_SECTION | ||
83 | b .__start_initialization_multiplatform | ||
84 | END_FTR_SECTION(0, 1) | ||
85 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
86 | |||
87 | /* Catch branch to 0 in real mode */ | ||
88 | trap | ||
89 | |||
90 | #ifdef CONFIG_PPC_ISERIES | ||
91 | /* | ||
92 | * At offset 0x20, there is a pointer to iSeries LPAR data. | ||
93 | * This is required by the hypervisor | ||
94 | */ | ||
95 | . = 0x20 | ||
96 | .llong hvReleaseData-KERNELBASE | ||
97 | |||
98 | /* | ||
99 | * At offset 0x28 and 0x30 are offsets to the mschunks_map | ||
100 | * array (used by the iSeries LPAR debugger to do translation | ||
101 | * between physical addresses and absolute addresses) and | ||
102 | * to the pidhash table (also used by the debugger) | ||
103 | */ | ||
104 | .llong mschunks_map-KERNELBASE | ||
105 | .llong 0 /* pidhash-KERNELBASE SFRXXX */ | ||
106 | |||
107 | /* Offset 0x38 - Pointer to start of embedded System.map */ | ||
108 | .globl embedded_sysmap_start | ||
109 | embedded_sysmap_start: | ||
110 | .llong 0 | ||
111 | /* Offset 0x40 - Pointer to end of embedded System.map */ | ||
112 | .globl embedded_sysmap_end | ||
113 | embedded_sysmap_end: | ||
114 | .llong 0 | ||
115 | |||
116 | #endif /* CONFIG_PPC_ISERIES */ | ||
117 | |||
118 | /* Secondary processors spin on this value until it goes to 1. */ | ||
119 | .globl __secondary_hold_spinloop | ||
120 | __secondary_hold_spinloop: | ||
121 | .llong 0x0 | ||
122 | |||
123 | /* Secondary processors write this value with their cpu # */ | ||
124 | /* after they enter the spin loop immediately below. */ | ||
125 | .globl __secondary_hold_acknowledge | ||
126 | __secondary_hold_acknowledge: | ||
127 | .llong 0x0 | ||
128 | |||
129 | . = 0x60 | ||
130 | /* | ||
131 | * The following code is used on pSeries to hold secondary processors | ||
132 | * in a spin loop after they have been freed from OpenFirmware, but | ||
133 | * before the bulk of the kernel has been relocated. This code | ||
134 | * is relocated to physical address 0x60 before prom_init is run. | ||
135 | * All of it must fit below the first exception vector at 0x100. | ||
136 | */ | ||
137 | _GLOBAL(__secondary_hold) | ||
138 | mfmsr r24 | ||
139 | ori r24,r24,MSR_RI | ||
140 | mtmsrd r24 /* RI on */ | ||
141 | |||
142 | /* Grab our linux cpu number */ | ||
143 | mr r24,r3 | ||
144 | |||
145 | /* Tell the master cpu we're here */ | ||
146 | /* Relocation is off & we are located at an address less */ | ||
147 | /* than 0x100, so only need to grab low order offset. */ | ||
148 | std r24,__secondary_hold_acknowledge@l(0) | ||
149 | sync | ||
150 | |||
151 | /* All secondary cpus wait here until told to start. */ | ||
152 | 100: ld r4,__secondary_hold_spinloop@l(0) | ||
153 | cmpdi 0,r4,1 | ||
154 | bne 100b | ||
155 | |||
156 | #ifdef CONFIG_HMT | ||
157 | b .hmt_init | ||
158 | #else | ||
159 | #ifdef CONFIG_SMP | ||
160 | mr r3,r24 | ||
161 | b .pSeries_secondary_smp_init | ||
162 | #else | ||
163 | BUG_OPCODE | ||
164 | #endif | ||
165 | #endif | ||
166 | |||
167 | /* This value is used to mark exception frames on the stack. */ | ||
168 | .section ".toc","aw" | ||
169 | exception_marker: | ||
170 | .tc ID_72656773_68657265[TC],0x7265677368657265 | ||
171 | .text | ||
172 | |||
173 | /* | ||
174 | * The following macros define the code that appears as | ||
175 | * the prologue to each of the exception handlers. They | ||
176 | * are split into two parts to allow a single kernel binary | ||
177 | * to be used for pSeries and iSeries. | ||
178 | * LOL. One day... - paulus | ||
179 | */ | ||
180 | |||
181 | /* | ||
182 | * We make as much of the exception code common between native | ||
183 | * exception handlers (including pSeries LPAR) and iSeries LPAR | ||
184 | * implementations as possible. | ||
185 | */ | ||
186 | |||
187 | /* | ||
188 | * This is the start of the interrupt handlers for pSeries | ||
189 | * This code runs with relocation off. | ||
190 | */ | ||
191 | #define EX_R9 0 | ||
192 | #define EX_R10 8 | ||
193 | #define EX_R11 16 | ||
194 | #define EX_R12 24 | ||
195 | #define EX_R13 32 | ||
196 | #define EX_SRR0 40 | ||
197 | #define EX_DAR 48 | ||
198 | #define EX_DSISR 56 | ||
199 | #define EX_CCR 60 | ||
200 | #define EX_R3 64 | ||
201 | #define EX_LR 72 | ||
202 | |||
203 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ | ||
204 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
205 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
206 | std r10,area+EX_R10(r13); \ | ||
207 | std r11,area+EX_R11(r13); \ | ||
208 | std r12,area+EX_R12(r13); \ | ||
209 | mfspr r9,SPRN_SPRG1; \ | ||
210 | std r9,area+EX_R13(r13); \ | ||
211 | mfcr r9; \ | ||
212 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
213 | mfmsr r10; \ | ||
214 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
215 | ori r12,r12,(label)@l; /* virt addr of handler */ \ | ||
216 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
217 | mtspr SPRN_SRR0,r12; \ | ||
218 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
219 | mtspr SPRN_SRR1,r10; \ | ||
220 | rfid; \ | ||
221 | b . /* prevent speculative execution */ | ||
222 | |||
223 | /* | ||
224 | * This is the start of the interrupt handlers for iSeries | ||
225 | * This code runs with relocation on. | ||
226 | */ | ||
227 | #define EXCEPTION_PROLOG_ISERIES_1(area) \ | ||
228 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
229 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
230 | std r10,area+EX_R10(r13); \ | ||
231 | std r11,area+EX_R11(r13); \ | ||
232 | std r12,area+EX_R12(r13); \ | ||
233 | mfspr r9,SPRN_SPRG1; \ | ||
234 | std r9,area+EX_R13(r13); \ | ||
235 | mfcr r9 | ||
236 | |||
237 | #define EXCEPTION_PROLOG_ISERIES_2 \ | ||
238 | mfmsr r10; \ | ||
239 | ld r11,PACALPPACA+LPPACASRR0(r13); \ | ||
240 | ld r12,PACALPPACA+LPPACASRR1(r13); \ | ||
241 | ori r10,r10,MSR_RI; \ | ||
242 | mtmsrd r10,1 | ||
243 | |||
244 | /* | ||
245 | * The common exception prolog is used for all except a few exceptions | ||
246 | * such as a segment miss on a kernel address. We have to be prepared | ||
247 | * to take another exception from the point where we first touch the | ||
248 | * kernel stack onwards. | ||
249 | * | ||
250 | * On entry r13 points to the paca, r9-r13 are saved in the paca, | ||
251 | * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and | ||
252 | * SRR1, and relocation is on. | ||
253 | */ | ||
254 | #define EXCEPTION_PROLOG_COMMON(n, area) \ | ||
255 | andi. r10,r12,MSR_PR; /* See if coming from user */ \ | ||
256 | mr r10,r1; /* Save r1 */ \ | ||
257 | subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ | ||
258 | beq- 1f; \ | ||
259 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ | ||
260 | 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ | ||
261 | bge- cr1,bad_stack; /* abort if it is */ \ | ||
262 | std r9,_CCR(r1); /* save CR in stackframe */ \ | ||
263 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ | ||
264 | std r12,_MSR(r1); /* save SRR1 in stackframe */ \ | ||
265 | std r10,0(r1); /* make stack chain pointer */ \ | ||
266 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | ||
267 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | ||
268 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
269 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | ||
270 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | ||
271 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ | ||
272 | ld r10,area+EX_R10(r13); \ | ||
273 | std r9,GPR9(r1); \ | ||
274 | std r10,GPR10(r1); \ | ||
275 | ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ | ||
276 | ld r10,area+EX_R12(r13); \ | ||
277 | ld r11,area+EX_R13(r13); \ | ||
278 | std r9,GPR11(r1); \ | ||
279 | std r10,GPR12(r1); \ | ||
280 | std r11,GPR13(r1); \ | ||
281 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ | ||
282 | mflr r9; /* save LR in stackframe */ \ | ||
283 | std r9,_LINK(r1); \ | ||
284 | mfctr r10; /* save CTR in stackframe */ \ | ||
285 | std r10,_CTR(r1); \ | ||
286 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ | ||
287 | std r11,_XER(r1); \ | ||
288 | li r9,(n)+1; \ | ||
289 | std r9,_TRAP(r1); /* set trap number */ \ | ||
290 | li r10,0; \ | ||
291 | ld r11,exception_marker@toc(r2); \ | ||
292 | std r10,RESULT(r1); /* clear regs->result */ \ | ||
293 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ | ||
294 | |||
295 | /* | ||
296 | * Exception vectors. | ||
297 | */ | ||
298 | #define STD_EXCEPTION_PSERIES(n, label) \ | ||
299 | . = n; \ | ||
300 | .globl label##_pSeries; \ | ||
301 | label##_pSeries: \ | ||
302 | HMT_MEDIUM; \ | ||
303 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
304 | RUNLATCH_ON(r13); \ | ||
305 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
306 | |||
307 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | ||
308 | .globl label##_iSeries; \ | ||
309 | label##_iSeries: \ | ||
310 | HMT_MEDIUM; \ | ||
311 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
312 | RUNLATCH_ON(r13); \ | ||
313 | EXCEPTION_PROLOG_ISERIES_1(area); \ | ||
314 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
315 | b label##_common | ||
316 | |||
317 | #define MASKABLE_EXCEPTION_ISERIES(n, label) \ | ||
318 | .globl label##_iSeries; \ | ||
319 | label##_iSeries: \ | ||
320 | HMT_MEDIUM; \ | ||
321 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
322 | RUNLATCH_ON(r13); \ | ||
323 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | ||
324 | lbz r10,PACAPROCENABLED(r13); \ | ||
325 | cmpwi 0,r10,0; \ | ||
326 | beq- label##_iSeries_masked; \ | ||
327 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
328 | b label##_common; \ | ||
329 | |||
330 | #ifdef DO_SOFT_DISABLE | ||
331 | #define DISABLE_INTS \ | ||
332 | lbz r10,PACAPROCENABLED(r13); \ | ||
333 | li r11,0; \ | ||
334 | std r10,SOFTE(r1); \ | ||
335 | mfmsr r10; \ | ||
336 | stb r11,PACAPROCENABLED(r13); \ | ||
337 | ori r10,r10,MSR_EE; \ | ||
338 | mtmsrd r10,1 | ||
339 | |||
340 | #define ENABLE_INTS \ | ||
341 | lbz r10,PACAPROCENABLED(r13); \ | ||
342 | mfmsr r11; \ | ||
343 | std r10,SOFTE(r1); \ | ||
344 | ori r11,r11,MSR_EE; \ | ||
345 | mtmsrd r11,1 | ||
346 | |||
347 | #else /* hard enable/disable interrupts */ | ||
348 | #define DISABLE_INTS | ||
349 | |||
350 | #define ENABLE_INTS \ | ||
351 | ld r12,_MSR(r1); \ | ||
352 | mfmsr r11; \ | ||
353 | rlwimi r11,r12,0,MSR_EE; \ | ||
354 | mtmsrd r11,1 | ||
355 | |||
356 | #endif | ||
357 | |||
358 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | ||
359 | .align 7; \ | ||
360 | .globl label##_common; \ | ||
361 | label##_common: \ | ||
362 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
363 | DISABLE_INTS; \ | ||
364 | bl .save_nvgprs; \ | ||
365 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
366 | bl hdlr; \ | ||
367 | b .ret_from_except | ||
368 | |||
369 | #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \ | ||
370 | .align 7; \ | ||
371 | .globl label##_common; \ | ||
372 | label##_common: \ | ||
373 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
374 | DISABLE_INTS; \ | ||
375 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
376 | bl hdlr; \ | ||
377 | b .ret_from_except_lite | ||
378 | |||
379 | /* | ||
380 | * Start of pSeries system interrupt routines | ||
381 | */ | ||
382 | . = 0x100 | ||
383 | .globl __start_interrupts | ||
384 | __start_interrupts: | ||
385 | |||
386 | STD_EXCEPTION_PSERIES(0x100, system_reset) | ||
387 | |||
388 | . = 0x200 | ||
389 | _machine_check_pSeries: | ||
390 | HMT_MEDIUM | ||
391 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
392 | RUNLATCH_ON(r13) | ||
393 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
394 | |||
395 | . = 0x300 | ||
396 | .globl data_access_pSeries | ||
397 | data_access_pSeries: | ||
398 | HMT_MEDIUM | ||
399 | mtspr SPRN_SPRG1,r13 | ||
400 | BEGIN_FTR_SECTION | ||
401 | mtspr SPRN_SPRG2,r12 | ||
402 | mfspr r13,SPRN_DAR | ||
403 | mfspr r12,SPRN_DSISR | ||
404 | srdi r13,r13,60 | ||
405 | rlwimi r13,r12,16,0x20 | ||
406 | mfcr r12 | ||
407 | cmpwi r13,0x2c | ||
408 | beq .do_stab_bolted_pSeries | ||
409 | mtcrf 0x80,r12 | ||
410 | mfspr r12,SPRN_SPRG2 | ||
411 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
412 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common) | ||
413 | |||
414 | . = 0x380 | ||
415 | .globl data_access_slb_pSeries | ||
416 | data_access_slb_pSeries: | ||
417 | HMT_MEDIUM | ||
418 | mtspr SPRN_SPRG1,r13 | ||
419 | RUNLATCH_ON(r13) | ||
420 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
421 | std r3,PACA_EXSLB+EX_R3(r13) | ||
422 | mfspr r3,SPRN_DAR | ||
423 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | ||
424 | mfcr r9 | ||
425 | #ifdef __DISABLED__ | ||
426 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
427 | cmpdi r3,0 | ||
428 | bge slb_miss_user_pseries | ||
429 | #endif /* __DISABLED__ */ | ||
430 | std r10,PACA_EXSLB+EX_R10(r13) | ||
431 | std r11,PACA_EXSLB+EX_R11(r13) | ||
432 | std r12,PACA_EXSLB+EX_R12(r13) | ||
433 | mfspr r10,SPRN_SPRG1 | ||
434 | std r10,PACA_EXSLB+EX_R13(r13) | ||
435 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | ||
436 | b .slb_miss_realmode /* Rel. branch works in real mode */ | ||
437 | |||
438 | STD_EXCEPTION_PSERIES(0x400, instruction_access) | ||
439 | |||
440 | . = 0x480 | ||
441 | .globl instruction_access_slb_pSeries | ||
442 | instruction_access_slb_pSeries: | ||
443 | HMT_MEDIUM | ||
444 | mtspr SPRN_SPRG1,r13 | ||
445 | RUNLATCH_ON(r13) | ||
446 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
447 | std r3,PACA_EXSLB+EX_R3(r13) | ||
448 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | ||
449 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | ||
450 | mfcr r9 | ||
451 | #ifdef __DISABLED__ | ||
452 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
453 | cmpdi r3,0 | ||
454 | bge slb_miss_user_pseries | ||
455 | #endif /* __DISABLED__ */ | ||
456 | std r10,PACA_EXSLB+EX_R10(r13) | ||
457 | std r11,PACA_EXSLB+EX_R11(r13) | ||
458 | std r12,PACA_EXSLB+EX_R12(r13) | ||
459 | mfspr r10,SPRN_SPRG1 | ||
460 | std r10,PACA_EXSLB+EX_R13(r13) | ||
461 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | ||
462 | b .slb_miss_realmode /* Rel. branch works in real mode */ | ||
463 | |||
464 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) | ||
465 | STD_EXCEPTION_PSERIES(0x600, alignment) | ||
466 | STD_EXCEPTION_PSERIES(0x700, program_check) | ||
467 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) | ||
468 | STD_EXCEPTION_PSERIES(0x900, decrementer) | ||
469 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) | ||
470 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) | ||
471 | |||
472 | . = 0xc00 | ||
473 | .globl system_call_pSeries | ||
474 | system_call_pSeries: | ||
475 | HMT_MEDIUM | ||
476 | RUNLATCH_ON(r9) | ||
477 | mr r9,r13 | ||
478 | mfmsr r10 | ||
479 | mfspr r13,SPRN_SPRG3 | ||
480 | mfspr r11,SPRN_SRR0 | ||
481 | clrrdi r12,r13,32 | ||
482 | oris r12,r12,system_call_common@h | ||
483 | ori r12,r12,system_call_common@l | ||
484 | mtspr SPRN_SRR0,r12 | ||
485 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
486 | mfspr r12,SPRN_SRR1 | ||
487 | mtspr SPRN_SRR1,r10 | ||
488 | rfid | ||
489 | b . /* prevent speculative execution */ | ||
490 | |||
491 | STD_EXCEPTION_PSERIES(0xd00, single_step) | ||
492 | STD_EXCEPTION_PSERIES(0xe00, trap_0e) | ||
493 | |||
494 | /* We need to deal with the Altivec unavailable exception | ||
495 | * here which is at 0xf20, thus in the middle of the | ||
496 | * prolog code of the PerformanceMonitor one. A little | ||
497 | * trickery is thus necessary | ||
498 | */ | ||
499 | . = 0xf00 | ||
500 | b performance_monitor_pSeries | ||
501 | |||
502 | STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) | ||
503 | |||
504 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) | ||
505 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) | ||
506 | |||
507 | . = 0x3000 | ||
508 | |||
509 | /*** pSeries interrupt support ***/ | ||
510 | |||
511 | /* moved from 0xf00 */ | ||
512 | STD_EXCEPTION_PSERIES(., performance_monitor) | ||
513 | |||
514 | .align 7 | ||
515 | _GLOBAL(do_stab_bolted_pSeries) | ||
516 | mtcrf 0x80,r12 | ||
517 | mfspr r12,SPRN_SPRG2 | ||
518 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | ||
519 | |||
520 | /* | ||
521 | * We have some room here we use that to put | ||
522 | * the peries slb miss user trampoline code so it's reasonably | ||
523 | * away from slb_miss_user_common to avoid problems with rfid | ||
524 | * | ||
525 | * This is used for when the SLB miss handler has to go virtual, | ||
526 | * which doesn't happen for now anymore but will once we re-implement | ||
527 | * dynamic VSIDs for shared page tables | ||
528 | */ | ||
529 | #ifdef __DISABLED__ | ||
530 | slb_miss_user_pseries: | ||
531 | std r10,PACA_EXGEN+EX_R10(r13) | ||
532 | std r11,PACA_EXGEN+EX_R11(r13) | ||
533 | std r12,PACA_EXGEN+EX_R12(r13) | ||
534 | mfspr r10,SPRG1 | ||
535 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
536 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
537 | std r10,PACA_EXGEN+EX_R13(r13) | ||
538 | std r11,PACA_EXGEN+EX_R9(r13) | ||
539 | std r12,PACA_EXGEN+EX_R3(r13) | ||
540 | clrrdi r12,r13,32 | ||
541 | mfmsr r10 | ||
542 | mfspr r11,SRR0 /* save SRR0 */ | ||
543 | ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ | ||
544 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
545 | mtspr SRR0,r12 | ||
546 | mfspr r12,SRR1 /* and SRR1 */ | ||
547 | mtspr SRR1,r10 | ||
548 | rfid | ||
549 | b . /* prevent spec. execution */ | ||
550 | #endif /* __DISABLED__ */ | ||
551 | |||
552 | /* | ||
553 | * Vectors for the FWNMI option. Share common code. | ||
554 | */ | ||
555 | .globl system_reset_fwnmi | ||
556 | system_reset_fwnmi: | ||
557 | HMT_MEDIUM | ||
558 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
559 | RUNLATCH_ON(r13) | ||
560 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | ||
561 | |||
562 | .globl machine_check_fwnmi | ||
563 | machine_check_fwnmi: | ||
564 | HMT_MEDIUM | ||
565 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
566 | RUNLATCH_ON(r13) | ||
567 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
568 | |||
569 | #ifdef CONFIG_PPC_ISERIES | ||
570 | /*** ISeries-LPAR interrupt handlers ***/ | ||
571 | |||
572 | STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) | ||
573 | |||
574 | .globl data_access_iSeries | ||
575 | data_access_iSeries: | ||
576 | mtspr SPRN_SPRG1,r13 | ||
577 | BEGIN_FTR_SECTION | ||
578 | mtspr SPRN_SPRG2,r12 | ||
579 | mfspr r13,SPRN_DAR | ||
580 | mfspr r12,SPRN_DSISR | ||
581 | srdi r13,r13,60 | ||
582 | rlwimi r13,r12,16,0x20 | ||
583 | mfcr r12 | ||
584 | cmpwi r13,0x2c | ||
585 | beq .do_stab_bolted_iSeries | ||
586 | mtcrf 0x80,r12 | ||
587 | mfspr r12,SPRN_SPRG2 | ||
588 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
589 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN) | ||
590 | EXCEPTION_PROLOG_ISERIES_2 | ||
591 | b data_access_common | ||
592 | |||
593 | .do_stab_bolted_iSeries: | ||
594 | mtcrf 0x80,r12 | ||
595 | mfspr r12,SPRN_SPRG2 | ||
596 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) | ||
597 | EXCEPTION_PROLOG_ISERIES_2 | ||
598 | b .do_stab_bolted | ||
599 | |||
600 | .globl data_access_slb_iSeries | ||
601 | data_access_slb_iSeries: | ||
602 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
603 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
604 | std r3,PACA_EXSLB+EX_R3(r13) | ||
605 | mfspr r3,SPRN_DAR | ||
606 | std r9,PACA_EXSLB+EX_R9(r13) | ||
607 | mfcr r9 | ||
608 | #ifdef __DISABLED__ | ||
609 | cmpdi r3,0 | ||
610 | bge slb_miss_user_iseries | ||
611 | #endif | ||
612 | std r10,PACA_EXSLB+EX_R10(r13) | ||
613 | std r11,PACA_EXSLB+EX_R11(r13) | ||
614 | std r12,PACA_EXSLB+EX_R12(r13) | ||
615 | mfspr r10,SPRN_SPRG1 | ||
616 | std r10,PACA_EXSLB+EX_R13(r13) | ||
617 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
618 | b .slb_miss_realmode | ||
619 | |||
620 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) | ||
621 | |||
622 | .globl instruction_access_slb_iSeries | ||
623 | instruction_access_slb_iSeries: | ||
624 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
625 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
626 | std r3,PACA_EXSLB+EX_R3(r13) | ||
627 | ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
628 | std r9,PACA_EXSLB+EX_R9(r13) | ||
629 | mfcr r9 | ||
630 | #ifdef __DISABLED__ | ||
631 | cmpdi r3,0 | ||
632 | bge .slb_miss_user_iseries | ||
633 | #endif | ||
634 | std r10,PACA_EXSLB+EX_R10(r13) | ||
635 | std r11,PACA_EXSLB+EX_R11(r13) | ||
636 | std r12,PACA_EXSLB+EX_R12(r13) | ||
637 | mfspr r10,SPRN_SPRG1 | ||
638 | std r10,PACA_EXSLB+EX_R13(r13) | ||
639 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
640 | b .slb_miss_realmode | ||
641 | |||
642 | #ifdef __DISABLED__ | ||
643 | slb_miss_user_iseries: | ||
644 | std r10,PACA_EXGEN+EX_R10(r13) | ||
645 | std r11,PACA_EXGEN+EX_R11(r13) | ||
646 | std r12,PACA_EXGEN+EX_R12(r13) | ||
647 | mfspr r10,SPRG1 | ||
648 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
649 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
650 | std r10,PACA_EXGEN+EX_R13(r13) | ||
651 | std r11,PACA_EXGEN+EX_R9(r13) | ||
652 | std r12,PACA_EXGEN+EX_R3(r13) | ||
653 | EXCEPTION_PROLOG_ISERIES_2 | ||
654 | b slb_miss_user_common | ||
655 | #endif | ||
656 | |||
657 | MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) | ||
658 | STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) | ||
659 | STD_EXCEPTION_ISERIES(0x700, program_check, PACA_EXGEN) | ||
660 | STD_EXCEPTION_ISERIES(0x800, fp_unavailable, PACA_EXGEN) | ||
661 | MASKABLE_EXCEPTION_ISERIES(0x900, decrementer) | ||
662 | STD_EXCEPTION_ISERIES(0xa00, trap_0a, PACA_EXGEN) | ||
663 | STD_EXCEPTION_ISERIES(0xb00, trap_0b, PACA_EXGEN) | ||
664 | |||
665 | .globl system_call_iSeries | ||
666 | system_call_iSeries: | ||
667 | mr r9,r13 | ||
668 | mfspr r13,SPRN_SPRG3 | ||
669 | EXCEPTION_PROLOG_ISERIES_2 | ||
670 | b system_call_common | ||
671 | |||
672 | STD_EXCEPTION_ISERIES( 0xd00, single_step, PACA_EXGEN) | ||
673 | STD_EXCEPTION_ISERIES( 0xe00, trap_0e, PACA_EXGEN) | ||
674 | STD_EXCEPTION_ISERIES( 0xf00, performance_monitor, PACA_EXGEN) | ||
675 | |||
676 | .globl system_reset_iSeries | ||
677 | system_reset_iSeries: | ||
678 | mfspr r13,SPRN_SPRG3 /* Get paca address */ | ||
679 | mfmsr r24 | ||
680 | ori r24,r24,MSR_RI | ||
681 | mtmsrd r24 /* RI on */ | ||
682 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | ||
683 | cmpwi 0,r24,0 /* Are we processor 0? */ | ||
684 | beq .__start_initialization_iSeries /* Start up the first processor */ | ||
685 | mfspr r4,SPRN_CTRLF | ||
686 | li r5,CTRL_RUNLATCH /* Turn off the run light */ | ||
687 | andc r4,r4,r5 | ||
688 | mtspr SPRN_CTRLT,r4 | ||
689 | |||
690 | 1: | ||
691 | HMT_LOW | ||
692 | #ifdef CONFIG_SMP | ||
693 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | ||
694 | * should start */ | ||
695 | sync | ||
696 | LOADADDR(r3,current_set) | ||
697 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
698 | ldx r3,r3,r28 | ||
699 | addi r1,r3,THREAD_SIZE | ||
700 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
701 | |||
702 | cmpwi 0,r23,0 | ||
703 | beq iSeries_secondary_smp_loop /* Loop until told to go */ | ||
704 | bne .__secondary_start /* Loop until told to go */ | ||
705 | iSeries_secondary_smp_loop: | ||
706 | /* Let the Hypervisor know we are alive */ | ||
707 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | ||
708 | lis r3,0x8002 | ||
709 | rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ | ||
710 | #else /* CONFIG_SMP */ | ||
711 | /* Yield the processor. This is required for non-SMP kernels | ||
712 | which are running on multi-threaded machines. */ | ||
713 | lis r3,0x8000 | ||
714 | rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ | ||
715 | addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ | ||
716 | li r4,0 /* "yield timed" */ | ||
717 | li r5,-1 /* "yield forever" */ | ||
718 | #endif /* CONFIG_SMP */ | ||
719 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | ||
720 | sc /* Invoke the hypervisor via a system call */ | ||
721 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ | ||
722 | b 1b /* If SMP not configured, secondaries | ||
723 | * loop forever */ | ||
724 | |||
725 | .globl decrementer_iSeries_masked | ||
726 | decrementer_iSeries_masked: | ||
727 | li r11,1 | ||
728 | stb r11,PACALPPACA+LPPACADECRINT(r13) | ||
729 | lwz r12,PACADEFAULTDECR(r13) | ||
730 | mtspr SPRN_DEC,r12 | ||
731 | /* fall through */ | ||
732 | |||
733 | .globl hardware_interrupt_iSeries_masked | ||
734 | hardware_interrupt_iSeries_masked: | ||
735 | mtcrf 0x80,r9 /* Restore regs */ | ||
736 | ld r11,PACALPPACA+LPPACASRR0(r13) | ||
737 | ld r12,PACALPPACA+LPPACASRR1(r13) | ||
738 | mtspr SPRN_SRR0,r11 | ||
739 | mtspr SPRN_SRR1,r12 | ||
740 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
741 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
742 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
743 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
744 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
745 | rfid | ||
746 | b . /* prevent speculative execution */ | ||
747 | #endif /* CONFIG_PPC_ISERIES */ | ||
748 | |||
749 | /*** Common interrupt handlers ***/ | ||
750 | |||
751 | STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) | ||
752 | |||
753 | /* | ||
754 | * Machine check is different because we use a different | ||
755 | * save area: PACA_EXMC instead of PACA_EXGEN. | ||
756 | */ | ||
757 | .align 7 | ||
758 | .globl machine_check_common | ||
759 | machine_check_common: | ||
760 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) | ||
761 | DISABLE_INTS | ||
762 | bl .save_nvgprs | ||
763 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
764 | bl .machine_check_exception | ||
765 | b .ret_from_except | ||
766 | |||
767 | STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt) | ||
768 | STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception) | ||
769 | STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) | ||
770 | STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) | ||
771 | STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception) | ||
772 | STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception) | ||
773 | STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) | ||
774 | #ifdef CONFIG_ALTIVEC | ||
775 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception) | ||
776 | #else | ||
777 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) | ||
778 | #endif | ||
779 | |||
780 | /* | ||
781 | * Here we have detected that the kernel stack pointer is bad. | ||
782 | * R9 contains the saved CR, r13 points to the paca, | ||
783 | * r10 contains the (bad) kernel stack pointer, | ||
784 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
785 | * We switch to using an emergency stack, save the registers there, | ||
786 | * and call kernel_bad_stack(), which panics. | ||
787 | */ | ||
788 | bad_stack: | ||
789 | ld r1,PACAEMERGSP(r13) | ||
790 | subi r1,r1,64+INT_FRAME_SIZE | ||
791 | std r9,_CCR(r1) | ||
792 | std r10,GPR1(r1) | ||
793 | std r11,_NIP(r1) | ||
794 | std r12,_MSR(r1) | ||
795 | mfspr r11,SPRN_DAR | ||
796 | mfspr r12,SPRN_DSISR | ||
797 | std r11,_DAR(r1) | ||
798 | std r12,_DSISR(r1) | ||
799 | mflr r10 | ||
800 | mfctr r11 | ||
801 | mfxer r12 | ||
802 | std r10,_LINK(r1) | ||
803 | std r11,_CTR(r1) | ||
804 | std r12,_XER(r1) | ||
805 | SAVE_GPR(0,r1) | ||
806 | SAVE_GPR(2,r1) | ||
807 | SAVE_4GPRS(3,r1) | ||
808 | SAVE_2GPRS(7,r1) | ||
809 | SAVE_10GPRS(12,r1) | ||
810 | SAVE_10GPRS(22,r1) | ||
811 | addi r11,r1,INT_FRAME_SIZE | ||
812 | std r11,0(r1) | ||
813 | li r12,0 | ||
814 | std r12,0(r11) | ||
815 | ld r2,PACATOC(r13) | ||
816 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
817 | bl .kernel_bad_stack | ||
818 | b 1b | ||
819 | |||
820 | /* | ||
821 | * Return from an exception with minimal checks. | ||
822 | * The caller is assumed to have done EXCEPTION_PROLOG_COMMON. | ||
823 | * If interrupts have been enabled, or anything has been | ||
824 | * done that might have changed the scheduling status of | ||
825 | * any task or sent any task a signal, you should use | ||
826 | * ret_from_except or ret_from_except_lite instead of this. | ||
827 | */ | ||
828 | .globl fast_exception_return | ||
829 | fast_exception_return: | ||
830 | ld r12,_MSR(r1) | ||
831 | ld r11,_NIP(r1) | ||
832 | andi. r3,r12,MSR_RI /* check if RI is set */ | ||
833 | beq- unrecov_fer | ||
834 | ld r3,_CCR(r1) | ||
835 | ld r4,_LINK(r1) | ||
836 | ld r5,_CTR(r1) | ||
837 | ld r6,_XER(r1) | ||
838 | mtcr r3 | ||
839 | mtlr r4 | ||
840 | mtctr r5 | ||
841 | mtxer r6 | ||
842 | REST_GPR(0, r1) | ||
843 | REST_8GPRS(2, r1) | ||
844 | |||
845 | mfmsr r10 | ||
846 | clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ | ||
847 | mtmsrd r10,1 | ||
848 | |||
849 | mtspr SPRN_SRR1,r12 | ||
850 | mtspr SPRN_SRR0,r11 | ||
851 | REST_4GPRS(10, r1) | ||
852 | ld r1,GPR1(r1) | ||
853 | rfid | ||
854 | b . /* prevent speculative execution */ | ||
855 | |||
856 | unrecov_fer: | ||
857 | bl .save_nvgprs | ||
858 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
859 | bl .unrecoverable_exception | ||
860 | b 1b | ||
861 | |||
862 | /* | ||
863 | * Here r13 points to the paca, r9 contains the saved CR, | ||
864 | * SRR0 and SRR1 are saved in r11 and r12, | ||
865 | * r9 - r13 are saved in paca->exgen. | ||
866 | */ | ||
867 | .align 7 | ||
868 | .globl data_access_common | ||
869 | data_access_common: | ||
870 | RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */ | ||
871 | mfspr r10,SPRN_DAR | ||
872 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
873 | mfspr r10,SPRN_DSISR | ||
874 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
875 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) | ||
876 | ld r3,PACA_EXGEN+EX_DAR(r13) | ||
877 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | ||
878 | li r5,0x300 | ||
879 | b .do_hash_page /* Try to handle as hpte fault */ | ||
880 | |||
881 | .align 7 | ||
882 | .globl instruction_access_common | ||
883 | instruction_access_common: | ||
884 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) | ||
885 | ld r3,_NIP(r1) | ||
886 | andis. r4,r12,0x5820 | ||
887 | li r5,0x400 | ||
888 | b .do_hash_page /* Try to handle as hpte fault */ | ||
889 | |||
890 | /* | ||
891 | * Here is the common SLB miss user that is used when going to virtual | ||
892 | * mode for SLB misses, that is currently not used | ||
893 | */ | ||
894 | #ifdef __DISABLED__ | ||
895 | .align 7 | ||
896 | .globl slb_miss_user_common | ||
897 | slb_miss_user_common: | ||
898 | mflr r10 | ||
899 | std r3,PACA_EXGEN+EX_DAR(r13) | ||
900 | stw r9,PACA_EXGEN+EX_CCR(r13) | ||
901 | std r10,PACA_EXGEN+EX_LR(r13) | ||
902 | std r11,PACA_EXGEN+EX_SRR0(r13) | ||
903 | bl .slb_allocate_user | ||
904 | |||
905 | ld r10,PACA_EXGEN+EX_LR(r13) | ||
906 | ld r3,PACA_EXGEN+EX_R3(r13) | ||
907 | lwz r9,PACA_EXGEN+EX_CCR(r13) | ||
908 | ld r11,PACA_EXGEN+EX_SRR0(r13) | ||
909 | mtlr r10 | ||
910 | beq- slb_miss_fault | ||
911 | |||
912 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
913 | beq- unrecov_user_slb | ||
914 | mfmsr r10 | ||
915 | |||
916 | .machine push | ||
917 | .machine "power4" | ||
918 | mtcrf 0x80,r9 | ||
919 | .machine pop | ||
920 | |||
921 | clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ | ||
922 | mtmsrd r10,1 | ||
923 | |||
924 | mtspr SRR0,r11 | ||
925 | mtspr SRR1,r12 | ||
926 | |||
927 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
928 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
929 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
930 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
931 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
932 | rfid | ||
933 | b . | ||
934 | |||
935 | slb_miss_fault: | ||
936 | EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) | ||
937 | ld r4,PACA_EXGEN+EX_DAR(r13) | ||
938 | li r5,0 | ||
939 | std r4,_DAR(r1) | ||
940 | std r5,_DSISR(r1) | ||
941 | b .handle_page_fault | ||
942 | |||
943 | unrecov_user_slb: | ||
944 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | ||
945 | DISABLE_INTS | ||
946 | bl .save_nvgprs | ||
947 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
948 | bl .unrecoverable_exception | ||
949 | b 1b | ||
950 | |||
951 | #endif /* __DISABLED__ */ | ||
952 | |||
953 | |||
954 | /* | ||
955 | * r13 points to the PACA, r9 contains the saved CR, | ||
956 | * r12 contain the saved SRR1, SRR0 is still ready for return | ||
957 | * r3 has the faulting address | ||
958 | * r9 - r13 are saved in paca->exslb. | ||
959 | * r3 is saved in paca->slb_r3 | ||
960 | * We assume we aren't going to take any exceptions during this procedure. | ||
961 | */ | ||
962 | _GLOBAL(slb_miss_realmode) | ||
963 | mflr r10 | ||
964 | |||
965 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
966 | std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ | ||
967 | |||
968 | bl .slb_allocate_realmode | ||
969 | |||
970 | /* All done -- return from exception. */ | ||
971 | |||
972 | ld r10,PACA_EXSLB+EX_LR(r13) | ||
973 | ld r3,PACA_EXSLB+EX_R3(r13) | ||
974 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
975 | #ifdef CONFIG_PPC_ISERIES | ||
976 | ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
977 | #endif /* CONFIG_PPC_ISERIES */ | ||
978 | |||
979 | mtlr r10 | ||
980 | |||
981 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
982 | beq- unrecov_slb | ||
983 | |||
984 | .machine push | ||
985 | .machine "power4" | ||
986 | mtcrf 0x80,r9 | ||
987 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
988 | .machine pop | ||
989 | |||
990 | #ifdef CONFIG_PPC_ISERIES | ||
991 | mtspr SPRN_SRR0,r11 | ||
992 | mtspr SPRN_SRR1,r12 | ||
993 | #endif /* CONFIG_PPC_ISERIES */ | ||
994 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
995 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
996 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
997 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
998 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
999 | rfid | ||
1000 | b . /* prevent speculative execution */ | ||
1001 | |||
1002 | unrecov_slb: | ||
1003 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | ||
1004 | DISABLE_INTS | ||
1005 | bl .save_nvgprs | ||
1006 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
1007 | bl .unrecoverable_exception | ||
1008 | b 1b | ||
1009 | |||
1010 | .align 7 | ||
1011 | .globl hardware_interrupt_common | ||
1012 | .globl hardware_interrupt_entry | ||
1013 | hardware_interrupt_common: | ||
1014 | EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) | ||
1015 | hardware_interrupt_entry: | ||
1016 | DISABLE_INTS | ||
1017 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1018 | bl .do_IRQ | ||
1019 | b .ret_from_except_lite | ||
1020 | |||
1021 | .align 7 | ||
1022 | .globl alignment_common | ||
1023 | alignment_common: | ||
1024 | mfspr r10,SPRN_DAR | ||
1025 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
1026 | mfspr r10,SPRN_DSISR | ||
1027 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
1028 | EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN) | ||
1029 | ld r3,PACA_EXGEN+EX_DAR(r13) | ||
1030 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | ||
1031 | std r3,_DAR(r1) | ||
1032 | std r4,_DSISR(r1) | ||
1033 | bl .save_nvgprs | ||
1034 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1035 | ENABLE_INTS | ||
1036 | bl .alignment_exception | ||
1037 | b .ret_from_except | ||
1038 | |||
1039 | .align 7 | ||
1040 | .globl program_check_common | ||
1041 | program_check_common: | ||
1042 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) | ||
1043 | bl .save_nvgprs | ||
1044 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1045 | ENABLE_INTS | ||
1046 | bl .program_check_exception | ||
1047 | b .ret_from_except | ||
1048 | |||
1049 | .align 7 | ||
1050 | .globl fp_unavailable_common | ||
1051 | fp_unavailable_common: | ||
1052 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | ||
1053 | bne .load_up_fpu /* if from user, just load it up */ | ||
1054 | bl .save_nvgprs | ||
1055 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1056 | ENABLE_INTS | ||
1057 | bl .kernel_fp_unavailable_exception | ||
1058 | BUG_OPCODE | ||
1059 | |||
1060 | .align 7 | ||
1061 | .globl altivec_unavailable_common | ||
1062 | altivec_unavailable_common: | ||
1063 | EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN) | ||
1064 | #ifdef CONFIG_ALTIVEC | ||
1065 | BEGIN_FTR_SECTION | ||
1066 | bne .load_up_altivec /* if from user, just load it up */ | ||
1067 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
1068 | #endif | ||
1069 | bl .save_nvgprs | ||
1070 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1071 | ENABLE_INTS | ||
1072 | bl .altivec_unavailable_exception | ||
1073 | b .ret_from_except | ||
1074 | |||
1075 | #ifdef CONFIG_ALTIVEC | ||
1076 | /* | ||
1077 | * load_up_altivec(unused, unused, tsk) | ||
1078 | * Disable VMX for the task which had it previously, | ||
1079 | * and save its vector registers in its thread_struct. | ||
1080 | * Enables the VMX for use in the kernel on return. | ||
1081 | * On SMP we know the VMX is free, since we give it up every | ||
1082 | * switch (ie, no lazy save of the vector registers). | ||
1083 | * On entry: r13 == 'current' && last_task_used_altivec != 'current' | ||
1084 | */ | ||
1085 | _STATIC(load_up_altivec) | ||
1086 | mfmsr r5 /* grab the current MSR */ | ||
1087 | oris r5,r5,MSR_VEC@h | ||
1088 | mtmsrd r5 /* enable use of VMX now */ | ||
1089 | isync | ||
1090 | |||
1091 | /* | ||
1092 | * For SMP, we don't do lazy VMX switching because it just gets too | ||
1093 | * horrendously complex, especially when a task switches from one CPU | ||
1094 | * to another. Instead we call giveup_altvec in switch_to. | ||
1095 | * VRSAVE isn't dealt with here, that is done in the normal context | ||
1096 | * switch code. Note that we could rely on vrsave value to eventually | ||
1097 | * avoid saving all of the VREGs here... | ||
1098 | */ | ||
1099 | #ifndef CONFIG_SMP | ||
1100 | ld r3,last_task_used_altivec@got(r2) | ||
1101 | ld r4,0(r3) | ||
1102 | cmpdi 0,r4,0 | ||
1103 | beq 1f | ||
1104 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | ||
1105 | addi r4,r4,THREAD | ||
1106 | SAVE_32VRS(0,r5,r4) | ||
1107 | mfvscr vr0 | ||
1108 | li r10,THREAD_VSCR | ||
1109 | stvx vr0,r10,r4 | ||
1110 | /* Disable VMX for last_task_used_altivec */ | ||
1111 | ld r5,PT_REGS(r4) | ||
1112 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1113 | lis r6,MSR_VEC@h | ||
1114 | andc r4,r4,r6 | ||
1115 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1116 | 1: | ||
1117 | #endif /* CONFIG_SMP */ | ||
1118 | /* Hack: if we get an altivec unavailable trap with VRSAVE | ||
1119 | * set to all zeros, we assume this is a broken application | ||
1120 | * that fails to set it properly, and thus we switch it to | ||
1121 | * all 1's | ||
1122 | */ | ||
1123 | mfspr r4,SPRN_VRSAVE | ||
1124 | cmpdi 0,r4,0 | ||
1125 | bne+ 1f | ||
1126 | li r4,-1 | ||
1127 | mtspr SPRN_VRSAVE,r4 | ||
1128 | 1: | ||
1129 | /* enable use of VMX after return */ | ||
1130 | ld r4,PACACURRENT(r13) | ||
1131 | addi r5,r4,THREAD /* Get THREAD */ | ||
1132 | oris r12,r12,MSR_VEC@h | ||
1133 | std r12,_MSR(r1) | ||
1134 | li r4,1 | ||
1135 | li r10,THREAD_VSCR | ||
1136 | stw r4,THREAD_USED_VR(r5) | ||
1137 | lvx vr0,r10,r5 | ||
1138 | mtvscr vr0 | ||
1139 | REST_32VRS(0,r4,r5) | ||
1140 | #ifndef CONFIG_SMP | ||
1141 | /* Update last_task_used_math to 'current' */ | ||
1142 | subi r4,r5,THREAD /* Back to 'current' */ | ||
1143 | std r4,0(r3) | ||
1144 | #endif /* CONFIG_SMP */ | ||
1145 | /* restore registers and return */ | ||
1146 | b fast_exception_return | ||
1147 | #endif /* CONFIG_ALTIVEC */ | ||
1148 | |||
1149 | /* | ||
1150 | * Hash table stuff | ||
1151 | */ | ||
1152 | .align 7 | ||
1153 | _GLOBAL(do_hash_page) | ||
1154 | std r3,_DAR(r1) | ||
1155 | std r4,_DSISR(r1) | ||
1156 | |||
1157 | andis. r0,r4,0xa450 /* weird error? */ | ||
1158 | bne- .handle_page_fault /* if not, try to insert a HPTE */ | ||
1159 | BEGIN_FTR_SECTION | ||
1160 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ | ||
1161 | bne- .do_ste_alloc /* If so handle it */ | ||
1162 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1163 | |||
1164 | /* | ||
1165 | * We need to set the _PAGE_USER bit if MSR_PR is set or if we are | ||
1166 | * accessing a userspace segment (even from the kernel). We assume | ||
1167 | * kernel addresses always have the high bit set. | ||
1168 | */ | ||
1169 | rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ | ||
1170 | rotldi r0,r3,15 /* Move high bit into MSR_PR posn */ | ||
1171 | orc r0,r12,r0 /* MSR_PR | ~high_bit */ | ||
1172 | rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ | ||
1173 | ori r4,r4,1 /* add _PAGE_PRESENT */ | ||
1174 | rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */ | ||
1175 | |||
1176 | /* | ||
1177 | * On iSeries, we soft-disable interrupts here, then | ||
1178 | * hard-enable interrupts so that the hash_page code can spin on | ||
1179 | * the hash_table_lock without problems on a shared processor. | ||
1180 | */ | ||
1181 | DISABLE_INTS | ||
1182 | |||
1183 | /* | ||
1184 | * r3 contains the faulting address | ||
1185 | * r4 contains the required access permissions | ||
1186 | * r5 contains the trap number | ||
1187 | * | ||
1188 | * at return r3 = 0 for success | ||
1189 | */ | ||
1190 | bl .hash_page /* build HPTE if possible */ | ||
1191 | cmpdi r3,0 /* see if hash_page succeeded */ | ||
1192 | |||
1193 | #ifdef DO_SOFT_DISABLE | ||
1194 | /* | ||
1195 | * If we had interrupts soft-enabled at the point where the | ||
1196 | * DSI/ISI occurred, and an interrupt came in during hash_page, | ||
1197 | * handle it now. | ||
1198 | * We jump to ret_from_except_lite rather than fast_exception_return | ||
1199 | * because ret_from_except_lite will check for and handle pending | ||
1200 | * interrupts if necessary. | ||
1201 | */ | ||
1202 | beq .ret_from_except_lite | ||
1203 | /* For a hash failure, we don't bother re-enabling interrupts */ | ||
1204 | ble- 12f | ||
1205 | |||
1206 | /* | ||
1207 | * hash_page couldn't handle it, set soft interrupt enable back | ||
1208 | * to what it was before the trap. Note that .local_irq_restore | ||
1209 | * handles any interrupts pending at this point. | ||
1210 | */ | ||
1211 | ld r3,SOFTE(r1) | ||
1212 | bl .local_irq_restore | ||
1213 | b 11f | ||
1214 | #else | ||
1215 | beq fast_exception_return /* Return from exception on success */ | ||
1216 | ble- 12f /* Failure return from hash_page */ | ||
1217 | |||
1218 | /* fall through */ | ||
1219 | #endif | ||
1220 | |||
1221 | /* Here we have a page fault that hash_page can't handle. */ | ||
1222 | _GLOBAL(handle_page_fault) | ||
1223 | ENABLE_INTS | ||
1224 | 11: ld r4,_DAR(r1) | ||
1225 | ld r5,_DSISR(r1) | ||
1226 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1227 | bl .do_page_fault | ||
1228 | cmpdi r3,0 | ||
1229 | beq+ .ret_from_except_lite | ||
1230 | bl .save_nvgprs | ||
1231 | mr r5,r3 | ||
1232 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1233 | lwz r4,_DAR(r1) | ||
1234 | bl .bad_page_fault | ||
1235 | b .ret_from_except | ||
1236 | |||
1237 | /* We have a page fault that hash_page could handle but HV refused | ||
1238 | * the PTE insertion | ||
1239 | */ | ||
1240 | 12: bl .save_nvgprs | ||
1241 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1242 | lwz r4,_DAR(r1) | ||
1243 | bl .low_hash_fault | ||
1244 | b .ret_from_except | ||
1245 | |||
1246 | /* here we have a segment miss */ | ||
1247 | _GLOBAL(do_ste_alloc) | ||
1248 | bl .ste_allocate /* try to insert stab entry */ | ||
1249 | cmpdi r3,0 | ||
1250 | beq+ fast_exception_return | ||
1251 | b .handle_page_fault | ||
1252 | |||
1253 | /* | ||
1254 | * r13 points to the PACA, r9 contains the saved CR, | ||
1255 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
1256 | * r9 - r13 are saved in paca->exslb. | ||
1257 | * We assume we aren't going to take any exceptions during this procedure. | ||
1258 | * We assume (DAR >> 60) == 0xc. | ||
1259 | */ | ||
1260 | .align 7 | ||
1261 | _GLOBAL(do_stab_bolted) | ||
1262 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
1263 | std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ | ||
1264 | |||
1265 | /* Hash to the primary group */ | ||
1266 | ld r10,PACASTABVIRT(r13) | ||
1267 | mfspr r11,SPRN_DAR | ||
1268 | srdi r11,r11,28 | ||
1269 | rldimi r10,r11,7,52 /* r10 = first ste of the group */ | ||
1270 | |||
1271 | /* Calculate VSID */ | ||
1272 | /* This is a kernel address, so protovsid = ESID */ | ||
1273 | ASM_VSID_SCRAMBLE(r11, r9) | ||
1274 | rldic r9,r11,12,16 /* r9 = vsid << 12 */ | ||
1275 | |||
1276 | /* Search the primary group for a free entry */ | ||
1277 | 1: ld r11,0(r10) /* Test valid bit of the current ste */ | ||
1278 | andi. r11,r11,0x80 | ||
1279 | beq 2f | ||
1280 | addi r10,r10,16 | ||
1281 | andi. r11,r10,0x70 | ||
1282 | bne 1b | ||
1283 | |||
1284 | /* Stick for only searching the primary group for now. */ | ||
1285 | /* At least for now, we use a very simple random castout scheme */ | ||
1286 | /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ | ||
1287 | mftb r11 | ||
1288 | rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ | ||
1289 | ori r11,r11,0x10 | ||
1290 | |||
1291 | /* r10 currently points to an ste one past the group of interest */ | ||
1292 | /* make it point to the randomly selected entry */ | ||
1293 | subi r10,r10,128 | ||
1294 | or r10,r10,r11 /* r10 is the entry to invalidate */ | ||
1295 | |||
1296 | isync /* mark the entry invalid */ | ||
1297 | ld r11,0(r10) | ||
1298 | rldicl r11,r11,56,1 /* clear the valid bit */ | ||
1299 | rotldi r11,r11,8 | ||
1300 | std r11,0(r10) | ||
1301 | sync | ||
1302 | |||
1303 | clrrdi r11,r11,28 /* Get the esid part of the ste */ | ||
1304 | slbie r11 | ||
1305 | |||
1306 | 2: std r9,8(r10) /* Store the vsid part of the ste */ | ||
1307 | eieio | ||
1308 | |||
1309 | mfspr r11,SPRN_DAR /* Get the new esid */ | ||
1310 | clrrdi r11,r11,28 /* Permits a full 32b of ESID */ | ||
1311 | ori r11,r11,0x90 /* Turn on valid and kp */ | ||
1312 | std r11,0(r10) /* Put new entry back into the stab */ | ||
1313 | |||
1314 | sync | ||
1315 | |||
1316 | /* All done -- return from exception. */ | ||
1317 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
1318 | ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ | ||
1319 | |||
1320 | andi. r10,r12,MSR_RI | ||
1321 | beq- unrecov_slb | ||
1322 | |||
1323 | mtcrf 0x80,r9 /* restore CR */ | ||
1324 | |||
1325 | mfmsr r10 | ||
1326 | clrrdi r10,r10,2 | ||
1327 | mtmsrd r10,1 | ||
1328 | |||
1329 | mtspr SPRN_SRR0,r11 | ||
1330 | mtspr SPRN_SRR1,r12 | ||
1331 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
1332 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
1333 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
1334 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
1335 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
1336 | rfid | ||
1337 | b . /* prevent speculative execution */ | ||
1338 | |||
1339 | /* | ||
1340 | * Space for CPU0's segment table. | ||
1341 | * | ||
1342 | * On iSeries, the hypervisor must fill in at least one entry before | ||
1343 | * we get control (with relocate on). The address is give to the hv | ||
1344 | * as a page number (see xLparMap in lpardata.c), so this must be at a | ||
1345 | * fixed address (the linker can't compute (u64)&initial_stab >> | ||
1346 | * PAGE_SHIFT). | ||
1347 | */ | ||
1348 | . = STAB0_PHYS_ADDR /* 0x6000 */ | ||
1349 | .globl initial_stab | ||
1350 | initial_stab: | ||
1351 | .space 4096 | ||
1352 | |||
1353 | /* | ||
1354 | * Data area reserved for FWNMI option. | ||
1355 | * This address (0x7000) is fixed by the RPA. | ||
1356 | */ | ||
1357 | .= 0x7000 | ||
1358 | .globl fwnmi_data_area | ||
1359 | fwnmi_data_area: | ||
1360 | |||
1361 | /* iSeries does not use the FWNMI stuff, so it is safe to put | ||
1362 | * this here, even if we later allow kernels that will boot on | ||
1363 | * both pSeries and iSeries */ | ||
1364 | #ifdef CONFIG_PPC_ISERIES | ||
1365 | . = LPARMAP_PHYS | ||
1366 | #include "lparmap.s" | ||
1367 | /* | ||
1368 | * This ".text" is here for old compilers that generate a trailing | ||
1369 | * .note section when compiling .c files to .s | ||
1370 | */ | ||
1371 | .text | ||
1372 | #endif /* CONFIG_PPC_ISERIES */ | ||
1373 | |||
1374 | . = 0x8000 | ||
1375 | |||
1376 | /* | ||
1377 | * On pSeries, secondary processors spin in the following code. | ||
1378 | * At entry, r3 = this processor's number (physical cpu id) | ||
1379 | */ | ||
1380 | _GLOBAL(pSeries_secondary_smp_init) | ||
1381 | mr r24,r3 | ||
1382 | |||
1383 | /* turn on 64-bit mode */ | ||
1384 | bl .enable_64b_mode | ||
1385 | isync | ||
1386 | |||
1387 | /* Copy some CPU settings from CPU 0 */ | ||
1388 | bl .__restore_cpu_setup | ||
1389 | |||
1390 | /* Set up a paca value for this processor. Since we have the | ||
1391 | * physical cpu id in r24, we need to search the pacas to find | ||
1392 | * which logical id maps to our physical one. | ||
1393 | */ | ||
1394 | LOADADDR(r13, paca) /* Get base vaddr of paca array */ | ||
1395 | li r5,0 /* logical cpu id */ | ||
1396 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ | ||
1397 | cmpw r6,r24 /* Compare to our id */ | ||
1398 | beq 2f | ||
1399 | addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */ | ||
1400 | addi r5,r5,1 | ||
1401 | cmpwi r5,NR_CPUS | ||
1402 | blt 1b | ||
1403 | |||
1404 | mr r3,r24 /* not found, copy phys to r3 */ | ||
1405 | b .kexec_wait /* next kernel might do better */ | ||
1406 | |||
1407 | 2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | ||
1408 | /* From now on, r24 is expected to be logical cpuid */ | ||
1409 | mr r24,r5 | ||
1410 | 3: HMT_LOW | ||
1411 | lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ | ||
1412 | /* start. */ | ||
1413 | sync | ||
1414 | |||
1415 | /* Create a temp kernel stack for use before relocation is on. */ | ||
1416 | ld r1,PACAEMERGSP(r13) | ||
1417 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
1418 | |||
1419 | cmpwi 0,r23,0 | ||
1420 | #ifdef CONFIG_SMP | ||
1421 | bne .__secondary_start | ||
1422 | #endif | ||
1423 | b 3b /* Loop until told to go */ | ||
1424 | |||
1425 | #ifdef CONFIG_PPC_ISERIES | ||
1426 | _STATIC(__start_initialization_iSeries) | ||
1427 | /* Clear out the BSS */ | ||
1428 | LOADADDR(r11,__bss_stop) | ||
1429 | LOADADDR(r8,__bss_start) | ||
1430 | sub r11,r11,r8 /* bss size */ | ||
1431 | addi r11,r11,7 /* round up to an even double word */ | ||
1432 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1433 | beq 4f | ||
1434 | addi r8,r8,-8 | ||
1435 | li r0,0 | ||
1436 | mtctr r11 /* zero this many doublewords */ | ||
1437 | 3: stdu r0,8(r8) | ||
1438 | bdnz 3b | ||
1439 | 4: | ||
1440 | LOADADDR(r1,init_thread_union) | ||
1441 | addi r1,r1,THREAD_SIZE | ||
1442 | li r0,0 | ||
1443 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1444 | |||
1445 | LOADADDR(r3,cpu_specs) | ||
1446 | LOADADDR(r4,cur_cpu_spec) | ||
1447 | li r5,0 | ||
1448 | bl .identify_cpu | ||
1449 | |||
1450 | LOADADDR(r2,__toc_start) | ||
1451 | addi r2,r2,0x4000 | ||
1452 | addi r2,r2,0x4000 | ||
1453 | |||
1454 | bl .iSeries_early_setup | ||
1455 | bl .early_setup | ||
1456 | |||
1457 | /* relocation is on at this point */ | ||
1458 | |||
1459 | b .start_here_common | ||
1460 | #endif /* CONFIG_PPC_ISERIES */ | ||
1461 | |||
1462 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1463 | |||
1464 | _STATIC(__mmu_off) | ||
1465 | mfmsr r3 | ||
1466 | andi. r0,r3,MSR_IR|MSR_DR | ||
1467 | beqlr | ||
1468 | andc r3,r3,r0 | ||
1469 | mtspr SPRN_SRR0,r4 | ||
1470 | mtspr SPRN_SRR1,r3 | ||
1471 | sync | ||
1472 | rfid | ||
1473 | b . /* prevent speculative execution */ | ||
1474 | |||
1475 | |||
1476 | /* | ||
1477 | * Here is our main kernel entry point. We support currently 2 kind of entries | ||
1478 | * depending on the value of r5. | ||
1479 | * | ||
1480 | * r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content | ||
1481 | * in r3...r7 | ||
1482 | * | ||
1483 | * r5 == NULL -> kexec style entry. r3 is a physical pointer to the | ||
1484 | * DT block, r4 is a physical pointer to the kernel itself | ||
1485 | * | ||
1486 | */ | ||
1487 | _GLOBAL(__start_initialization_multiplatform) | ||
1488 | /* | ||
1489 | * Are we booted from a PROM Of-type client-interface ? | ||
1490 | */ | ||
1491 | cmpldi cr0,r5,0 | ||
1492 | bne .__boot_from_prom /* yes -> prom */ | ||
1493 | |||
1494 | /* Save parameters */ | ||
1495 | mr r31,r3 | ||
1496 | mr r30,r4 | ||
1497 | |||
1498 | /* Make sure we are running in 64 bits mode */ | ||
1499 | bl .enable_64b_mode | ||
1500 | |||
1501 | /* Setup some critical 970 SPRs before switching MMU off */ | ||
1502 | bl .__970_cpu_preinit | ||
1503 | |||
1504 | /* cpu # */ | ||
1505 | li r24,0 | ||
1506 | |||
1507 | /* Switch off MMU if not already */ | ||
1508 | LOADADDR(r4, .__after_prom_start - KERNELBASE) | ||
1509 | add r4,r4,r30 | ||
1510 | bl .__mmu_off | ||
1511 | b .__after_prom_start | ||
1512 | |||
1513 | _STATIC(__boot_from_prom) | ||
1514 | /* Save parameters */ | ||
1515 | mr r31,r3 | ||
1516 | mr r30,r4 | ||
1517 | mr r29,r5 | ||
1518 | mr r28,r6 | ||
1519 | mr r27,r7 | ||
1520 | |||
1521 | /* Make sure we are running in 64 bits mode */ | ||
1522 | bl .enable_64b_mode | ||
1523 | |||
1524 | /* put a relocation offset into r3 */ | ||
1525 | bl .reloc_offset | ||
1526 | |||
1527 | LOADADDR(r2,__toc_start) | ||
1528 | addi r2,r2,0x4000 | ||
1529 | addi r2,r2,0x4000 | ||
1530 | |||
1531 | /* Relocate the TOC from a virt addr to a real addr */ | ||
1532 | sub r2,r2,r3 | ||
1533 | |||
1534 | /* Restore parameters */ | ||
1535 | mr r3,r31 | ||
1536 | mr r4,r30 | ||
1537 | mr r5,r29 | ||
1538 | mr r6,r28 | ||
1539 | mr r7,r27 | ||
1540 | |||
1541 | /* Do all of the interaction with OF client interface */ | ||
1542 | bl .prom_init | ||
1543 | /* We never return */ | ||
1544 | trap | ||
1545 | |||
1546 | /* | ||
1547 | * At this point, r3 contains the physical address we are running at, | ||
1548 | * returned by prom_init() | ||
1549 | */ | ||
1550 | _STATIC(__after_prom_start) | ||
1551 | |||
1552 | /* | ||
1553 | * We need to run with __start at physical address 0. | ||
1554 | * This will leave some code in the first 256B of | ||
1555 | * real memory, which are reserved for software use. | ||
1556 | * The remainder of the first page is loaded with the fixed | ||
1557 | * interrupt vectors. The next two pages are filled with | ||
1558 | * unknown exception placeholders. | ||
1559 | * | ||
1560 | * Note: This process overwrites the OF exception vectors. | ||
1561 | * r26 == relocation offset | ||
1562 | * r27 == KERNELBASE | ||
1563 | */ | ||
1564 | bl .reloc_offset | ||
1565 | mr r26,r3 | ||
1566 | SET_REG_TO_CONST(r27,KERNELBASE) | ||
1567 | |||
1568 | li r3,0 /* target addr */ | ||
1569 | |||
1570 | // XXX FIXME: Use phys returned by OF (r30) | ||
1571 | sub r4,r27,r26 /* source addr */ | ||
1572 | /* current address of _start */ | ||
1573 | /* i.e. where we are running */ | ||
1574 | /* the source addr */ | ||
1575 | |||
1576 | LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ | ||
1577 | sub r5,r5,r27 | ||
1578 | |||
1579 | li r6,0x100 /* Start offset, the first 0x100 */ | ||
1580 | /* bytes were copied earlier. */ | ||
1581 | |||
1582 | bl .copy_and_flush /* copy the first n bytes */ | ||
1583 | /* this includes the code being */ | ||
1584 | /* executed here. */ | ||
1585 | |||
1586 | LOADADDR(r0, 4f) /* Jump to the copy of this code */ | ||
1587 | mtctr r0 /* that we just made/relocated */ | ||
1588 | bctr | ||
1589 | |||
1590 | 4: LOADADDR(r5,klimit) | ||
1591 | sub r5,r5,r26 | ||
1592 | ld r5,0(r5) /* get the value of klimit */ | ||
1593 | sub r5,r5,r27 | ||
1594 | bl .copy_and_flush /* copy the rest */ | ||
1595 | b .start_here_multiplatform | ||
1596 | |||
1597 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1598 | |||
1599 | /* | ||
1600 | * Copy routine used to copy the kernel to start at physical address 0 | ||
1601 | * and flush and invalidate the caches as needed. | ||
1602 | * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset | ||
1603 | * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. | ||
1604 | * | ||
1605 | * Note: this routine *only* clobbers r0, r6 and lr | ||
1606 | */ | ||
1607 | _GLOBAL(copy_and_flush) | ||
1608 | addi r5,r5,-8 | ||
1609 | addi r6,r6,-8 | ||
1610 | 4: li r0,16 /* Use the least common */ | ||
1611 | /* denominator cache line */ | ||
1612 | /* size. This results in */ | ||
1613 | /* extra cache line flushes */ | ||
1614 | /* but operation is correct. */ | ||
1615 | /* Can't get cache line size */ | ||
1616 | /* from NACA as it is being */ | ||
1617 | /* moved too. */ | ||
1618 | |||
1619 | mtctr r0 /* put # words/line in ctr */ | ||
1620 | 3: addi r6,r6,8 /* copy a cache line */ | ||
1621 | ldx r0,r6,r4 | ||
1622 | stdx r0,r6,r3 | ||
1623 | bdnz 3b | ||
1624 | dcbst r6,r3 /* write it to memory */ | ||
1625 | sync | ||
1626 | icbi r6,r3 /* flush the icache line */ | ||
1627 | cmpld 0,r6,r5 | ||
1628 | blt 4b | ||
1629 | sync | ||
1630 | addi r5,r5,8 | ||
1631 | addi r6,r6,8 | ||
1632 | blr | ||
1633 | |||
1634 | .align 8 | ||
1635 | copy_to_here: | ||
1636 | |||
1637 | #ifdef CONFIG_SMP | ||
1638 | #ifdef CONFIG_PPC_PMAC | ||
1639 | /* | ||
1640 | * On PowerMac, secondary processors starts from the reset vector, which | ||
1641 | * is temporarily turned into a call to one of the functions below. | ||
1642 | */ | ||
1643 | .section ".text"; | ||
1644 | .align 2 ; | ||
1645 | |||
1646 | .globl __secondary_start_pmac_0 | ||
1647 | __secondary_start_pmac_0: | ||
1648 | /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ | ||
1649 | li r24,0 | ||
1650 | b 1f | ||
1651 | li r24,1 | ||
1652 | b 1f | ||
1653 | li r24,2 | ||
1654 | b 1f | ||
1655 | li r24,3 | ||
1656 | 1: | ||
1657 | |||
1658 | _GLOBAL(pmac_secondary_start) | ||
1659 | /* turn on 64-bit mode */ | ||
1660 | bl .enable_64b_mode | ||
1661 | isync | ||
1662 | |||
1663 | /* Copy some CPU settings from CPU 0 */ | ||
1664 | bl .__restore_cpu_setup | ||
1665 | |||
1666 | /* pSeries do that early though I don't think we really need it */ | ||
1667 | mfmsr r3 | ||
1668 | ori r3,r3,MSR_RI | ||
1669 | mtmsrd r3 /* RI on */ | ||
1670 | |||
1671 | /* Set up a paca value for this processor. */ | ||
1672 | LOADADDR(r4, paca) /* Get base vaddr of paca array */ | ||
1673 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1674 | add r13,r13,r4 /* for this processor. */ | ||
1675 | mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | ||
1676 | |||
1677 | /* Create a temp kernel stack for use before relocation is on. */ | ||
1678 | ld r1,PACAEMERGSP(r13) | ||
1679 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
1680 | |||
1681 | b .__secondary_start | ||
1682 | |||
1683 | #endif /* CONFIG_PPC_PMAC */ | ||
1684 | |||
1685 | /* | ||
1686 | * This function is called after the master CPU has released the | ||
1687 | * secondary processors. The execution environment is relocation off. | ||
1688 | * The paca for this processor has the following fields initialized at | ||
1689 | * this point: | ||
1690 | * 1. Processor number | ||
1691 | * 2. Segment table pointer (virtual address) | ||
1692 | * On entry the following are set: | ||
1693 | * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries | ||
1694 | * r24 = cpu# (in Linux terms) | ||
1695 | * r13 = paca virtual address | ||
1696 | * SPRG3 = paca virtual address | ||
1697 | */ | ||
1698 | _GLOBAL(__secondary_start) | ||
1699 | |||
1700 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | ||
1701 | |||
1702 | ld r2,PACATOC(r13) | ||
1703 | |||
1704 | /* Do early setup for that CPU */ | ||
1705 | bl .early_setup_secondary | ||
1706 | |||
1707 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | ||
1708 | LOADADDR(r3,current_set) | ||
1709 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
1710 | ldx r1,r3,r28 | ||
1711 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | ||
1712 | std r1,PACAKSAVE(r13) | ||
1713 | |||
1714 | li r7,0 | ||
1715 | mtlr r7 | ||
1716 | |||
1717 | /* enable MMU and jump to start_secondary */ | ||
1718 | LOADADDR(r3,.start_secondary_prolog) | ||
1719 | SET_REG_TO_CONST(r4, MSR_KERNEL) | ||
1720 | #ifdef DO_SOFT_DISABLE | ||
1721 | ori r4,r4,MSR_EE | ||
1722 | #endif | ||
1723 | mtspr SPRN_SRR0,r3 | ||
1724 | mtspr SPRN_SRR1,r4 | ||
1725 | rfid | ||
1726 | b . /* prevent speculative execution */ | ||
1727 | |||
1728 | /* | ||
1729 | * Running with relocation on at this point. All we want to do is | ||
1730 | * zero the stack back-chain pointer before going into C code. | ||
1731 | */ | ||
1732 | _GLOBAL(start_secondary_prolog) | ||
1733 | li r3,0 | ||
1734 | std r3,0(r1) /* Zero the stack frame pointer */ | ||
1735 | bl .start_secondary | ||
1736 | #endif | ||
1737 | |||
1738 | /* | ||
1739 | * This subroutine clobbers r11 and r12 | ||
1740 | */ | ||
1741 | _GLOBAL(enable_64b_mode) | ||
1742 | mfmsr r11 /* grab the current MSR */ | ||
1743 | li r12,1 | ||
1744 | rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) | ||
1745 | or r11,r11,r12 | ||
1746 | li r12,1 | ||
1747 | rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) | ||
1748 | or r11,r11,r12 | ||
1749 | mtmsrd r11 | ||
1750 | isync | ||
1751 | blr | ||
1752 | |||
1753 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1754 | /* | ||
1755 | * This is where the main kernel code starts. | ||
1756 | */ | ||
1757 | _STATIC(start_here_multiplatform) | ||
1758 | /* get a new offset, now that the kernel has moved. */ | ||
1759 | bl .reloc_offset | ||
1760 | mr r26,r3 | ||
1761 | |||
1762 | /* Clear out the BSS. It may have been done in prom_init, | ||
1763 | * already but that's irrelevant since prom_init will soon | ||
1764 | * be detached from the kernel completely. Besides, we need | ||
1765 | * to clear it now for kexec-style entry. | ||
1766 | */ | ||
1767 | LOADADDR(r11,__bss_stop) | ||
1768 | LOADADDR(r8,__bss_start) | ||
1769 | sub r11,r11,r8 /* bss size */ | ||
1770 | addi r11,r11,7 /* round up to an even double word */ | ||
1771 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1772 | beq 4f | ||
1773 | addi r8,r8,-8 | ||
1774 | li r0,0 | ||
1775 | mtctr r11 /* zero this many doublewords */ | ||
1776 | 3: stdu r0,8(r8) | ||
1777 | bdnz 3b | ||
1778 | 4: | ||
1779 | |||
1780 | mfmsr r6 | ||
1781 | ori r6,r6,MSR_RI | ||
1782 | mtmsrd r6 /* RI on */ | ||
1783 | |||
1784 | #ifdef CONFIG_HMT | ||
1785 | /* Start up the second thread on cpu 0 */ | ||
1786 | mfspr r3,SPRN_PVR | ||
1787 | srwi r3,r3,16 | ||
1788 | cmpwi r3,0x34 /* Pulsar */ | ||
1789 | beq 90f | ||
1790 | cmpwi r3,0x36 /* Icestar */ | ||
1791 | beq 90f | ||
1792 | cmpwi r3,0x37 /* SStar */ | ||
1793 | beq 90f | ||
1794 | b 91f /* HMT not supported */ | ||
1795 | 90: li r3,0 | ||
1796 | bl .hmt_start_secondary | ||
1797 | 91: | ||
1798 | #endif | ||
1799 | |||
1800 | /* The following gets the stack and TOC set up with the regs */ | ||
1801 | /* pointing to the real addr of the kernel stack. This is */ | ||
1802 | /* all done to support the C function call below which sets */ | ||
1803 | /* up the htab. This is done because we have relocated the */ | ||
1804 | /* kernel but are still running in real mode. */ | ||
1805 | |||
1806 | LOADADDR(r3,init_thread_union) | ||
1807 | sub r3,r3,r26 | ||
1808 | |||
1809 | /* set up a stack pointer (physical address) */ | ||
1810 | addi r1,r3,THREAD_SIZE | ||
1811 | li r0,0 | ||
1812 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1813 | |||
1814 | /* set up the TOC (physical address) */ | ||
1815 | LOADADDR(r2,__toc_start) | ||
1816 | addi r2,r2,0x4000 | ||
1817 | addi r2,r2,0x4000 | ||
1818 | sub r2,r2,r26 | ||
1819 | |||
1820 | LOADADDR(r3,cpu_specs) | ||
1821 | sub r3,r3,r26 | ||
1822 | LOADADDR(r4,cur_cpu_spec) | ||
1823 | sub r4,r4,r26 | ||
1824 | mr r5,r26 | ||
1825 | bl .identify_cpu | ||
1826 | |||
1827 | /* Save some low level config HIDs of CPU0 to be copied to | ||
1828 | * other CPUs later on, or used for suspend/resume | ||
1829 | */ | ||
1830 | bl .__save_cpu_setup | ||
1831 | sync | ||
1832 | |||
1833 | /* Setup a valid physical PACA pointer in SPRG3 for early_setup | ||
1834 | * note that boot_cpuid can always be 0 nowadays since there is | ||
1835 | * nowhere it can be initialized differently before we reach this | ||
1836 | * code | ||
1837 | */ | ||
1838 | LOADADDR(r27, boot_cpuid) | ||
1839 | sub r27,r27,r26 | ||
1840 | lwz r27,0(r27) | ||
1841 | |||
1842 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | ||
1843 | mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1844 | add r13,r13,r24 /* for this processor. */ | ||
1845 | sub r13,r13,r26 /* convert to physical addr */ | ||
1846 | mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */ | ||
1847 | |||
1848 | /* Do very early kernel initializations, including initial hash table, | ||
1849 | * stab and slb setup before we turn on relocation. */ | ||
1850 | |||
1851 | /* Restore parameters passed from prom_init/kexec */ | ||
1852 | mr r3,r31 | ||
1853 | bl .early_setup | ||
1854 | |||
1855 | LOADADDR(r3,.start_here_common) | ||
1856 | SET_REG_TO_CONST(r4, MSR_KERNEL) | ||
1857 | mtspr SPRN_SRR0,r3 | ||
1858 | mtspr SPRN_SRR1,r4 | ||
1859 | rfid | ||
1860 | b . /* prevent speculative execution */ | ||
1861 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1862 | |||
1863 | /* This is where all platforms converge execution */ | ||
1864 | _STATIC(start_here_common) | ||
1865 | /* relocation is on at this point */ | ||
1866 | |||
1867 | /* The following code sets up the SP and TOC now that we are */ | ||
1868 | /* running with translation enabled. */ | ||
1869 | |||
1870 | LOADADDR(r3,init_thread_union) | ||
1871 | |||
1872 | /* set up the stack */ | ||
1873 | addi r1,r3,THREAD_SIZE | ||
1874 | li r0,0 | ||
1875 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1876 | |||
1877 | /* Apply the CPUs-specific fixups (nop out sections not relevant | ||
1878 | * to this CPU | ||
1879 | */ | ||
1880 | li r3,0 | ||
1881 | bl .do_cpu_ftr_fixups | ||
1882 | |||
1883 | LOADADDR(r26, boot_cpuid) | ||
1884 | lwz r26,0(r26) | ||
1885 | |||
1886 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | ||
1887 | mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1888 | add r13,r13,r24 /* for this processor. */ | ||
1889 | mtspr SPRN_SPRG3,r13 | ||
1890 | |||
1891 | /* ptr to current */ | ||
1892 | LOADADDR(r4,init_task) | ||
1893 | std r4,PACACURRENT(r13) | ||
1894 | |||
1895 | /* Load the TOC */ | ||
1896 | ld r2,PACATOC(r13) | ||
1897 | std r1,PACAKSAVE(r13) | ||
1898 | |||
1899 | bl .setup_system | ||
1900 | |||
1901 | /* Load up the kernel context */ | ||
1902 | 5: | ||
1903 | #ifdef DO_SOFT_DISABLE | ||
1904 | li r5,0 | ||
1905 | stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ | ||
1906 | mfmsr r5 | ||
1907 | ori r5,r5,MSR_EE /* Hard Enabled */ | ||
1908 | mtmsrd r5 | ||
1909 | #endif | ||
1910 | |||
1911 | bl .start_kernel | ||
1912 | |||
1913 | _GLOBAL(hmt_init) | ||
1914 | #ifdef CONFIG_HMT | ||
1915 | LOADADDR(r5, hmt_thread_data) | ||
1916 | mfspr r7,SPRN_PVR | ||
1917 | srwi r7,r7,16 | ||
1918 | cmpwi r7,0x34 /* Pulsar */ | ||
1919 | beq 90f | ||
1920 | cmpwi r7,0x36 /* Icestar */ | ||
1921 | beq 91f | ||
1922 | cmpwi r7,0x37 /* SStar */ | ||
1923 | beq 91f | ||
1924 | b 101f | ||
1925 | 90: mfspr r6,SPRN_PIR | ||
1926 | andi. r6,r6,0x1f | ||
1927 | b 92f | ||
1928 | 91: mfspr r6,SPRN_PIR | ||
1929 | andi. r6,r6,0x3ff | ||
1930 | 92: sldi r4,r24,3 | ||
1931 | stwx r6,r5,r4 | ||
1932 | bl .hmt_start_secondary | ||
1933 | b 101f | ||
1934 | |||
1935 | __hmt_secondary_hold: | ||
1936 | LOADADDR(r5, hmt_thread_data) | ||
1937 | clrldi r5,r5,4 | ||
1938 | li r7,0 | ||
1939 | mfspr r6,SPRN_PIR | ||
1940 | mfspr r8,SPRN_PVR | ||
1941 | srwi r8,r8,16 | ||
1942 | cmpwi r8,0x34 | ||
1943 | bne 93f | ||
1944 | andi. r6,r6,0x1f | ||
1945 | b 103f | ||
1946 | 93: andi. r6,r6,0x3f | ||
1947 | |||
1948 | 103: lwzx r8,r5,r7 | ||
1949 | cmpw r8,r6 | ||
1950 | beq 104f | ||
1951 | addi r7,r7,8 | ||
1952 | b 103b | ||
1953 | |||
1954 | 104: addi r7,r7,4 | ||
1955 | lwzx r9,r5,r7 | ||
1956 | mr r24,r9 | ||
1957 | 101: | ||
1958 | #endif | ||
1959 | mr r3,r24 | ||
1960 | b .pSeries_secondary_smp_init | ||
1961 | |||
1962 | #ifdef CONFIG_HMT | ||
1963 | _GLOBAL(hmt_start_secondary) | ||
1964 | LOADADDR(r4,__hmt_secondary_hold) | ||
1965 | clrldi r4,r4,4 | ||
1966 | mtspr SPRN_NIADORM, r4 | ||
1967 | mfspr r4, SPRN_MSRDORM | ||
1968 | li r5, -65 | ||
1969 | and r4, r4, r5 | ||
1970 | mtspr SPRN_MSRDORM, r4 | ||
1971 | lis r4,0xffef | ||
1972 | ori r4,r4,0x7403 | ||
1973 | mtspr SPRN_TSC, r4 | ||
1974 | li r4,0x1f4 | ||
1975 | mtspr SPRN_TST, r4 | ||
1976 | mfspr r4, SPRN_HID0 | ||
1977 | ori r4, r4, 0x1 | ||
1978 | mtspr SPRN_HID0, r4 | ||
1979 | mfspr r4, SPRN_CTRLF | ||
1980 | oris r4, r4, 0x40 | ||
1981 | mtspr SPRN_CTRLT, r4 | ||
1982 | blr | ||
1983 | #endif | ||
1984 | |||
1985 | /* | ||
1986 | * We put a few things here that have to be page-aligned. | ||
1987 | * This stuff goes at the beginning of the bss, which is page-aligned. | ||
1988 | */ | ||
1989 | .section ".bss" | ||
1990 | |||
1991 | .align PAGE_SHIFT | ||
1992 | |||
1993 | .globl empty_zero_page | ||
1994 | empty_zero_page: | ||
1995 | .space PAGE_SIZE | ||
1996 | |||
1997 | .globl swapper_pg_dir | ||
1998 | swapper_pg_dir: | ||
1999 | .space PAGE_SIZE | ||
2000 | |||
2001 | /* | ||
2002 | * This space gets a copy of optional info passed to us by the bootstrap | ||
2003 | * Used to pass parameters into the kernel like root=/dev/sda1, etc. | ||
2004 | */ | ||
2005 | .globl cmd_line | ||
2006 | cmd_line: | ||
2007 | .space COMMAND_LINE_SIZE | ||
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S deleted file mode 100644 index 5e089deb0a2b..000000000000 --- a/arch/ppc64/kernel/misc.S +++ /dev/null | |||
@@ -1,940 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc/kernel/misc.S | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | * This file contains miscellaneous low-level functions. | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * | ||
9 | * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) | ||
10 | * and Paul Mackerras. | ||
11 | * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) | ||
12 | * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version | ||
17 | * 2 of the License, or (at your option) any later version. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/sys.h> | ||
23 | #include <asm/unistd.h> | ||
24 | #include <asm/errno.h> | ||
25 | #include <asm/processor.h> | ||
26 | #include <asm/page.h> | ||
27 | #include <asm/cache.h> | ||
28 | #include <asm/ppc_asm.h> | ||
29 | #include <asm/asm-offsets.h> | ||
30 | #include <asm/cputable.h> | ||
31 | #include <asm/thread_info.h> | ||
32 | |||
33 | .text | ||
34 | |||
35 | /* | ||
36 | * Returns (address we were linked at) - (address we are running at) | ||
37 | * for use before the text and data are mapped to KERNELBASE. | ||
38 | */ | ||
39 | |||
40 | _GLOBAL(reloc_offset) | ||
41 | mflr r0 | ||
42 | bl 1f | ||
43 | 1: mflr r3 | ||
44 | LOADADDR(r4,1b) | ||
45 | sub r3,r4,r3 | ||
46 | mtlr r0 | ||
47 | blr | ||
48 | |||
49 | _GLOBAL(get_msr) | ||
50 | mfmsr r3 | ||
51 | blr | ||
52 | |||
53 | _GLOBAL(get_dar) | ||
54 | mfdar r3 | ||
55 | blr | ||
56 | |||
57 | _GLOBAL(get_srr0) | ||
58 | mfsrr0 r3 | ||
59 | blr | ||
60 | |||
61 | _GLOBAL(get_srr1) | ||
62 | mfsrr1 r3 | ||
63 | blr | ||
64 | |||
65 | _GLOBAL(get_sp) | ||
66 | mr r3,r1 | ||
67 | blr | ||
68 | |||
69 | #ifdef CONFIG_IRQSTACKS | ||
70 | _GLOBAL(call_do_softirq) | ||
71 | mflr r0 | ||
72 | std r0,16(r1) | ||
73 | stdu r1,THREAD_SIZE-112(r3) | ||
74 | mr r1,r3 | ||
75 | bl .__do_softirq | ||
76 | ld r1,0(r1) | ||
77 | ld r0,16(r1) | ||
78 | mtlr r0 | ||
79 | blr | ||
80 | |||
81 | _GLOBAL(call___do_IRQ) | ||
82 | mflr r0 | ||
83 | std r0,16(r1) | ||
84 | stdu r1,THREAD_SIZE-112(r5) | ||
85 | mr r1,r5 | ||
86 | bl .__do_IRQ | ||
87 | ld r1,0(r1) | ||
88 | ld r0,16(r1) | ||
89 | mtlr r0 | ||
90 | blr | ||
91 | #endif /* CONFIG_IRQSTACKS */ | ||
92 | |||
93 | /* | ||
94 | * To be called by C code which needs to do some operations with MMU | ||
95 | * disabled. Note that interrupts have to be disabled by the caller | ||
96 | * prior to calling us. The code called _MUST_ be in the RMO of course | ||
97 | * and part of the linear mapping as we don't attempt to translate the | ||
98 | * stack pointer at all. The function is called with the stack switched | ||
99 | * to this CPU emergency stack | ||
100 | * | ||
101 | * prototype is void *call_with_mmu_off(void *func, void *data); | ||
102 | * | ||
103 | * the called function is expected to be of the form | ||
104 | * | ||
105 | * void *called(void *data); | ||
106 | */ | ||
107 | _GLOBAL(call_with_mmu_off) | ||
108 | mflr r0 /* get link, save it on stackframe */ | ||
109 | std r0,16(r1) | ||
110 | mr r1,r5 /* save old stack ptr */ | ||
111 | ld r1,PACAEMERGSP(r13) /* get emerg. stack */ | ||
112 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
113 | std r0,16(r1) /* save link on emerg. stack */ | ||
114 | std r5,0(r1) /* save old stack ptr in backchain */ | ||
115 | ld r3,0(r3) /* get to real function ptr (assume same TOC) */ | ||
116 | bl 2f /* we need LR to return, continue at label 2 */ | ||
117 | |||
118 | ld r0,16(r1) /* we return here from the call, get LR and */ | ||
119 | ld r1,0(r1) /* .. old stack ptr */ | ||
120 | mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */ | ||
121 | mfmsr r4 | ||
122 | ori r4,r4,MSR_IR|MSR_DR | ||
123 | mtspr SPRN_SRR1,r4 | ||
124 | rfid | ||
125 | |||
126 | 2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */ | ||
127 | mr r3,r4 /* get parameter */ | ||
128 | mfmsr r0 | ||
129 | ori r0,r0,MSR_IR|MSR_DR | ||
130 | xori r0,r0,MSR_IR|MSR_DR | ||
131 | mtspr SPRN_SRR1,r0 | ||
132 | rfid | ||
133 | |||
134 | |||
135 | .section ".toc","aw" | ||
136 | PPC64_CACHES: | ||
137 | .tc ppc64_caches[TC],ppc64_caches | ||
138 | .section ".text" | ||
139 | |||
140 | /* | ||
141 | * Write any modified data cache blocks out to memory | ||
142 | * and invalidate the corresponding instruction cache blocks. | ||
143 | * | ||
144 | * flush_icache_range(unsigned long start, unsigned long stop) | ||
145 | * | ||
146 | * flush all bytes from start through stop-1 inclusive | ||
147 | */ | ||
148 | |||
149 | _KPROBE(__flush_icache_range) | ||
150 | |||
151 | /* | ||
152 | * Flush the data cache to memory | ||
153 | * | ||
154 | * Different systems have different cache line sizes | ||
155 | * and in some cases i-cache and d-cache line sizes differ from | ||
156 | * each other. | ||
157 | */ | ||
158 | ld r10,PPC64_CACHES@toc(r2) | ||
159 | lwz r7,DCACHEL1LINESIZE(r10)/* Get cache line size */ | ||
160 | addi r5,r7,-1 | ||
161 | andc r6,r3,r5 /* round low to line bdy */ | ||
162 | subf r8,r6,r4 /* compute length */ | ||
163 | add r8,r8,r5 /* ensure we get enough */ | ||
164 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ | ||
165 | srw. r8,r8,r9 /* compute line count */ | ||
166 | beqlr /* nothing to do? */ | ||
167 | mtctr r8 | ||
168 | 1: dcbst 0,r6 | ||
169 | add r6,r6,r7 | ||
170 | bdnz 1b | ||
171 | sync | ||
172 | |||
173 | /* Now invalidate the instruction cache */ | ||
174 | |||
175 | lwz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ | ||
176 | addi r5,r7,-1 | ||
177 | andc r6,r3,r5 /* round low to line bdy */ | ||
178 | subf r8,r6,r4 /* compute length */ | ||
179 | add r8,r8,r5 | ||
180 | lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ | ||
181 | srw. r8,r8,r9 /* compute line count */ | ||
182 | beqlr /* nothing to do? */ | ||
183 | mtctr r8 | ||
184 | 2: icbi 0,r6 | ||
185 | add r6,r6,r7 | ||
186 | bdnz 2b | ||
187 | isync | ||
188 | blr | ||
189 | |||
190 | .text | ||
191 | /* | ||
192 | * Like above, but only do the D-cache. | ||
193 | * | ||
194 | * flush_dcache_range(unsigned long start, unsigned long stop) | ||
195 | * | ||
196 | * flush all bytes from start to stop-1 inclusive | ||
197 | */ | ||
198 | _GLOBAL(flush_dcache_range) | ||
199 | |||
200 | /* | ||
201 | * Flush the data cache to memory | ||
202 | * | ||
203 | * Different systems have different cache line sizes | ||
204 | */ | ||
205 | ld r10,PPC64_CACHES@toc(r2) | ||
206 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
207 | addi r5,r7,-1 | ||
208 | andc r6,r3,r5 /* round low to line bdy */ | ||
209 | subf r8,r6,r4 /* compute length */ | ||
210 | add r8,r8,r5 /* ensure we get enough */ | ||
211 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ | ||
212 | srw. r8,r8,r9 /* compute line count */ | ||
213 | beqlr /* nothing to do? */ | ||
214 | mtctr r8 | ||
215 | 0: dcbst 0,r6 | ||
216 | add r6,r6,r7 | ||
217 | bdnz 0b | ||
218 | sync | ||
219 | blr | ||
220 | |||
221 | /* | ||
222 | * Like above, but works on non-mapped physical addresses. | ||
223 | * Use only for non-LPAR setups ! It also assumes real mode | ||
224 | * is cacheable. Used for flushing out the DART before using | ||
225 | * it as uncacheable memory | ||
226 | * | ||
227 | * flush_dcache_phys_range(unsigned long start, unsigned long stop) | ||
228 | * | ||
229 | * flush all bytes from start to stop-1 inclusive | ||
230 | */ | ||
231 | _GLOBAL(flush_dcache_phys_range) | ||
232 | ld r10,PPC64_CACHES@toc(r2) | ||
233 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
234 | addi r5,r7,-1 | ||
235 | andc r6,r3,r5 /* round low to line bdy */ | ||
236 | subf r8,r6,r4 /* compute length */ | ||
237 | add r8,r8,r5 /* ensure we get enough */ | ||
238 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ | ||
239 | srw. r8,r8,r9 /* compute line count */ | ||
240 | beqlr /* nothing to do? */ | ||
241 | mfmsr r5 /* Disable MMU Data Relocation */ | ||
242 | ori r0,r5,MSR_DR | ||
243 | xori r0,r0,MSR_DR | ||
244 | sync | ||
245 | mtmsr r0 | ||
246 | sync | ||
247 | isync | ||
248 | mtctr r8 | ||
249 | 0: dcbst 0,r6 | ||
250 | add r6,r6,r7 | ||
251 | bdnz 0b | ||
252 | sync | ||
253 | isync | ||
254 | mtmsr r5 /* Re-enable MMU Data Relocation */ | ||
255 | sync | ||
256 | isync | ||
257 | blr | ||
258 | |||
259 | _GLOBAL(flush_inval_dcache_range) | ||
260 | ld r10,PPC64_CACHES@toc(r2) | ||
261 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
262 | addi r5,r7,-1 | ||
263 | andc r6,r3,r5 /* round low to line bdy */ | ||
264 | subf r8,r6,r4 /* compute length */ | ||
265 | add r8,r8,r5 /* ensure we get enough */ | ||
266 | lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */ | ||
267 | srw. r8,r8,r9 /* compute line count */ | ||
268 | beqlr /* nothing to do? */ | ||
269 | sync | ||
270 | isync | ||
271 | mtctr r8 | ||
272 | 0: dcbf 0,r6 | ||
273 | add r6,r6,r7 | ||
274 | bdnz 0b | ||
275 | sync | ||
276 | isync | ||
277 | blr | ||
278 | |||
279 | |||
280 | /* | ||
281 | * Flush a particular page from the data cache to RAM. | ||
282 | * Note: this is necessary because the instruction cache does *not* | ||
283 | * snoop from the data cache. | ||
284 | * | ||
285 | * void __flush_dcache_icache(void *page) | ||
286 | */ | ||
287 | _GLOBAL(__flush_dcache_icache) | ||
288 | /* | ||
289 | * Flush the data cache to memory | ||
290 | * | ||
291 | * Different systems have different cache line sizes | ||
292 | */ | ||
293 | |||
294 | /* Flush the dcache */ | ||
295 | ld r7,PPC64_CACHES@toc(r2) | ||
296 | clrrdi r3,r3,PAGE_SHIFT /* Page align */ | ||
297 | lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ | ||
298 | lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ | ||
299 | mr r6,r3 | ||
300 | mtctr r4 | ||
301 | 0: dcbst 0,r6 | ||
302 | add r6,r6,r5 | ||
303 | bdnz 0b | ||
304 | sync | ||
305 | |||
306 | /* Now invalidate the icache */ | ||
307 | |||
308 | lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ | ||
309 | lwz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ | ||
310 | mtctr r4 | ||
311 | 1: icbi 0,r3 | ||
312 | add r3,r3,r5 | ||
313 | bdnz 1b | ||
314 | isync | ||
315 | blr | ||
316 | |||
317 | /* | ||
318 | * I/O string operations | ||
319 | * | ||
320 | * insb(port, buf, len) | ||
321 | * outsb(port, buf, len) | ||
322 | * insw(port, buf, len) | ||
323 | * outsw(port, buf, len) | ||
324 | * insl(port, buf, len) | ||
325 | * outsl(port, buf, len) | ||
326 | * insw_ns(port, buf, len) | ||
327 | * outsw_ns(port, buf, len) | ||
328 | * insl_ns(port, buf, len) | ||
329 | * outsl_ns(port, buf, len) | ||
330 | * | ||
331 | * The *_ns versions don't do byte-swapping. | ||
332 | */ | ||
333 | _GLOBAL(_insb) | ||
334 | cmpwi 0,r5,0 | ||
335 | mtctr r5 | ||
336 | subi r4,r4,1 | ||
337 | blelr- | ||
338 | 00: lbz r5,0(r3) | ||
339 | eieio | ||
340 | stbu r5,1(r4) | ||
341 | bdnz 00b | ||
342 | twi 0,r5,0 | ||
343 | isync | ||
344 | blr | ||
345 | |||
346 | _GLOBAL(_outsb) | ||
347 | cmpwi 0,r5,0 | ||
348 | mtctr r5 | ||
349 | subi r4,r4,1 | ||
350 | blelr- | ||
351 | 00: lbzu r5,1(r4) | ||
352 | stb r5,0(r3) | ||
353 | bdnz 00b | ||
354 | sync | ||
355 | blr | ||
356 | |||
357 | _GLOBAL(_insw) | ||
358 | cmpwi 0,r5,0 | ||
359 | mtctr r5 | ||
360 | subi r4,r4,2 | ||
361 | blelr- | ||
362 | 00: lhbrx r5,0,r3 | ||
363 | eieio | ||
364 | sthu r5,2(r4) | ||
365 | bdnz 00b | ||
366 | twi 0,r5,0 | ||
367 | isync | ||
368 | blr | ||
369 | |||
370 | _GLOBAL(_outsw) | ||
371 | cmpwi 0,r5,0 | ||
372 | mtctr r5 | ||
373 | subi r4,r4,2 | ||
374 | blelr- | ||
375 | 00: lhzu r5,2(r4) | ||
376 | sthbrx r5,0,r3 | ||
377 | bdnz 00b | ||
378 | sync | ||
379 | blr | ||
380 | |||
381 | _GLOBAL(_insl) | ||
382 | cmpwi 0,r5,0 | ||
383 | mtctr r5 | ||
384 | subi r4,r4,4 | ||
385 | blelr- | ||
386 | 00: lwbrx r5,0,r3 | ||
387 | eieio | ||
388 | stwu r5,4(r4) | ||
389 | bdnz 00b | ||
390 | twi 0,r5,0 | ||
391 | isync | ||
392 | blr | ||
393 | |||
394 | _GLOBAL(_outsl) | ||
395 | cmpwi 0,r5,0 | ||
396 | mtctr r5 | ||
397 | subi r4,r4,4 | ||
398 | blelr- | ||
399 | 00: lwzu r5,4(r4) | ||
400 | stwbrx r5,0,r3 | ||
401 | bdnz 00b | ||
402 | sync | ||
403 | blr | ||
404 | |||
405 | /* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */ | ||
406 | _GLOBAL(_insw_ns) | ||
407 | cmpwi 0,r5,0 | ||
408 | mtctr r5 | ||
409 | subi r4,r4,2 | ||
410 | blelr- | ||
411 | 00: lhz r5,0(r3) | ||
412 | eieio | ||
413 | sthu r5,2(r4) | ||
414 | bdnz 00b | ||
415 | twi 0,r5,0 | ||
416 | isync | ||
417 | blr | ||
418 | |||
419 | /* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */ | ||
420 | _GLOBAL(_outsw_ns) | ||
421 | cmpwi 0,r5,0 | ||
422 | mtctr r5 | ||
423 | subi r4,r4,2 | ||
424 | blelr- | ||
425 | 00: lhzu r5,2(r4) | ||
426 | sth r5,0(r3) | ||
427 | bdnz 00b | ||
428 | sync | ||
429 | blr | ||
430 | |||
431 | _GLOBAL(_insl_ns) | ||
432 | cmpwi 0,r5,0 | ||
433 | mtctr r5 | ||
434 | subi r4,r4,4 | ||
435 | blelr- | ||
436 | 00: lwz r5,0(r3) | ||
437 | eieio | ||
438 | stwu r5,4(r4) | ||
439 | bdnz 00b | ||
440 | twi 0,r5,0 | ||
441 | isync | ||
442 | blr | ||
443 | |||
444 | _GLOBAL(_outsl_ns) | ||
445 | cmpwi 0,r5,0 | ||
446 | mtctr r5 | ||
447 | subi r4,r4,4 | ||
448 | blelr- | ||
449 | 00: lwzu r5,4(r4) | ||
450 | stw r5,0(r3) | ||
451 | bdnz 00b | ||
452 | sync | ||
453 | blr | ||
454 | |||
455 | /* | ||
456 | * identify_cpu and calls setup_cpu | ||
457 | * In: r3 = base of the cpu_specs array | ||
458 | * r4 = address of cur_cpu_spec | ||
459 | * r5 = relocation offset | ||
460 | */ | ||
461 | _GLOBAL(identify_cpu) | ||
462 | mfpvr r7 | ||
463 | 1: | ||
464 | lwz r8,CPU_SPEC_PVR_MASK(r3) | ||
465 | and r8,r8,r7 | ||
466 | lwz r9,CPU_SPEC_PVR_VALUE(r3) | ||
467 | cmplw 0,r9,r8 | ||
468 | beq 1f | ||
469 | addi r3,r3,CPU_SPEC_ENTRY_SIZE | ||
470 | b 1b | ||
471 | 1: | ||
472 | add r0,r3,r5 | ||
473 | std r0,0(r4) | ||
474 | ld r4,CPU_SPEC_SETUP(r3) | ||
475 | sub r4,r4,r5 | ||
476 | ld r4,0(r4) | ||
477 | sub r4,r4,r5 | ||
478 | mtctr r4 | ||
479 | /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ | ||
480 | mr r4,r3 | ||
481 | mr r3,r5 | ||
482 | bctr | ||
483 | |||
484 | /* | ||
485 | * do_cpu_ftr_fixups - goes through the list of CPU feature fixups | ||
486 | * and writes nop's over sections of code that don't apply for this cpu. | ||
487 | * r3 = data offset (not changed) | ||
488 | */ | ||
489 | _GLOBAL(do_cpu_ftr_fixups) | ||
490 | /* Get CPU 0 features */ | ||
491 | LOADADDR(r6,cur_cpu_spec) | ||
492 | sub r6,r6,r3 | ||
493 | ld r4,0(r6) | ||
494 | sub r4,r4,r3 | ||
495 | ld r4,CPU_SPEC_FEATURES(r4) | ||
496 | /* Get the fixup table */ | ||
497 | LOADADDR(r6,__start___ftr_fixup) | ||
498 | sub r6,r6,r3 | ||
499 | LOADADDR(r7,__stop___ftr_fixup) | ||
500 | sub r7,r7,r3 | ||
501 | /* Do the fixup */ | ||
502 | 1: cmpld r6,r7 | ||
503 | bgelr | ||
504 | addi r6,r6,32 | ||
505 | ld r8,-32(r6) /* mask */ | ||
506 | and r8,r8,r4 | ||
507 | ld r9,-24(r6) /* value */ | ||
508 | cmpld r8,r9 | ||
509 | beq 1b | ||
510 | ld r8,-16(r6) /* section begin */ | ||
511 | ld r9,-8(r6) /* section end */ | ||
512 | subf. r9,r8,r9 | ||
513 | beq 1b | ||
514 | /* write nops over the section of code */ | ||
515 | /* todo: if large section, add a branch at the start of it */ | ||
516 | srwi r9,r9,2 | ||
517 | mtctr r9 | ||
518 | sub r8,r8,r3 | ||
519 | lis r0,0x60000000@h /* nop */ | ||
520 | 3: stw r0,0(r8) | ||
521 | andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l | ||
522 | beq 2f | ||
523 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
524 | sync | ||
525 | icbi 0,r8 | ||
526 | 2: addi r8,r8,4 | ||
527 | bdnz 3b | ||
528 | sync /* additional sync needed on g4 */ | ||
529 | isync | ||
530 | b 1b | ||
531 | |||
532 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) | ||
533 | /* | ||
534 | * Do an IO access in real mode | ||
535 | */ | ||
536 | _GLOBAL(real_readb) | ||
537 | mfmsr r7 | ||
538 | ori r0,r7,MSR_DR | ||
539 | xori r0,r0,MSR_DR | ||
540 | sync | ||
541 | mtmsrd r0 | ||
542 | sync | ||
543 | isync | ||
544 | mfspr r6,SPRN_HID4 | ||
545 | rldicl r5,r6,32,0 | ||
546 | ori r5,r5,0x100 | ||
547 | rldicl r5,r5,32,0 | ||
548 | sync | ||
549 | mtspr SPRN_HID4,r5 | ||
550 | isync | ||
551 | slbia | ||
552 | isync | ||
553 | lbz r3,0(r3) | ||
554 | sync | ||
555 | mtspr SPRN_HID4,r6 | ||
556 | isync | ||
557 | slbia | ||
558 | isync | ||
559 | mtmsrd r7 | ||
560 | sync | ||
561 | isync | ||
562 | blr | ||
563 | |||
564 | /* | ||
565 | * Do an IO access in real mode | ||
566 | */ | ||
567 | _GLOBAL(real_writeb) | ||
568 | mfmsr r7 | ||
569 | ori r0,r7,MSR_DR | ||
570 | xori r0,r0,MSR_DR | ||
571 | sync | ||
572 | mtmsrd r0 | ||
573 | sync | ||
574 | isync | ||
575 | mfspr r6,SPRN_HID4 | ||
576 | rldicl r5,r6,32,0 | ||
577 | ori r5,r5,0x100 | ||
578 | rldicl r5,r5,32,0 | ||
579 | sync | ||
580 | mtspr SPRN_HID4,r5 | ||
581 | isync | ||
582 | slbia | ||
583 | isync | ||
584 | stb r3,0(r4) | ||
585 | sync | ||
586 | mtspr SPRN_HID4,r6 | ||
587 | isync | ||
588 | slbia | ||
589 | isync | ||
590 | mtmsrd r7 | ||
591 | sync | ||
592 | isync | ||
593 | blr | ||
594 | #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ | ||
595 | |||
596 | /* | ||
597 | * SCOM access functions for 970 (FX only for now) | ||
598 | * | ||
599 | * unsigned long scom970_read(unsigned int address); | ||
600 | * void scom970_write(unsigned int address, unsigned long value); | ||
601 | * | ||
602 | * The address passed in is the 24 bits register address. This code | ||
603 | * is 970 specific and will not check the status bits, so you should | ||
604 | * know what you are doing. | ||
605 | */ | ||
606 | _GLOBAL(scom970_read) | ||
607 | /* interrupts off */ | ||
608 | mfmsr r4 | ||
609 | ori r0,r4,MSR_EE | ||
610 | xori r0,r0,MSR_EE | ||
611 | mtmsrd r0,1 | ||
612 | |||
613 | /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits | ||
614 | * (including parity). On current CPUs they must be 0'd, | ||
615 | * and finally or in RW bit | ||
616 | */ | ||
617 | rlwinm r3,r3,8,0,15 | ||
618 | ori r3,r3,0x8000 | ||
619 | |||
620 | /* do the actual scom read */ | ||
621 | sync | ||
622 | mtspr SPRN_SCOMC,r3 | ||
623 | isync | ||
624 | mfspr r3,SPRN_SCOMD | ||
625 | isync | ||
626 | mfspr r0,SPRN_SCOMC | ||
627 | isync | ||
628 | |||
629 | /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah | ||
630 | * that's the best we can do). Not implemented yet as we don't use | ||
631 | * the scom on any of the bogus CPUs yet, but may have to be done | ||
632 | * ultimately | ||
633 | */ | ||
634 | |||
635 | /* restore interrupts */ | ||
636 | mtmsrd r4,1 | ||
637 | blr | ||
638 | |||
639 | |||
640 | _GLOBAL(scom970_write) | ||
641 | /* interrupts off */ | ||
642 | mfmsr r5 | ||
643 | ori r0,r5,MSR_EE | ||
644 | xori r0,r0,MSR_EE | ||
645 | mtmsrd r0,1 | ||
646 | |||
647 | /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits | ||
648 | * (including parity). On current CPUs they must be 0'd. | ||
649 | */ | ||
650 | |||
651 | rlwinm r3,r3,8,0,15 | ||
652 | |||
653 | sync | ||
654 | mtspr SPRN_SCOMD,r4 /* write data */ | ||
655 | isync | ||
656 | mtspr SPRN_SCOMC,r3 /* write command */ | ||
657 | isync | ||
658 | mfspr 3,SPRN_SCOMC | ||
659 | isync | ||
660 | |||
661 | /* restore interrupts */ | ||
662 | mtmsrd r5,1 | ||
663 | blr | ||
664 | |||
665 | |||
666 | /* | ||
667 | * Create a kernel thread | ||
668 | * kernel_thread(fn, arg, flags) | ||
669 | */ | ||
670 | _GLOBAL(kernel_thread) | ||
671 | std r29,-24(r1) | ||
672 | std r30,-16(r1) | ||
673 | stdu r1,-STACK_FRAME_OVERHEAD(r1) | ||
674 | mr r29,r3 | ||
675 | mr r30,r4 | ||
676 | ori r3,r5,CLONE_VM /* flags */ | ||
677 | oris r3,r3,(CLONE_UNTRACED>>16) | ||
678 | li r4,0 /* new sp (unused) */ | ||
679 | li r0,__NR_clone | ||
680 | sc | ||
681 | cmpdi 0,r3,0 /* parent or child? */ | ||
682 | bne 1f /* return if parent */ | ||
683 | li r0,0 | ||
684 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
685 | ld r2,8(r29) | ||
686 | ld r29,0(r29) | ||
687 | mtlr r29 /* fn addr in lr */ | ||
688 | mr r3,r30 /* load arg and call fn */ | ||
689 | blrl | ||
690 | li r0,__NR_exit /* exit after child exits */ | ||
691 | li r3,0 | ||
692 | sc | ||
693 | 1: addi r1,r1,STACK_FRAME_OVERHEAD | ||
694 | ld r29,-24(r1) | ||
695 | ld r30,-16(r1) | ||
696 | blr | ||
697 | |||
698 | /* | ||
699 | * disable_kernel_fp() | ||
700 | * Disable the FPU. | ||
701 | */ | ||
702 | _GLOBAL(disable_kernel_fp) | ||
703 | mfmsr r3 | ||
704 | rldicl r0,r3,(63-MSR_FP_LG),1 | ||
705 | rldicl r3,r0,(MSR_FP_LG+1),0 | ||
706 | mtmsrd r3 /* disable use of fpu now */ | ||
707 | isync | ||
708 | blr | ||
709 | |||
710 | #ifdef CONFIG_ALTIVEC | ||
711 | |||
712 | #if 0 /* this has no callers for now */ | ||
713 | /* | ||
714 | * disable_kernel_altivec() | ||
715 | * Disable the VMX. | ||
716 | */ | ||
717 | _GLOBAL(disable_kernel_altivec) | ||
718 | mfmsr r3 | ||
719 | rldicl r0,r3,(63-MSR_VEC_LG),1 | ||
720 | rldicl r3,r0,(MSR_VEC_LG+1),0 | ||
721 | mtmsrd r3 /* disable use of VMX now */ | ||
722 | isync | ||
723 | blr | ||
724 | #endif /* 0 */ | ||
725 | |||
726 | /* | ||
727 | * giveup_altivec(tsk) | ||
728 | * Disable VMX for the task given as the argument, | ||
729 | * and save the vector registers in its thread_struct. | ||
730 | * Enables the VMX for use in the kernel on return. | ||
731 | */ | ||
732 | _GLOBAL(giveup_altivec) | ||
733 | mfmsr r5 | ||
734 | oris r5,r5,MSR_VEC@h | ||
735 | mtmsrd r5 /* enable use of VMX now */ | ||
736 | isync | ||
737 | cmpdi 0,r3,0 | ||
738 | beqlr- /* if no previous owner, done */ | ||
739 | addi r3,r3,THREAD /* want THREAD of task */ | ||
740 | ld r5,PT_REGS(r3) | ||
741 | cmpdi 0,r5,0 | ||
742 | SAVE_32VRS(0,r4,r3) | ||
743 | mfvscr vr0 | ||
744 | li r4,THREAD_VSCR | ||
745 | stvx vr0,r4,r3 | ||
746 | beq 1f | ||
747 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
748 | lis r3,MSR_VEC@h | ||
749 | andc r4,r4,r3 /* disable FP for previous task */ | ||
750 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
751 | 1: | ||
752 | #ifndef CONFIG_SMP | ||
753 | li r5,0 | ||
754 | ld r4,last_task_used_altivec@got(r2) | ||
755 | std r5,0(r4) | ||
756 | #endif /* CONFIG_SMP */ | ||
757 | blr | ||
758 | |||
759 | #endif /* CONFIG_ALTIVEC */ | ||
760 | |||
761 | _GLOBAL(__setup_cpu_power3) | ||
762 | blr | ||
763 | |||
764 | _GLOBAL(execve) | ||
765 | li r0,__NR_execve | ||
766 | sc | ||
767 | bnslr | ||
768 | neg r3,r3 | ||
769 | blr | ||
770 | |||
771 | /* kexec_wait(phys_cpu) | ||
772 | * | ||
773 | * wait for the flag to change, indicating this kernel is going away but | ||
774 | * the slave code for the next one is at addresses 0 to 100. | ||
775 | * | ||
776 | * This is used by all slaves. | ||
777 | * | ||
778 | * Physical (hardware) cpu id should be in r3. | ||
779 | */ | ||
780 | _GLOBAL(kexec_wait) | ||
781 | bl 1f | ||
782 | 1: mflr r5 | ||
783 | addi r5,r5,kexec_flag-1b | ||
784 | |||
785 | 99: HMT_LOW | ||
786 | #ifdef CONFIG_KEXEC /* use no memory without kexec */ | ||
787 | lwz r4,0(r5) | ||
788 | cmpwi 0,r4,0 | ||
789 | bnea 0x60 | ||
790 | #endif | ||
791 | b 99b | ||
792 | |||
793 | /* this can be in text because we won't change it until we are | ||
794 | * running in real anyways | ||
795 | */ | ||
796 | kexec_flag: | ||
797 | .long 0 | ||
798 | |||
799 | |||
800 | #ifdef CONFIG_KEXEC | ||
801 | |||
802 | /* kexec_smp_wait(void) | ||
803 | * | ||
804 | * call with interrupts off | ||
805 | * note: this is a terminal routine, it does not save lr | ||
806 | * | ||
807 | * get phys id from paca | ||
808 | * set paca id to -1 to say we got here | ||
809 | * switch to real mode | ||
810 | * join other cpus in kexec_wait(phys_id) | ||
811 | */ | ||
812 | _GLOBAL(kexec_smp_wait) | ||
813 | lhz r3,PACAHWCPUID(r13) | ||
814 | li r4,-1 | ||
815 | sth r4,PACAHWCPUID(r13) /* let others know we left */ | ||
816 | bl real_mode | ||
817 | b .kexec_wait | ||
818 | |||
819 | /* | ||
820 | * switch to real mode (turn mmu off) | ||
821 | * we use the early kernel trick that the hardware ignores bits | ||
822 | * 0 and 1 (big endian) of the effective address in real mode | ||
823 | * | ||
824 | * don't overwrite r3 here, it is live for kexec_wait above. | ||
825 | */ | ||
826 | real_mode: /* assume normal blr return */ | ||
827 | 1: li r9,MSR_RI | ||
828 | li r10,MSR_DR|MSR_IR | ||
829 | mflr r11 /* return address to SRR0 */ | ||
830 | mfmsr r12 | ||
831 | andc r9,r12,r9 | ||
832 | andc r10,r12,r10 | ||
833 | |||
834 | mtmsrd r9,1 | ||
835 | mtspr SPRN_SRR1,r10 | ||
836 | mtspr SPRN_SRR0,r11 | ||
837 | rfid | ||
838 | |||
839 | |||
840 | /* | ||
841 | * kexec_sequence(newstack, start, image, control, clear_all()) | ||
842 | * | ||
843 | * does the grungy work with stack switching and real mode switches | ||
844 | * also does simple calls to other code | ||
845 | */ | ||
846 | |||
847 | _GLOBAL(kexec_sequence) | ||
848 | mflr r0 | ||
849 | std r0,16(r1) | ||
850 | |||
851 | /* switch stacks to newstack -- &kexec_stack.stack */ | ||
852 | stdu r1,THREAD_SIZE-112(r3) | ||
853 | mr r1,r3 | ||
854 | |||
855 | li r0,0 | ||
856 | std r0,16(r1) | ||
857 | |||
858 | /* save regs for local vars on new stack. | ||
859 | * yes, we won't go back, but ... | ||
860 | */ | ||
861 | std r31,-8(r1) | ||
862 | std r30,-16(r1) | ||
863 | std r29,-24(r1) | ||
864 | std r28,-32(r1) | ||
865 | std r27,-40(r1) | ||
866 | std r26,-48(r1) | ||
867 | std r25,-56(r1) | ||
868 | |||
869 | stdu r1,-112-64(r1) | ||
870 | |||
871 | /* save args into preserved regs */ | ||
872 | mr r31,r3 /* newstack (both) */ | ||
873 | mr r30,r4 /* start (real) */ | ||
874 | mr r29,r5 /* image (virt) */ | ||
875 | mr r28,r6 /* control, unused */ | ||
876 | mr r27,r7 /* clear_all() fn desc */ | ||
877 | mr r26,r8 /* spare */ | ||
878 | lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ | ||
879 | |||
880 | /* disable interrupts, we are overwriting kernel data next */ | ||
881 | mfmsr r3 | ||
882 | rlwinm r3,r3,0,17,15 | ||
883 | mtmsrd r3,1 | ||
884 | |||
885 | /* copy dest pages, flush whole dest image */ | ||
886 | mr r3,r29 | ||
887 | bl .kexec_copy_flush /* (image) */ | ||
888 | |||
889 | /* turn off mmu */ | ||
890 | bl real_mode | ||
891 | |||
892 | /* clear out hardware hash page table and tlb */ | ||
893 | ld r5,0(r27) /* deref function descriptor */ | ||
894 | mtctr r5 | ||
895 | bctrl /* ppc_md.hash_clear_all(void); */ | ||
896 | |||
897 | /* | ||
898 | * kexec image calling is: | ||
899 | * the first 0x100 bytes of the entry point are copied to 0 | ||
900 | * | ||
901 | * all slaves branch to slave = 0x60 (absolute) | ||
902 | * slave(phys_cpu_id); | ||
903 | * | ||
904 | * master goes to start = entry point | ||
905 | * start(phys_cpu_id, start, 0); | ||
906 | * | ||
907 | * | ||
908 | * a wrapper is needed to call existing kernels, here is an approximate | ||
909 | * description of one method: | ||
910 | * | ||
911 | * v2: (2.6.10) | ||
912 | * start will be near the boot_block (maybe 0x100 bytes before it?) | ||
913 | * it will have a 0x60, which will b to boot_block, where it will wait | ||
914 | * and 0 will store phys into struct boot-block and load r3 from there, | ||
915 | * copy kernel 0-0x100 and tell slaves to back down to 0x60 again | ||
916 | * | ||
917 | * v1: (2.6.9) | ||
918 | * boot block will have all cpus scanning device tree to see if they | ||
919 | * are the boot cpu ????? | ||
920 | * other device tree differences (prop sizes, va vs pa, etc)... | ||
921 | */ | ||
922 | |||
923 | /* copy 0x100 bytes starting at start to 0 */ | ||
924 | li r3,0 | ||
925 | mr r4,r30 | ||
926 | li r5,0x100 | ||
927 | li r6,0 | ||
928 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
929 | 1: /* assume normal blr return */ | ||
930 | |||
931 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
932 | mflr r5 | ||
933 | li r6,1 | ||
934 | stw r6,kexec_flag-1b(5) | ||
935 | mr r3,r25 # my phys cpu | ||
936 | mr r4,r30 # start, aka phys mem offset | ||
937 | mtlr 4 | ||
938 | li r5,0 | ||
939 | blr /* image->start(physid, image->start, 0); */ | ||
940 | #endif /* CONFIG_KEXEC */ | ||
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c deleted file mode 100644 index 84006e26342c..000000000000 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /* | ||
2 | * c 2001 PPC 64 Team, IBM Corp | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <linux/config.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/console.h> | ||
13 | #include <net/checksum.h> | ||
14 | |||
15 | #include <asm/processor.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/hw_irq.h> | ||
20 | #include <asm/abs_addr.h> | ||
21 | #include <asm/cacheflush.h> | ||
22 | |||
23 | EXPORT_SYMBOL(strcpy); | ||
24 | EXPORT_SYMBOL(strncpy); | ||
25 | EXPORT_SYMBOL(strcat); | ||
26 | EXPORT_SYMBOL(strncat); | ||
27 | EXPORT_SYMBOL(strchr); | ||
28 | EXPORT_SYMBOL(strrchr); | ||
29 | EXPORT_SYMBOL(strpbrk); | ||
30 | EXPORT_SYMBOL(strstr); | ||
31 | EXPORT_SYMBOL(strlen); | ||
32 | EXPORT_SYMBOL(strnlen); | ||
33 | EXPORT_SYMBOL(strcmp); | ||
34 | EXPORT_SYMBOL(strncmp); | ||
35 | |||
36 | EXPORT_SYMBOL(csum_partial); | ||
37 | EXPORT_SYMBOL(csum_partial_copy_generic); | ||
38 | EXPORT_SYMBOL(ip_fast_csum); | ||
39 | EXPORT_SYMBOL(csum_tcpudp_magic); | ||
40 | |||
41 | EXPORT_SYMBOL(__copy_tofrom_user); | ||
42 | EXPORT_SYMBOL(__clear_user); | ||
43 | EXPORT_SYMBOL(__strncpy_from_user); | ||
44 | EXPORT_SYMBOL(__strnlen_user); | ||
45 | |||
46 | EXPORT_SYMBOL(reloc_offset); | ||
47 | |||
48 | EXPORT_SYMBOL(_insb); | ||
49 | EXPORT_SYMBOL(_outsb); | ||
50 | EXPORT_SYMBOL(_insw); | ||
51 | EXPORT_SYMBOL(_outsw); | ||
52 | EXPORT_SYMBOL(_insl); | ||
53 | EXPORT_SYMBOL(_outsl); | ||
54 | EXPORT_SYMBOL(_insw_ns); | ||
55 | EXPORT_SYMBOL(_outsw_ns); | ||
56 | EXPORT_SYMBOL(_insl_ns); | ||
57 | EXPORT_SYMBOL(_outsl_ns); | ||
58 | |||
59 | EXPORT_SYMBOL(kernel_thread); | ||
60 | |||
61 | EXPORT_SYMBOL(giveup_fpu); | ||
62 | #ifdef CONFIG_ALTIVEC | ||
63 | EXPORT_SYMBOL(giveup_altivec); | ||
64 | #endif | ||
65 | EXPORT_SYMBOL(__flush_icache_range); | ||
66 | EXPORT_SYMBOL(flush_dcache_range); | ||
67 | |||
68 | EXPORT_SYMBOL(memcpy); | ||
69 | EXPORT_SYMBOL(memset); | ||
70 | EXPORT_SYMBOL(memmove); | ||
71 | EXPORT_SYMBOL(memscan); | ||
72 | EXPORT_SYMBOL(memcmp); | ||
73 | EXPORT_SYMBOL(memchr); | ||
74 | |||
75 | EXPORT_SYMBOL(timer_interrupt); | ||
76 | EXPORT_SYMBOL(console_drivers); | ||
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c deleted file mode 100644 index fbad2c360784..000000000000 --- a/arch/ppc64/kernel/prom.c +++ /dev/null | |||
@@ -1,1954 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Procedures for interfacing to Open Firmware. | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996 Paul Mackerras. | ||
8 | * | ||
9 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
10 | * {engebret|bergner}@us.ibm.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/stringify.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/initrd.h> | ||
32 | #include <linux/bitops.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <asm/prom.h> | ||
37 | #include <asm/rtas.h> | ||
38 | #include <asm/lmb.h> | ||
39 | #include <asm/abs_addr.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <asm/processor.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/smp.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/mmu.h> | ||
47 | #include <asm/pgtable.h> | ||
48 | #include <asm/pci.h> | ||
49 | #include <asm/iommu.h> | ||
50 | #include <asm/btext.h> | ||
51 | #include <asm/sections.h> | ||
52 | #include <asm/machdep.h> | ||
53 | #include <asm/pSeries_reconfig.h> | ||
54 | |||
55 | #ifdef DEBUG | ||
56 | #define DBG(fmt...) udbg_printf(fmt) | ||
57 | #else | ||
58 | #define DBG(fmt...) | ||
59 | #endif | ||
60 | |||
61 | struct pci_reg_property { | ||
62 | struct pci_address addr; | ||
63 | u32 size_hi; | ||
64 | u32 size_lo; | ||
65 | }; | ||
66 | |||
67 | struct isa_reg_property { | ||
68 | u32 space; | ||
69 | u32 address; | ||
70 | u32 size; | ||
71 | }; | ||
72 | |||
73 | |||
74 | typedef int interpret_func(struct device_node *, unsigned long *, | ||
75 | int, int, int); | ||
76 | |||
77 | extern struct rtas_t rtas; | ||
78 | extern struct lmb lmb; | ||
79 | extern unsigned long klimit; | ||
80 | extern unsigned long memory_limit; | ||
81 | |||
82 | static int __initdata dt_root_addr_cells; | ||
83 | static int __initdata dt_root_size_cells; | ||
84 | static int __initdata iommu_is_off; | ||
85 | int __initdata iommu_force_on; | ||
86 | unsigned long tce_alloc_start, tce_alloc_end; | ||
87 | |||
88 | typedef u32 cell_t; | ||
89 | |||
90 | #if 0 | ||
91 | static struct boot_param_header *initial_boot_params __initdata; | ||
92 | #else | ||
93 | struct boot_param_header *initial_boot_params; | ||
94 | #endif | ||
95 | |||
96 | static struct device_node *allnodes = NULL; | ||
97 | |||
98 | /* use when traversing tree through the allnext, child, sibling, | ||
99 | * or parent members of struct device_node. | ||
100 | */ | ||
101 | static DEFINE_RWLOCK(devtree_lock); | ||
102 | |||
103 | /* export that to outside world */ | ||
104 | struct device_node *of_chosen; | ||
105 | |||
106 | /* | ||
107 | * Wrapper for allocating memory for various data that needs to be | ||
108 | * attached to device nodes as they are processed at boot or when | ||
109 | * added to the device tree later (e.g. DLPAR). At boot there is | ||
110 | * already a region reserved so we just increment *mem_start by size; | ||
111 | * otherwise we call kmalloc. | ||
112 | */ | ||
113 | static void * prom_alloc(unsigned long size, unsigned long *mem_start) | ||
114 | { | ||
115 | unsigned long tmp; | ||
116 | |||
117 | if (!mem_start) | ||
118 | return kmalloc(size, GFP_KERNEL); | ||
119 | |||
120 | tmp = *mem_start; | ||
121 | *mem_start += size; | ||
122 | return (void *)tmp; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Find the device_node with a given phandle. | ||
127 | */ | ||
128 | static struct device_node * find_phandle(phandle ph) | ||
129 | { | ||
130 | struct device_node *np; | ||
131 | |||
132 | for (np = allnodes; np != 0; np = np->allnext) | ||
133 | if (np->linux_phandle == ph) | ||
134 | return np; | ||
135 | return NULL; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Find the interrupt parent of a node. | ||
140 | */ | ||
141 | static struct device_node * __devinit intr_parent(struct device_node *p) | ||
142 | { | ||
143 | phandle *parp; | ||
144 | |||
145 | parp = (phandle *) get_property(p, "interrupt-parent", NULL); | ||
146 | if (parp == NULL) | ||
147 | return p->parent; | ||
148 | return find_phandle(*parp); | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Find out the size of each entry of the interrupts property | ||
153 | * for a node. | ||
154 | */ | ||
155 | int __devinit prom_n_intr_cells(struct device_node *np) | ||
156 | { | ||
157 | struct device_node *p; | ||
158 | unsigned int *icp; | ||
159 | |||
160 | for (p = np; (p = intr_parent(p)) != NULL; ) { | ||
161 | icp = (unsigned int *) | ||
162 | get_property(p, "#interrupt-cells", NULL); | ||
163 | if (icp != NULL) | ||
164 | return *icp; | ||
165 | if (get_property(p, "interrupt-controller", NULL) != NULL | ||
166 | || get_property(p, "interrupt-map", NULL) != NULL) { | ||
167 | printk("oops, node %s doesn't have #interrupt-cells\n", | ||
168 | p->full_name); | ||
169 | return 1; | ||
170 | } | ||
171 | } | ||
172 | #ifdef DEBUG_IRQ | ||
173 | printk("prom_n_intr_cells failed for %s\n", np->full_name); | ||
174 | #endif | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Map an interrupt from a device up to the platform interrupt | ||
180 | * descriptor. | ||
181 | */ | ||
182 | static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, | ||
183 | struct device_node *np, unsigned int *ints, | ||
184 | int nintrc) | ||
185 | { | ||
186 | struct device_node *p, *ipar; | ||
187 | unsigned int *imap, *imask, *ip; | ||
188 | int i, imaplen, match; | ||
189 | int newintrc = 0, newaddrc = 0; | ||
190 | unsigned int *reg; | ||
191 | int naddrc; | ||
192 | |||
193 | reg = (unsigned int *) get_property(np, "reg", NULL); | ||
194 | naddrc = prom_n_addr_cells(np); | ||
195 | p = intr_parent(np); | ||
196 | while (p != NULL) { | ||
197 | if (get_property(p, "interrupt-controller", NULL) != NULL) | ||
198 | /* this node is an interrupt controller, stop here */ | ||
199 | break; | ||
200 | imap = (unsigned int *) | ||
201 | get_property(p, "interrupt-map", &imaplen); | ||
202 | if (imap == NULL) { | ||
203 | p = intr_parent(p); | ||
204 | continue; | ||
205 | } | ||
206 | imask = (unsigned int *) | ||
207 | get_property(p, "interrupt-map-mask", NULL); | ||
208 | if (imask == NULL) { | ||
209 | printk("oops, %s has interrupt-map but no mask\n", | ||
210 | p->full_name); | ||
211 | return 0; | ||
212 | } | ||
213 | imaplen /= sizeof(unsigned int); | ||
214 | match = 0; | ||
215 | ipar = NULL; | ||
216 | while (imaplen > 0 && !match) { | ||
217 | /* check the child-interrupt field */ | ||
218 | match = 1; | ||
219 | for (i = 0; i < naddrc && match; ++i) | ||
220 | match = ((reg[i] ^ imap[i]) & imask[i]) == 0; | ||
221 | for (; i < naddrc + nintrc && match; ++i) | ||
222 | match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; | ||
223 | imap += naddrc + nintrc; | ||
224 | imaplen -= naddrc + nintrc; | ||
225 | /* grab the interrupt parent */ | ||
226 | ipar = find_phandle((phandle) *imap++); | ||
227 | --imaplen; | ||
228 | if (ipar == NULL) { | ||
229 | printk("oops, no int parent %x in map of %s\n", | ||
230 | imap[-1], p->full_name); | ||
231 | return 0; | ||
232 | } | ||
233 | /* find the parent's # addr and intr cells */ | ||
234 | ip = (unsigned int *) | ||
235 | get_property(ipar, "#interrupt-cells", NULL); | ||
236 | if (ip == NULL) { | ||
237 | printk("oops, no #interrupt-cells on %s\n", | ||
238 | ipar->full_name); | ||
239 | return 0; | ||
240 | } | ||
241 | newintrc = *ip; | ||
242 | ip = (unsigned int *) | ||
243 | get_property(ipar, "#address-cells", NULL); | ||
244 | newaddrc = (ip == NULL)? 0: *ip; | ||
245 | imap += newaddrc + newintrc; | ||
246 | imaplen -= newaddrc + newintrc; | ||
247 | } | ||
248 | if (imaplen < 0) { | ||
249 | printk("oops, error decoding int-map on %s, len=%d\n", | ||
250 | p->full_name, imaplen); | ||
251 | return 0; | ||
252 | } | ||
253 | if (!match) { | ||
254 | #ifdef DEBUG_IRQ | ||
255 | printk("oops, no match in %s int-map for %s\n", | ||
256 | p->full_name, np->full_name); | ||
257 | #endif | ||
258 | return 0; | ||
259 | } | ||
260 | p = ipar; | ||
261 | naddrc = newaddrc; | ||
262 | nintrc = newintrc; | ||
263 | ints = imap - nintrc; | ||
264 | reg = ints - naddrc; | ||
265 | } | ||
266 | if (p == NULL) { | ||
267 | #ifdef DEBUG_IRQ | ||
268 | printk("hmmm, int tree for %s doesn't have ctrler\n", | ||
269 | np->full_name); | ||
270 | #endif | ||
271 | return 0; | ||
272 | } | ||
273 | *irq = ints; | ||
274 | *ictrler = p; | ||
275 | return nintrc; | ||
276 | } | ||
277 | |||
278 | static int __devinit finish_node_interrupts(struct device_node *np, | ||
279 | unsigned long *mem_start, | ||
280 | int measure_only) | ||
281 | { | ||
282 | unsigned int *ints; | ||
283 | int intlen, intrcells, intrcount; | ||
284 | int i, j, n; | ||
285 | unsigned int *irq, virq; | ||
286 | struct device_node *ic; | ||
287 | |||
288 | ints = (unsigned int *) get_property(np, "interrupts", &intlen); | ||
289 | if (ints == NULL) | ||
290 | return 0; | ||
291 | intrcells = prom_n_intr_cells(np); | ||
292 | intlen /= intrcells * sizeof(unsigned int); | ||
293 | |||
294 | np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); | ||
295 | if (!np->intrs) | ||
296 | return -ENOMEM; | ||
297 | |||
298 | if (measure_only) | ||
299 | return 0; | ||
300 | |||
301 | intrcount = 0; | ||
302 | for (i = 0; i < intlen; ++i, ints += intrcells) { | ||
303 | n = map_interrupt(&irq, &ic, np, ints, intrcells); | ||
304 | if (n <= 0) | ||
305 | continue; | ||
306 | |||
307 | /* don't map IRQ numbers under a cascaded 8259 controller */ | ||
308 | if (ic && device_is_compatible(ic, "chrp,iic")) { | ||
309 | np->intrs[intrcount].line = irq[0]; | ||
310 | } else { | ||
311 | virq = virt_irq_create_mapping(irq[0]); | ||
312 | if (virq == NO_IRQ) { | ||
313 | printk(KERN_CRIT "Could not allocate interrupt" | ||
314 | " number for %s\n", np->full_name); | ||
315 | continue; | ||
316 | } | ||
317 | np->intrs[intrcount].line = irq_offset_up(virq); | ||
318 | } | ||
319 | |||
320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | ||
321 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { | ||
322 | char *name = get_property(ic->parent, "name", NULL); | ||
323 | if (name && !strcmp(name, "u3")) | ||
324 | np->intrs[intrcount].line += 128; | ||
325 | else if (!(name && !strcmp(name, "mac-io"))) | ||
326 | /* ignore other cascaded controllers, such as | ||
327 | the k2-sata-root */ | ||
328 | break; | ||
329 | } | ||
330 | np->intrs[intrcount].sense = 1; | ||
331 | if (n > 1) | ||
332 | np->intrs[intrcount].sense = irq[1]; | ||
333 | if (n > 2) { | ||
334 | printk("hmmm, got %d intr cells for %s:", n, | ||
335 | np->full_name); | ||
336 | for (j = 0; j < n; ++j) | ||
337 | printk(" %d", irq[j]); | ||
338 | printk("\n"); | ||
339 | } | ||
340 | ++intrcount; | ||
341 | } | ||
342 | np->n_intrs = intrcount; | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int __devinit interpret_pci_props(struct device_node *np, | ||
348 | unsigned long *mem_start, | ||
349 | int naddrc, int nsizec, | ||
350 | int measure_only) | ||
351 | { | ||
352 | struct address_range *adr; | ||
353 | struct pci_reg_property *pci_addrs; | ||
354 | int i, l, n_addrs; | ||
355 | |||
356 | pci_addrs = (struct pci_reg_property *) | ||
357 | get_property(np, "assigned-addresses", &l); | ||
358 | if (!pci_addrs) | ||
359 | return 0; | ||
360 | |||
361 | n_addrs = l / sizeof(*pci_addrs); | ||
362 | |||
363 | adr = prom_alloc(n_addrs * sizeof(*adr), mem_start); | ||
364 | if (!adr) | ||
365 | return -ENOMEM; | ||
366 | |||
367 | if (measure_only) | ||
368 | return 0; | ||
369 | |||
370 | np->addrs = adr; | ||
371 | np->n_addrs = n_addrs; | ||
372 | |||
373 | for (i = 0; i < n_addrs; i++) { | ||
374 | adr[i].space = pci_addrs[i].addr.a_hi; | ||
375 | adr[i].address = pci_addrs[i].addr.a_lo | | ||
376 | ((u64)pci_addrs[i].addr.a_mid << 32); | ||
377 | adr[i].size = pci_addrs[i].size_lo; | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int __init interpret_dbdma_props(struct device_node *np, | ||
384 | unsigned long *mem_start, | ||
385 | int naddrc, int nsizec, | ||
386 | int measure_only) | ||
387 | { | ||
388 | struct reg_property32 *rp; | ||
389 | struct address_range *adr; | ||
390 | unsigned long base_address; | ||
391 | int i, l; | ||
392 | struct device_node *db; | ||
393 | |||
394 | base_address = 0; | ||
395 | if (!measure_only) { | ||
396 | for (db = np->parent; db != NULL; db = db->parent) { | ||
397 | if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { | ||
398 | base_address = db->addrs[0].address; | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
405 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
406 | i = 0; | ||
407 | adr = (struct address_range *) (*mem_start); | ||
408 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
409 | if (!measure_only) { | ||
410 | adr[i].space = 2; | ||
411 | adr[i].address = rp[i].address + base_address; | ||
412 | adr[i].size = rp[i].size; | ||
413 | } | ||
414 | ++i; | ||
415 | } | ||
416 | np->addrs = adr; | ||
417 | np->n_addrs = i; | ||
418 | (*mem_start) += i * sizeof(struct address_range); | ||
419 | } | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int __init interpret_macio_props(struct device_node *np, | ||
425 | unsigned long *mem_start, | ||
426 | int naddrc, int nsizec, | ||
427 | int measure_only) | ||
428 | { | ||
429 | struct reg_property32 *rp; | ||
430 | struct address_range *adr; | ||
431 | unsigned long base_address; | ||
432 | int i, l; | ||
433 | struct device_node *db; | ||
434 | |||
435 | base_address = 0; | ||
436 | if (!measure_only) { | ||
437 | for (db = np->parent; db != NULL; db = db->parent) { | ||
438 | if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { | ||
439 | base_address = db->addrs[0].address; | ||
440 | break; | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | |||
445 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
446 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
447 | i = 0; | ||
448 | adr = (struct address_range *) (*mem_start); | ||
449 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
450 | if (!measure_only) { | ||
451 | adr[i].space = 2; | ||
452 | adr[i].address = rp[i].address + base_address; | ||
453 | adr[i].size = rp[i].size; | ||
454 | } | ||
455 | ++i; | ||
456 | } | ||
457 | np->addrs = adr; | ||
458 | np->n_addrs = i; | ||
459 | (*mem_start) += i * sizeof(struct address_range); | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int __init interpret_isa_props(struct device_node *np, | ||
466 | unsigned long *mem_start, | ||
467 | int naddrc, int nsizec, | ||
468 | int measure_only) | ||
469 | { | ||
470 | struct isa_reg_property *rp; | ||
471 | struct address_range *adr; | ||
472 | int i, l; | ||
473 | |||
474 | rp = (struct isa_reg_property *) get_property(np, "reg", &l); | ||
475 | if (rp != 0 && l >= sizeof(struct isa_reg_property)) { | ||
476 | i = 0; | ||
477 | adr = (struct address_range *) (*mem_start); | ||
478 | while ((l -= sizeof(struct isa_reg_property)) >= 0) { | ||
479 | if (!measure_only) { | ||
480 | adr[i].space = rp[i].space; | ||
481 | adr[i].address = rp[i].address; | ||
482 | adr[i].size = rp[i].size; | ||
483 | } | ||
484 | ++i; | ||
485 | } | ||
486 | np->addrs = adr; | ||
487 | np->n_addrs = i; | ||
488 | (*mem_start) += i * sizeof(struct address_range); | ||
489 | } | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int __init interpret_root_props(struct device_node *np, | ||
495 | unsigned long *mem_start, | ||
496 | int naddrc, int nsizec, | ||
497 | int measure_only) | ||
498 | { | ||
499 | struct address_range *adr; | ||
500 | int i, l; | ||
501 | unsigned int *rp; | ||
502 | int rpsize = (naddrc + nsizec) * sizeof(unsigned int); | ||
503 | |||
504 | rp = (unsigned int *) get_property(np, "reg", &l); | ||
505 | if (rp != 0 && l >= rpsize) { | ||
506 | i = 0; | ||
507 | adr = (struct address_range *) (*mem_start); | ||
508 | while ((l -= rpsize) >= 0) { | ||
509 | if (!measure_only) { | ||
510 | adr[i].space = 0; | ||
511 | adr[i].address = rp[naddrc - 1]; | ||
512 | adr[i].size = rp[naddrc + nsizec - 1]; | ||
513 | } | ||
514 | ++i; | ||
515 | rp += naddrc + nsizec; | ||
516 | } | ||
517 | np->addrs = adr; | ||
518 | np->n_addrs = i; | ||
519 | (*mem_start) += i * sizeof(struct address_range); | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int __devinit finish_node(struct device_node *np, | ||
526 | unsigned long *mem_start, | ||
527 | interpret_func *ifunc, | ||
528 | int naddrc, int nsizec, | ||
529 | int measure_only) | ||
530 | { | ||
531 | struct device_node *child; | ||
532 | int *ip, rc = 0; | ||
533 | |||
534 | /* get the device addresses and interrupts */ | ||
535 | if (ifunc != NULL) | ||
536 | rc = ifunc(np, mem_start, naddrc, nsizec, measure_only); | ||
537 | if (rc) | ||
538 | goto out; | ||
539 | |||
540 | rc = finish_node_interrupts(np, mem_start, measure_only); | ||
541 | if (rc) | ||
542 | goto out; | ||
543 | |||
544 | /* Look for #address-cells and #size-cells properties. */ | ||
545 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
546 | if (ip != NULL) | ||
547 | naddrc = *ip; | ||
548 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
549 | if (ip != NULL) | ||
550 | nsizec = *ip; | ||
551 | |||
552 | if (!strcmp(np->name, "device-tree") || np->parent == NULL) | ||
553 | ifunc = interpret_root_props; | ||
554 | else if (np->type == 0) | ||
555 | ifunc = NULL; | ||
556 | else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) | ||
557 | ifunc = interpret_pci_props; | ||
558 | else if (!strcmp(np->type, "dbdma")) | ||
559 | ifunc = interpret_dbdma_props; | ||
560 | else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) | ||
561 | ifunc = interpret_macio_props; | ||
562 | else if (!strcmp(np->type, "isa")) | ||
563 | ifunc = interpret_isa_props; | ||
564 | else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) | ||
565 | ifunc = interpret_root_props; | ||
566 | else if (!((ifunc == interpret_dbdma_props | ||
567 | || ifunc == interpret_macio_props) | ||
568 | && (!strcmp(np->type, "escc") | ||
569 | || !strcmp(np->type, "media-bay")))) | ||
570 | ifunc = NULL; | ||
571 | |||
572 | for (child = np->child; child != NULL; child = child->sibling) { | ||
573 | rc = finish_node(child, mem_start, ifunc, | ||
574 | naddrc, nsizec, measure_only); | ||
575 | if (rc) | ||
576 | goto out; | ||
577 | } | ||
578 | out: | ||
579 | return rc; | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * finish_device_tree is called once things are running normally | ||
584 | * (i.e. with text and data mapped to the address they were linked at). | ||
585 | * It traverses the device tree and fills in some of the additional, | ||
586 | * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt | ||
587 | * mapping is also initialized at this point. | ||
588 | */ | ||
589 | void __init finish_device_tree(void) | ||
590 | { | ||
591 | unsigned long start, end, size = 0; | ||
592 | |||
593 | DBG(" -> finish_device_tree\n"); | ||
594 | |||
595 | if (ppc64_interrupt_controller == IC_INVALID) { | ||
596 | DBG("failed to configure interrupt controller type\n"); | ||
597 | panic("failed to configure interrupt controller type\n"); | ||
598 | } | ||
599 | |||
600 | /* Initialize virtual IRQ map */ | ||
601 | virt_irq_init(); | ||
602 | |||
603 | /* | ||
604 | * Finish device-tree (pre-parsing some properties etc...) | ||
605 | * We do this in 2 passes. One with "measure_only" set, which | ||
606 | * will only measure the amount of memory needed, then we can | ||
607 | * allocate that memory, and call finish_node again. However, | ||
608 | * we must be careful as most routines will fail nowadays when | ||
609 | * prom_alloc() returns 0, so we must make sure our first pass | ||
610 | * doesn't start at 0. We pre-initialize size to 16 for that | ||
611 | * reason and then remove those additional 16 bytes | ||
612 | */ | ||
613 | size = 16; | ||
614 | finish_node(allnodes, &size, NULL, 0, 0, 1); | ||
615 | size -= 16; | ||
616 | end = start = (unsigned long)abs_to_virt(lmb_alloc(size, 128)); | ||
617 | finish_node(allnodes, &end, NULL, 0, 0, 0); | ||
618 | BUG_ON(end != start + size); | ||
619 | |||
620 | DBG(" <- finish_device_tree\n"); | ||
621 | } | ||
622 | |||
623 | #ifdef DEBUG | ||
624 | #define printk udbg_printf | ||
625 | #endif | ||
626 | |||
627 | static inline char *find_flat_dt_string(u32 offset) | ||
628 | { | ||
629 | return ((char *)initial_boot_params) + | ||
630 | initial_boot_params->off_dt_strings + offset; | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * This function is used to scan the flattened device-tree, it is | ||
635 | * used to extract the memory informations at boot before we can | ||
636 | * unflatten the tree | ||
637 | */ | ||
638 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
639 | const char *uname, int depth, | ||
640 | void *data), | ||
641 | void *data) | ||
642 | { | ||
643 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
644 | initial_boot_params->off_dt_struct; | ||
645 | int rc = 0; | ||
646 | int depth = -1; | ||
647 | |||
648 | do { | ||
649 | u32 tag = *((u32 *)p); | ||
650 | char *pathp; | ||
651 | |||
652 | p += 4; | ||
653 | if (tag == OF_DT_END_NODE) { | ||
654 | depth --; | ||
655 | continue; | ||
656 | } | ||
657 | if (tag == OF_DT_NOP) | ||
658 | continue; | ||
659 | if (tag == OF_DT_END) | ||
660 | break; | ||
661 | if (tag == OF_DT_PROP) { | ||
662 | u32 sz = *((u32 *)p); | ||
663 | p += 8; | ||
664 | if (initial_boot_params->version < 0x10) | ||
665 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
666 | p += sz; | ||
667 | p = _ALIGN(p, 4); | ||
668 | continue; | ||
669 | } | ||
670 | if (tag != OF_DT_BEGIN_NODE) { | ||
671 | printk(KERN_WARNING "Invalid tag %x scanning flattened" | ||
672 | " device tree !\n", tag); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | depth++; | ||
676 | pathp = (char *)p; | ||
677 | p = _ALIGN(p + strlen(pathp) + 1, 4); | ||
678 | if ((*pathp) == '/') { | ||
679 | char *lp, *np; | ||
680 | for (lp = NULL, np = pathp; *np; np++) | ||
681 | if ((*np) == '/') | ||
682 | lp = np+1; | ||
683 | if (lp != NULL) | ||
684 | pathp = lp; | ||
685 | } | ||
686 | rc = it(p, pathp, depth, data); | ||
687 | if (rc != 0) | ||
688 | break; | ||
689 | } while(1); | ||
690 | |||
691 | return rc; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * This function can be used within scan_flattened_dt callback to get | ||
696 | * access to properties | ||
697 | */ | ||
698 | void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
699 | unsigned long *size) | ||
700 | { | ||
701 | unsigned long p = node; | ||
702 | |||
703 | do { | ||
704 | u32 tag = *((u32 *)p); | ||
705 | u32 sz, noff; | ||
706 | const char *nstr; | ||
707 | |||
708 | p += 4; | ||
709 | if (tag == OF_DT_NOP) | ||
710 | continue; | ||
711 | if (tag != OF_DT_PROP) | ||
712 | return NULL; | ||
713 | |||
714 | sz = *((u32 *)p); | ||
715 | noff = *((u32 *)(p + 4)); | ||
716 | p += 8; | ||
717 | if (initial_boot_params->version < 0x10) | ||
718 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
719 | |||
720 | nstr = find_flat_dt_string(noff); | ||
721 | if (nstr == NULL) { | ||
722 | printk(KERN_WARNING "Can't find property index" | ||
723 | " name !\n"); | ||
724 | return NULL; | ||
725 | } | ||
726 | if (strcmp(name, nstr) == 0) { | ||
727 | if (size) | ||
728 | *size = sz; | ||
729 | return (void *)p; | ||
730 | } | ||
731 | p += sz; | ||
732 | p = _ALIGN(p, 4); | ||
733 | } while(1); | ||
734 | } | ||
735 | |||
736 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | ||
737 | unsigned long align) | ||
738 | { | ||
739 | void *res; | ||
740 | |||
741 | *mem = _ALIGN(*mem, align); | ||
742 | res = (void *)*mem; | ||
743 | *mem += size; | ||
744 | |||
745 | return res; | ||
746 | } | ||
747 | |||
748 | static unsigned long __init unflatten_dt_node(unsigned long mem, | ||
749 | unsigned long *p, | ||
750 | struct device_node *dad, | ||
751 | struct device_node ***allnextpp, | ||
752 | unsigned long fpsize) | ||
753 | { | ||
754 | struct device_node *np; | ||
755 | struct property *pp, **prev_pp = NULL; | ||
756 | char *pathp; | ||
757 | u32 tag; | ||
758 | unsigned int l, allocl; | ||
759 | int has_name = 0; | ||
760 | int new_format = 0; | ||
761 | |||
762 | tag = *((u32 *)(*p)); | ||
763 | if (tag != OF_DT_BEGIN_NODE) { | ||
764 | printk("Weird tag at start of node: %x\n", tag); | ||
765 | return mem; | ||
766 | } | ||
767 | *p += 4; | ||
768 | pathp = (char *)*p; | ||
769 | l = allocl = strlen(pathp) + 1; | ||
770 | *p = _ALIGN(*p + l, 4); | ||
771 | |||
772 | /* version 0x10 has a more compact unit name here instead of the full | ||
773 | * path. we accumulate the full path size using "fpsize", we'll rebuild | ||
774 | * it later. We detect this because the first character of the name is | ||
775 | * not '/'. | ||
776 | */ | ||
777 | if ((*pathp) != '/') { | ||
778 | new_format = 1; | ||
779 | if (fpsize == 0) { | ||
780 | /* root node: special case. fpsize accounts for path | ||
781 | * plus terminating zero. root node only has '/', so | ||
782 | * fpsize should be 2, but we want to avoid the first | ||
783 | * level nodes to have two '/' so we use fpsize 1 here | ||
784 | */ | ||
785 | fpsize = 1; | ||
786 | allocl = 2; | ||
787 | } else { | ||
788 | /* account for '/' and path size minus terminal 0 | ||
789 | * already in 'l' | ||
790 | */ | ||
791 | fpsize += l; | ||
792 | allocl = fpsize; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | |||
797 | np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, | ||
798 | __alignof__(struct device_node)); | ||
799 | if (allnextpp) { | ||
800 | memset(np, 0, sizeof(*np)); | ||
801 | np->full_name = ((char*)np) + sizeof(struct device_node); | ||
802 | if (new_format) { | ||
803 | char *p = np->full_name; | ||
804 | /* rebuild full path for new format */ | ||
805 | if (dad && dad->parent) { | ||
806 | strcpy(p, dad->full_name); | ||
807 | #ifdef DEBUG | ||
808 | if ((strlen(p) + l + 1) != allocl) { | ||
809 | DBG("%s: p: %d, l: %d, a: %d\n", | ||
810 | pathp, strlen(p), l, allocl); | ||
811 | } | ||
812 | #endif | ||
813 | p += strlen(p); | ||
814 | } | ||
815 | *(p++) = '/'; | ||
816 | memcpy(p, pathp, l); | ||
817 | } else | ||
818 | memcpy(np->full_name, pathp, l); | ||
819 | prev_pp = &np->properties; | ||
820 | **allnextpp = np; | ||
821 | *allnextpp = &np->allnext; | ||
822 | if (dad != NULL) { | ||
823 | np->parent = dad; | ||
824 | /* we temporarily use the next field as `last_child'*/ | ||
825 | if (dad->next == 0) | ||
826 | dad->child = np; | ||
827 | else | ||
828 | dad->next->sibling = np; | ||
829 | dad->next = np; | ||
830 | } | ||
831 | kref_init(&np->kref); | ||
832 | } | ||
833 | while(1) { | ||
834 | u32 sz, noff; | ||
835 | char *pname; | ||
836 | |||
837 | tag = *((u32 *)(*p)); | ||
838 | if (tag == OF_DT_NOP) { | ||
839 | *p += 4; | ||
840 | continue; | ||
841 | } | ||
842 | if (tag != OF_DT_PROP) | ||
843 | break; | ||
844 | *p += 4; | ||
845 | sz = *((u32 *)(*p)); | ||
846 | noff = *((u32 *)((*p) + 4)); | ||
847 | *p += 8; | ||
848 | if (initial_boot_params->version < 0x10) | ||
849 | *p = _ALIGN(*p, sz >= 8 ? 8 : 4); | ||
850 | |||
851 | pname = find_flat_dt_string(noff); | ||
852 | if (pname == NULL) { | ||
853 | printk("Can't find property name in list !\n"); | ||
854 | break; | ||
855 | } | ||
856 | if (strcmp(pname, "name") == 0) | ||
857 | has_name = 1; | ||
858 | l = strlen(pname) + 1; | ||
859 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | ||
860 | __alignof__(struct property)); | ||
861 | if (allnextpp) { | ||
862 | if (strcmp(pname, "linux,phandle") == 0) { | ||
863 | np->node = *((u32 *)*p); | ||
864 | if (np->linux_phandle == 0) | ||
865 | np->linux_phandle = np->node; | ||
866 | } | ||
867 | if (strcmp(pname, "ibm,phandle") == 0) | ||
868 | np->linux_phandle = *((u32 *)*p); | ||
869 | pp->name = pname; | ||
870 | pp->length = sz; | ||
871 | pp->value = (void *)*p; | ||
872 | *prev_pp = pp; | ||
873 | prev_pp = &pp->next; | ||
874 | } | ||
875 | *p = _ALIGN((*p) + sz, 4); | ||
876 | } | ||
877 | /* with version 0x10 we may not have the name property, recreate | ||
878 | * it here from the unit name if absent | ||
879 | */ | ||
880 | if (!has_name) { | ||
881 | char *p = pathp, *ps = pathp, *pa = NULL; | ||
882 | int sz; | ||
883 | |||
884 | while (*p) { | ||
885 | if ((*p) == '@') | ||
886 | pa = p; | ||
887 | if ((*p) == '/') | ||
888 | ps = p + 1; | ||
889 | p++; | ||
890 | } | ||
891 | if (pa < ps) | ||
892 | pa = p; | ||
893 | sz = (pa - ps) + 1; | ||
894 | pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, | ||
895 | __alignof__(struct property)); | ||
896 | if (allnextpp) { | ||
897 | pp->name = "name"; | ||
898 | pp->length = sz; | ||
899 | pp->value = (unsigned char *)(pp + 1); | ||
900 | *prev_pp = pp; | ||
901 | prev_pp = &pp->next; | ||
902 | memcpy(pp->value, ps, sz - 1); | ||
903 | ((char *)pp->value)[sz - 1] = 0; | ||
904 | DBG("fixed up name for %s -> %s\n", pathp, pp->value); | ||
905 | } | ||
906 | } | ||
907 | if (allnextpp) { | ||
908 | *prev_pp = NULL; | ||
909 | np->name = get_property(np, "name", NULL); | ||
910 | np->type = get_property(np, "device_type", NULL); | ||
911 | |||
912 | if (!np->name) | ||
913 | np->name = "<NULL>"; | ||
914 | if (!np->type) | ||
915 | np->type = "<NULL>"; | ||
916 | } | ||
917 | while (tag == OF_DT_BEGIN_NODE) { | ||
918 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | ||
919 | tag = *((u32 *)(*p)); | ||
920 | } | ||
921 | if (tag != OF_DT_END_NODE) { | ||
922 | printk("Weird tag at end of node: %x\n", tag); | ||
923 | return mem; | ||
924 | } | ||
925 | *p += 4; | ||
926 | return mem; | ||
927 | } | ||
928 | |||
929 | |||
930 | /** | ||
931 | * unflattens the device-tree passed by the firmware, creating the | ||
932 | * tree of struct device_node. It also fills the "name" and "type" | ||
933 | * pointers of the nodes so the normal device-tree walking functions | ||
934 | * can be used (this used to be done by finish_device_tree) | ||
935 | */ | ||
936 | void __init unflatten_device_tree(void) | ||
937 | { | ||
938 | unsigned long start, mem, size; | ||
939 | struct device_node **allnextp = &allnodes; | ||
940 | char *p = NULL; | ||
941 | int l = 0; | ||
942 | |||
943 | DBG(" -> unflatten_device_tree()\n"); | ||
944 | |||
945 | /* First pass, scan for size */ | ||
946 | start = ((unsigned long)initial_boot_params) + | ||
947 | initial_boot_params->off_dt_struct; | ||
948 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
949 | size = (size | 3) + 1; | ||
950 | |||
951 | DBG(" size is %lx, allocating...\n", size); | ||
952 | |||
953 | /* Allocate memory for the expanded device tree */ | ||
954 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); | ||
955 | if (!mem) { | ||
956 | DBG("Couldn't allocate memory with lmb_alloc()!\n"); | ||
957 | panic("Couldn't allocate memory with lmb_alloc()!\n"); | ||
958 | } | ||
959 | mem = (unsigned long)abs_to_virt(mem); | ||
960 | |||
961 | ((u32 *)mem)[size / 4] = 0xdeadbeef; | ||
962 | |||
963 | DBG(" unflattening...\n", mem); | ||
964 | |||
965 | /* Second pass, do actual unflattening */ | ||
966 | start = ((unsigned long)initial_boot_params) + | ||
967 | initial_boot_params->off_dt_struct; | ||
968 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
969 | if (*((u32 *)start) != OF_DT_END) | ||
970 | printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
971 | if (((u32 *)mem)[size / 4] != 0xdeadbeef) | ||
972 | printk(KERN_WARNING "End of tree marker overwritten: %08x\n", | ||
973 | ((u32 *)mem)[size / 4] ); | ||
974 | *allnextp = NULL; | ||
975 | |||
976 | /* Get pointer to OF "/chosen" node for use everywhere */ | ||
977 | of_chosen = of_find_node_by_path("/chosen"); | ||
978 | |||
979 | /* Retreive command line */ | ||
980 | if (of_chosen != NULL) { | ||
981 | p = (char *)get_property(of_chosen, "bootargs", &l); | ||
982 | if (p != NULL && l > 0) | ||
983 | strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE)); | ||
984 | } | ||
985 | #ifdef CONFIG_CMDLINE | ||
986 | if (l == 0 || (l == 1 && (*p) == 0)) | ||
987 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | ||
988 | #endif /* CONFIG_CMDLINE */ | ||
989 | |||
990 | DBG("Command line is: %s\n", cmd_line); | ||
991 | |||
992 | DBG(" <- unflatten_device_tree()\n"); | ||
993 | } | ||
994 | |||
995 | |||
996 | static int __init early_init_dt_scan_cpus(unsigned long node, | ||
997 | const char *uname, int depth, void *data) | ||
998 | { | ||
999 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1000 | u32 *prop; | ||
1001 | unsigned long size; | ||
1002 | |||
1003 | /* We are scanning "cpu" nodes only */ | ||
1004 | if (type == NULL || strcmp(type, "cpu") != 0) | ||
1005 | return 0; | ||
1006 | |||
1007 | if (initial_boot_params && initial_boot_params->version >= 2) { | ||
1008 | /* version 2 of the kexec param format adds the phys cpuid | ||
1009 | * of booted proc. | ||
1010 | */ | ||
1011 | boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; | ||
1012 | boot_cpuid = 0; | ||
1013 | } else { | ||
1014 | /* Check if it's the boot-cpu, set it's hw index in paca now */ | ||
1015 | if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) | ||
1016 | != NULL) { | ||
1017 | u32 *prop = of_get_flat_dt_prop(node, "reg", NULL); | ||
1018 | set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); | ||
1019 | boot_cpuid_phys = get_hard_smp_processor_id(0); | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | #ifdef CONFIG_ALTIVEC | ||
1024 | /* Check if we have a VMX and eventually update CPU features */ | ||
1025 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); | ||
1026 | if (prop && (*prop) > 0) { | ||
1027 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | ||
1028 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | ||
1029 | } | ||
1030 | |||
1031 | /* Same goes for Apple's "altivec" property */ | ||
1032 | prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); | ||
1033 | if (prop) { | ||
1034 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | ||
1035 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | ||
1036 | } | ||
1037 | #endif /* CONFIG_ALTIVEC */ | ||
1038 | |||
1039 | /* | ||
1040 | * Check for an SMT capable CPU and set the CPU feature. We do | ||
1041 | * this by looking at the size of the ibm,ppc-interrupt-server#s | ||
1042 | * property | ||
1043 | */ | ||
1044 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | ||
1045 | &size); | ||
1046 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
1047 | if (prop && ((size / sizeof(u32)) > 1)) | ||
1048 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | ||
1049 | |||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1053 | static int __init early_init_dt_scan_chosen(unsigned long node, | ||
1054 | const char *uname, int depth, void *data) | ||
1055 | { | ||
1056 | u32 *prop; | ||
1057 | u64 *prop64; | ||
1058 | |||
1059 | DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | ||
1060 | |||
1061 | if (depth != 1 || strcmp(uname, "chosen") != 0) | ||
1062 | return 0; | ||
1063 | |||
1064 | /* get platform type */ | ||
1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | ||
1066 | if (prop == NULL) | ||
1067 | return 0; | ||
1068 | _machine = *prop; | ||
1069 | |||
1070 | /* check if iommu is forced on or off */ | ||
1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | ||
1072 | iommu_is_off = 1; | ||
1073 | if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) | ||
1074 | iommu_force_on = 1; | ||
1075 | |||
1076 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL); | ||
1077 | if (prop64) | ||
1078 | memory_limit = *prop64; | ||
1079 | |||
1080 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL); | ||
1081 | if (prop64) | ||
1082 | tce_alloc_start = *prop64; | ||
1083 | |||
1084 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); | ||
1085 | if (prop64) | ||
1086 | tce_alloc_end = *prop64; | ||
1087 | |||
1088 | #ifdef CONFIG_PPC_RTAS | ||
1089 | /* To help early debugging via the front panel, we retreive a minimal | ||
1090 | * set of RTAS infos now if available | ||
1091 | */ | ||
1092 | { | ||
1093 | u64 *basep, *entryp; | ||
1094 | |||
1095 | basep = (u64*)of_get_flat_dt_prop(node, | ||
1096 | "linux,rtas-base", NULL); | ||
1097 | entryp = (u64*)of_get_flat_dt_prop(node, | ||
1098 | "linux,rtas-entry", NULL); | ||
1099 | prop = (u32*)of_get_flat_dt_prop(node, | ||
1100 | "linux,rtas-size", NULL); | ||
1101 | if (basep && entryp && prop) { | ||
1102 | rtas.base = *basep; | ||
1103 | rtas.entry = *entryp; | ||
1104 | rtas.size = *prop; | ||
1105 | } | ||
1106 | } | ||
1107 | #endif /* CONFIG_PPC_RTAS */ | ||
1108 | |||
1109 | /* break now */ | ||
1110 | return 1; | ||
1111 | } | ||
1112 | |||
1113 | static int __init early_init_dt_scan_root(unsigned long node, | ||
1114 | const char *uname, int depth, void *data) | ||
1115 | { | ||
1116 | u32 *prop; | ||
1117 | |||
1118 | if (depth != 0) | ||
1119 | return 0; | ||
1120 | |||
1121 | prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL); | ||
1122 | dt_root_size_cells = (prop == NULL) ? 1 : *prop; | ||
1123 | DBG("dt_root_size_cells = %x\n", dt_root_size_cells); | ||
1124 | |||
1125 | prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL); | ||
1126 | dt_root_addr_cells = (prop == NULL) ? 2 : *prop; | ||
1127 | DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); | ||
1128 | |||
1129 | /* break now */ | ||
1130 | return 1; | ||
1131 | } | ||
1132 | |||
1133 | static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) | ||
1134 | { | ||
1135 | cell_t *p = *cellp; | ||
1136 | unsigned long r = 0; | ||
1137 | |||
1138 | /* Ignore more than 2 cells */ | ||
1139 | while (s > 2) { | ||
1140 | p++; | ||
1141 | s--; | ||
1142 | } | ||
1143 | while (s) { | ||
1144 | r <<= 32; | ||
1145 | r |= *(p++); | ||
1146 | s--; | ||
1147 | } | ||
1148 | |||
1149 | *cellp = p; | ||
1150 | return r; | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | static int __init early_init_dt_scan_memory(unsigned long node, | ||
1155 | const char *uname, int depth, void *data) | ||
1156 | { | ||
1157 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1158 | cell_t *reg, *endp; | ||
1159 | unsigned long l; | ||
1160 | |||
1161 | /* We are scanning "memory" nodes only */ | ||
1162 | if (type == NULL || strcmp(type, "memory") != 0) | ||
1163 | return 0; | ||
1164 | |||
1165 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | ||
1166 | if (reg == NULL) | ||
1167 | return 0; | ||
1168 | |||
1169 | endp = reg + (l / sizeof(cell_t)); | ||
1170 | |||
1171 | DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n", | ||
1172 | uname, l, reg[0], reg[1], reg[2], reg[3]); | ||
1173 | |||
1174 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { | ||
1175 | unsigned long base, size; | ||
1176 | |||
1177 | base = dt_mem_next_cell(dt_root_addr_cells, ®); | ||
1178 | size = dt_mem_next_cell(dt_root_size_cells, ®); | ||
1179 | |||
1180 | if (size == 0) | ||
1181 | continue; | ||
1182 | DBG(" - %lx , %lx\n", base, size); | ||
1183 | if (iommu_is_off) { | ||
1184 | if (base >= 0x80000000ul) | ||
1185 | continue; | ||
1186 | if ((base + size) > 0x80000000ul) | ||
1187 | size = 0x80000000ul - base; | ||
1188 | } | ||
1189 | lmb_add(base, size); | ||
1190 | } | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | static void __init early_reserve_mem(void) | ||
1195 | { | ||
1196 | u64 base, size; | ||
1197 | u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) + | ||
1198 | initial_boot_params->off_mem_rsvmap); | ||
1199 | while (1) { | ||
1200 | base = *(reserve_map++); | ||
1201 | size = *(reserve_map++); | ||
1202 | if (size == 0) | ||
1203 | break; | ||
1204 | DBG("reserving: %lx -> %lx\n", base, size); | ||
1205 | lmb_reserve(base, size); | ||
1206 | } | ||
1207 | |||
1208 | #if 0 | ||
1209 | DBG("memory reserved, lmbs :\n"); | ||
1210 | lmb_dump_all(); | ||
1211 | #endif | ||
1212 | } | ||
1213 | |||
1214 | void __init early_init_devtree(void *params) | ||
1215 | { | ||
1216 | DBG(" -> early_init_devtree()\n"); | ||
1217 | |||
1218 | /* Setup flat device-tree pointer */ | ||
1219 | initial_boot_params = params; | ||
1220 | |||
1221 | /* Retreive various informations from the /chosen node of the | ||
1222 | * device-tree, including the platform type, initrd location and | ||
1223 | * size, TCE reserve, and more ... | ||
1224 | */ | ||
1225 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); | ||
1226 | |||
1227 | /* Scan memory nodes and rebuild LMBs */ | ||
1228 | lmb_init(); | ||
1229 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
1231 | lmb_enforce_memory_limit(memory_limit); | ||
1232 | lmb_analyze(); | ||
1233 | lmb_reserve(0, __pa(klimit)); | ||
1234 | |||
1235 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | ||
1236 | early_reserve_mem(); | ||
1237 | |||
1238 | DBG("Scanning CPUs ...\n"); | ||
1239 | |||
1240 | /* Retreive hash table size from flattened tree plus other | ||
1241 | * CPU related informations (altivec support, boot CPU ID, ...) | ||
1242 | */ | ||
1243 | of_scan_flat_dt(early_init_dt_scan_cpus, NULL); | ||
1244 | |||
1245 | DBG(" <- early_init_devtree()\n"); | ||
1246 | } | ||
1247 | |||
1248 | #undef printk | ||
1249 | |||
1250 | int | ||
1251 | prom_n_addr_cells(struct device_node* np) | ||
1252 | { | ||
1253 | int* ip; | ||
1254 | do { | ||
1255 | if (np->parent) | ||
1256 | np = np->parent; | ||
1257 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
1258 | if (ip != NULL) | ||
1259 | return *ip; | ||
1260 | } while (np->parent); | ||
1261 | /* No #address-cells property for the root node, default to 1 */ | ||
1262 | return 1; | ||
1263 | } | ||
1264 | |||
1265 | int | ||
1266 | prom_n_size_cells(struct device_node* np) | ||
1267 | { | ||
1268 | int* ip; | ||
1269 | do { | ||
1270 | if (np->parent) | ||
1271 | np = np->parent; | ||
1272 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
1273 | if (ip != NULL) | ||
1274 | return *ip; | ||
1275 | } while (np->parent); | ||
1276 | /* No #size-cells property for the root node, default to 1 */ | ||
1277 | return 1; | ||
1278 | } | ||
1279 | |||
1280 | /** | ||
1281 | * Work out the sense (active-low level / active-high edge) | ||
1282 | * of each interrupt from the device tree. | ||
1283 | */ | ||
1284 | void __init prom_get_irq_senses(unsigned char *senses, int off, int max) | ||
1285 | { | ||
1286 | struct device_node *np; | ||
1287 | int i, j; | ||
1288 | |||
1289 | /* default to level-triggered */ | ||
1290 | memset(senses, 1, max - off); | ||
1291 | |||
1292 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1293 | for (j = 0; j < np->n_intrs; j++) { | ||
1294 | i = np->intrs[j].line; | ||
1295 | if (i >= off && i < max) | ||
1296 | senses[i-off] = np->intrs[j].sense ? | ||
1297 | IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE : | ||
1298 | IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE; | ||
1299 | } | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | /** | ||
1304 | * Construct and return a list of the device_nodes with a given name. | ||
1305 | */ | ||
1306 | struct device_node * | ||
1307 | find_devices(const char *name) | ||
1308 | { | ||
1309 | struct device_node *head, **prevp, *np; | ||
1310 | |||
1311 | prevp = &head; | ||
1312 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1313 | if (np->name != 0 && strcasecmp(np->name, name) == 0) { | ||
1314 | *prevp = np; | ||
1315 | prevp = &np->next; | ||
1316 | } | ||
1317 | } | ||
1318 | *prevp = NULL; | ||
1319 | return head; | ||
1320 | } | ||
1321 | EXPORT_SYMBOL(find_devices); | ||
1322 | |||
1323 | /** | ||
1324 | * Construct and return a list of the device_nodes with a given type. | ||
1325 | */ | ||
1326 | struct device_node * | ||
1327 | find_type_devices(const char *type) | ||
1328 | { | ||
1329 | struct device_node *head, **prevp, *np; | ||
1330 | |||
1331 | prevp = &head; | ||
1332 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1333 | if (np->type != 0 && strcasecmp(np->type, type) == 0) { | ||
1334 | *prevp = np; | ||
1335 | prevp = &np->next; | ||
1336 | } | ||
1337 | } | ||
1338 | *prevp = NULL; | ||
1339 | return head; | ||
1340 | } | ||
1341 | EXPORT_SYMBOL(find_type_devices); | ||
1342 | |||
1343 | /** | ||
1344 | * Returns all nodes linked together | ||
1345 | */ | ||
1346 | struct device_node * | ||
1347 | find_all_nodes(void) | ||
1348 | { | ||
1349 | struct device_node *head, **prevp, *np; | ||
1350 | |||
1351 | prevp = &head; | ||
1352 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1353 | *prevp = np; | ||
1354 | prevp = &np->next; | ||
1355 | } | ||
1356 | *prevp = NULL; | ||
1357 | return head; | ||
1358 | } | ||
1359 | EXPORT_SYMBOL(find_all_nodes); | ||
1360 | |||
1361 | /** Checks if the given "compat" string matches one of the strings in | ||
1362 | * the device's "compatible" property | ||
1363 | */ | ||
1364 | int | ||
1365 | device_is_compatible(struct device_node *device, const char *compat) | ||
1366 | { | ||
1367 | const char* cp; | ||
1368 | int cplen, l; | ||
1369 | |||
1370 | cp = (char *) get_property(device, "compatible", &cplen); | ||
1371 | if (cp == NULL) | ||
1372 | return 0; | ||
1373 | while (cplen > 0) { | ||
1374 | if (strncasecmp(cp, compat, strlen(compat)) == 0) | ||
1375 | return 1; | ||
1376 | l = strlen(cp) + 1; | ||
1377 | cp += l; | ||
1378 | cplen -= l; | ||
1379 | } | ||
1380 | |||
1381 | return 0; | ||
1382 | } | ||
1383 | EXPORT_SYMBOL(device_is_compatible); | ||
1384 | |||
1385 | |||
1386 | /** | ||
1387 | * Indicates whether the root node has a given value in its | ||
1388 | * compatible property. | ||
1389 | */ | ||
1390 | int | ||
1391 | machine_is_compatible(const char *compat) | ||
1392 | { | ||
1393 | struct device_node *root; | ||
1394 | int rc = 0; | ||
1395 | |||
1396 | root = of_find_node_by_path("/"); | ||
1397 | if (root) { | ||
1398 | rc = device_is_compatible(root, compat); | ||
1399 | of_node_put(root); | ||
1400 | } | ||
1401 | return rc; | ||
1402 | } | ||
1403 | EXPORT_SYMBOL(machine_is_compatible); | ||
1404 | |||
1405 | /** | ||
1406 | * Construct and return a list of the device_nodes with a given type | ||
1407 | * and compatible property. | ||
1408 | */ | ||
1409 | struct device_node * | ||
1410 | find_compatible_devices(const char *type, const char *compat) | ||
1411 | { | ||
1412 | struct device_node *head, **prevp, *np; | ||
1413 | |||
1414 | prevp = &head; | ||
1415 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1416 | if (type != NULL | ||
1417 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1418 | continue; | ||
1419 | if (device_is_compatible(np, compat)) { | ||
1420 | *prevp = np; | ||
1421 | prevp = &np->next; | ||
1422 | } | ||
1423 | } | ||
1424 | *prevp = NULL; | ||
1425 | return head; | ||
1426 | } | ||
1427 | EXPORT_SYMBOL(find_compatible_devices); | ||
1428 | |||
1429 | /** | ||
1430 | * Find the device_node with a given full_name. | ||
1431 | */ | ||
1432 | struct device_node * | ||
1433 | find_path_device(const char *path) | ||
1434 | { | ||
1435 | struct device_node *np; | ||
1436 | |||
1437 | for (np = allnodes; np != 0; np = np->allnext) | ||
1438 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) | ||
1439 | return np; | ||
1440 | return NULL; | ||
1441 | } | ||
1442 | EXPORT_SYMBOL(find_path_device); | ||
1443 | |||
1444 | /******* | ||
1445 | * | ||
1446 | * New implementation of the OF "find" APIs, return a refcounted | ||
1447 | * object, call of_node_put() when done. The device tree and list | ||
1448 | * are protected by a rw_lock. | ||
1449 | * | ||
1450 | * Note that property management will need some locking as well, | ||
1451 | * this isn't dealt with yet. | ||
1452 | * | ||
1453 | *******/ | ||
1454 | |||
1455 | /** | ||
1456 | * of_find_node_by_name - Find a node by its "name" property | ||
1457 | * @from: The node to start searching from or NULL, the node | ||
1458 | * you pass will not be searched, only the next one | ||
1459 | * will; typically, you pass what the previous call | ||
1460 | * returned. of_node_put() will be called on it | ||
1461 | * @name: The name string to match against | ||
1462 | * | ||
1463 | * Returns a node pointer with refcount incremented, use | ||
1464 | * of_node_put() on it when done. | ||
1465 | */ | ||
1466 | struct device_node *of_find_node_by_name(struct device_node *from, | ||
1467 | const char *name) | ||
1468 | { | ||
1469 | struct device_node *np; | ||
1470 | |||
1471 | read_lock(&devtree_lock); | ||
1472 | np = from ? from->allnext : allnodes; | ||
1473 | for (; np != 0; np = np->allnext) | ||
1474 | if (np->name != 0 && strcasecmp(np->name, name) == 0 | ||
1475 | && of_node_get(np)) | ||
1476 | break; | ||
1477 | if (from) | ||
1478 | of_node_put(from); | ||
1479 | read_unlock(&devtree_lock); | ||
1480 | return np; | ||
1481 | } | ||
1482 | EXPORT_SYMBOL(of_find_node_by_name); | ||
1483 | |||
1484 | /** | ||
1485 | * of_find_node_by_type - Find a node by its "device_type" property | ||
1486 | * @from: The node to start searching from or NULL, the node | ||
1487 | * you pass will not be searched, only the next one | ||
1488 | * will; typically, you pass what the previous call | ||
1489 | * returned. of_node_put() will be called on it | ||
1490 | * @name: The type string to match against | ||
1491 | * | ||
1492 | * Returns a node pointer with refcount incremented, use | ||
1493 | * of_node_put() on it when done. | ||
1494 | */ | ||
1495 | struct device_node *of_find_node_by_type(struct device_node *from, | ||
1496 | const char *type) | ||
1497 | { | ||
1498 | struct device_node *np; | ||
1499 | |||
1500 | read_lock(&devtree_lock); | ||
1501 | np = from ? from->allnext : allnodes; | ||
1502 | for (; np != 0; np = np->allnext) | ||
1503 | if (np->type != 0 && strcasecmp(np->type, type) == 0 | ||
1504 | && of_node_get(np)) | ||
1505 | break; | ||
1506 | if (from) | ||
1507 | of_node_put(from); | ||
1508 | read_unlock(&devtree_lock); | ||
1509 | return np; | ||
1510 | } | ||
1511 | EXPORT_SYMBOL(of_find_node_by_type); | ||
1512 | |||
1513 | /** | ||
1514 | * of_find_compatible_node - Find a node based on type and one of the | ||
1515 | * tokens in its "compatible" property | ||
1516 | * @from: The node to start searching from or NULL, the node | ||
1517 | * you pass will not be searched, only the next one | ||
1518 | * will; typically, you pass what the previous call | ||
1519 | * returned. of_node_put() will be called on it | ||
1520 | * @type: The type string to match "device_type" or NULL to ignore | ||
1521 | * @compatible: The string to match to one of the tokens in the device | ||
1522 | * "compatible" list. | ||
1523 | * | ||
1524 | * Returns a node pointer with refcount incremented, use | ||
1525 | * of_node_put() on it when done. | ||
1526 | */ | ||
1527 | struct device_node *of_find_compatible_node(struct device_node *from, | ||
1528 | const char *type, const char *compatible) | ||
1529 | { | ||
1530 | struct device_node *np; | ||
1531 | |||
1532 | read_lock(&devtree_lock); | ||
1533 | np = from ? from->allnext : allnodes; | ||
1534 | for (; np != 0; np = np->allnext) { | ||
1535 | if (type != NULL | ||
1536 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1537 | continue; | ||
1538 | if (device_is_compatible(np, compatible) && of_node_get(np)) | ||
1539 | break; | ||
1540 | } | ||
1541 | if (from) | ||
1542 | of_node_put(from); | ||
1543 | read_unlock(&devtree_lock); | ||
1544 | return np; | ||
1545 | } | ||
1546 | EXPORT_SYMBOL(of_find_compatible_node); | ||
1547 | |||
1548 | /** | ||
1549 | * of_find_node_by_path - Find a node matching a full OF path | ||
1550 | * @path: The full path to match | ||
1551 | * | ||
1552 | * Returns a node pointer with refcount incremented, use | ||
1553 | * of_node_put() on it when done. | ||
1554 | */ | ||
1555 | struct device_node *of_find_node_by_path(const char *path) | ||
1556 | { | ||
1557 | struct device_node *np = allnodes; | ||
1558 | |||
1559 | read_lock(&devtree_lock); | ||
1560 | for (; np != 0; np = np->allnext) { | ||
1561 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 | ||
1562 | && of_node_get(np)) | ||
1563 | break; | ||
1564 | } | ||
1565 | read_unlock(&devtree_lock); | ||
1566 | return np; | ||
1567 | } | ||
1568 | EXPORT_SYMBOL(of_find_node_by_path); | ||
1569 | |||
1570 | /** | ||
1571 | * of_find_node_by_phandle - Find a node given a phandle | ||
1572 | * @handle: phandle of the node to find | ||
1573 | * | ||
1574 | * Returns a node pointer with refcount incremented, use | ||
1575 | * of_node_put() on it when done. | ||
1576 | */ | ||
1577 | struct device_node *of_find_node_by_phandle(phandle handle) | ||
1578 | { | ||
1579 | struct device_node *np; | ||
1580 | |||
1581 | read_lock(&devtree_lock); | ||
1582 | for (np = allnodes; np != 0; np = np->allnext) | ||
1583 | if (np->linux_phandle == handle) | ||
1584 | break; | ||
1585 | if (np) | ||
1586 | of_node_get(np); | ||
1587 | read_unlock(&devtree_lock); | ||
1588 | return np; | ||
1589 | } | ||
1590 | EXPORT_SYMBOL(of_find_node_by_phandle); | ||
1591 | |||
1592 | /** | ||
1593 | * of_find_all_nodes - Get next node in global list | ||
1594 | * @prev: Previous node or NULL to start iteration | ||
1595 | * of_node_put() will be called on it | ||
1596 | * | ||
1597 | * Returns a node pointer with refcount incremented, use | ||
1598 | * of_node_put() on it when done. | ||
1599 | */ | ||
1600 | struct device_node *of_find_all_nodes(struct device_node *prev) | ||
1601 | { | ||
1602 | struct device_node *np; | ||
1603 | |||
1604 | read_lock(&devtree_lock); | ||
1605 | np = prev ? prev->allnext : allnodes; | ||
1606 | for (; np != 0; np = np->allnext) | ||
1607 | if (of_node_get(np)) | ||
1608 | break; | ||
1609 | if (prev) | ||
1610 | of_node_put(prev); | ||
1611 | read_unlock(&devtree_lock); | ||
1612 | return np; | ||
1613 | } | ||
1614 | EXPORT_SYMBOL(of_find_all_nodes); | ||
1615 | |||
1616 | /** | ||
1617 | * of_get_parent - Get a node's parent if any | ||
1618 | * @node: Node to get parent | ||
1619 | * | ||
1620 | * Returns a node pointer with refcount incremented, use | ||
1621 | * of_node_put() on it when done. | ||
1622 | */ | ||
1623 | struct device_node *of_get_parent(const struct device_node *node) | ||
1624 | { | ||
1625 | struct device_node *np; | ||
1626 | |||
1627 | if (!node) | ||
1628 | return NULL; | ||
1629 | |||
1630 | read_lock(&devtree_lock); | ||
1631 | np = of_node_get(node->parent); | ||
1632 | read_unlock(&devtree_lock); | ||
1633 | return np; | ||
1634 | } | ||
1635 | EXPORT_SYMBOL(of_get_parent); | ||
1636 | |||
1637 | /** | ||
1638 | * of_get_next_child - Iterate a node childs | ||
1639 | * @node: parent node | ||
1640 | * @prev: previous child of the parent node, or NULL to get first | ||
1641 | * | ||
1642 | * Returns a node pointer with refcount incremented, use | ||
1643 | * of_node_put() on it when done. | ||
1644 | */ | ||
1645 | struct device_node *of_get_next_child(const struct device_node *node, | ||
1646 | struct device_node *prev) | ||
1647 | { | ||
1648 | struct device_node *next; | ||
1649 | |||
1650 | read_lock(&devtree_lock); | ||
1651 | next = prev ? prev->sibling : node->child; | ||
1652 | for (; next != 0; next = next->sibling) | ||
1653 | if (of_node_get(next)) | ||
1654 | break; | ||
1655 | if (prev) | ||
1656 | of_node_put(prev); | ||
1657 | read_unlock(&devtree_lock); | ||
1658 | return next; | ||
1659 | } | ||
1660 | EXPORT_SYMBOL(of_get_next_child); | ||
1661 | |||
1662 | /** | ||
1663 | * of_node_get - Increment refcount of a node | ||
1664 | * @node: Node to inc refcount, NULL is supported to | ||
1665 | * simplify writing of callers | ||
1666 | * | ||
1667 | * Returns node. | ||
1668 | */ | ||
1669 | struct device_node *of_node_get(struct device_node *node) | ||
1670 | { | ||
1671 | if (node) | ||
1672 | kref_get(&node->kref); | ||
1673 | return node; | ||
1674 | } | ||
1675 | EXPORT_SYMBOL(of_node_get); | ||
1676 | |||
1677 | static inline struct device_node * kref_to_device_node(struct kref *kref) | ||
1678 | { | ||
1679 | return container_of(kref, struct device_node, kref); | ||
1680 | } | ||
1681 | |||
1682 | /** | ||
1683 | * of_node_release - release a dynamically allocated node | ||
1684 | * @kref: kref element of the node to be released | ||
1685 | * | ||
1686 | * In of_node_put() this function is passed to kref_put() | ||
1687 | * as the destructor. | ||
1688 | */ | ||
1689 | static void of_node_release(struct kref *kref) | ||
1690 | { | ||
1691 | struct device_node *node = kref_to_device_node(kref); | ||
1692 | struct property *prop = node->properties; | ||
1693 | |||
1694 | if (!OF_IS_DYNAMIC(node)) | ||
1695 | return; | ||
1696 | while (prop) { | ||
1697 | struct property *next = prop->next; | ||
1698 | kfree(prop->name); | ||
1699 | kfree(prop->value); | ||
1700 | kfree(prop); | ||
1701 | prop = next; | ||
1702 | } | ||
1703 | kfree(node->intrs); | ||
1704 | kfree(node->addrs); | ||
1705 | kfree(node->full_name); | ||
1706 | kfree(node->data); | ||
1707 | kfree(node); | ||
1708 | } | ||
1709 | |||
1710 | /** | ||
1711 | * of_node_put - Decrement refcount of a node | ||
1712 | * @node: Node to dec refcount, NULL is supported to | ||
1713 | * simplify writing of callers | ||
1714 | * | ||
1715 | */ | ||
1716 | void of_node_put(struct device_node *node) | ||
1717 | { | ||
1718 | if (node) | ||
1719 | kref_put(&node->kref, of_node_release); | ||
1720 | } | ||
1721 | EXPORT_SYMBOL(of_node_put); | ||
1722 | |||
1723 | /* | ||
1724 | * Fix up the uninitialized fields in a new device node: | ||
1725 | * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields | ||
1726 | * | ||
1727 | * A lot of boot-time code is duplicated here, because functions such | ||
1728 | * as finish_node_interrupts, interpret_pci_props, etc. cannot use the | ||
1729 | * slab allocator. | ||
1730 | * | ||
1731 | * This should probably be split up into smaller chunks. | ||
1732 | */ | ||
1733 | |||
1734 | static int of_finish_dynamic_node(struct device_node *node, | ||
1735 | unsigned long *unused1, int unused2, | ||
1736 | int unused3, int unused4) | ||
1737 | { | ||
1738 | struct device_node *parent = of_get_parent(node); | ||
1739 | int err = 0; | ||
1740 | phandle *ibm_phandle; | ||
1741 | |||
1742 | node->name = get_property(node, "name", NULL); | ||
1743 | node->type = get_property(node, "device_type", NULL); | ||
1744 | |||
1745 | if (!parent) { | ||
1746 | err = -ENODEV; | ||
1747 | goto out; | ||
1748 | } | ||
1749 | |||
1750 | /* We don't support that function on PowerMac, at least | ||
1751 | * not yet | ||
1752 | */ | ||
1753 | if (_machine == PLATFORM_POWERMAC) | ||
1754 | return -ENODEV; | ||
1755 | |||
1756 | /* fix up new node's linux_phandle field */ | ||
1757 | if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL))) | ||
1758 | node->linux_phandle = *ibm_phandle; | ||
1759 | |||
1760 | out: | ||
1761 | of_node_put(parent); | ||
1762 | return err; | ||
1763 | } | ||
1764 | |||
1765 | /* | ||
1766 | * Plug a device node into the tree and global list. | ||
1767 | */ | ||
1768 | void of_attach_node(struct device_node *np) | ||
1769 | { | ||
1770 | write_lock(&devtree_lock); | ||
1771 | np->sibling = np->parent->child; | ||
1772 | np->allnext = allnodes; | ||
1773 | np->parent->child = np; | ||
1774 | allnodes = np; | ||
1775 | write_unlock(&devtree_lock); | ||
1776 | } | ||
1777 | |||
1778 | /* | ||
1779 | * "Unplug" a node from the device tree. The caller must hold | ||
1780 | * a reference to the node. The memory associated with the node | ||
1781 | * is not freed until its refcount goes to zero. | ||
1782 | */ | ||
1783 | void of_detach_node(const struct device_node *np) | ||
1784 | { | ||
1785 | struct device_node *parent; | ||
1786 | |||
1787 | write_lock(&devtree_lock); | ||
1788 | |||
1789 | parent = np->parent; | ||
1790 | |||
1791 | if (allnodes == np) | ||
1792 | allnodes = np->allnext; | ||
1793 | else { | ||
1794 | struct device_node *prev; | ||
1795 | for (prev = allnodes; | ||
1796 | prev->allnext != np; | ||
1797 | prev = prev->allnext) | ||
1798 | ; | ||
1799 | prev->allnext = np->allnext; | ||
1800 | } | ||
1801 | |||
1802 | if (parent->child == np) | ||
1803 | parent->child = np->sibling; | ||
1804 | else { | ||
1805 | struct device_node *prevsib; | ||
1806 | for (prevsib = np->parent->child; | ||
1807 | prevsib->sibling != np; | ||
1808 | prevsib = prevsib->sibling) | ||
1809 | ; | ||
1810 | prevsib->sibling = np->sibling; | ||
1811 | } | ||
1812 | |||
1813 | write_unlock(&devtree_lock); | ||
1814 | } | ||
1815 | |||
1816 | static int prom_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | ||
1817 | { | ||
1818 | int err; | ||
1819 | |||
1820 | switch (action) { | ||
1821 | case PSERIES_RECONFIG_ADD: | ||
1822 | err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0); | ||
1823 | if (err < 0) { | ||
1824 | printk(KERN_ERR "finish_node returned %d\n", err); | ||
1825 | err = NOTIFY_BAD; | ||
1826 | } | ||
1827 | break; | ||
1828 | default: | ||
1829 | err = NOTIFY_DONE; | ||
1830 | break; | ||
1831 | } | ||
1832 | return err; | ||
1833 | } | ||
1834 | |||
1835 | static struct notifier_block prom_reconfig_nb = { | ||
1836 | .notifier_call = prom_reconfig_notifier, | ||
1837 | .priority = 10, /* This one needs to run first */ | ||
1838 | }; | ||
1839 | |||
1840 | static int __init prom_reconfig_setup(void) | ||
1841 | { | ||
1842 | return pSeries_reconfig_notifier_register(&prom_reconfig_nb); | ||
1843 | } | ||
1844 | __initcall(prom_reconfig_setup); | ||
1845 | |||
1846 | /* | ||
1847 | * Find a property with a given name for a given node | ||
1848 | * and return the value. | ||
1849 | */ | ||
1850 | unsigned char * | ||
1851 | get_property(struct device_node *np, const char *name, int *lenp) | ||
1852 | { | ||
1853 | struct property *pp; | ||
1854 | |||
1855 | for (pp = np->properties; pp != 0; pp = pp->next) | ||
1856 | if (strcmp(pp->name, name) == 0) { | ||
1857 | if (lenp != 0) | ||
1858 | *lenp = pp->length; | ||
1859 | return pp->value; | ||
1860 | } | ||
1861 | return NULL; | ||
1862 | } | ||
1863 | EXPORT_SYMBOL(get_property); | ||
1864 | |||
1865 | /* | ||
1866 | * Add a property to a node. | ||
1867 | */ | ||
1868 | int | ||
1869 | prom_add_property(struct device_node* np, struct property* prop) | ||
1870 | { | ||
1871 | struct property **next; | ||
1872 | |||
1873 | prop->next = NULL; | ||
1874 | write_lock(&devtree_lock); | ||
1875 | next = &np->properties; | ||
1876 | while (*next) { | ||
1877 | if (strcmp(prop->name, (*next)->name) == 0) { | ||
1878 | /* duplicate ! don't insert it */ | ||
1879 | write_unlock(&devtree_lock); | ||
1880 | return -1; | ||
1881 | } | ||
1882 | next = &(*next)->next; | ||
1883 | } | ||
1884 | *next = prop; | ||
1885 | write_unlock(&devtree_lock); | ||
1886 | |||
1887 | /* try to add to proc as well if it was initialized */ | ||
1888 | if (np->pde) | ||
1889 | proc_device_tree_add_prop(np->pde, prop); | ||
1890 | |||
1891 | return 0; | ||
1892 | } | ||
1893 | |||
1894 | #if 0 | ||
1895 | void | ||
1896 | print_properties(struct device_node *np) | ||
1897 | { | ||
1898 | struct property *pp; | ||
1899 | char *cp; | ||
1900 | int i, n; | ||
1901 | |||
1902 | for (pp = np->properties; pp != 0; pp = pp->next) { | ||
1903 | printk(KERN_INFO "%s", pp->name); | ||
1904 | for (i = strlen(pp->name); i < 16; ++i) | ||
1905 | printk(" "); | ||
1906 | cp = (char *) pp->value; | ||
1907 | for (i = pp->length; i > 0; --i, ++cp) | ||
1908 | if ((i > 1 && (*cp < 0x20 || *cp > 0x7e)) | ||
1909 | || (i == 1 && *cp != 0)) | ||
1910 | break; | ||
1911 | if (i == 0 && pp->length > 1) { | ||
1912 | /* looks like a string */ | ||
1913 | printk(" %s\n", (char *) pp->value); | ||
1914 | } else { | ||
1915 | /* dump it in hex */ | ||
1916 | n = pp->length; | ||
1917 | if (n > 64) | ||
1918 | n = 64; | ||
1919 | if (pp->length % 4 == 0) { | ||
1920 | unsigned int *p = (unsigned int *) pp->value; | ||
1921 | |||
1922 | n /= 4; | ||
1923 | for (i = 0; i < n; ++i) { | ||
1924 | if (i != 0 && (i % 4) == 0) | ||
1925 | printk("\n "); | ||
1926 | printk(" %08x", *p++); | ||
1927 | } | ||
1928 | } else { | ||
1929 | unsigned char *bp = pp->value; | ||
1930 | |||
1931 | for (i = 0; i < n; ++i) { | ||
1932 | if (i != 0 && (i % 16) == 0) | ||
1933 | printk("\n "); | ||
1934 | printk(" %02x", *bp++); | ||
1935 | } | ||
1936 | } | ||
1937 | printk("\n"); | ||
1938 | if (pp->length > 64) | ||
1939 | printk(" ... (length = %d)\n", | ||
1940 | pp->length); | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | #endif | ||
1945 | |||
1946 | |||
1947 | |||
1948 | |||
1949 | |||
1950 | |||
1951 | |||
1952 | |||
1953 | |||
1954 | |||
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c deleted file mode 100644 index 6375f40b23db..000000000000 --- a/arch/ppc64/kernel/prom_init.c +++ /dev/null | |||
@@ -1,2051 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Procedures for interfacing to Open Firmware. | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996 Paul Mackerras. | ||
8 | * | ||
9 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
10 | * {engebret|bergner}@us.ibm.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG_PROM | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/proc_fs.h> | ||
30 | #include <linux/stringify.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/bitops.h> | ||
34 | #include <asm/prom.h> | ||
35 | #include <asm/rtas.h> | ||
36 | #include <asm/abs_addr.h> | ||
37 | #include <asm/page.h> | ||
38 | #include <asm/processor.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/smp.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/mmu.h> | ||
44 | #include <asm/pgtable.h> | ||
45 | #include <asm/pci.h> | ||
46 | #include <asm/iommu.h> | ||
47 | #include <asm/btext.h> | ||
48 | #include <asm/sections.h> | ||
49 | #include <asm/machdep.h> | ||
50 | |||
51 | #ifdef CONFIG_LOGO_LINUX_CLUT224 | ||
52 | #include <linux/linux_logo.h> | ||
53 | extern const struct linux_logo logo_linux_clut224; | ||
54 | #endif | ||
55 | |||
56 | /* | ||
57 | * Properties whose value is longer than this get excluded from our | ||
58 | * copy of the device tree. This value does need to be big enough to | ||
59 | * ensure that we don't lose things like the interrupt-map property | ||
60 | * on a PCI-PCI bridge. | ||
61 | */ | ||
62 | #define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024) | ||
63 | |||
64 | /* | ||
65 | * Eventually bump that one up | ||
66 | */ | ||
67 | #define DEVTREE_CHUNK_SIZE 0x100000 | ||
68 | |||
69 | /* | ||
70 | * This is the size of the local memory reserve map that gets copied | ||
71 | * into the boot params passed to the kernel. That size is totally | ||
72 | * flexible as the kernel just reads the list until it encounters an | ||
73 | * entry with size 0, so it can be changed without breaking binary | ||
74 | * compatibility | ||
75 | */ | ||
76 | #define MEM_RESERVE_MAP_SIZE 8 | ||
77 | |||
78 | /* | ||
79 | * prom_init() is called very early on, before the kernel text | ||
80 | * and data have been mapped to KERNELBASE. At this point the code | ||
81 | * is running at whatever address it has been loaded at, so | ||
82 | * references to extern and static variables must be relocated | ||
83 | * explicitly. The procedure reloc_offset() returns the address | ||
84 | * we're currently running at minus the address we were linked at. | ||
85 | * (Note that strings count as static variables.) | ||
86 | * | ||
87 | * Because OF may have mapped I/O devices into the area starting at | ||
88 | * KERNELBASE, particularly on CHRP machines, we can't safely call | ||
89 | * OF once the kernel has been mapped to KERNELBASE. Therefore all | ||
90 | * OF calls should be done within prom_init(), and prom_init() | ||
91 | * and all routines called within it must be careful to relocate | ||
92 | * references as necessary. | ||
93 | * | ||
94 | * Note that the bss is cleared *after* prom_init runs, so we have | ||
95 | * to make sure that any static or extern variables it accesses | ||
96 | * are put in the data segment. | ||
97 | */ | ||
98 | |||
99 | |||
100 | #define PROM_BUG() do { \ | ||
101 | prom_printf("kernel BUG at %s line 0x%x!\n", \ | ||
102 | RELOC(__FILE__), __LINE__); \ | ||
103 | __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \ | ||
104 | } while (0) | ||
105 | |||
106 | #ifdef DEBUG_PROM | ||
107 | #define prom_debug(x...) prom_printf(x) | ||
108 | #else | ||
109 | #define prom_debug(x...) | ||
110 | #endif | ||
111 | |||
112 | |||
113 | typedef u32 prom_arg_t; | ||
114 | |||
115 | struct prom_args { | ||
116 | u32 service; | ||
117 | u32 nargs; | ||
118 | u32 nret; | ||
119 | prom_arg_t args[10]; | ||
120 | prom_arg_t *rets; /* Pointer to return values in args[16]. */ | ||
121 | }; | ||
122 | |||
123 | struct prom_t { | ||
124 | unsigned long entry; | ||
125 | ihandle root; | ||
126 | ihandle chosen; | ||
127 | int cpu; | ||
128 | ihandle stdout; | ||
129 | ihandle disp_node; | ||
130 | struct prom_args args; | ||
131 | unsigned long version; | ||
132 | unsigned long root_size_cells; | ||
133 | unsigned long root_addr_cells; | ||
134 | }; | ||
135 | |||
136 | struct pci_reg_property { | ||
137 | struct pci_address addr; | ||
138 | u32 size_hi; | ||
139 | u32 size_lo; | ||
140 | }; | ||
141 | |||
142 | struct mem_map_entry { | ||
143 | u64 base; | ||
144 | u64 size; | ||
145 | }; | ||
146 | |||
147 | typedef u32 cell_t; | ||
148 | |||
149 | extern void __start(unsigned long r3, unsigned long r4, unsigned long r5); | ||
150 | |||
151 | extern void enter_prom(struct prom_args *args, unsigned long entry); | ||
152 | extern void copy_and_flush(unsigned long dest, unsigned long src, | ||
153 | unsigned long size, unsigned long offset); | ||
154 | |||
155 | extern unsigned long klimit; | ||
156 | |||
157 | /* prom structure */ | ||
158 | static struct prom_t __initdata prom; | ||
159 | |||
160 | #define PROM_SCRATCH_SIZE 256 | ||
161 | |||
162 | static char __initdata of_stdout_device[256]; | ||
163 | static char __initdata prom_scratch[PROM_SCRATCH_SIZE]; | ||
164 | |||
165 | static unsigned long __initdata dt_header_start; | ||
166 | static unsigned long __initdata dt_struct_start, dt_struct_end; | ||
167 | static unsigned long __initdata dt_string_start, dt_string_end; | ||
168 | |||
169 | static unsigned long __initdata prom_initrd_start, prom_initrd_end; | ||
170 | |||
171 | static int __initdata iommu_force_on; | ||
172 | static int __initdata ppc64_iommu_off; | ||
173 | static int __initdata of_platform; | ||
174 | |||
175 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | ||
176 | |||
177 | static unsigned long __initdata prom_memory_limit; | ||
178 | static unsigned long __initdata prom_tce_alloc_start; | ||
179 | static unsigned long __initdata prom_tce_alloc_end; | ||
180 | |||
181 | static unsigned long __initdata alloc_top; | ||
182 | static unsigned long __initdata alloc_top_high; | ||
183 | static unsigned long __initdata alloc_bottom; | ||
184 | static unsigned long __initdata rmo_top; | ||
185 | static unsigned long __initdata ram_top; | ||
186 | |||
187 | static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; | ||
188 | static int __initdata mem_reserve_cnt; | ||
189 | |||
190 | static cell_t __initdata regbuf[1024]; | ||
191 | |||
192 | |||
193 | #define MAX_CPU_THREADS 2 | ||
194 | |||
195 | /* TO GO */ | ||
196 | #ifdef CONFIG_HMT | ||
197 | struct { | ||
198 | unsigned int pir; | ||
199 | unsigned int threadid; | ||
200 | } hmt_thread_data[NR_CPUS]; | ||
201 | #endif /* CONFIG_HMT */ | ||
202 | |||
203 | /* | ||
204 | * This are used in calls to call_prom. The 4th and following | ||
205 | * arguments to call_prom should be 32-bit values. 64 bit values | ||
206 | * are truncated to 32 bits (and fortunately don't get interpreted | ||
207 | * as two arguments). | ||
208 | */ | ||
209 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) | ||
210 | |||
211 | /* | ||
212 | * Error results ... some OF calls will return "-1" on error, some | ||
213 | * will return 0, some will return either. To simplify, here are | ||
214 | * macros to use with any ihandle or phandle return value to check if | ||
215 | * it is valid | ||
216 | */ | ||
217 | |||
218 | #define PROM_ERROR (-1u) | ||
219 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) | ||
220 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) | ||
221 | |||
222 | |||
223 | /* This is the one and *ONLY* place where we actually call open | ||
224 | * firmware from, since we need to make sure we're running in 32b | ||
225 | * mode when we do. We switch back to 64b mode upon return. | ||
226 | */ | ||
227 | |||
228 | static int __init call_prom(const char *service, int nargs, int nret, ...) | ||
229 | { | ||
230 | int i; | ||
231 | unsigned long offset = reloc_offset(); | ||
232 | struct prom_t *_prom = PTRRELOC(&prom); | ||
233 | va_list list; | ||
234 | |||
235 | _prom->args.service = ADDR(service); | ||
236 | _prom->args.nargs = nargs; | ||
237 | _prom->args.nret = nret; | ||
238 | _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]); | ||
239 | |||
240 | va_start(list, nret); | ||
241 | for (i=0; i < nargs; i++) | ||
242 | _prom->args.args[i] = va_arg(list, prom_arg_t); | ||
243 | va_end(list); | ||
244 | |||
245 | for (i=0; i < nret ;i++) | ||
246 | _prom->args.rets[i] = 0; | ||
247 | |||
248 | enter_prom(&_prom->args, _prom->entry); | ||
249 | |||
250 | return (nret > 0) ? _prom->args.rets[0] : 0; | ||
251 | } | ||
252 | |||
253 | |||
254 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | ||
255 | unsigned long align) | ||
256 | { | ||
257 | return (unsigned int)call_prom("claim", 3, 1, | ||
258 | (prom_arg_t)virt, (prom_arg_t)size, | ||
259 | (prom_arg_t)align); | ||
260 | } | ||
261 | |||
262 | static void __init prom_print(const char *msg) | ||
263 | { | ||
264 | const char *p, *q; | ||
265 | unsigned long offset = reloc_offset(); | ||
266 | struct prom_t *_prom = PTRRELOC(&prom); | ||
267 | |||
268 | if (_prom->stdout == 0) | ||
269 | return; | ||
270 | |||
271 | for (p = msg; *p != 0; p = q) { | ||
272 | for (q = p; *q != 0 && *q != '\n'; ++q) | ||
273 | ; | ||
274 | if (q > p) | ||
275 | call_prom("write", 3, 1, _prom->stdout, p, q - p); | ||
276 | if (*q == 0) | ||
277 | break; | ||
278 | ++q; | ||
279 | call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | |||
284 | static void __init prom_print_hex(unsigned long val) | ||
285 | { | ||
286 | unsigned long offset = reloc_offset(); | ||
287 | int i, nibbles = sizeof(val)*2; | ||
288 | char buf[sizeof(val)*2+1]; | ||
289 | struct prom_t *_prom = PTRRELOC(&prom); | ||
290 | |||
291 | for (i = nibbles-1; i >= 0; i--) { | ||
292 | buf[i] = (val & 0xf) + '0'; | ||
293 | if (buf[i] > '9') | ||
294 | buf[i] += ('a'-'0'-10); | ||
295 | val >>= 4; | ||
296 | } | ||
297 | buf[nibbles] = '\0'; | ||
298 | call_prom("write", 3, 1, _prom->stdout, buf, nibbles); | ||
299 | } | ||
300 | |||
301 | |||
302 | static void __init prom_printf(const char *format, ...) | ||
303 | { | ||
304 | unsigned long offset = reloc_offset(); | ||
305 | const char *p, *q, *s; | ||
306 | va_list args; | ||
307 | unsigned long v; | ||
308 | struct prom_t *_prom = PTRRELOC(&prom); | ||
309 | |||
310 | va_start(args, format); | ||
311 | for (p = PTRRELOC(format); *p != 0; p = q) { | ||
312 | for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q) | ||
313 | ; | ||
314 | if (q > p) | ||
315 | call_prom("write", 3, 1, _prom->stdout, p, q - p); | ||
316 | if (*q == 0) | ||
317 | break; | ||
318 | if (*q == '\n') { | ||
319 | ++q; | ||
320 | call_prom("write", 3, 1, _prom->stdout, | ||
321 | ADDR("\r\n"), 2); | ||
322 | continue; | ||
323 | } | ||
324 | ++q; | ||
325 | if (*q == 0) | ||
326 | break; | ||
327 | switch (*q) { | ||
328 | case 's': | ||
329 | ++q; | ||
330 | s = va_arg(args, const char *); | ||
331 | prom_print(s); | ||
332 | break; | ||
333 | case 'x': | ||
334 | ++q; | ||
335 | v = va_arg(args, unsigned long); | ||
336 | prom_print_hex(v); | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | |||
343 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | ||
344 | { | ||
345 | unsigned long offset = reloc_offset(); | ||
346 | |||
347 | prom_print(PTRRELOC(reason)); | ||
348 | /* ToDo: should put up an SRC here */ | ||
349 | call_prom("exit", 0, 0); | ||
350 | |||
351 | for (;;) /* should never get here */ | ||
352 | ; | ||
353 | } | ||
354 | |||
355 | |||
356 | static int __init prom_next_node(phandle *nodep) | ||
357 | { | ||
358 | phandle node; | ||
359 | |||
360 | if ((node = *nodep) != 0 | ||
361 | && (*nodep = call_prom("child", 1, 1, node)) != 0) | ||
362 | return 1; | ||
363 | if ((*nodep = call_prom("peer", 1, 1, node)) != 0) | ||
364 | return 1; | ||
365 | for (;;) { | ||
366 | if ((node = call_prom("parent", 1, 1, node)) == 0) | ||
367 | return 0; | ||
368 | if ((*nodep = call_prom("peer", 1, 1, node)) != 0) | ||
369 | return 1; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | static int __init prom_getprop(phandle node, const char *pname, | ||
374 | void *value, size_t valuelen) | ||
375 | { | ||
376 | unsigned long offset = reloc_offset(); | ||
377 | |||
378 | return call_prom("getprop", 4, 1, node, ADDR(pname), | ||
379 | (u32)(unsigned long) value, (u32) valuelen); | ||
380 | } | ||
381 | |||
382 | static int __init prom_getproplen(phandle node, const char *pname) | ||
383 | { | ||
384 | unsigned long offset = reloc_offset(); | ||
385 | |||
386 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); | ||
387 | } | ||
388 | |||
389 | static int __init prom_setprop(phandle node, const char *pname, | ||
390 | void *value, size_t valuelen) | ||
391 | { | ||
392 | unsigned long offset = reloc_offset(); | ||
393 | |||
394 | return call_prom("setprop", 4, 1, node, ADDR(pname), | ||
395 | (u32)(unsigned long) value, (u32) valuelen); | ||
396 | } | ||
397 | |||
398 | /* We can't use the standard versions because of RELOC headaches. */ | ||
399 | #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ | ||
400 | || ('a' <= (c) && (c) <= 'f') \ | ||
401 | || ('A' <= (c) && (c) <= 'F')) | ||
402 | |||
403 | #define isdigit(c) ('0' <= (c) && (c) <= '9') | ||
404 | #define islower(c) ('a' <= (c) && (c) <= 'z') | ||
405 | #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c)) | ||
406 | |||
407 | unsigned long prom_strtoul(const char *cp, const char **endp) | ||
408 | { | ||
409 | unsigned long result = 0, base = 10, value; | ||
410 | |||
411 | if (*cp == '0') { | ||
412 | base = 8; | ||
413 | cp++; | ||
414 | if (toupper(*cp) == 'X') { | ||
415 | cp++; | ||
416 | base = 16; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | while (isxdigit(*cp) && | ||
421 | (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) { | ||
422 | result = result * base + value; | ||
423 | cp++; | ||
424 | } | ||
425 | |||
426 | if (endp) | ||
427 | *endp = cp; | ||
428 | |||
429 | return result; | ||
430 | } | ||
431 | |||
432 | unsigned long prom_memparse(const char *ptr, const char **retptr) | ||
433 | { | ||
434 | unsigned long ret = prom_strtoul(ptr, retptr); | ||
435 | int shift = 0; | ||
436 | |||
437 | /* | ||
438 | * We can't use a switch here because GCC *may* generate a | ||
439 | * jump table which won't work, because we're not running at | ||
440 | * the address we're linked at. | ||
441 | */ | ||
442 | if ('G' == **retptr || 'g' == **retptr) | ||
443 | shift = 30; | ||
444 | |||
445 | if ('M' == **retptr || 'm' == **retptr) | ||
446 | shift = 20; | ||
447 | |||
448 | if ('K' == **retptr || 'k' == **retptr) | ||
449 | shift = 10; | ||
450 | |||
451 | if (shift) { | ||
452 | ret <<= shift; | ||
453 | (*retptr)++; | ||
454 | } | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Early parsing of the command line passed to the kernel, used for | ||
461 | * "mem=x" and the options that affect the iommu | ||
462 | */ | ||
463 | static void __init early_cmdline_parse(void) | ||
464 | { | ||
465 | unsigned long offset = reloc_offset(); | ||
466 | struct prom_t *_prom = PTRRELOC(&prom); | ||
467 | char *opt, *p; | ||
468 | int l = 0; | ||
469 | |||
470 | RELOC(prom_cmd_line[0]) = 0; | ||
471 | p = RELOC(prom_cmd_line); | ||
472 | if ((long)_prom->chosen > 0) | ||
473 | l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); | ||
474 | #ifdef CONFIG_CMDLINE | ||
475 | if (l == 0) /* dbl check */ | ||
476 | strlcpy(RELOC(prom_cmd_line), | ||
477 | RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); | ||
478 | #endif /* CONFIG_CMDLINE */ | ||
479 | prom_printf("command line: %s\n", RELOC(prom_cmd_line)); | ||
480 | |||
481 | opt = strstr(RELOC(prom_cmd_line), RELOC("iommu=")); | ||
482 | if (opt) { | ||
483 | prom_printf("iommu opt is: %s\n", opt); | ||
484 | opt += 6; | ||
485 | while (*opt && *opt == ' ') | ||
486 | opt++; | ||
487 | if (!strncmp(opt, RELOC("off"), 3)) | ||
488 | RELOC(ppc64_iommu_off) = 1; | ||
489 | else if (!strncmp(opt, RELOC("force"), 5)) | ||
490 | RELOC(iommu_force_on) = 1; | ||
491 | } | ||
492 | |||
493 | opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); | ||
494 | if (opt) { | ||
495 | opt += 4; | ||
496 | RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); | ||
497 | /* Align to 16 MB == size of large page */ | ||
498 | RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * To tell the firmware what our capabilities are, we have to pass | ||
504 | * it a fake 32-bit ELF header containing a couple of PT_NOTE sections | ||
505 | * that contain structures that contain the actual values. | ||
506 | */ | ||
507 | static struct fake_elf { | ||
508 | Elf32_Ehdr elfhdr; | ||
509 | Elf32_Phdr phdr[2]; | ||
510 | struct chrpnote { | ||
511 | u32 namesz; | ||
512 | u32 descsz; | ||
513 | u32 type; | ||
514 | char name[8]; /* "PowerPC" */ | ||
515 | struct chrpdesc { | ||
516 | u32 real_mode; | ||
517 | u32 real_base; | ||
518 | u32 real_size; | ||
519 | u32 virt_base; | ||
520 | u32 virt_size; | ||
521 | u32 load_base; | ||
522 | } chrpdesc; | ||
523 | } chrpnote; | ||
524 | struct rpanote { | ||
525 | u32 namesz; | ||
526 | u32 descsz; | ||
527 | u32 type; | ||
528 | char name[24]; /* "IBM,RPA-Client-Config" */ | ||
529 | struct rpadesc { | ||
530 | u32 lpar_affinity; | ||
531 | u32 min_rmo_size; | ||
532 | u32 min_rmo_percent; | ||
533 | u32 max_pft_size; | ||
534 | u32 splpar; | ||
535 | u32 min_load; | ||
536 | u32 new_mem_def; | ||
537 | u32 ignore_me; | ||
538 | } rpadesc; | ||
539 | } rpanote; | ||
540 | } fake_elf = { | ||
541 | .elfhdr = { | ||
542 | .e_ident = { 0x7f, 'E', 'L', 'F', | ||
543 | ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, | ||
544 | .e_type = ET_EXEC, /* yeah right */ | ||
545 | .e_machine = EM_PPC, | ||
546 | .e_version = EV_CURRENT, | ||
547 | .e_phoff = offsetof(struct fake_elf, phdr), | ||
548 | .e_phentsize = sizeof(Elf32_Phdr), | ||
549 | .e_phnum = 2 | ||
550 | }, | ||
551 | .phdr = { | ||
552 | [0] = { | ||
553 | .p_type = PT_NOTE, | ||
554 | .p_offset = offsetof(struct fake_elf, chrpnote), | ||
555 | .p_filesz = sizeof(struct chrpnote) | ||
556 | }, [1] = { | ||
557 | .p_type = PT_NOTE, | ||
558 | .p_offset = offsetof(struct fake_elf, rpanote), | ||
559 | .p_filesz = sizeof(struct rpanote) | ||
560 | } | ||
561 | }, | ||
562 | .chrpnote = { | ||
563 | .namesz = sizeof("PowerPC"), | ||
564 | .descsz = sizeof(struct chrpdesc), | ||
565 | .type = 0x1275, | ||
566 | .name = "PowerPC", | ||
567 | .chrpdesc = { | ||
568 | .real_mode = ~0U, /* ~0 means "don't care" */ | ||
569 | .real_base = ~0U, | ||
570 | .real_size = ~0U, | ||
571 | .virt_base = ~0U, | ||
572 | .virt_size = ~0U, | ||
573 | .load_base = ~0U | ||
574 | }, | ||
575 | }, | ||
576 | .rpanote = { | ||
577 | .namesz = sizeof("IBM,RPA-Client-Config"), | ||
578 | .descsz = sizeof(struct rpadesc), | ||
579 | .type = 0x12759999, | ||
580 | .name = "IBM,RPA-Client-Config", | ||
581 | .rpadesc = { | ||
582 | .lpar_affinity = 0, | ||
583 | .min_rmo_size = 64, /* in megabytes */ | ||
584 | .min_rmo_percent = 0, | ||
585 | .max_pft_size = 48, /* 2^48 bytes max PFT size */ | ||
586 | .splpar = 1, | ||
587 | .min_load = ~0U, | ||
588 | .new_mem_def = 0 | ||
589 | } | ||
590 | } | ||
591 | }; | ||
592 | |||
593 | static void __init prom_send_capabilities(void) | ||
594 | { | ||
595 | unsigned long offset = reloc_offset(); | ||
596 | ihandle elfloader; | ||
597 | |||
598 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | ||
599 | if (elfloader == 0) { | ||
600 | prom_printf("couldn't open /packages/elf-loader\n"); | ||
601 | return; | ||
602 | } | ||
603 | call_prom("call-method", 3, 1, ADDR("process-elf-header"), | ||
604 | elfloader, ADDR(&fake_elf)); | ||
605 | call_prom("close", 1, 0, elfloader); | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * Memory allocation strategy... our layout is normally: | ||
610 | * | ||
611 | * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd | ||
612 | * might end up beeing before the kernel though. We assume this won't override | ||
613 | * the final kernel at 0, we have no provision to handle that in this version, | ||
614 | * but it should hopefully never happen. | ||
615 | * | ||
616 | * alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap | ||
617 | * alloc_bottom is set to the top of kernel/initrd | ||
618 | * | ||
619 | * from there, allocations are done that way : rtas is allocated topmost, and | ||
620 | * the device-tree is allocated from the bottom. We try to grow the device-tree | ||
621 | * allocation as we progress. If we can't, then we fail, we don't currently have | ||
622 | * a facility to restart elsewhere, but that shouldn't be necessary neither | ||
623 | * | ||
624 | * Note that calls to reserve_mem have to be done explicitely, memory allocated | ||
625 | * with either alloc_up or alloc_down isn't automatically reserved. | ||
626 | */ | ||
627 | |||
628 | |||
629 | /* | ||
630 | * Allocates memory in the RMO upward from the kernel/initrd | ||
631 | * | ||
632 | * When align is 0, this is a special case, it means to allocate in place | ||
633 | * at the current location of alloc_bottom or fail (that is basically | ||
634 | * extending the previous allocation). Used for the device-tree flattening | ||
635 | */ | ||
636 | static unsigned long __init alloc_up(unsigned long size, unsigned long align) | ||
637 | { | ||
638 | unsigned long offset = reloc_offset(); | ||
639 | unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align); | ||
640 | unsigned long addr = 0; | ||
641 | |||
642 | prom_debug("alloc_up(%x, %x)\n", size, align); | ||
643 | if (RELOC(ram_top) == 0) | ||
644 | prom_panic("alloc_up() called with mem not initialized\n"); | ||
645 | |||
646 | if (align) | ||
647 | base = _ALIGN_UP(RELOC(alloc_bottom), align); | ||
648 | else | ||
649 | base = RELOC(alloc_bottom); | ||
650 | |||
651 | for(; (base + size) <= RELOC(alloc_top); | ||
652 | base = _ALIGN_UP(base + 0x100000, align)) { | ||
653 | prom_debug(" trying: 0x%x\n\r", base); | ||
654 | addr = (unsigned long)prom_claim(base, size, 0); | ||
655 | if (addr != PROM_ERROR) | ||
656 | break; | ||
657 | addr = 0; | ||
658 | if (align == 0) | ||
659 | break; | ||
660 | } | ||
661 | if (addr == 0) | ||
662 | return 0; | ||
663 | RELOC(alloc_bottom) = addr; | ||
664 | |||
665 | prom_debug(" -> %x\n", addr); | ||
666 | prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
667 | prom_debug(" alloc_top : %x\n", RELOC(alloc_top)); | ||
668 | prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
669 | prom_debug(" rmo_top : %x\n", RELOC(rmo_top)); | ||
670 | prom_debug(" ram_top : %x\n", RELOC(ram_top)); | ||
671 | |||
672 | return addr; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Allocates memory downard, either from top of RMO, or if highmem | ||
677 | * is set, from the top of RAM. Note that this one doesn't handle | ||
678 | * failures. In does claim memory if highmem is not set. | ||
679 | */ | ||
680 | static unsigned long __init alloc_down(unsigned long size, unsigned long align, | ||
681 | int highmem) | ||
682 | { | ||
683 | unsigned long offset = reloc_offset(); | ||
684 | unsigned long base, addr = 0; | ||
685 | |||
686 | prom_debug("alloc_down(%x, %x, %s)\n", size, align, | ||
687 | highmem ? RELOC("(high)") : RELOC("(low)")); | ||
688 | if (RELOC(ram_top) == 0) | ||
689 | prom_panic("alloc_down() called with mem not initialized\n"); | ||
690 | |||
691 | if (highmem) { | ||
692 | /* Carve out storage for the TCE table. */ | ||
693 | addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align); | ||
694 | if (addr <= RELOC(alloc_bottom)) | ||
695 | return 0; | ||
696 | else { | ||
697 | /* Will we bump into the RMO ? If yes, check out that we | ||
698 | * didn't overlap existing allocations there, if we did, | ||
699 | * we are dead, we must be the first in town ! | ||
700 | */ | ||
701 | if (addr < RELOC(rmo_top)) { | ||
702 | /* Good, we are first */ | ||
703 | if (RELOC(alloc_top) == RELOC(rmo_top)) | ||
704 | RELOC(alloc_top) = RELOC(rmo_top) = addr; | ||
705 | else | ||
706 | return 0; | ||
707 | } | ||
708 | RELOC(alloc_top_high) = addr; | ||
709 | } | ||
710 | goto bail; | ||
711 | } | ||
712 | |||
713 | base = _ALIGN_DOWN(RELOC(alloc_top) - size, align); | ||
714 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { | ||
715 | prom_debug(" trying: 0x%x\n\r", base); | ||
716 | addr = (unsigned long)prom_claim(base, size, 0); | ||
717 | if (addr != PROM_ERROR) | ||
718 | break; | ||
719 | addr = 0; | ||
720 | } | ||
721 | if (addr == 0) | ||
722 | return 0; | ||
723 | RELOC(alloc_top) = addr; | ||
724 | |||
725 | bail: | ||
726 | prom_debug(" -> %x\n", addr); | ||
727 | prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
728 | prom_debug(" alloc_top : %x\n", RELOC(alloc_top)); | ||
729 | prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
730 | prom_debug(" rmo_top : %x\n", RELOC(rmo_top)); | ||
731 | prom_debug(" ram_top : %x\n", RELOC(ram_top)); | ||
732 | |||
733 | return addr; | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * Parse a "reg" cell | ||
738 | */ | ||
739 | static unsigned long __init prom_next_cell(int s, cell_t **cellp) | ||
740 | { | ||
741 | cell_t *p = *cellp; | ||
742 | unsigned long r = 0; | ||
743 | |||
744 | /* Ignore more than 2 cells */ | ||
745 | while (s > 2) { | ||
746 | p++; | ||
747 | s--; | ||
748 | } | ||
749 | while (s) { | ||
750 | r <<= 32; | ||
751 | r |= *(p++); | ||
752 | s--; | ||
753 | } | ||
754 | |||
755 | *cellp = p; | ||
756 | return r; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Very dumb function for adding to the memory reserve list, but | ||
761 | * we don't need anything smarter at this point | ||
762 | * | ||
763 | * XXX Eventually check for collisions. They should NEVER happen | ||
764 | * if problems seem to show up, it would be a good start to track | ||
765 | * them down. | ||
766 | */ | ||
767 | static void reserve_mem(unsigned long base, unsigned long size) | ||
768 | { | ||
769 | unsigned long offset = reloc_offset(); | ||
770 | unsigned long top = base + size; | ||
771 | unsigned long cnt = RELOC(mem_reserve_cnt); | ||
772 | |||
773 | if (size == 0) | ||
774 | return; | ||
775 | |||
776 | /* We need to always keep one empty entry so that we | ||
777 | * have our terminator with "size" set to 0 since we are | ||
778 | * dumb and just copy this entire array to the boot params | ||
779 | */ | ||
780 | base = _ALIGN_DOWN(base, PAGE_SIZE); | ||
781 | top = _ALIGN_UP(top, PAGE_SIZE); | ||
782 | size = top - base; | ||
783 | |||
784 | if (cnt >= (MEM_RESERVE_MAP_SIZE - 1)) | ||
785 | prom_panic("Memory reserve map exhausted !\n"); | ||
786 | RELOC(mem_reserve_map)[cnt].base = base; | ||
787 | RELOC(mem_reserve_map)[cnt].size = size; | ||
788 | RELOC(mem_reserve_cnt) = cnt + 1; | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * Initialize memory allocation mecanism, parse "memory" nodes and | ||
793 | * obtain that way the top of memory and RMO to setup out local allocator | ||
794 | */ | ||
795 | static void __init prom_init_mem(void) | ||
796 | { | ||
797 | phandle node; | ||
798 | char *path, type[64]; | ||
799 | unsigned int plen; | ||
800 | cell_t *p, *endp; | ||
801 | unsigned long offset = reloc_offset(); | ||
802 | struct prom_t *_prom = PTRRELOC(&prom); | ||
803 | |||
804 | /* | ||
805 | * We iterate the memory nodes to find | ||
806 | * 1) top of RMO (first node) | ||
807 | * 2) top of memory | ||
808 | */ | ||
809 | prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells); | ||
810 | prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells); | ||
811 | |||
812 | prom_debug("scanning memory:\n"); | ||
813 | path = RELOC(prom_scratch); | ||
814 | |||
815 | for (node = 0; prom_next_node(&node); ) { | ||
816 | type[0] = 0; | ||
817 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
818 | |||
819 | if (strcmp(type, RELOC("memory"))) | ||
820 | continue; | ||
821 | |||
822 | plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf)); | ||
823 | if (plen > sizeof(regbuf)) { | ||
824 | prom_printf("memory node too large for buffer !\n"); | ||
825 | plen = sizeof(regbuf); | ||
826 | } | ||
827 | p = RELOC(regbuf); | ||
828 | endp = p + (plen / sizeof(cell_t)); | ||
829 | |||
830 | #ifdef DEBUG_PROM | ||
831 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
832 | call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); | ||
833 | prom_debug(" node %s :\n", path); | ||
834 | #endif /* DEBUG_PROM */ | ||
835 | |||
836 | while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) { | ||
837 | unsigned long base, size; | ||
838 | |||
839 | base = prom_next_cell(_prom->root_addr_cells, &p); | ||
840 | size = prom_next_cell(_prom->root_size_cells, &p); | ||
841 | |||
842 | if (size == 0) | ||
843 | continue; | ||
844 | prom_debug(" %x %x\n", base, size); | ||
845 | if (base == 0) | ||
846 | RELOC(rmo_top) = size; | ||
847 | if ((base + size) > RELOC(ram_top)) | ||
848 | RELOC(ram_top) = base + size; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000); | ||
853 | |||
854 | /* Check if we have an initrd after the kernel, if we do move our bottom | ||
855 | * point to after it | ||
856 | */ | ||
857 | if (RELOC(prom_initrd_start)) { | ||
858 | if (RELOC(prom_initrd_end) > RELOC(alloc_bottom)) | ||
859 | RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end)); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * If prom_memory_limit is set we reduce the upper limits *except* for | ||
864 | * alloc_top_high. This must be the real top of RAM so we can put | ||
865 | * TCE's up there. | ||
866 | */ | ||
867 | |||
868 | RELOC(alloc_top_high) = RELOC(ram_top); | ||
869 | |||
870 | if (RELOC(prom_memory_limit)) { | ||
871 | if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { | ||
872 | prom_printf("Ignoring mem=%x <= alloc_bottom.\n", | ||
873 | RELOC(prom_memory_limit)); | ||
874 | RELOC(prom_memory_limit) = 0; | ||
875 | } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { | ||
876 | prom_printf("Ignoring mem=%x >= ram_top.\n", | ||
877 | RELOC(prom_memory_limit)); | ||
878 | RELOC(prom_memory_limit) = 0; | ||
879 | } else { | ||
880 | RELOC(ram_top) = RELOC(prom_memory_limit); | ||
881 | RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * Setup our top alloc point, that is top of RMO or top of | ||
887 | * segment 0 when running non-LPAR. | ||
888 | */ | ||
889 | if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) | ||
890 | RELOC(alloc_top) = RELOC(rmo_top); | ||
891 | else | ||
892 | /* Some RS64 machines have buggy firmware where claims up at 1GB | ||
893 | * fails. Cap at 768MB as a workaround. Still plenty of room. | ||
894 | */ | ||
895 | RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top)); | ||
896 | |||
897 | prom_printf("memory layout at init:\n"); | ||
898 | prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); | ||
899 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
900 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); | ||
901 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
902 | prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); | ||
903 | prom_printf(" ram_top : %x\n", RELOC(ram_top)); | ||
904 | } | ||
905 | |||
906 | |||
907 | /* | ||
908 | * Allocate room for and instanciate RTAS | ||
909 | */ | ||
910 | static void __init prom_instantiate_rtas(void) | ||
911 | { | ||
912 | unsigned long offset = reloc_offset(); | ||
913 | struct prom_t *_prom = PTRRELOC(&prom); | ||
914 | phandle rtas_node; | ||
915 | ihandle rtas_inst; | ||
916 | u32 base, entry = 0; | ||
917 | u32 size = 0; | ||
918 | |||
919 | prom_debug("prom_instantiate_rtas: start...\n"); | ||
920 | |||
921 | rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); | ||
922 | prom_debug("rtas_node: %x\n", rtas_node); | ||
923 | if (!PHANDLE_VALID(rtas_node)) | ||
924 | return; | ||
925 | |||
926 | prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); | ||
927 | if (size == 0) | ||
928 | return; | ||
929 | |||
930 | base = alloc_down(size, PAGE_SIZE, 0); | ||
931 | if (base == 0) { | ||
932 | prom_printf("RTAS allocation failed !\n"); | ||
933 | return; | ||
934 | } | ||
935 | |||
936 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); | ||
937 | if (!IHANDLE_VALID(rtas_inst)) { | ||
938 | prom_printf("opening rtas package failed"); | ||
939 | return; | ||
940 | } | ||
941 | |||
942 | prom_printf("instantiating rtas at 0x%x ...", base); | ||
943 | |||
944 | if (call_prom("call-method", 3, 2, | ||
945 | ADDR("instantiate-rtas"), | ||
946 | rtas_inst, base) != PROM_ERROR) { | ||
947 | entry = (long)_prom->args.rets[1]; | ||
948 | } | ||
949 | if (entry == 0) { | ||
950 | prom_printf(" failed\n"); | ||
951 | return; | ||
952 | } | ||
953 | prom_printf(" done\n"); | ||
954 | |||
955 | reserve_mem(base, size); | ||
956 | |||
957 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); | ||
958 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); | ||
959 | |||
960 | prom_debug("rtas base = 0x%x\n", base); | ||
961 | prom_debug("rtas entry = 0x%x\n", entry); | ||
962 | prom_debug("rtas size = 0x%x\n", (long)size); | ||
963 | |||
964 | prom_debug("prom_instantiate_rtas: end...\n"); | ||
965 | } | ||
966 | |||
967 | |||
968 | /* | ||
969 | * Allocate room for and initialize TCE tables | ||
970 | */ | ||
971 | static void __init prom_initialize_tce_table(void) | ||
972 | { | ||
973 | phandle node; | ||
974 | ihandle phb_node; | ||
975 | unsigned long offset = reloc_offset(); | ||
976 | char compatible[64], type[64], model[64]; | ||
977 | char *path = RELOC(prom_scratch); | ||
978 | u64 base, align; | ||
979 | u32 minalign, minsize; | ||
980 | u64 tce_entry, *tce_entryp; | ||
981 | u64 local_alloc_top, local_alloc_bottom; | ||
982 | u64 i; | ||
983 | |||
984 | if (RELOC(ppc64_iommu_off)) | ||
985 | return; | ||
986 | |||
987 | prom_debug("starting prom_initialize_tce_table\n"); | ||
988 | |||
989 | /* Cache current top of allocs so we reserve a single block */ | ||
990 | local_alloc_top = RELOC(alloc_top_high); | ||
991 | local_alloc_bottom = local_alloc_top; | ||
992 | |||
993 | /* Search all nodes looking for PHBs. */ | ||
994 | for (node = 0; prom_next_node(&node); ) { | ||
995 | compatible[0] = 0; | ||
996 | type[0] = 0; | ||
997 | model[0] = 0; | ||
998 | prom_getprop(node, "compatible", | ||
999 | compatible, sizeof(compatible)); | ||
1000 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1001 | prom_getprop(node, "model", model, sizeof(model)); | ||
1002 | |||
1003 | if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) | ||
1004 | continue; | ||
1005 | |||
1006 | /* Keep the old logic in tack to avoid regression. */ | ||
1007 | if (compatible[0] != 0) { | ||
1008 | if ((strstr(compatible, RELOC("python")) == NULL) && | ||
1009 | (strstr(compatible, RELOC("Speedwagon")) == NULL) && | ||
1010 | (strstr(compatible, RELOC("Winnipeg")) == NULL)) | ||
1011 | continue; | ||
1012 | } else if (model[0] != 0) { | ||
1013 | if ((strstr(model, RELOC("ython")) == NULL) && | ||
1014 | (strstr(model, RELOC("peedwagon")) == NULL) && | ||
1015 | (strstr(model, RELOC("innipeg")) == NULL)) | ||
1016 | continue; | ||
1017 | } | ||
1018 | |||
1019 | if (prom_getprop(node, "tce-table-minalign", &minalign, | ||
1020 | sizeof(minalign)) == PROM_ERROR) | ||
1021 | minalign = 0; | ||
1022 | if (prom_getprop(node, "tce-table-minsize", &minsize, | ||
1023 | sizeof(minsize)) == PROM_ERROR) | ||
1024 | minsize = 4UL << 20; | ||
1025 | |||
1026 | /* | ||
1027 | * Even though we read what OF wants, we just set the table | ||
1028 | * size to 4 MB. This is enough to map 2GB of PCI DMA space. | ||
1029 | * By doing this, we avoid the pitfalls of trying to DMA to | ||
1030 | * MMIO space and the DMA alias hole. | ||
1031 | * | ||
1032 | * On POWER4, firmware sets the TCE region by assuming | ||
1033 | * each TCE table is 8MB. Using this memory for anything | ||
1034 | * else will impact performance, so we always allocate 8MB. | ||
1035 | * Anton | ||
1036 | */ | ||
1037 | if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) | ||
1038 | minsize = 8UL << 20; | ||
1039 | else | ||
1040 | minsize = 4UL << 20; | ||
1041 | |||
1042 | /* Align to the greater of the align or size */ | ||
1043 | align = max(minalign, minsize); | ||
1044 | base = alloc_down(minsize, align, 1); | ||
1045 | if (base == 0) | ||
1046 | prom_panic("ERROR, cannot find space for TCE table.\n"); | ||
1047 | if (base < local_alloc_bottom) | ||
1048 | local_alloc_bottom = base; | ||
1049 | |||
1050 | /* Save away the TCE table attributes for later use. */ | ||
1051 | prom_setprop(node, "linux,tce-base", &base, sizeof(base)); | ||
1052 | prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1053 | |||
1054 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1055 | memset(path, 0, sizeof(path)); | ||
1056 | /* Call OF to setup the TCE hardware */ | ||
1057 | if (call_prom("package-to-path", 3, 1, node, | ||
1058 | path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) { | ||
1059 | prom_printf("package-to-path failed\n"); | ||
1060 | } | ||
1061 | |||
1062 | prom_debug("TCE table: %s\n", path); | ||
1063 | prom_debug("\tnode = 0x%x\n", node); | ||
1064 | prom_debug("\tbase = 0x%x\n", base); | ||
1065 | prom_debug("\tsize = 0x%x\n", minsize); | ||
1066 | |||
1067 | /* Initialize the table to have a one-to-one mapping | ||
1068 | * over the allocated size. | ||
1069 | */ | ||
1070 | tce_entryp = (unsigned long *)base; | ||
1071 | for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { | ||
1072 | tce_entry = (i << PAGE_SHIFT); | ||
1073 | tce_entry |= 0x3; | ||
1074 | *tce_entryp = tce_entry; | ||
1075 | } | ||
1076 | |||
1077 | prom_printf("opening PHB %s", path); | ||
1078 | phb_node = call_prom("open", 1, 1, path); | ||
1079 | if (phb_node == 0) | ||
1080 | prom_printf("... failed\n"); | ||
1081 | else | ||
1082 | prom_printf("... done\n"); | ||
1083 | |||
1084 | call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"), | ||
1085 | phb_node, -1, minsize, | ||
1086 | (u32) base, (u32) (base >> 32)); | ||
1087 | call_prom("close", 1, 0, phb_node); | ||
1088 | } | ||
1089 | |||
1090 | reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); | ||
1091 | |||
1092 | if (RELOC(prom_memory_limit)) { | ||
1093 | /* | ||
1094 | * We align the start to a 16MB boundary so we can map the TCE area | ||
1095 | * using large pages if possible. The end should be the top of RAM | ||
1096 | * so no need to align it. | ||
1097 | */ | ||
1098 | RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000); | ||
1099 | RELOC(prom_tce_alloc_end) = local_alloc_top; | ||
1100 | } | ||
1101 | |||
1102 | /* Flag the first invalid entry */ | ||
1103 | prom_debug("ending prom_initialize_tce_table\n"); | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1107 | * With CHRP SMP we need to use the OF to start the other | ||
1108 | * processors so we can't wait until smp_boot_cpus (the OF is | ||
1109 | * trashed by then) so we have to put the processors into | ||
1110 | * a holding pattern controlled by the kernel (not OF) before | ||
1111 | * we destroy the OF. | ||
1112 | * | ||
1113 | * This uses a chunk of low memory, puts some holding pattern | ||
1114 | * code there and sends the other processors off to there until | ||
1115 | * smp_boot_cpus tells them to do something. The holding pattern | ||
1116 | * checks that address until its cpu # is there, when it is that | ||
1117 | * cpu jumps to __secondary_start(). smp_boot_cpus() takes care | ||
1118 | * of setting those values. | ||
1119 | * | ||
1120 | * We also use physical address 0x4 here to tell when a cpu | ||
1121 | * is in its holding pattern code. | ||
1122 | * | ||
1123 | * Fixup comment... DRENG / PPPBBB - Peter | ||
1124 | * | ||
1125 | * -- Cort | ||
1126 | */ | ||
1127 | static void __init prom_hold_cpus(void) | ||
1128 | { | ||
1129 | unsigned long i; | ||
1130 | unsigned int reg; | ||
1131 | phandle node; | ||
1132 | unsigned long offset = reloc_offset(); | ||
1133 | char type[64]; | ||
1134 | int cpuid = 0; | ||
1135 | unsigned int interrupt_server[MAX_CPU_THREADS]; | ||
1136 | unsigned int cpu_threads, hw_cpu_num; | ||
1137 | int propsize; | ||
1138 | extern void __secondary_hold(void); | ||
1139 | extern unsigned long __secondary_hold_spinloop; | ||
1140 | extern unsigned long __secondary_hold_acknowledge; | ||
1141 | unsigned long *spinloop | ||
1142 | = (void *)virt_to_abs(&__secondary_hold_spinloop); | ||
1143 | unsigned long *acknowledge | ||
1144 | = (void *)virt_to_abs(&__secondary_hold_acknowledge); | ||
1145 | unsigned long secondary_hold | ||
1146 | = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold)); | ||
1147 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1148 | |||
1149 | prom_debug("prom_hold_cpus: start...\n"); | ||
1150 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); | ||
1151 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); | ||
1152 | prom_debug(" 1) acknowledge = 0x%x\n", | ||
1153 | (unsigned long)acknowledge); | ||
1154 | prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge); | ||
1155 | prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold); | ||
1156 | |||
1157 | /* Set the common spinloop variable, so all of the secondary cpus | ||
1158 | * will block when they are awakened from their OF spinloop. | ||
1159 | * This must occur for both SMP and non SMP kernels, since OF will | ||
1160 | * be trashed when we move the kernel. | ||
1161 | */ | ||
1162 | *spinloop = 0; | ||
1163 | |||
1164 | #ifdef CONFIG_HMT | ||
1165 | for (i=0; i < NR_CPUS; i++) { | ||
1166 | RELOC(hmt_thread_data)[i].pir = 0xdeadbeef; | ||
1167 | } | ||
1168 | #endif | ||
1169 | /* look for cpus */ | ||
1170 | for (node = 0; prom_next_node(&node); ) { | ||
1171 | type[0] = 0; | ||
1172 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1173 | if (strcmp(type, RELOC("cpu")) != 0) | ||
1174 | continue; | ||
1175 | |||
1176 | /* Skip non-configured cpus. */ | ||
1177 | if (prom_getprop(node, "status", type, sizeof(type)) > 0) | ||
1178 | if (strcmp(type, RELOC("okay")) != 0) | ||
1179 | continue; | ||
1180 | |||
1181 | reg = -1; | ||
1182 | prom_getprop(node, "reg", ®, sizeof(reg)); | ||
1183 | |||
1184 | prom_debug("\ncpuid = 0x%x\n", cpuid); | ||
1185 | prom_debug("cpu hw idx = 0x%x\n", reg); | ||
1186 | |||
1187 | /* Init the acknowledge var which will be reset by | ||
1188 | * the secondary cpu when it awakens from its OF | ||
1189 | * spinloop. | ||
1190 | */ | ||
1191 | *acknowledge = (unsigned long)-1; | ||
1192 | |||
1193 | propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s", | ||
1194 | &interrupt_server, | ||
1195 | sizeof(interrupt_server)); | ||
1196 | if (propsize < 0) { | ||
1197 | /* no property. old hardware has no SMT */ | ||
1198 | cpu_threads = 1; | ||
1199 | interrupt_server[0] = reg; /* fake it with phys id */ | ||
1200 | } else { | ||
1201 | /* We have a threaded processor */ | ||
1202 | cpu_threads = propsize / sizeof(u32); | ||
1203 | if (cpu_threads > MAX_CPU_THREADS) { | ||
1204 | prom_printf("SMT: too many threads!\n" | ||
1205 | "SMT: found %x, max is %x\n", | ||
1206 | cpu_threads, MAX_CPU_THREADS); | ||
1207 | cpu_threads = 1; /* ToDo: panic? */ | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | hw_cpu_num = interrupt_server[0]; | ||
1212 | if (hw_cpu_num != _prom->cpu) { | ||
1213 | /* Primary Thread of non-boot cpu */ | ||
1214 | prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg); | ||
1215 | call_prom("start-cpu", 3, 0, node, | ||
1216 | secondary_hold, reg); | ||
1217 | |||
1218 | for ( i = 0 ; (i < 100000000) && | ||
1219 | (*acknowledge == ((unsigned long)-1)); i++ ) | ||
1220 | mb(); | ||
1221 | |||
1222 | if (*acknowledge == reg) { | ||
1223 | prom_printf("done\n"); | ||
1224 | /* We have to get every CPU out of OF, | ||
1225 | * even if we never start it. */ | ||
1226 | if (cpuid >= NR_CPUS) | ||
1227 | goto next; | ||
1228 | } else { | ||
1229 | prom_printf("failed: %x\n", *acknowledge); | ||
1230 | } | ||
1231 | } | ||
1232 | #ifdef CONFIG_SMP | ||
1233 | else | ||
1234 | prom_printf("%x : boot cpu %x\n", cpuid, reg); | ||
1235 | #endif | ||
1236 | next: | ||
1237 | #ifdef CONFIG_SMP | ||
1238 | /* Init paca for secondary threads. They start later. */ | ||
1239 | for (i=1; i < cpu_threads; i++) { | ||
1240 | cpuid++; | ||
1241 | if (cpuid >= NR_CPUS) | ||
1242 | continue; | ||
1243 | } | ||
1244 | #endif /* CONFIG_SMP */ | ||
1245 | cpuid++; | ||
1246 | } | ||
1247 | #ifdef CONFIG_HMT | ||
1248 | /* Only enable HMT on processors that provide support. */ | ||
1249 | if (__is_processor(PV_PULSAR) || | ||
1250 | __is_processor(PV_ICESTAR) || | ||
1251 | __is_processor(PV_SSTAR)) { | ||
1252 | prom_printf(" starting secondary threads\n"); | ||
1253 | |||
1254 | for (i = 0; i < NR_CPUS; i += 2) { | ||
1255 | if (!cpu_online(i)) | ||
1256 | continue; | ||
1257 | |||
1258 | if (i == 0) { | ||
1259 | unsigned long pir = mfspr(SPRN_PIR); | ||
1260 | if (__is_processor(PV_PULSAR)) { | ||
1261 | RELOC(hmt_thread_data)[i].pir = | ||
1262 | pir & 0x1f; | ||
1263 | } else { | ||
1264 | RELOC(hmt_thread_data)[i].pir = | ||
1265 | pir & 0x3ff; | ||
1266 | } | ||
1267 | } | ||
1268 | } | ||
1269 | } else { | ||
1270 | prom_printf("Processor is not HMT capable\n"); | ||
1271 | } | ||
1272 | #endif | ||
1273 | |||
1274 | if (cpuid > NR_CPUS) | ||
1275 | prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS) | ||
1276 | ") exceeded: ignoring extras\n"); | ||
1277 | |||
1278 | prom_debug("prom_hold_cpus: end...\n"); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | static void __init prom_init_client_services(unsigned long pp) | ||
1283 | { | ||
1284 | unsigned long offset = reloc_offset(); | ||
1285 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1286 | |||
1287 | /* Get a handle to the prom entry point before anything else */ | ||
1288 | _prom->entry = pp; | ||
1289 | |||
1290 | /* Init default value for phys size */ | ||
1291 | _prom->root_size_cells = 1; | ||
1292 | _prom->root_addr_cells = 2; | ||
1293 | |||
1294 | /* get a handle for the stdout device */ | ||
1295 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); | ||
1296 | if (!PHANDLE_VALID(_prom->chosen)) | ||
1297 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ | ||
1298 | |||
1299 | /* get device tree root */ | ||
1300 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); | ||
1301 | if (!PHANDLE_VALID(_prom->root)) | ||
1302 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ | ||
1303 | } | ||
1304 | |||
1305 | static void __init prom_init_stdout(void) | ||
1306 | { | ||
1307 | unsigned long offset = reloc_offset(); | ||
1308 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1309 | char *path = RELOC(of_stdout_device); | ||
1310 | char type[16]; | ||
1311 | u32 val; | ||
1312 | |||
1313 | if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0) | ||
1314 | prom_panic("cannot find stdout"); | ||
1315 | |||
1316 | _prom->stdout = val; | ||
1317 | |||
1318 | /* Get the full OF pathname of the stdout device */ | ||
1319 | memset(path, 0, 256); | ||
1320 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); | ||
1321 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); | ||
1322 | prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); | ||
1323 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); | ||
1324 | prom_setprop(_prom->chosen, "linux,stdout-path", | ||
1325 | RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); | ||
1326 | |||
1327 | /* If it's a display, note it */ | ||
1328 | memset(type, 0, sizeof(type)); | ||
1329 | prom_getprop(val, "device_type", type, sizeof(type)); | ||
1330 | if (strcmp(type, RELOC("display")) == 0) { | ||
1331 | _prom->disp_node = val; | ||
1332 | prom_setprop(val, "linux,boot-display", NULL, 0); | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | static void __init prom_close_stdin(void) | ||
1337 | { | ||
1338 | unsigned long offset = reloc_offset(); | ||
1339 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1340 | ihandle val; | ||
1341 | |||
1342 | if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0) | ||
1343 | call_prom("close", 1, 0, val); | ||
1344 | } | ||
1345 | |||
1346 | static int __init prom_find_machine_type(void) | ||
1347 | { | ||
1348 | unsigned long offset = reloc_offset(); | ||
1349 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1350 | char compat[256]; | ||
1351 | int len, i = 0; | ||
1352 | phandle rtas; | ||
1353 | |||
1354 | len = prom_getprop(_prom->root, "compatible", | ||
1355 | compat, sizeof(compat)-1); | ||
1356 | if (len > 0) { | ||
1357 | compat[len] = 0; | ||
1358 | while (i < len) { | ||
1359 | char *p = &compat[i]; | ||
1360 | int sl = strlen(p); | ||
1361 | if (sl == 0) | ||
1362 | break; | ||
1363 | if (strstr(p, RELOC("Power Macintosh")) || | ||
1364 | strstr(p, RELOC("MacRISC4"))) | ||
1365 | return PLATFORM_POWERMAC; | ||
1366 | if (strstr(p, RELOC("Momentum,Maple"))) | ||
1367 | return PLATFORM_MAPLE; | ||
1368 | i += sl + 1; | ||
1369 | } | ||
1370 | } | ||
1371 | /* Default to pSeries. We need to know if we are running LPAR */ | ||
1372 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | ||
1373 | if (PHANDLE_VALID(rtas)) { | ||
1374 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); | ||
1375 | if (x != PROM_ERROR) { | ||
1376 | prom_printf("Hypertas detected, assuming LPAR !\n"); | ||
1377 | return PLATFORM_PSERIES_LPAR; | ||
1378 | } | ||
1379 | } | ||
1380 | return PLATFORM_PSERIES; | ||
1381 | } | ||
1382 | |||
1383 | static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) | ||
1384 | { | ||
1385 | unsigned long offset = reloc_offset(); | ||
1386 | |||
1387 | return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r); | ||
1388 | } | ||
1389 | |||
1390 | /* | ||
1391 | * If we have a display that we don't know how to drive, | ||
1392 | * we will want to try to execute OF's open method for it | ||
1393 | * later. However, OF will probably fall over if we do that | ||
1394 | * we've taken over the MMU. | ||
1395 | * So we check whether we will need to open the display, | ||
1396 | * and if so, open it now. | ||
1397 | */ | ||
1398 | static void __init prom_check_displays(void) | ||
1399 | { | ||
1400 | unsigned long offset = reloc_offset(); | ||
1401 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1402 | char type[16], *path; | ||
1403 | phandle node; | ||
1404 | ihandle ih; | ||
1405 | int i; | ||
1406 | |||
1407 | static unsigned char default_colors[] = { | ||
1408 | 0x00, 0x00, 0x00, | ||
1409 | 0x00, 0x00, 0xaa, | ||
1410 | 0x00, 0xaa, 0x00, | ||
1411 | 0x00, 0xaa, 0xaa, | ||
1412 | 0xaa, 0x00, 0x00, | ||
1413 | 0xaa, 0x00, 0xaa, | ||
1414 | 0xaa, 0xaa, 0x00, | ||
1415 | 0xaa, 0xaa, 0xaa, | ||
1416 | 0x55, 0x55, 0x55, | ||
1417 | 0x55, 0x55, 0xff, | ||
1418 | 0x55, 0xff, 0x55, | ||
1419 | 0x55, 0xff, 0xff, | ||
1420 | 0xff, 0x55, 0x55, | ||
1421 | 0xff, 0x55, 0xff, | ||
1422 | 0xff, 0xff, 0x55, | ||
1423 | 0xff, 0xff, 0xff | ||
1424 | }; | ||
1425 | const unsigned char *clut; | ||
1426 | |||
1427 | prom_printf("Looking for displays\n"); | ||
1428 | for (node = 0; prom_next_node(&node); ) { | ||
1429 | memset(type, 0, sizeof(type)); | ||
1430 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1431 | if (strcmp(type, RELOC("display")) != 0) | ||
1432 | continue; | ||
1433 | |||
1434 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1435 | path = RELOC(prom_scratch); | ||
1436 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
1437 | |||
1438 | /* | ||
1439 | * leave some room at the end of the path for appending extra | ||
1440 | * arguments | ||
1441 | */ | ||
1442 | if (call_prom("package-to-path", 3, 1, node, path, | ||
1443 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | ||
1444 | continue; | ||
1445 | prom_printf("found display : %s, opening ... ", path); | ||
1446 | |||
1447 | ih = call_prom("open", 1, 1, path); | ||
1448 | if (ih == 0) { | ||
1449 | prom_printf("failed\n"); | ||
1450 | continue; | ||
1451 | } | ||
1452 | |||
1453 | /* Success */ | ||
1454 | prom_printf("done\n"); | ||
1455 | prom_setprop(node, "linux,opened", NULL, 0); | ||
1456 | |||
1457 | /* | ||
1458 | * stdout wasn't a display node, pick the first we can find | ||
1459 | * for btext | ||
1460 | */ | ||
1461 | if (_prom->disp_node == 0) | ||
1462 | _prom->disp_node = node; | ||
1463 | |||
1464 | /* Setup a useable color table when the appropriate | ||
1465 | * method is available. Should update this to set-colors */ | ||
1466 | clut = RELOC(default_colors); | ||
1467 | for (i = 0; i < 32; i++, clut += 3) | ||
1468 | if (prom_set_color(ih, i, clut[0], clut[1], | ||
1469 | clut[2]) != 0) | ||
1470 | break; | ||
1471 | |||
1472 | #ifdef CONFIG_LOGO_LINUX_CLUT224 | ||
1473 | clut = PTRRELOC(RELOC(logo_linux_clut224.clut)); | ||
1474 | for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3) | ||
1475 | if (prom_set_color(ih, i + 32, clut[0], clut[1], | ||
1476 | clut[2]) != 0) | ||
1477 | break; | ||
1478 | #endif /* CONFIG_LOGO_LINUX_CLUT224 */ | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | /* Return (relocated) pointer to this much memory: moves initrd if reqd. */ | ||
1484 | static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end, | ||
1485 | unsigned long needed, unsigned long align) | ||
1486 | { | ||
1487 | unsigned long offset = reloc_offset(); | ||
1488 | void *ret; | ||
1489 | |||
1490 | *mem_start = _ALIGN(*mem_start, align); | ||
1491 | while ((*mem_start + needed) > *mem_end) { | ||
1492 | unsigned long room, chunk; | ||
1493 | |||
1494 | prom_debug("Chunk exhausted, claiming more at %x...\n", | ||
1495 | RELOC(alloc_bottom)); | ||
1496 | room = RELOC(alloc_top) - RELOC(alloc_bottom); | ||
1497 | if (room > DEVTREE_CHUNK_SIZE) | ||
1498 | room = DEVTREE_CHUNK_SIZE; | ||
1499 | if (room < PAGE_SIZE) | ||
1500 | prom_panic("No memory for flatten_device_tree (no room)"); | ||
1501 | chunk = alloc_up(room, 0); | ||
1502 | if (chunk == 0) | ||
1503 | prom_panic("No memory for flatten_device_tree (claim failed)"); | ||
1504 | *mem_end = RELOC(alloc_top); | ||
1505 | } | ||
1506 | |||
1507 | ret = (void *)*mem_start; | ||
1508 | *mem_start += needed; | ||
1509 | |||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | #define dt_push_token(token, mem_start, mem_end) \ | ||
1514 | do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0) | ||
1515 | |||
1516 | static unsigned long __init dt_find_string(char *str) | ||
1517 | { | ||
1518 | unsigned long offset = reloc_offset(); | ||
1519 | char *s, *os; | ||
1520 | |||
1521 | s = os = (char *)RELOC(dt_string_start); | ||
1522 | s += 4; | ||
1523 | while (s < (char *)RELOC(dt_string_end)) { | ||
1524 | if (strcmp(s, str) == 0) | ||
1525 | return s - os; | ||
1526 | s += strlen(s) + 1; | ||
1527 | } | ||
1528 | return 0; | ||
1529 | } | ||
1530 | |||
1531 | /* | ||
1532 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
1533 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
1534 | */ | ||
1535 | #define MAX_PROPERTY_NAME 64 | ||
1536 | |||
1537 | static void __init scan_dt_build_strings(phandle node, | ||
1538 | unsigned long *mem_start, | ||
1539 | unsigned long *mem_end) | ||
1540 | { | ||
1541 | unsigned long offset = reloc_offset(); | ||
1542 | char *prev_name, *namep, *sstart; | ||
1543 | unsigned long soff; | ||
1544 | phandle child; | ||
1545 | |||
1546 | sstart = (char *)RELOC(dt_string_start); | ||
1547 | |||
1548 | /* get and store all property names */ | ||
1549 | prev_name = RELOC(""); | ||
1550 | for (;;) { | ||
1551 | /* 64 is max len of name including nul. */ | ||
1552 | namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); | ||
1553 | if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) { | ||
1554 | /* No more nodes: unwind alloc */ | ||
1555 | *mem_start = (unsigned long)namep; | ||
1556 | break; | ||
1557 | } | ||
1558 | |||
1559 | /* skip "name" */ | ||
1560 | if (strcmp(namep, RELOC("name")) == 0) { | ||
1561 | *mem_start = (unsigned long)namep; | ||
1562 | prev_name = RELOC("name"); | ||
1563 | continue; | ||
1564 | } | ||
1565 | /* get/create string entry */ | ||
1566 | soff = dt_find_string(namep); | ||
1567 | if (soff != 0) { | ||
1568 | *mem_start = (unsigned long)namep; | ||
1569 | namep = sstart + soff; | ||
1570 | } else { | ||
1571 | /* Trim off some if we can */ | ||
1572 | *mem_start = (unsigned long)namep + strlen(namep) + 1; | ||
1573 | RELOC(dt_string_end) = *mem_start; | ||
1574 | } | ||
1575 | prev_name = namep; | ||
1576 | } | ||
1577 | |||
1578 | /* do all our children */ | ||
1579 | child = call_prom("child", 1, 1, node); | ||
1580 | while (child != 0) { | ||
1581 | scan_dt_build_strings(child, mem_start, mem_end); | ||
1582 | child = call_prom("peer", 1, 1, child); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1586 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | ||
1587 | unsigned long *mem_end) | ||
1588 | { | ||
1589 | phandle child; | ||
1590 | char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; | ||
1591 | unsigned long soff; | ||
1592 | unsigned char *valp; | ||
1593 | unsigned long offset = reloc_offset(); | ||
1594 | static char pname[MAX_PROPERTY_NAME]; | ||
1595 | int l; | ||
1596 | |||
1597 | dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); | ||
1598 | |||
1599 | /* get the node's full name */ | ||
1600 | namep = (char *)*mem_start; | ||
1601 | l = call_prom("package-to-path", 3, 1, node, | ||
1602 | namep, *mem_end - *mem_start); | ||
1603 | if (l >= 0) { | ||
1604 | /* Didn't fit? Get more room. */ | ||
1605 | if ((l+1) > (*mem_end - *mem_start)) { | ||
1606 | namep = make_room(mem_start, mem_end, l+1, 1); | ||
1607 | call_prom("package-to-path", 3, 1, node, namep, l); | ||
1608 | } | ||
1609 | namep[l] = '\0'; | ||
1610 | |||
1611 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
1612 | * middle of the path in some properties | ||
1613 | */ | ||
1614 | for (p = namep, ep = namep + l; p < ep; p++) | ||
1615 | if (*p == '\0') { | ||
1616 | memmove(p, p+1, ep - p); | ||
1617 | ep--; l--; p--; | ||
1618 | } | ||
1619 | |||
1620 | /* now try to extract the unit name in that mess */ | ||
1621 | for (p = namep, lp = NULL; *p; p++) | ||
1622 | if (*p == '/') | ||
1623 | lp = p + 1; | ||
1624 | if (lp != NULL) | ||
1625 | memmove(namep, lp, strlen(lp) + 1); | ||
1626 | *mem_start = _ALIGN(((unsigned long) namep) + | ||
1627 | strlen(namep) + 1, 4); | ||
1628 | } | ||
1629 | |||
1630 | /* get it again for debugging */ | ||
1631 | path = RELOC(prom_scratch); | ||
1632 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
1633 | call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); | ||
1634 | |||
1635 | /* get and store all properties */ | ||
1636 | prev_name = RELOC(""); | ||
1637 | sstart = (char *)RELOC(dt_string_start); | ||
1638 | for (;;) { | ||
1639 | if (call_prom("nextprop", 3, 1, node, prev_name, | ||
1640 | RELOC(pname)) != 1) | ||
1641 | break; | ||
1642 | |||
1643 | /* skip "name" */ | ||
1644 | if (strcmp(RELOC(pname), RELOC("name")) == 0) { | ||
1645 | prev_name = RELOC("name"); | ||
1646 | continue; | ||
1647 | } | ||
1648 | |||
1649 | /* find string offset */ | ||
1650 | soff = dt_find_string(RELOC(pname)); | ||
1651 | if (soff == 0) { | ||
1652 | prom_printf("WARNING: Can't find string index for" | ||
1653 | " <%s>, node %s\n", RELOC(pname), path); | ||
1654 | break; | ||
1655 | } | ||
1656 | prev_name = sstart + soff; | ||
1657 | |||
1658 | /* get length */ | ||
1659 | l = call_prom("getproplen", 2, 1, node, RELOC(pname)); | ||
1660 | |||
1661 | /* sanity checks */ | ||
1662 | if (l == PROM_ERROR) | ||
1663 | continue; | ||
1664 | if (l > MAX_PROPERTY_LENGTH) { | ||
1665 | prom_printf("WARNING: ignoring large property "); | ||
1666 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1667 | prom_printf("[%s] ", path); | ||
1668 | prom_printf("%s length 0x%x\n", RELOC(pname), l); | ||
1669 | continue; | ||
1670 | } | ||
1671 | |||
1672 | /* push property head */ | ||
1673 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | ||
1674 | dt_push_token(l, mem_start, mem_end); | ||
1675 | dt_push_token(soff, mem_start, mem_end); | ||
1676 | |||
1677 | /* push property content */ | ||
1678 | valp = make_room(mem_start, mem_end, l, 4); | ||
1679 | call_prom("getprop", 4, 1, node, RELOC(pname), valp, l); | ||
1680 | *mem_start = _ALIGN(*mem_start, 4); | ||
1681 | } | ||
1682 | |||
1683 | /* Add a "linux,phandle" property. */ | ||
1684 | soff = dt_find_string(RELOC("linux,phandle")); | ||
1685 | if (soff == 0) | ||
1686 | prom_printf("WARNING: Can't find string index for" | ||
1687 | " <linux-phandle> node %s\n", path); | ||
1688 | else { | ||
1689 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | ||
1690 | dt_push_token(4, mem_start, mem_end); | ||
1691 | dt_push_token(soff, mem_start, mem_end); | ||
1692 | valp = make_room(mem_start, mem_end, 4, 4); | ||
1693 | *(u32 *)valp = node; | ||
1694 | } | ||
1695 | |||
1696 | /* do all our children */ | ||
1697 | child = call_prom("child", 1, 1, node); | ||
1698 | while (child != 0) { | ||
1699 | scan_dt_build_struct(child, mem_start, mem_end); | ||
1700 | child = call_prom("peer", 1, 1, child); | ||
1701 | } | ||
1702 | |||
1703 | dt_push_token(OF_DT_END_NODE, mem_start, mem_end); | ||
1704 | } | ||
1705 | |||
1706 | static void __init flatten_device_tree(void) | ||
1707 | { | ||
1708 | phandle root; | ||
1709 | unsigned long offset = reloc_offset(); | ||
1710 | unsigned long mem_start, mem_end, room; | ||
1711 | struct boot_param_header *hdr; | ||
1712 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1713 | char *namep; | ||
1714 | u64 *rsvmap; | ||
1715 | |||
1716 | /* | ||
1717 | * Check how much room we have between alloc top & bottom (+/- a | ||
1718 | * few pages), crop to 4Mb, as this is our "chuck" size | ||
1719 | */ | ||
1720 | room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000; | ||
1721 | if (room > DEVTREE_CHUNK_SIZE) | ||
1722 | room = DEVTREE_CHUNK_SIZE; | ||
1723 | prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom)); | ||
1724 | |||
1725 | /* Now try to claim that */ | ||
1726 | mem_start = (unsigned long)alloc_up(room, PAGE_SIZE); | ||
1727 | if (mem_start == 0) | ||
1728 | prom_panic("Can't allocate initial device-tree chunk\n"); | ||
1729 | mem_end = RELOC(alloc_top); | ||
1730 | |||
1731 | /* Get root of tree */ | ||
1732 | root = call_prom("peer", 1, 1, (phandle)0); | ||
1733 | if (root == (phandle)0) | ||
1734 | prom_panic ("couldn't get device tree root\n"); | ||
1735 | |||
1736 | /* Build header and make room for mem rsv map */ | ||
1737 | mem_start = _ALIGN(mem_start, 4); | ||
1738 | hdr = make_room(&mem_start, &mem_end, | ||
1739 | sizeof(struct boot_param_header), 4); | ||
1740 | RELOC(dt_header_start) = (unsigned long)hdr; | ||
1741 | rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); | ||
1742 | |||
1743 | /* Start of strings */ | ||
1744 | mem_start = PAGE_ALIGN(mem_start); | ||
1745 | RELOC(dt_string_start) = mem_start; | ||
1746 | mem_start += 4; /* hole */ | ||
1747 | |||
1748 | /* Add "linux,phandle" in there, we'll need it */ | ||
1749 | namep = make_room(&mem_start, &mem_end, 16, 1); | ||
1750 | strcpy(namep, RELOC("linux,phandle")); | ||
1751 | mem_start = (unsigned long)namep + strlen(namep) + 1; | ||
1752 | |||
1753 | /* Build string array */ | ||
1754 | prom_printf("Building dt strings...\n"); | ||
1755 | scan_dt_build_strings(root, &mem_start, &mem_end); | ||
1756 | RELOC(dt_string_end) = mem_start; | ||
1757 | |||
1758 | /* Build structure */ | ||
1759 | mem_start = PAGE_ALIGN(mem_start); | ||
1760 | RELOC(dt_struct_start) = mem_start; | ||
1761 | prom_printf("Building dt structure...\n"); | ||
1762 | scan_dt_build_struct(root, &mem_start, &mem_end); | ||
1763 | dt_push_token(OF_DT_END, &mem_start, &mem_end); | ||
1764 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); | ||
1765 | |||
1766 | /* Finish header */ | ||
1767 | hdr->boot_cpuid_phys = _prom->cpu; | ||
1768 | hdr->magic = OF_DT_HEADER; | ||
1769 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); | ||
1770 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); | ||
1771 | hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); | ||
1772 | hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start); | ||
1773 | hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); | ||
1774 | hdr->version = OF_DT_VERSION; | ||
1775 | /* Version 16 is not backward compatible */ | ||
1776 | hdr->last_comp_version = 0x10; | ||
1777 | |||
1778 | /* Reserve the whole thing and copy the reserve map in, we | ||
1779 | * also bump mem_reserve_cnt to cause further reservations to | ||
1780 | * fail since it's too late. | ||
1781 | */ | ||
1782 | reserve_mem(RELOC(dt_header_start), hdr->totalsize); | ||
1783 | memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); | ||
1784 | |||
1785 | #ifdef DEBUG_PROM | ||
1786 | { | ||
1787 | int i; | ||
1788 | prom_printf("reserved memory map:\n"); | ||
1789 | for (i = 0; i < RELOC(mem_reserve_cnt); i++) | ||
1790 | prom_printf(" %x - %x\n", RELOC(mem_reserve_map)[i].base, | ||
1791 | RELOC(mem_reserve_map)[i].size); | ||
1792 | } | ||
1793 | #endif | ||
1794 | RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; | ||
1795 | |||
1796 | prom_printf("Device tree strings 0x%x -> 0x%x\n", | ||
1797 | RELOC(dt_string_start), RELOC(dt_string_end)); | ||
1798 | prom_printf("Device tree struct 0x%x -> 0x%x\n", | ||
1799 | RELOC(dt_struct_start), RELOC(dt_struct_end)); | ||
1800 | |||
1801 | } | ||
1802 | |||
1803 | |||
1804 | static void __init fixup_device_tree(void) | ||
1805 | { | ||
1806 | unsigned long offset = reloc_offset(); | ||
1807 | phandle u3, i2c, mpic; | ||
1808 | u32 u3_rev; | ||
1809 | u32 interrupts[2]; | ||
1810 | u32 parent; | ||
1811 | |||
1812 | /* Some G5s have a missing interrupt definition, fix it up here */ | ||
1813 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | ||
1814 | if (!PHANDLE_VALID(u3)) | ||
1815 | return; | ||
1816 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | ||
1817 | if (!PHANDLE_VALID(i2c)) | ||
1818 | return; | ||
1819 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | ||
1820 | if (!PHANDLE_VALID(mpic)) | ||
1821 | return; | ||
1822 | |||
1823 | /* check if proper rev of u3 */ | ||
1824 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) | ||
1825 | == PROM_ERROR) | ||
1826 | return; | ||
1827 | if (u3_rev < 0x35 || u3_rev > 0x39) | ||
1828 | return; | ||
1829 | /* does it need fixup ? */ | ||
1830 | if (prom_getproplen(i2c, "interrupts") > 0) | ||
1831 | return; | ||
1832 | |||
1833 | prom_printf("fixing up bogus interrupts for u3 i2c...\n"); | ||
1834 | |||
1835 | /* interrupt on this revision of u3 is number 0 and level */ | ||
1836 | interrupts[0] = 0; | ||
1837 | interrupts[1] = 1; | ||
1838 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | ||
1839 | parent = (u32)mpic; | ||
1840 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | ||
1841 | } | ||
1842 | |||
1843 | |||
1844 | static void __init prom_find_boot_cpu(void) | ||
1845 | { | ||
1846 | unsigned long offset = reloc_offset(); | ||
1847 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1848 | u32 getprop_rval; | ||
1849 | ihandle prom_cpu; | ||
1850 | phandle cpu_pkg; | ||
1851 | |||
1852 | if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0) | ||
1853 | prom_panic("cannot find boot cpu"); | ||
1854 | |||
1855 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); | ||
1856 | |||
1857 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); | ||
1858 | _prom->cpu = getprop_rval; | ||
1859 | |||
1860 | prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu); | ||
1861 | } | ||
1862 | |||
1863 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | ||
1864 | { | ||
1865 | #ifdef CONFIG_BLK_DEV_INITRD | ||
1866 | unsigned long offset = reloc_offset(); | ||
1867 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1868 | |||
1869 | if ( r3 && r4 && r4 != 0xdeadbeef) { | ||
1870 | u64 val; | ||
1871 | |||
1872 | RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3; | ||
1873 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; | ||
1874 | |||
1875 | val = (u64)RELOC(prom_initrd_start); | ||
1876 | prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val)); | ||
1877 | val = (u64)RELOC(prom_initrd_end); | ||
1878 | prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val)); | ||
1879 | |||
1880 | reserve_mem(RELOC(prom_initrd_start), | ||
1881 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); | ||
1882 | |||
1883 | prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start)); | ||
1884 | prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end)); | ||
1885 | } | ||
1886 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * We enter here early on, when the Open Firmware prom is still | ||
1891 | * handling exceptions and the MMU hash table for us. | ||
1892 | */ | ||
1893 | |||
1894 | unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp, | ||
1895 | unsigned long r6, unsigned long r7) | ||
1896 | { | ||
1897 | unsigned long offset = reloc_offset(); | ||
1898 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1899 | unsigned long phys = KERNELBASE - offset; | ||
1900 | u32 getprop_rval; | ||
1901 | |||
1902 | /* | ||
1903 | * First zero the BSS | ||
1904 | */ | ||
1905 | memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start); | ||
1906 | |||
1907 | /* | ||
1908 | * Init interface to Open Firmware, get some node references, | ||
1909 | * like /chosen | ||
1910 | */ | ||
1911 | prom_init_client_services(pp); | ||
1912 | |||
1913 | /* | ||
1914 | * Init prom stdout device | ||
1915 | */ | ||
1916 | prom_init_stdout(); | ||
1917 | prom_debug("klimit=0x%x\n", RELOC(klimit)); | ||
1918 | prom_debug("offset=0x%x\n", offset); | ||
1919 | |||
1920 | /* | ||
1921 | * Check for an initrd | ||
1922 | */ | ||
1923 | prom_check_initrd(r3, r4); | ||
1924 | |||
1925 | /* | ||
1926 | * Get default machine type. At this point, we do not differenciate | ||
1927 | * between pSeries SMP and pSeries LPAR | ||
1928 | */ | ||
1929 | RELOC(of_platform) = prom_find_machine_type(); | ||
1930 | getprop_rval = RELOC(of_platform); | ||
1931 | prom_setprop(_prom->chosen, "linux,platform", | ||
1932 | &getprop_rval, sizeof(getprop_rval)); | ||
1933 | |||
1934 | /* | ||
1935 | * On pSeries, inform the firmware about our capabilities | ||
1936 | */ | ||
1937 | if (RELOC(of_platform) == PLATFORM_PSERIES || | ||
1938 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
1939 | prom_send_capabilities(); | ||
1940 | |||
1941 | /* | ||
1942 | * On pSeries and Cell, copy the CPU hold code | ||
1943 | */ | ||
1944 | if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_CELL)) | ||
1945 | copy_and_flush(0, KERNELBASE - offset, 0x100, 0); | ||
1946 | |||
1947 | /* | ||
1948 | * Get memory cells format | ||
1949 | */ | ||
1950 | getprop_rval = 1; | ||
1951 | prom_getprop(_prom->root, "#size-cells", | ||
1952 | &getprop_rval, sizeof(getprop_rval)); | ||
1953 | _prom->root_size_cells = getprop_rval; | ||
1954 | getprop_rval = 2; | ||
1955 | prom_getprop(_prom->root, "#address-cells", | ||
1956 | &getprop_rval, sizeof(getprop_rval)); | ||
1957 | _prom->root_addr_cells = getprop_rval; | ||
1958 | |||
1959 | /* | ||
1960 | * Do early parsing of command line | ||
1961 | */ | ||
1962 | early_cmdline_parse(); | ||
1963 | |||
1964 | /* | ||
1965 | * Initialize memory management within prom_init | ||
1966 | */ | ||
1967 | prom_init_mem(); | ||
1968 | |||
1969 | /* | ||
1970 | * Determine which cpu is actually running right _now_ | ||
1971 | */ | ||
1972 | prom_find_boot_cpu(); | ||
1973 | |||
1974 | /* | ||
1975 | * Initialize display devices | ||
1976 | */ | ||
1977 | prom_check_displays(); | ||
1978 | |||
1979 | /* | ||
1980 | * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else | ||
1981 | * that uses the allocator, we need to make sure we get the top of memory | ||
1982 | * available for us here... | ||
1983 | */ | ||
1984 | if (RELOC(of_platform) == PLATFORM_PSERIES) | ||
1985 | prom_initialize_tce_table(); | ||
1986 | |||
1987 | /* | ||
1988 | * On non-powermacs, try to instantiate RTAS and puts all CPUs | ||
1989 | * in spin-loops. PowerMacs don't have a working RTAS and use | ||
1990 | * a different way to spin CPUs | ||
1991 | */ | ||
1992 | if (RELOC(of_platform) != PLATFORM_POWERMAC) { | ||
1993 | prom_instantiate_rtas(); | ||
1994 | prom_hold_cpus(); | ||
1995 | } | ||
1996 | |||
1997 | /* | ||
1998 | * Fill in some infos for use by the kernel later on | ||
1999 | */ | ||
2000 | if (RELOC(ppc64_iommu_off)) | ||
2001 | prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); | ||
2002 | |||
2003 | if (RELOC(iommu_force_on)) | ||
2004 | prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); | ||
2005 | |||
2006 | if (RELOC(prom_memory_limit)) | ||
2007 | prom_setprop(_prom->chosen, "linux,memory-limit", | ||
2008 | PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit))); | ||
2009 | |||
2010 | if (RELOC(prom_tce_alloc_start)) { | ||
2011 | prom_setprop(_prom->chosen, "linux,tce-alloc-start", | ||
2012 | PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start))); | ||
2013 | prom_setprop(_prom->chosen, "linux,tce-alloc-end", | ||
2014 | PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end))); | ||
2015 | } | ||
2016 | |||
2017 | /* | ||
2018 | * Fixup any known bugs in the device-tree | ||
2019 | */ | ||
2020 | fixup_device_tree(); | ||
2021 | |||
2022 | /* | ||
2023 | * Now finally create the flattened device-tree | ||
2024 | */ | ||
2025 | prom_printf("copying OF device tree ...\n"); | ||
2026 | flatten_device_tree(); | ||
2027 | |||
2028 | /* in case stdin is USB and still active on IBM machines... */ | ||
2029 | prom_close_stdin(); | ||
2030 | |||
2031 | /* | ||
2032 | * Call OF "quiesce" method to shut down pending DMA's from | ||
2033 | * devices etc... | ||
2034 | */ | ||
2035 | prom_printf("Calling quiesce ...\n"); | ||
2036 | call_prom("quiesce", 0, 0); | ||
2037 | |||
2038 | /* | ||
2039 | * And finally, call the kernel passing it the flattened device | ||
2040 | * tree and NULL as r5, thus triggering the new entry point which | ||
2041 | * is common to us and kexec | ||
2042 | */ | ||
2043 | prom_printf("returning from prom_init\n"); | ||
2044 | prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start)); | ||
2045 | prom_debug("->phys=0x%x\n", phys); | ||
2046 | |||
2047 | __start(RELOC(dt_header_start), phys, 0); | ||
2048 | |||
2049 | return 0; | ||
2050 | } | ||
2051 | |||
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c deleted file mode 100644 index 79e7ed2858dd..000000000000 --- a/arch/ppc64/kernel/rtc.c +++ /dev/null | |||
@@ -1,358 +0,0 @@ | |||
1 | /* | ||
2 | * Real Time Clock interface for PPC64. | ||
3 | * | ||
4 | * Based on rtc.c by Paul Gortmaker | ||
5 | * | ||
6 | * This driver allows use of the real time clock | ||
7 | * from user space. It exports the /dev/rtc | ||
8 | * interface supporting various ioctl() and also the | ||
9 | * /proc/driver/rtc pseudo-file for status information. | ||
10 | * | ||
11 | * Interface does not support RTC interrupts nor an alarm. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * 1.0 Mike Corrigan: IBM iSeries rtc support | ||
19 | * 1.1 Dave Engebretsen: IBM pSeries rtc support | ||
20 | */ | ||
21 | |||
22 | #define RTC_VERSION "1.1" | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/fcntl.h> | ||
31 | #include <linux/mc146818rtc.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/proc_fs.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/bcd.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/delay.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/time.h> | ||
44 | #include <asm/rtas.h> | ||
45 | |||
46 | #include <asm/machdep.h> | ||
47 | |||
48 | /* | ||
49 | * We sponge a minor off of the misc major. No need slurping | ||
50 | * up another valuable major dev number for this. If you add | ||
51 | * an ioctl, make sure you don't conflict with SPARC's RTC | ||
52 | * ioctls. | ||
53 | */ | ||
54 | |||
55 | static ssize_t rtc_read(struct file *file, char __user *buf, | ||
56 | size_t count, loff_t *ppos); | ||
57 | |||
58 | static int rtc_ioctl(struct inode *inode, struct file *file, | ||
59 | unsigned int cmd, unsigned long arg); | ||
60 | |||
61 | static int rtc_read_proc(char *page, char **start, off_t off, | ||
62 | int count, int *eof, void *data); | ||
63 | |||
64 | /* | ||
65 | * If this driver ever becomes modularised, it will be really nice | ||
66 | * to make the epoch retain its value across module reload... | ||
67 | */ | ||
68 | |||
69 | static unsigned long epoch = 1900; /* year corresponding to 0x00 */ | ||
70 | |||
71 | static const unsigned char days_in_mo[] = | ||
72 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | ||
73 | |||
74 | /* | ||
75 | * Now all the various file operations that we export. | ||
76 | */ | ||
77 | |||
78 | static ssize_t rtc_read(struct file *file, char __user *buf, | ||
79 | size_t count, loff_t *ppos) | ||
80 | { | ||
81 | return -EIO; | ||
82 | } | ||
83 | |||
84 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
85 | unsigned long arg) | ||
86 | { | ||
87 | struct rtc_time wtime; | ||
88 | |||
89 | switch (cmd) { | ||
90 | case RTC_RD_TIME: /* Read the time/date from RTC */ | ||
91 | { | ||
92 | memset(&wtime, 0, sizeof(struct rtc_time)); | ||
93 | ppc_md.get_rtc_time(&wtime); | ||
94 | break; | ||
95 | } | ||
96 | case RTC_SET_TIME: /* Set the RTC */ | ||
97 | { | ||
98 | struct rtc_time rtc_tm; | ||
99 | unsigned char mon, day, hrs, min, sec, leap_yr; | ||
100 | unsigned int yrs; | ||
101 | |||
102 | if (!capable(CAP_SYS_TIME)) | ||
103 | return -EACCES; | ||
104 | |||
105 | if (copy_from_user(&rtc_tm, (struct rtc_time __user *)arg, | ||
106 | sizeof(struct rtc_time))) | ||
107 | return -EFAULT; | ||
108 | |||
109 | yrs = rtc_tm.tm_year; | ||
110 | mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ | ||
111 | day = rtc_tm.tm_mday; | ||
112 | hrs = rtc_tm.tm_hour; | ||
113 | min = rtc_tm.tm_min; | ||
114 | sec = rtc_tm.tm_sec; | ||
115 | |||
116 | if (yrs < 70) | ||
117 | return -EINVAL; | ||
118 | |||
119 | leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); | ||
120 | |||
121 | if ((mon > 12) || (day == 0)) | ||
122 | return -EINVAL; | ||
123 | |||
124 | if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) | ||
125 | return -EINVAL; | ||
126 | |||
127 | if ((hrs >= 24) || (min >= 60) || (sec >= 60)) | ||
128 | return -EINVAL; | ||
129 | |||
130 | if ( yrs > 169 ) | ||
131 | return -EINVAL; | ||
132 | |||
133 | ppc_md.set_rtc_time(&rtc_tm); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | case RTC_EPOCH_READ: /* Read the epoch. */ | ||
138 | { | ||
139 | return put_user (epoch, (unsigned long __user *)arg); | ||
140 | } | ||
141 | case RTC_EPOCH_SET: /* Set the epoch. */ | ||
142 | { | ||
143 | /* | ||
144 | * There were no RTC clocks before 1900. | ||
145 | */ | ||
146 | if (arg < 1900) | ||
147 | return -EINVAL; | ||
148 | |||
149 | if (!capable(CAP_SYS_TIME)) | ||
150 | return -EACCES; | ||
151 | |||
152 | epoch = arg; | ||
153 | return 0; | ||
154 | } | ||
155 | default: | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | return copy_to_user((void __user *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; | ||
159 | } | ||
160 | |||
161 | static int rtc_open(struct inode *inode, struct file *file) | ||
162 | { | ||
163 | nonseekable_open(inode, file); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int rtc_release(struct inode *inode, struct file *file) | ||
168 | { | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * The various file operations we support. | ||
174 | */ | ||
175 | static struct file_operations rtc_fops = { | ||
176 | .owner = THIS_MODULE, | ||
177 | .llseek = no_llseek, | ||
178 | .read = rtc_read, | ||
179 | .ioctl = rtc_ioctl, | ||
180 | .open = rtc_open, | ||
181 | .release = rtc_release, | ||
182 | }; | ||
183 | |||
184 | static struct miscdevice rtc_dev = { | ||
185 | .minor = RTC_MINOR, | ||
186 | .name = "rtc", | ||
187 | .fops = &rtc_fops | ||
188 | }; | ||
189 | |||
190 | static int __init rtc_init(void) | ||
191 | { | ||
192 | int retval; | ||
193 | |||
194 | retval = misc_register(&rtc_dev); | ||
195 | if(retval < 0) | ||
196 | return retval; | ||
197 | |||
198 | #ifdef CONFIG_PROC_FS | ||
199 | if (create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL) | ||
200 | == NULL) { | ||
201 | misc_deregister(&rtc_dev); | ||
202 | return -ENOMEM; | ||
203 | } | ||
204 | #endif | ||
205 | |||
206 | printk(KERN_INFO "i/pSeries Real Time Clock Driver v" RTC_VERSION "\n"); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static void __exit rtc_exit (void) | ||
212 | { | ||
213 | remove_proc_entry ("driver/rtc", NULL); | ||
214 | misc_deregister(&rtc_dev); | ||
215 | } | ||
216 | |||
217 | module_init(rtc_init); | ||
218 | module_exit(rtc_exit); | ||
219 | |||
220 | /* | ||
221 | * Info exported via "/proc/driver/rtc". | ||
222 | */ | ||
223 | |||
224 | static int rtc_proc_output (char *buf) | ||
225 | { | ||
226 | |||
227 | char *p; | ||
228 | struct rtc_time tm; | ||
229 | |||
230 | p = buf; | ||
231 | |||
232 | ppc_md.get_rtc_time(&tm); | ||
233 | |||
234 | /* | ||
235 | * There is no way to tell if the luser has the RTC set for local | ||
236 | * time or for Universal Standard Time (GMT). Probably local though. | ||
237 | */ | ||
238 | p += sprintf(p, | ||
239 | "rtc_time\t: %02d:%02d:%02d\n" | ||
240 | "rtc_date\t: %04d-%02d-%02d\n" | ||
241 | "rtc_epoch\t: %04lu\n", | ||
242 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
243 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); | ||
244 | |||
245 | p += sprintf(p, | ||
246 | "DST_enable\t: no\n" | ||
247 | "BCD\t\t: yes\n" | ||
248 | "24hr\t\t: yes\n" ); | ||
249 | |||
250 | return p - buf; | ||
251 | } | ||
252 | |||
253 | static int rtc_read_proc(char *page, char **start, off_t off, | ||
254 | int count, int *eof, void *data) | ||
255 | { | ||
256 | int len = rtc_proc_output (page); | ||
257 | if (len <= off+count) *eof = 1; | ||
258 | *start = page + off; | ||
259 | len -= off; | ||
260 | if (len>count) len = count; | ||
261 | if (len<0) len = 0; | ||
262 | return len; | ||
263 | } | ||
264 | |||
265 | #ifdef CONFIG_PPC_RTAS | ||
266 | #define MAX_RTC_WAIT 5000 /* 5 sec */ | ||
267 | #define RTAS_CLOCK_BUSY (-2) | ||
268 | unsigned long rtas_get_boot_time(void) | ||
269 | { | ||
270 | int ret[8]; | ||
271 | int error, wait_time; | ||
272 | unsigned long max_wait_tb; | ||
273 | |||
274 | max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
275 | do { | ||
276 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
277 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
278 | wait_time = rtas_extended_busy_delay_time(error); | ||
279 | /* This is boot time so we spin. */ | ||
280 | udelay(wait_time*1000); | ||
281 | error = RTAS_CLOCK_BUSY; | ||
282 | } | ||
283 | } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); | ||
284 | |||
285 | if (error != 0 && printk_ratelimit()) { | ||
286 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
287 | error); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); | ||
292 | } | ||
293 | |||
294 | /* NOTE: get_rtc_time will get an error if executed in interrupt context | ||
295 | * and if a delay is needed to read the clock. In this case we just | ||
296 | * silently return without updating rtc_tm. | ||
297 | */ | ||
298 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | ||
299 | { | ||
300 | int ret[8]; | ||
301 | int error, wait_time; | ||
302 | unsigned long max_wait_tb; | ||
303 | |||
304 | max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
305 | do { | ||
306 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
307 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
308 | if (in_interrupt() && printk_ratelimit()) { | ||
309 | printk(KERN_WARNING "error: reading clock would delay interrupt\n"); | ||
310 | return; /* delay not allowed */ | ||
311 | } | ||
312 | wait_time = rtas_extended_busy_delay_time(error); | ||
313 | msleep_interruptible(wait_time); | ||
314 | error = RTAS_CLOCK_BUSY; | ||
315 | } | ||
316 | } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); | ||
317 | |||
318 | if (error != 0 && printk_ratelimit()) { | ||
319 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
320 | error); | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | rtc_tm->tm_sec = ret[5]; | ||
325 | rtc_tm->tm_min = ret[4]; | ||
326 | rtc_tm->tm_hour = ret[3]; | ||
327 | rtc_tm->tm_mday = ret[2]; | ||
328 | rtc_tm->tm_mon = ret[1] - 1; | ||
329 | rtc_tm->tm_year = ret[0] - 1900; | ||
330 | } | ||
331 | |||
332 | int rtas_set_rtc_time(struct rtc_time *tm) | ||
333 | { | ||
334 | int error, wait_time; | ||
335 | unsigned long max_wait_tb; | ||
336 | |||
337 | max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
338 | do { | ||
339 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, | ||
340 | tm->tm_year + 1900, tm->tm_mon + 1, | ||
341 | tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
342 | tm->tm_sec, 0); | ||
343 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
344 | if (in_interrupt()) | ||
345 | return 1; /* probably decrementer */ | ||
346 | wait_time = rtas_extended_busy_delay_time(error); | ||
347 | msleep_interruptible(wait_time); | ||
348 | error = RTAS_CLOCK_BUSY; | ||
349 | } | ||
350 | } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); | ||
351 | |||
352 | if (error != 0 && printk_ratelimit()) | ||
353 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | ||
354 | error); | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | #endif | ||
diff --git a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c deleted file mode 100644 index a1c1db573e9c..000000000000 --- a/arch/ppc64/kernel/semaphore.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * PowerPC-specific semaphore code. | ||
5 | * | ||
6 | * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * April 2001 - Reworked by Paul Mackerras <paulus@samba.org> | ||
14 | * to eliminate the SMP races in the old version between the updates | ||
15 | * of `count' and `waking'. Now we use negative `count' values to | ||
16 | * indicate that some process(es) are waiting for the semaphore. | ||
17 | */ | ||
18 | |||
19 | #include <linux/sched.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include <asm/atomic.h> | ||
24 | #include <asm/semaphore.h> | ||
25 | #include <asm/errno.h> | ||
26 | |||
27 | /* | ||
28 | * Atomically update sem->count. | ||
29 | * This does the equivalent of the following: | ||
30 | * | ||
31 | * old_count = sem->count; | ||
32 | * tmp = MAX(old_count, 0) + incr; | ||
33 | * sem->count = tmp; | ||
34 | * return old_count; | ||
35 | */ | ||
36 | static inline int __sem_update_count(struct semaphore *sem, int incr) | ||
37 | { | ||
38 | int old_count, tmp; | ||
39 | |||
40 | __asm__ __volatile__("\n" | ||
41 | "1: lwarx %0,0,%3\n" | ||
42 | " srawi %1,%0,31\n" | ||
43 | " andc %1,%0,%1\n" | ||
44 | " add %1,%1,%4\n" | ||
45 | " stwcx. %1,0,%3\n" | ||
46 | " bne 1b" | ||
47 | : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) | ||
48 | : "r" (&sem->count), "r" (incr), "m" (sem->count) | ||
49 | : "cc"); | ||
50 | |||
51 | return old_count; | ||
52 | } | ||
53 | |||
54 | void __up(struct semaphore *sem) | ||
55 | { | ||
56 | /* | ||
57 | * Note that we incremented count in up() before we came here, | ||
58 | * but that was ineffective since the result was <= 0, and | ||
59 | * any negative value of count is equivalent to 0. | ||
60 | * This ends up setting count to 1, unless count is now > 0 | ||
61 | * (i.e. because some other cpu has called up() in the meantime), | ||
62 | * in which case we just increment count. | ||
63 | */ | ||
64 | __sem_update_count(sem, 1); | ||
65 | wake_up(&sem->wait); | ||
66 | } | ||
67 | EXPORT_SYMBOL(__up); | ||
68 | |||
69 | /* | ||
70 | * Note that when we come in to __down or __down_interruptible, | ||
71 | * we have already decremented count, but that decrement was | ||
72 | * ineffective since the result was < 0, and any negative value | ||
73 | * of count is equivalent to 0. | ||
74 | * Thus it is only when we decrement count from some value > 0 | ||
75 | * that we have actually got the semaphore. | ||
76 | */ | ||
77 | void __sched __down(struct semaphore *sem) | ||
78 | { | ||
79 | struct task_struct *tsk = current; | ||
80 | DECLARE_WAITQUEUE(wait, tsk); | ||
81 | |||
82 | __set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
83 | add_wait_queue_exclusive(&sem->wait, &wait); | ||
84 | |||
85 | /* | ||
86 | * Try to get the semaphore. If the count is > 0, then we've | ||
87 | * got the semaphore; we decrement count and exit the loop. | ||
88 | * If the count is 0 or negative, we set it to -1, indicating | ||
89 | * that we are asleep, and then sleep. | ||
90 | */ | ||
91 | while (__sem_update_count(sem, -1) <= 0) { | ||
92 | schedule(); | ||
93 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
94 | } | ||
95 | remove_wait_queue(&sem->wait, &wait); | ||
96 | __set_task_state(tsk, TASK_RUNNING); | ||
97 | |||
98 | /* | ||
99 | * If there are any more sleepers, wake one of them up so | ||
100 | * that it can either get the semaphore, or set count to -1 | ||
101 | * indicating that there are still processes sleeping. | ||
102 | */ | ||
103 | wake_up(&sem->wait); | ||
104 | } | ||
105 | EXPORT_SYMBOL(__down); | ||
106 | |||
107 | int __sched __down_interruptible(struct semaphore * sem) | ||
108 | { | ||
109 | int retval = 0; | ||
110 | struct task_struct *tsk = current; | ||
111 | DECLARE_WAITQUEUE(wait, tsk); | ||
112 | |||
113 | __set_task_state(tsk, TASK_INTERRUPTIBLE); | ||
114 | add_wait_queue_exclusive(&sem->wait, &wait); | ||
115 | |||
116 | while (__sem_update_count(sem, -1) <= 0) { | ||
117 | if (signal_pending(current)) { | ||
118 | /* | ||
119 | * A signal is pending - give up trying. | ||
120 | * Set sem->count to 0 if it is negative, | ||
121 | * since we are no longer sleeping. | ||
122 | */ | ||
123 | __sem_update_count(sem, 0); | ||
124 | retval = -EINTR; | ||
125 | break; | ||
126 | } | ||
127 | schedule(); | ||
128 | set_task_state(tsk, TASK_INTERRUPTIBLE); | ||
129 | } | ||
130 | remove_wait_queue(&sem->wait, &wait); | ||
131 | __set_task_state(tsk, TASK_RUNNING); | ||
132 | |||
133 | wake_up(&sem->wait); | ||
134 | return retval; | ||
135 | } | ||
136 | EXPORT_SYMBOL(__down_interruptible); | ||
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c deleted file mode 100644 index 1bbacac44988..000000000000 --- a/arch/ppc64/kernel/vdso.c +++ /dev/null | |||
@@ -1,625 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/ppc64/kernel/vdso.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. | ||
5 | * <benh@kernel.crashing.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/smp.h> | ||
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/unistd.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/user.h> | ||
25 | #include <linux/elf.h> | ||
26 | #include <linux/security.h> | ||
27 | #include <linux/bootmem.h> | ||
28 | |||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/mmu.h> | ||
33 | #include <asm/mmu_context.h> | ||
34 | #include <asm/machdep.h> | ||
35 | #include <asm/cputable.h> | ||
36 | #include <asm/sections.h> | ||
37 | #include <asm/systemcfg.h> | ||
38 | #include <asm/vdso.h> | ||
39 | |||
40 | #undef DEBUG | ||
41 | |||
42 | #ifdef DEBUG | ||
43 | #define DBG(fmt...) printk(fmt) | ||
44 | #else | ||
45 | #define DBG(fmt...) | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /* | ||
50 | * The vDSOs themselves are here | ||
51 | */ | ||
52 | extern char vdso64_start, vdso64_end; | ||
53 | extern char vdso32_start, vdso32_end; | ||
54 | |||
55 | static void *vdso64_kbase = &vdso64_start; | ||
56 | static void *vdso32_kbase = &vdso32_start; | ||
57 | |||
58 | unsigned int vdso64_pages; | ||
59 | unsigned int vdso32_pages; | ||
60 | |||
61 | /* Signal trampolines user addresses */ | ||
62 | |||
63 | unsigned long vdso64_rt_sigtramp; | ||
64 | unsigned long vdso32_sigtramp; | ||
65 | unsigned long vdso32_rt_sigtramp; | ||
66 | |||
67 | /* Format of the patch table */ | ||
68 | struct vdso_patch_def | ||
69 | { | ||
70 | u32 pvr_mask, pvr_value; | ||
71 | const char *gen_name; | ||
72 | const char *fix_name; | ||
73 | }; | ||
74 | |||
75 | /* Table of functions to patch based on the CPU type/revision | ||
76 | * | ||
77 | * TODO: Improve by adding whole lists for each entry | ||
78 | */ | ||
79 | static struct vdso_patch_def vdso_patches[] = { | ||
80 | { | ||
81 | 0xffff0000, 0x003a0000, /* POWER5 */ | ||
82 | "__kernel_sync_dicache", "__kernel_sync_dicache_p5" | ||
83 | }, | ||
84 | { | ||
85 | 0xffff0000, 0x003b0000, /* POWER5 */ | ||
86 | "__kernel_sync_dicache", "__kernel_sync_dicache_p5" | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * Some infos carried around for each of them during parsing at | ||
92 | * boot time. | ||
93 | */ | ||
94 | struct lib32_elfinfo | ||
95 | { | ||
96 | Elf32_Ehdr *hdr; /* ptr to ELF */ | ||
97 | Elf32_Sym *dynsym; /* ptr to .dynsym section */ | ||
98 | unsigned long dynsymsize; /* size of .dynsym section */ | ||
99 | char *dynstr; /* ptr to .dynstr section */ | ||
100 | unsigned long text; /* offset of .text section in .so */ | ||
101 | }; | ||
102 | |||
103 | struct lib64_elfinfo | ||
104 | { | ||
105 | Elf64_Ehdr *hdr; | ||
106 | Elf64_Sym *dynsym; | ||
107 | unsigned long dynsymsize; | ||
108 | char *dynstr; | ||
109 | unsigned long text; | ||
110 | }; | ||
111 | |||
112 | |||
113 | #ifdef __DEBUG | ||
114 | static void dump_one_vdso_page(struct page *pg, struct page *upg) | ||
115 | { | ||
116 | printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT), | ||
117 | page_count(pg), | ||
118 | pg->flags); | ||
119 | if (upg/* && pg != upg*/) { | ||
120 | printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg) << PAGE_SHIFT), | ||
121 | page_count(upg), | ||
122 | upg->flags); | ||
123 | } | ||
124 | printk("\n"); | ||
125 | } | ||
126 | |||
127 | static void dump_vdso_pages(struct vm_area_struct * vma) | ||
128 | { | ||
129 | int i; | ||
130 | |||
131 | if (!vma || test_thread_flag(TIF_32BIT)) { | ||
132 | printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase); | ||
133 | for (i=0; i<vdso32_pages; i++) { | ||
134 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
135 | struct page *upg = (vma && vma->vm_mm) ? | ||
136 | follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0) | ||
137 | : NULL; | ||
138 | dump_one_vdso_page(pg, upg); | ||
139 | } | ||
140 | } | ||
141 | if (!vma || !test_thread_flag(TIF_32BIT)) { | ||
142 | printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase); | ||
143 | for (i=0; i<vdso64_pages; i++) { | ||
144 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
145 | struct page *upg = (vma && vma->vm_mm) ? | ||
146 | follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0) | ||
147 | : NULL; | ||
148 | dump_one_vdso_page(pg, upg); | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | #endif /* DEBUG */ | ||
153 | |||
154 | /* | ||
155 | * Keep a dummy vma_close for now, it will prevent VMA merging. | ||
156 | */ | ||
157 | static void vdso_vma_close(struct vm_area_struct * vma) | ||
158 | { | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Our nopage() function, maps in the actual vDSO kernel pages, they will | ||
163 | * be mapped read-only by do_no_page(), and eventually COW'ed, either | ||
164 | * right away for an initial write access, or by do_wp_page(). | ||
165 | */ | ||
166 | static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | ||
167 | unsigned long address, int *type) | ||
168 | { | ||
169 | unsigned long offset = address - vma->vm_start; | ||
170 | struct page *pg; | ||
171 | void *vbase = test_thread_flag(TIF_32BIT) ? vdso32_kbase : vdso64_kbase; | ||
172 | |||
173 | DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n", | ||
174 | current->comm, address, offset); | ||
175 | |||
176 | if (address < vma->vm_start || address > vma->vm_end) | ||
177 | return NOPAGE_SIGBUS; | ||
178 | |||
179 | /* | ||
180 | * Last page is systemcfg. | ||
181 | */ | ||
182 | if ((vma->vm_end - address) <= PAGE_SIZE) | ||
183 | pg = virt_to_page(_systemcfg); | ||
184 | else | ||
185 | pg = virt_to_page(vbase + offset); | ||
186 | |||
187 | get_page(pg); | ||
188 | DBG(" ->page count: %d\n", page_count(pg)); | ||
189 | |||
190 | return pg; | ||
191 | } | ||
192 | |||
193 | static struct vm_operations_struct vdso_vmops = { | ||
194 | .close = vdso_vma_close, | ||
195 | .nopage = vdso_vma_nopage, | ||
196 | }; | ||
197 | |||
198 | /* | ||
199 | * This is called from binfmt_elf, we create the special vma for the | ||
200 | * vDSO and insert it into the mm struct tree | ||
201 | */ | ||
202 | int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | ||
203 | { | ||
204 | struct mm_struct *mm = current->mm; | ||
205 | struct vm_area_struct *vma; | ||
206 | unsigned long vdso_pages; | ||
207 | unsigned long vdso_base; | ||
208 | |||
209 | if (test_thread_flag(TIF_32BIT)) { | ||
210 | vdso_pages = vdso32_pages; | ||
211 | vdso_base = VDSO32_MBASE; | ||
212 | } else { | ||
213 | vdso_pages = vdso64_pages; | ||
214 | vdso_base = VDSO64_MBASE; | ||
215 | } | ||
216 | |||
217 | current->thread.vdso_base = 0; | ||
218 | |||
219 | /* vDSO has a problem and was disabled, just don't "enable" it for the | ||
220 | * process | ||
221 | */ | ||
222 | if (vdso_pages == 0) | ||
223 | return 0; | ||
224 | |||
225 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | ||
226 | if (vma == NULL) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | memset(vma, 0, sizeof(*vma)); | ||
230 | |||
231 | /* | ||
232 | * pick a base address for the vDSO in process space. We try to put it | ||
233 | * at vdso_base which is the "natural" base for it, but we might fail | ||
234 | * and end up putting it elsewhere. | ||
235 | */ | ||
236 | vdso_base = get_unmapped_area(NULL, vdso_base, | ||
237 | vdso_pages << PAGE_SHIFT, 0, 0); | ||
238 | if (vdso_base & ~PAGE_MASK) { | ||
239 | kmem_cache_free(vm_area_cachep, vma); | ||
240 | return (int)vdso_base; | ||
241 | } | ||
242 | |||
243 | current->thread.vdso_base = vdso_base; | ||
244 | |||
245 | vma->vm_mm = mm; | ||
246 | vma->vm_start = current->thread.vdso_base; | ||
247 | |||
248 | /* | ||
249 | * the VMA size is one page more than the vDSO since systemcfg | ||
250 | * is mapped in the last one | ||
251 | */ | ||
252 | vma->vm_end = vma->vm_start + ((vdso_pages + 1) << PAGE_SHIFT); | ||
253 | |||
254 | /* | ||
255 | * our vma flags don't have VM_WRITE so by default, the process isn't allowed | ||
256 | * to write those pages. | ||
257 | * gdb can break that with ptrace interface, and thus trigger COW on those | ||
258 | * pages but it's then your responsibility to never do that on the "data" page | ||
259 | * of the vDSO or you'll stop getting kernel updates and your nice userland | ||
260 | * gettimeofday will be totally dead. It's fine to use that for setting | ||
261 | * breakpoints in the vDSO code pages though | ||
262 | */ | ||
263 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_RESERVED; | ||
264 | vma->vm_flags |= mm->def_flags; | ||
265 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | ||
266 | vma->vm_ops = &vdso_vmops; | ||
267 | |||
268 | down_write(&mm->mmap_sem); | ||
269 | if (insert_vm_struct(mm, vma)) { | ||
270 | up_write(&mm->mmap_sem); | ||
271 | kmem_cache_free(vm_area_cachep, vma); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | ||
275 | up_write(&mm->mmap_sem); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, | ||
281 | unsigned long *size) | ||
282 | { | ||
283 | Elf32_Shdr *sechdrs; | ||
284 | unsigned int i; | ||
285 | char *secnames; | ||
286 | |||
287 | /* Grab section headers and strings so we can tell who is who */ | ||
288 | sechdrs = (void *)ehdr + ehdr->e_shoff; | ||
289 | secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; | ||
290 | |||
291 | /* Find the section they want */ | ||
292 | for (i = 1; i < ehdr->e_shnum; i++) { | ||
293 | if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { | ||
294 | if (size) | ||
295 | *size = sechdrs[i].sh_size; | ||
296 | return (void *)ehdr + sechdrs[i].sh_offset; | ||
297 | } | ||
298 | } | ||
299 | *size = 0; | ||
300 | return NULL; | ||
301 | } | ||
302 | |||
303 | static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname, | ||
304 | unsigned long *size) | ||
305 | { | ||
306 | Elf64_Shdr *sechdrs; | ||
307 | unsigned int i; | ||
308 | char *secnames; | ||
309 | |||
310 | /* Grab section headers and strings so we can tell who is who */ | ||
311 | sechdrs = (void *)ehdr + ehdr->e_shoff; | ||
312 | secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; | ||
313 | |||
314 | /* Find the section they want */ | ||
315 | for (i = 1; i < ehdr->e_shnum; i++) { | ||
316 | if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { | ||
317 | if (size) | ||
318 | *size = sechdrs[i].sh_size; | ||
319 | return (void *)ehdr + sechdrs[i].sh_offset; | ||
320 | } | ||
321 | } | ||
322 | if (size) | ||
323 | *size = 0; | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, const char *symname) | ||
328 | { | ||
329 | unsigned int i; | ||
330 | char name[32], *c; | ||
331 | |||
332 | for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) { | ||
333 | if (lib->dynsym[i].st_name == 0) | ||
334 | continue; | ||
335 | strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32); | ||
336 | c = strchr(name, '@'); | ||
337 | if (c) | ||
338 | *c = 0; | ||
339 | if (strcmp(symname, name) == 0) | ||
340 | return &lib->dynsym[i]; | ||
341 | } | ||
342 | return NULL; | ||
343 | } | ||
344 | |||
345 | static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, const char *symname) | ||
346 | { | ||
347 | unsigned int i; | ||
348 | char name[32], *c; | ||
349 | |||
350 | for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) { | ||
351 | if (lib->dynsym[i].st_name == 0) | ||
352 | continue; | ||
353 | strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32); | ||
354 | c = strchr(name, '@'); | ||
355 | if (c) | ||
356 | *c = 0; | ||
357 | if (strcmp(symname, name) == 0) | ||
358 | return &lib->dynsym[i]; | ||
359 | } | ||
360 | return NULL; | ||
361 | } | ||
362 | |||
363 | /* Note that we assume the section is .text and the symbol is relative to | ||
364 | * the library base | ||
365 | */ | ||
366 | static unsigned long __init find_function32(struct lib32_elfinfo *lib, const char *symname) | ||
367 | { | ||
368 | Elf32_Sym *sym = find_symbol32(lib, symname); | ||
369 | |||
370 | if (sym == NULL) { | ||
371 | printk(KERN_WARNING "vDSO32: function %s not found !\n", symname); | ||
372 | return 0; | ||
373 | } | ||
374 | return sym->st_value - VDSO32_LBASE; | ||
375 | } | ||
376 | |||
377 | /* Note that we assume the section is .text and the symbol is relative to | ||
378 | * the library base | ||
379 | */ | ||
380 | static unsigned long __init find_function64(struct lib64_elfinfo *lib, const char *symname) | ||
381 | { | ||
382 | Elf64_Sym *sym = find_symbol64(lib, symname); | ||
383 | |||
384 | if (sym == NULL) { | ||
385 | printk(KERN_WARNING "vDSO64: function %s not found !\n", symname); | ||
386 | return 0; | ||
387 | } | ||
388 | #ifdef VDS64_HAS_DESCRIPTORS | ||
389 | return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - VDSO64_LBASE; | ||
390 | #else | ||
391 | return sym->st_value - VDSO64_LBASE; | ||
392 | #endif | ||
393 | } | ||
394 | |||
395 | |||
396 | static __init int vdso_do_find_sections(struct lib32_elfinfo *v32, | ||
397 | struct lib64_elfinfo *v64) | ||
398 | { | ||
399 | void *sect; | ||
400 | |||
401 | /* | ||
402 | * Locate symbol tables & text section | ||
403 | */ | ||
404 | |||
405 | v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize); | ||
406 | v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL); | ||
407 | if (v32->dynsym == NULL || v32->dynstr == NULL) { | ||
408 | printk(KERN_ERR "vDSO32: a required symbol section was not found\n"); | ||
409 | return -1; | ||
410 | } | ||
411 | sect = find_section32(v32->hdr, ".text", NULL); | ||
412 | if (sect == NULL) { | ||
413 | printk(KERN_ERR "vDSO32: the .text section was not found\n"); | ||
414 | return -1; | ||
415 | } | ||
416 | v32->text = sect - vdso32_kbase; | ||
417 | |||
418 | v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize); | ||
419 | v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL); | ||
420 | if (v64->dynsym == NULL || v64->dynstr == NULL) { | ||
421 | printk(KERN_ERR "vDSO64: a required symbol section was not found\n"); | ||
422 | return -1; | ||
423 | } | ||
424 | sect = find_section64(v64->hdr, ".text", NULL); | ||
425 | if (sect == NULL) { | ||
426 | printk(KERN_ERR "vDSO64: the .text section was not found\n"); | ||
427 | return -1; | ||
428 | } | ||
429 | v64->text = sect - vdso64_kbase; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, | ||
435 | struct lib64_elfinfo *v64) | ||
436 | { | ||
437 | /* | ||
438 | * Find signal trampolines | ||
439 | */ | ||
440 | |||
441 | vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64"); | ||
442 | vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32"); | ||
443 | vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32"); | ||
444 | } | ||
445 | |||
446 | static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, | ||
447 | struct lib64_elfinfo *v64) | ||
448 | { | ||
449 | Elf32_Sym *sym32; | ||
450 | Elf64_Sym *sym64; | ||
451 | |||
452 | sym32 = find_symbol32(v32, "__kernel_datapage_offset"); | ||
453 | if (sym32 == NULL) { | ||
454 | printk(KERN_ERR "vDSO32: Can't find symbol __kernel_datapage_offset !\n"); | ||
455 | return -1; | ||
456 | } | ||
457 | *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) = | ||
458 | (vdso32_pages << PAGE_SHIFT) - (sym32->st_value - VDSO32_LBASE); | ||
459 | |||
460 | sym64 = find_symbol64(v64, "__kernel_datapage_offset"); | ||
461 | if (sym64 == NULL) { | ||
462 | printk(KERN_ERR "vDSO64: Can't find symbol __kernel_datapage_offset !\n"); | ||
463 | return -1; | ||
464 | } | ||
465 | *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) = | ||
466 | (vdso64_pages << PAGE_SHIFT) - (sym64->st_value - VDSO64_LBASE); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int vdso_do_func_patch32(struct lib32_elfinfo *v32, | ||
472 | struct lib64_elfinfo *v64, | ||
473 | const char *orig, const char *fix) | ||
474 | { | ||
475 | Elf32_Sym *sym32_gen, *sym32_fix; | ||
476 | |||
477 | sym32_gen = find_symbol32(v32, orig); | ||
478 | if (sym32_gen == NULL) { | ||
479 | printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig); | ||
480 | return -1; | ||
481 | } | ||
482 | sym32_fix = find_symbol32(v32, fix); | ||
483 | if (sym32_fix == NULL) { | ||
484 | printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix); | ||
485 | return -1; | ||
486 | } | ||
487 | sym32_gen->st_value = sym32_fix->st_value; | ||
488 | sym32_gen->st_size = sym32_fix->st_size; | ||
489 | sym32_gen->st_info = sym32_fix->st_info; | ||
490 | sym32_gen->st_other = sym32_fix->st_other; | ||
491 | sym32_gen->st_shndx = sym32_fix->st_shndx; | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int vdso_do_func_patch64(struct lib32_elfinfo *v32, | ||
497 | struct lib64_elfinfo *v64, | ||
498 | const char *orig, const char *fix) | ||
499 | { | ||
500 | Elf64_Sym *sym64_gen, *sym64_fix; | ||
501 | |||
502 | sym64_gen = find_symbol64(v64, orig); | ||
503 | if (sym64_gen == NULL) { | ||
504 | printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig); | ||
505 | return -1; | ||
506 | } | ||
507 | sym64_fix = find_symbol64(v64, fix); | ||
508 | if (sym64_fix == NULL) { | ||
509 | printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix); | ||
510 | return -1; | ||
511 | } | ||
512 | sym64_gen->st_value = sym64_fix->st_value; | ||
513 | sym64_gen->st_size = sym64_fix->st_size; | ||
514 | sym64_gen->st_info = sym64_fix->st_info; | ||
515 | sym64_gen->st_other = sym64_fix->st_other; | ||
516 | sym64_gen->st_shndx = sym64_fix->st_shndx; | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, | ||
522 | struct lib64_elfinfo *v64) | ||
523 | { | ||
524 | u32 pvr; | ||
525 | int i; | ||
526 | |||
527 | pvr = mfspr(SPRN_PVR); | ||
528 | for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) { | ||
529 | struct vdso_patch_def *patch = &vdso_patches[i]; | ||
530 | int match = (pvr & patch->pvr_mask) == patch->pvr_value; | ||
531 | |||
532 | DBG("patch %d (mask: %x, pvr: %x) : %s\n", | ||
533 | i, patch->pvr_mask, patch->pvr_value, match ? "match" : "skip"); | ||
534 | |||
535 | if (!match) | ||
536 | continue; | ||
537 | |||
538 | DBG("replacing %s with %s...\n", patch->gen_name, patch->fix_name); | ||
539 | |||
540 | /* | ||
541 | * Patch the 32 bits and 64 bits symbols. Note that we do not patch | ||
542 | * the "." symbol on 64 bits. It would be easy to do, but doesn't | ||
543 | * seem to be necessary, patching the OPD symbol is enough. | ||
544 | */ | ||
545 | vdso_do_func_patch32(v32, v64, patch->gen_name, patch->fix_name); | ||
546 | vdso_do_func_patch64(v32, v64, patch->gen_name, patch->fix_name); | ||
547 | } | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | |||
553 | static __init int vdso_setup(void) | ||
554 | { | ||
555 | struct lib32_elfinfo v32; | ||
556 | struct lib64_elfinfo v64; | ||
557 | |||
558 | v32.hdr = vdso32_kbase; | ||
559 | v64.hdr = vdso64_kbase; | ||
560 | |||
561 | if (vdso_do_find_sections(&v32, &v64)) | ||
562 | return -1; | ||
563 | |||
564 | if (vdso_fixup_datapage(&v32, &v64)) | ||
565 | return -1; | ||
566 | |||
567 | if (vdso_fixup_alt_funcs(&v32, &v64)) | ||
568 | return -1; | ||
569 | |||
570 | vdso_setup_trampolines(&v32, &v64); | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | void __init vdso_init(void) | ||
576 | { | ||
577 | int i; | ||
578 | |||
579 | vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT; | ||
580 | vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT; | ||
581 | |||
582 | DBG("vdso64_kbase: %p, 0x%x pages, vdso32_kbase: %p, 0x%x pages\n", | ||
583 | vdso64_kbase, vdso64_pages, vdso32_kbase, vdso32_pages); | ||
584 | |||
585 | /* | ||
586 | * Initialize the vDSO images in memory, that is do necessary | ||
587 | * fixups of vDSO symbols, locate trampolines, etc... | ||
588 | */ | ||
589 | if (vdso_setup()) { | ||
590 | printk(KERN_ERR "vDSO setup failure, not enabled !\n"); | ||
591 | /* XXX should free pages here ? */ | ||
592 | vdso64_pages = vdso32_pages = 0; | ||
593 | return; | ||
594 | } | ||
595 | |||
596 | /* Make sure pages are in the correct state */ | ||
597 | for (i = 0; i < vdso64_pages; i++) { | ||
598 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
599 | ClearPageReserved(pg); | ||
600 | get_page(pg); | ||
601 | } | ||
602 | for (i = 0; i < vdso32_pages; i++) { | ||
603 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
604 | ClearPageReserved(pg); | ||
605 | get_page(pg); | ||
606 | } | ||
607 | |||
608 | get_page(virt_to_page(_systemcfg)); | ||
609 | } | ||
610 | |||
611 | int in_gate_area_no_task(unsigned long addr) | ||
612 | { | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | int in_gate_area(struct task_struct *task, unsigned long addr) | ||
617 | { | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | ||
622 | { | ||
623 | return NULL; | ||
624 | } | ||
625 | |||
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S deleted file mode 100644 index 022f220e772f..000000000000 --- a/arch/ppc64/kernel/vmlinux.lds.S +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | #include <asm/page.h> | ||
2 | #include <asm-generic/vmlinux.lds.h> | ||
3 | |||
4 | OUTPUT_ARCH(powerpc:common64) | ||
5 | jiffies = jiffies_64; | ||
6 | SECTIONS | ||
7 | { | ||
8 | /* Sections to be discarded. */ | ||
9 | /DISCARD/ : { | ||
10 | *(.exitcall.exit) | ||
11 | } | ||
12 | |||
13 | |||
14 | /* Read-only sections, merged into text segment: */ | ||
15 | .text : { | ||
16 | *(.text .text.*) | ||
17 | SCHED_TEXT | ||
18 | LOCK_TEXT | ||
19 | KPROBES_TEXT | ||
20 | *(.fixup) | ||
21 | . = ALIGN(PAGE_SIZE); | ||
22 | _etext = .; | ||
23 | } | ||
24 | |||
25 | __ex_table : { | ||
26 | __start___ex_table = .; | ||
27 | *(__ex_table) | ||
28 | __stop___ex_table = .; | ||
29 | } | ||
30 | |||
31 | __bug_table : { | ||
32 | __start___bug_table = .; | ||
33 | *(__bug_table) | ||
34 | __stop___bug_table = .; | ||
35 | } | ||
36 | |||
37 | __ftr_fixup : { | ||
38 | __start___ftr_fixup = .; | ||
39 | *(__ftr_fixup) | ||
40 | __stop___ftr_fixup = .; | ||
41 | } | ||
42 | |||
43 | RODATA | ||
44 | |||
45 | |||
46 | /* will be freed after init */ | ||
47 | . = ALIGN(PAGE_SIZE); | ||
48 | __init_begin = .; | ||
49 | |||
50 | .init.text : { | ||
51 | _sinittext = .; | ||
52 | *(.init.text) | ||
53 | _einittext = .; | ||
54 | } | ||
55 | |||
56 | .init.data : { | ||
57 | *(.init.data) | ||
58 | } | ||
59 | |||
60 | . = ALIGN(16); | ||
61 | .init.setup : { | ||
62 | __setup_start = .; | ||
63 | *(.init.setup) | ||
64 | __setup_end = .; | ||
65 | } | ||
66 | |||
67 | .initcall.init : { | ||
68 | __initcall_start = .; | ||
69 | *(.initcall1.init) | ||
70 | *(.initcall2.init) | ||
71 | *(.initcall3.init) | ||
72 | *(.initcall4.init) | ||
73 | *(.initcall5.init) | ||
74 | *(.initcall6.init) | ||
75 | *(.initcall7.init) | ||
76 | __initcall_end = .; | ||
77 | } | ||
78 | |||
79 | .con_initcall.init : { | ||
80 | __con_initcall_start = .; | ||
81 | *(.con_initcall.init) | ||
82 | __con_initcall_end = .; | ||
83 | } | ||
84 | |||
85 | SECURITY_INIT | ||
86 | |||
87 | . = ALIGN(PAGE_SIZE); | ||
88 | .init.ramfs : { | ||
89 | __initramfs_start = .; | ||
90 | *(.init.ramfs) | ||
91 | __initramfs_end = .; | ||
92 | } | ||
93 | |||
94 | .data.percpu : { | ||
95 | __per_cpu_start = .; | ||
96 | *(.data.percpu) | ||
97 | __per_cpu_end = .; | ||
98 | } | ||
99 | |||
100 | . = ALIGN(PAGE_SIZE); | ||
101 | . = ALIGN(16384); | ||
102 | __init_end = .; | ||
103 | /* freed after init ends here */ | ||
104 | |||
105 | |||
106 | /* Read/write sections */ | ||
107 | . = ALIGN(PAGE_SIZE); | ||
108 | . = ALIGN(16384); | ||
109 | _sdata = .; | ||
110 | /* The initial task and kernel stack */ | ||
111 | .data.init_task : { | ||
112 | *(.data.init_task) | ||
113 | } | ||
114 | |||
115 | . = ALIGN(PAGE_SIZE); | ||
116 | .data.page_aligned : { | ||
117 | *(.data.page_aligned) | ||
118 | } | ||
119 | |||
120 | .data.cacheline_aligned : { | ||
121 | *(.data.cacheline_aligned) | ||
122 | } | ||
123 | |||
124 | .data : { | ||
125 | *(.data .data.rel* .toc1) | ||
126 | *(.branch_lt) | ||
127 | } | ||
128 | |||
129 | .opd : { | ||
130 | *(.opd) | ||
131 | } | ||
132 | |||
133 | .got : { | ||
134 | __toc_start = .; | ||
135 | *(.got) | ||
136 | *(.toc) | ||
137 | . = ALIGN(PAGE_SIZE); | ||
138 | _edata = .; | ||
139 | } | ||
140 | |||
141 | |||
142 | . = ALIGN(PAGE_SIZE); | ||
143 | .bss : { | ||
144 | __bss_start = .; | ||
145 | *(.bss) | ||
146 | __bss_stop = .; | ||
147 | } | ||
148 | |||
149 | . = ALIGN(PAGE_SIZE); | ||
150 | _end = . ; | ||
151 | } | ||
diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h deleted file mode 100644 index 02eb40dac0b3..000000000000 --- a/arch/ppc64/xmon/privinst.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996 Paul Mackerras. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define GETREG(reg) \ | ||
11 | static inline unsigned long get_ ## reg (void) \ | ||
12 | { unsigned long ret; asm volatile ("mf" #reg " %0" : "=r" (ret) :); return ret; } | ||
13 | |||
14 | #define SETREG(reg) \ | ||
15 | static inline void set_ ## reg (unsigned long val) \ | ||
16 | { asm volatile ("mt" #reg " %0" : : "r" (val)); } | ||
17 | |||
18 | GETREG(msr) | ||
19 | SETREG(msrd) | ||
20 | GETREG(cr) | ||
21 | |||
22 | #define GSETSPR(n, name) \ | ||
23 | static inline long get_ ## name (void) \ | ||
24 | { long ret; asm volatile ("mfspr %0," #n : "=r" (ret) : ); return ret; } \ | ||
25 | static inline void set_ ## name (long val) \ | ||
26 | { asm volatile ("mtspr " #n ",%0" : : "r" (val)); } | ||
27 | |||
28 | GSETSPR(0, mq) | ||
29 | GSETSPR(1, xer) | ||
30 | GSETSPR(4, rtcu) | ||
31 | GSETSPR(5, rtcl) | ||
32 | GSETSPR(8, lr) | ||
33 | GSETSPR(9, ctr) | ||
34 | GSETSPR(18, dsisr) | ||
35 | GSETSPR(19, dar) | ||
36 | GSETSPR(22, dec) | ||
37 | GSETSPR(25, sdr1) | ||
38 | GSETSPR(26, srr0) | ||
39 | GSETSPR(27, srr1) | ||
40 | GSETSPR(272, sprg0) | ||
41 | GSETSPR(273, sprg1) | ||
42 | GSETSPR(274, sprg2) | ||
43 | GSETSPR(275, sprg3) | ||
44 | GSETSPR(282, ear) | ||
45 | GSETSPR(287, pvr) | ||
46 | GSETSPR(1008, hid0) | ||
47 | GSETSPR(1009, hid1) | ||
48 | GSETSPR(1010, iabr) | ||
49 | GSETSPR(1023, pir) | ||
50 | |||
51 | static inline void store_inst(void *p) | ||
52 | { | ||
53 | asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p)); | ||
54 | } | ||
55 | |||
56 | static inline void cflush(void *p) | ||
57 | { | ||
58 | asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p)); | ||
59 | } | ||
60 | |||
61 | static inline void cinval(void *p) | ||
62 | { | ||
63 | asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); | ||
64 | } | ||
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index 2e64e8c3e8e5..cb3cf0f22822 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c | |||
@@ -37,17 +37,43 @@ int __atomic_add_return(int i, atomic_t *v) | |||
37 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 37 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
38 | return ret; | 38 | return ret; |
39 | } | 39 | } |
40 | EXPORT_SYMBOL(__atomic_add_return); | ||
40 | 41 | ||
41 | void atomic_set(atomic_t *v, int i) | 42 | int atomic_cmpxchg(atomic_t *v, int old, int new) |
42 | { | 43 | { |
44 | int ret; | ||
43 | unsigned long flags; | 45 | unsigned long flags; |
46 | |||
44 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | 47 | spin_lock_irqsave(ATOMIC_HASH(v), flags); |
48 | ret = v->counter; | ||
49 | if (likely(ret == old)) | ||
50 | v->counter = new; | ||
45 | 51 | ||
46 | v->counter = i; | 52 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
53 | return ret; | ||
54 | } | ||
55 | |||
56 | int atomic_add_unless(atomic_t *v, int a, int u) | ||
57 | { | ||
58 | int ret; | ||
59 | unsigned long flags; | ||
47 | 60 | ||
61 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
62 | ret = v->counter; | ||
63 | if (ret != u) | ||
64 | v->counter += a; | ||
48 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 65 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
66 | return ret != u; | ||
49 | } | 67 | } |
50 | 68 | ||
51 | EXPORT_SYMBOL(__atomic_add_return); | 69 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
52 | EXPORT_SYMBOL(atomic_set); | 70 | /* Atomic operations are already serializing */ |
71 | void atomic_set(atomic_t *v, int i) | ||
72 | { | ||
73 | unsigned long flags; | ||
53 | 74 | ||
75 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
76 | v->counter = i; | ||
77 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | ||
78 | } | ||
79 | EXPORT_SYMBOL(atomic_set); | ||
diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c index 94b05e8c906c..2e168d16547f 100644 --- a/arch/sparc/lib/bitext.c +++ b/arch/sparc/lib/bitext.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/string.h> | ||
13 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
14 | 15 | ||
15 | #include <asm/bitext.h> | 16 | #include <asm/bitext.h> |
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 3b5f47c46907..563301fe5df8 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig | |||
@@ -7,7 +7,6 @@ config UML | |||
7 | bool | 7 | bool |
8 | default y | 8 | default y |
9 | 9 | ||
10 | # XXX: does UM have a mmu/swap? | ||
11 | config MMU | 10 | config MMU |
12 | bool | 11 | bool |
13 | default y | 12 | default y |
@@ -36,12 +35,6 @@ config IRQ_RELEASE_METHOD | |||
36 | bool | 35 | bool |
37 | default y | 36 | default y |
38 | 37 | ||
39 | menu "Host processor type and features" | ||
40 | |||
41 | source "arch/i386/Kconfig.cpu" | ||
42 | |||
43 | endmenu | ||
44 | |||
45 | menu "UML-specific options" | 38 | menu "UML-specific options" |
46 | 39 | ||
47 | config MODE_TT | 40 | config MODE_TT |
@@ -209,7 +202,8 @@ config MAGIC_SYSRQ | |||
209 | config SMP | 202 | config SMP |
210 | bool "Symmetric multi-processing support (EXPERIMENTAL)" | 203 | bool "Symmetric multi-processing support (EXPERIMENTAL)" |
211 | default n | 204 | default n |
212 | depends on (MODE_TT && EXPERIMENTAL && !SMP_BROKEN) || (BROKEN && SMP_BROKEN) | 205 | #SMP_BROKEN is for x86_64. |
206 | depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) | ||
213 | help | 207 | help |
214 | This option enables UML SMP support. | 208 | This option enables UML SMP support. |
215 | It is NOT related to having a real SMP box. Not directly, at least. | 209 | It is NOT related to having a real SMP box. Not directly, at least. |
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 5d92cacd56c6..c71b39a677aa 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
@@ -1,3 +1,9 @@ | |||
1 | menu "Host processor type and features" | ||
2 | |||
3 | source "arch/i386/Kconfig.cpu" | ||
4 | |||
5 | endmenu | ||
6 | |||
1 | config UML_X86 | 7 | config UML_X86 |
2 | bool | 8 | bool |
3 | default y | 9 | default y |
@@ -42,7 +48,3 @@ config ARCH_HAS_SC_SIGNALS | |||
42 | config ARCH_REUSE_HOST_VSYSCALL_AREA | 48 | config ARCH_REUSE_HOST_VSYSCALL_AREA |
43 | bool | 49 | bool |
44 | default y | 50 | default y |
45 | |||
46 | config X86_CMPXCHG | ||
47 | bool | ||
48 | default y | ||
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 1f7dcb064aee..7a0e04e34bf9 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 | |||
@@ -35,4 +35,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) | |||
35 | 35 | ||
36 | CFLAGS += $(cflags-y) | 36 | CFLAGS += $(cflags-y) |
37 | USER_CFLAGS += $(cflags-y) | 37 | USER_CFLAGS += $(cflags-y) |
38 | |||
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 16e7dc89f61d..5b58fad45290 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -89,8 +89,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data) | |||
89 | return(-EIO); | 89 | return(-EIO); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int not_configged_console_write(int fd, const char *buf, int len, | 92 | static int not_configged_console_write(int fd, const char *buf, int len) |
93 | void *data) | ||
94 | { | 93 | { |
95 | my_puts("Using a channel type which is configured out of " | 94 | my_puts("Using a channel type which is configured out of " |
96 | "UML\n"); | 95 | "UML\n"); |
@@ -299,7 +298,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) | |||
299 | chan = list_entry(ele, struct chan, list); | 298 | chan = list_entry(ele, struct chan, list); |
300 | if(!chan->output || (chan->ops->console_write == NULL)) | 299 | if(!chan->output || (chan->ops->console_write == NULL)) |
301 | continue; | 300 | continue; |
302 | n = chan->ops->console_write(chan->fd, buf, len, chan->data); | 301 | n = chan->ops->console_write(chan->fd, buf, len); |
303 | if(chan->primary) ret = n; | 302 | if(chan->primary) ret = n; |
304 | } | 303 | } |
305 | return(ret); | 304 | return(ret); |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 1c55d5802489..5d50d4a44abf 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "choose-mode.h" | 20 | #include "choose-mode.h" |
21 | #include "mode.h" | 21 | #include "mode.h" |
22 | 22 | ||
23 | int generic_console_write(int fd, const char *buf, int n, void *unused) | 23 | int generic_console_write(int fd, const char *buf, int n) |
24 | { | 24 | { |
25 | struct termios save, new; | 25 | struct termios save, new; |
26 | int err; | 26 | int err; |
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index c1b03f7c1daa..1bb085b2824d 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c | |||
@@ -98,7 +98,7 @@ static int connect_to_switch(struct daemon_data *pri) | |||
98 | printk("daemon_open : control setup request failed, err = %d\n", | 98 | printk("daemon_open : control setup request failed, err = %d\n", |
99 | -n); | 99 | -n); |
100 | err = -ENOTCONN; | 100 | err = -ENOTCONN; |
101 | goto out; | 101 | goto out_free; |
102 | } | 102 | } |
103 | 103 | ||
104 | n = os_read_file(pri->control, sun, sizeof(*sun)); | 104 | n = os_read_file(pri->control, sun, sizeof(*sun)); |
@@ -106,12 +106,14 @@ static int connect_to_switch(struct daemon_data *pri) | |||
106 | printk("daemon_open : read of data socket failed, err = %d\n", | 106 | printk("daemon_open : read of data socket failed, err = %d\n", |
107 | -n); | 107 | -n); |
108 | err = -ENOTCONN; | 108 | err = -ENOTCONN; |
109 | goto out_close; | 109 | goto out_free; |
110 | } | 110 | } |
111 | 111 | ||
112 | pri->data_addr = sun; | 112 | pri->data_addr = sun; |
113 | return(fd); | 113 | return(fd); |
114 | 114 | ||
115 | out_free: | ||
116 | kfree(sun); | ||
115 | out_close: | 117 | out_close: |
116 | os_close_file(fd); | 118 | os_close_file(fd); |
117 | out: | 119 | out: |
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index f0b888f66e05..3296e86a03a5 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c | |||
@@ -76,13 +76,6 @@ static void fd_close(int fd, void *d) | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | static int fd_console_write(int fd, const char *buf, int n, void *d) | ||
80 | { | ||
81 | struct fd_chan *data = d; | ||
82 | |||
83 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
84 | } | ||
85 | |||
86 | struct chan_ops fd_ops = { | 79 | struct chan_ops fd_ops = { |
87 | .type = "fd", | 80 | .type = "fd", |
88 | .init = fd_init, | 81 | .init = fd_init, |
@@ -90,7 +83,7 @@ struct chan_ops fd_ops = { | |||
90 | .close = fd_close, | 83 | .close = fd_close, |
91 | .read = generic_read, | 84 | .read = generic_read, |
92 | .write = generic_write, | 85 | .write = generic_write, |
93 | .console_write = fd_console_write, | 86 | .console_write = generic_console_write, |
94 | .window_size = generic_window_size, | 87 | .window_size = generic_window_size, |
95 | .free = generic_free, | 88 | .free = generic_free, |
96 | .winch = 1, | 89 | .winch = 1, |
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 5db136e2651c..afe85bfa66e0 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c | |||
@@ -54,7 +54,7 @@ static int mcast_open(void *data) | |||
54 | struct mcast_data *pri = data; | 54 | struct mcast_data *pri = data; |
55 | struct sockaddr_in *sin = pri->mcast_addr; | 55 | struct sockaddr_in *sin = pri->mcast_addr; |
56 | struct ip_mreq mreq; | 56 | struct ip_mreq mreq; |
57 | int fd, yes = 1, err = 0; | 57 | int fd, yes = 1, err = -EINVAL; |
58 | 58 | ||
59 | 59 | ||
60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) | 60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) |
@@ -63,40 +63,40 @@ static int mcast_open(void *data) | |||
63 | fd = socket(AF_INET, SOCK_DGRAM, 0); | 63 | fd = socket(AF_INET, SOCK_DGRAM, 0); |
64 | 64 | ||
65 | if (fd < 0){ | 65 | if (fd < 0){ |
66 | err = -errno; | ||
66 | printk("mcast_open : data socket failed, errno = %d\n", | 67 | printk("mcast_open : data socket failed, errno = %d\n", |
67 | errno); | 68 | errno); |
68 | err = -errno; | ||
69 | goto out; | 69 | goto out; |
70 | } | 70 | } |
71 | 71 | ||
72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | 72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { |
73 | err = -errno; | ||
73 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", | 74 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", |
74 | errno); | 75 | errno); |
75 | err = -errno; | ||
76 | goto out_close; | 76 | goto out_close; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* set ttl according to config */ | 79 | /* set ttl according to config */ |
80 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, | 80 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, |
81 | sizeof(pri->ttl)) < 0) { | 81 | sizeof(pri->ttl)) < 0) { |
82 | err = -errno; | ||
82 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", | 83 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", |
83 | errno); | 84 | errno); |
84 | err = -errno; | ||
85 | goto out_close; | 85 | goto out_close; |
86 | } | 86 | } |
87 | 87 | ||
88 | /* set LOOP, so data does get fed back to local sockets */ | 88 | /* set LOOP, so data does get fed back to local sockets */ |
89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { | 89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { |
90 | err = -errno; | ||
90 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", | 91 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", |
91 | errno); | 92 | errno); |
92 | err = -errno; | ||
93 | goto out_close; | 93 | goto out_close; |
94 | } | 94 | } |
95 | 95 | ||
96 | /* bind socket to mcast address */ | 96 | /* bind socket to mcast address */ |
97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { | 97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { |
98 | printk("mcast_open : data bind failed, errno = %d\n", errno); | ||
99 | err = -errno; | 98 | err = -errno; |
99 | printk("mcast_open : data bind failed, errno = %d\n", errno); | ||
100 | goto out_close; | 100 | goto out_close; |
101 | } | 101 | } |
102 | 102 | ||
@@ -105,22 +105,22 @@ static int mcast_open(void *data) | |||
105 | mreq.imr_interface.s_addr = 0; | 105 | mreq.imr_interface.s_addr = 0; |
106 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, | 106 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, |
107 | &mreq, sizeof(mreq)) < 0) { | 107 | &mreq, sizeof(mreq)) < 0) { |
108 | err = -errno; | ||
108 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", | 109 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", |
109 | errno); | 110 | errno); |
110 | printk("There appears not to be a multicast-capable network " | 111 | printk("There appears not to be a multicast-capable network " |
111 | "interface on the host.\n"); | 112 | "interface on the host.\n"); |
112 | printk("eth0 should be configured in order to use the " | 113 | printk("eth0 should be configured in order to use the " |
113 | "multicast transport.\n"); | 114 | "multicast transport.\n"); |
114 | err = -errno; | 115 | goto out_close; |
115 | goto out_close; | ||
116 | } | 116 | } |
117 | 117 | ||
118 | return fd; | 118 | return fd; |
119 | 119 | ||
120 | out_close: | 120 | out_close: |
121 | os_close_file(fd); | 121 | os_close_file(fd); |
122 | out: | 122 | out: |
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static void mcast_close(int fd, void *data) | 126 | static void mcast_close(int fd, void *data) |
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index ed4a1a6c5d83..c43e8bb32502 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c | |||
@@ -100,13 +100,6 @@ static void port_close(int fd, void *d) | |||
100 | os_close_file(fd); | 100 | os_close_file(fd); |
101 | } | 101 | } |
102 | 102 | ||
103 | static int port_console_write(int fd, const char *buf, int n, void *d) | ||
104 | { | ||
105 | struct port_chan *data = d; | ||
106 | |||
107 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
108 | } | ||
109 | |||
110 | struct chan_ops port_ops = { | 103 | struct chan_ops port_ops = { |
111 | .type = "port", | 104 | .type = "port", |
112 | .init = port_init, | 105 | .init = port_init, |
@@ -114,7 +107,7 @@ struct chan_ops port_ops = { | |||
114 | .close = port_close, | 107 | .close = port_close, |
115 | .read = generic_read, | 108 | .read = generic_read, |
116 | .write = generic_write, | 109 | .write = generic_write, |
117 | .console_write = port_console_write, | 110 | .console_write = generic_console_write, |
118 | .window_size = generic_window_size, | 111 | .window_size = generic_window_size, |
119 | .free = port_free, | 112 | .free = port_free, |
120 | .winch = 1, | 113 | .winch = 1, |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 0306a1b215b7..1c555c38de4d 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
@@ -118,13 +118,6 @@ static int pty_open(int input, int output, int primary, void *d, | |||
118 | return(fd); | 118 | return(fd); |
119 | } | 119 | } |
120 | 120 | ||
121 | static int pty_console_write(int fd, const char *buf, int n, void *d) | ||
122 | { | ||
123 | struct pty_chan *data = d; | ||
124 | |||
125 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
126 | } | ||
127 | |||
128 | struct chan_ops pty_ops = { | 121 | struct chan_ops pty_ops = { |
129 | .type = "pty", | 122 | .type = "pty", |
130 | .init = pty_chan_init, | 123 | .init = pty_chan_init, |
@@ -132,7 +125,7 @@ struct chan_ops pty_ops = { | |||
132 | .close = generic_close, | 125 | .close = generic_close, |
133 | .read = generic_read, | 126 | .read = generic_read, |
134 | .write = generic_write, | 127 | .write = generic_write, |
135 | .console_write = pty_console_write, | 128 | .console_write = generic_console_write, |
136 | .window_size = generic_window_size, | 129 | .window_size = generic_window_size, |
137 | .free = generic_free, | 130 | .free = generic_free, |
138 | .winch = 0, | 131 | .winch = 0, |
@@ -145,7 +138,7 @@ struct chan_ops pts_ops = { | |||
145 | .close = generic_close, | 138 | .close = generic_close, |
146 | .read = generic_read, | 139 | .read = generic_read, |
147 | .write = generic_write, | 140 | .write = generic_write, |
148 | .console_write = pty_console_write, | 141 | .console_write = generic_console_write, |
149 | .window_size = generic_window_size, | 142 | .window_size = generic_window_size, |
150 | .free = generic_free, | 143 | .free = generic_free, |
151 | .winch = 0, | 144 | .winch = 0, |
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 6fbb670ee274..94c9265a4f2c 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c | |||
@@ -60,13 +60,6 @@ static int tty_open(int input, int output, int primary, void *d, | |||
60 | return(fd); | 60 | return(fd); |
61 | } | 61 | } |
62 | 62 | ||
63 | static int tty_console_write(int fd, const char *buf, int n, void *d) | ||
64 | { | ||
65 | struct tty_chan *data = d; | ||
66 | |||
67 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
68 | } | ||
69 | |||
70 | struct chan_ops tty_ops = { | 63 | struct chan_ops tty_ops = { |
71 | .type = "tty", | 64 | .type = "tty", |
72 | .init = tty_chan_init, | 65 | .init = tty_chan_init, |
@@ -74,7 +67,7 @@ struct chan_ops tty_ops = { | |||
74 | .close = generic_close, | 67 | .close = generic_close, |
75 | .read = generic_read, | 68 | .read = generic_read, |
76 | .write = generic_write, | 69 | .write = generic_write, |
77 | .console_write = tty_console_write, | 70 | .console_write = generic_console_write, |
78 | .window_size = generic_window_size, | 71 | .window_size = generic_window_size, |
79 | .free = generic_free, | 72 | .free = generic_free, |
80 | .winch = 0, | 73 | .winch = 0, |
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index b530f1a6540d..aaa636661043 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
@@ -194,13 +194,6 @@ static void xterm_free(void *d) | |||
194 | free(d); | 194 | free(d); |
195 | } | 195 | } |
196 | 196 | ||
197 | static int xterm_console_write(int fd, const char *buf, int n, void *d) | ||
198 | { | ||
199 | struct xterm_chan *data = d; | ||
200 | |||
201 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
202 | } | ||
203 | |||
204 | struct chan_ops xterm_ops = { | 197 | struct chan_ops xterm_ops = { |
205 | .type = "xterm", | 198 | .type = "xterm", |
206 | .init = xterm_init, | 199 | .init = xterm_init, |
@@ -208,7 +201,7 @@ struct chan_ops xterm_ops = { | |||
208 | .close = xterm_close, | 201 | .close = xterm_close, |
209 | .read = generic_read, | 202 | .read = generic_read, |
210 | .write = generic_write, | 203 | .write = generic_write, |
211 | .console_write = xterm_console_write, | 204 | .console_write = generic_console_write, |
212 | .window_size = generic_window_size, | 205 | .window_size = generic_window_size, |
213 | .free = xterm_free, | 206 | .free = xterm_free, |
214 | .winch = 1, | 207 | .winch = 1, |
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index f77d9aa4c164..659bb3cac32f 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h | |||
@@ -25,7 +25,7 @@ struct chan_ops { | |||
25 | void (*close)(int, void *); | 25 | void (*close)(int, void *); |
26 | int (*read)(int, char *, void *); | 26 | int (*read)(int, char *, void *); |
27 | int (*write)(int, const char *, int, void *); | 27 | int (*write)(int, const char *, int, void *); |
28 | int (*console_write)(int, const char *, int, void *); | 28 | int (*console_write)(int, const char *, int); |
29 | int (*window_size)(int, void *, unsigned short *, unsigned short *); | 29 | int (*window_size)(int, void *, unsigned short *, unsigned short *); |
30 | void (*free)(void *); | 30 | void (*free)(void *); |
31 | int winch; | 31 | int winch; |
@@ -37,7 +37,7 @@ extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, | |||
37 | extern void generic_close(int fd, void *unused); | 37 | extern void generic_close(int fd, void *unused); |
38 | extern int generic_read(int fd, char *c_out, void *unused); | 38 | extern int generic_read(int fd, char *c_out, void *unused); |
39 | extern int generic_write(int fd, const char *buf, int n, void *unused); | 39 | extern int generic_write(int fd, const char *buf, int n, void *unused); |
40 | extern int generic_console_write(int fd, const char *buf, int n, void *state); | 40 | extern int generic_console_write(int fd, const char *buf, int n); |
41 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, | 41 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, |
42 | unsigned short *cols_out); | 42 | unsigned short *cols_out); |
43 | extern void generic_free(void *data); | 43 | extern void generic_free(void *data); |
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 84c0868cd561..f8760a3f43b0 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h | |||
@@ -17,8 +17,25 @@ | |||
17 | #include "uaccess-skas.h" | 17 | #include "uaccess-skas.h" |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #define __under_task_size(addr, size) \ | ||
21 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
22 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | ||
23 | |||
24 | #define __access_ok_vsyscall(type, addr, size) \ | ||
25 | ((type == VERIFY_READ) && \ | ||
26 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
27 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
28 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) | ||
29 | |||
30 | #define __addr_range_nowrap(addr, size) \ | ||
31 | ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) | ||
32 | |||
20 | #define access_ok(type, addr, size) \ | 33 | #define access_ok(type, addr, size) \ |
21 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) | 34 | (__addr_range_nowrap(addr, size) && \ |
35 | (__under_task_size(addr, size) || \ | ||
36 | __access_ok_vsyscall(type, addr, size) || \ | ||
37 | segment_eq(get_fs(), KERNEL_DS) || \ | ||
38 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) | ||
22 | 39 | ||
23 | static inline int copy_from_user(void *to, const void __user *from, int n) | 40 | static inline int copy_from_user(void *to, const void __user *from, int n) |
24 | { | 41 | { |
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 7da0c2def0ef..f611f83ad4ff 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h | |||
@@ -9,14 +9,8 @@ | |||
9 | #include "asm/errno.h" | 9 | #include "asm/errno.h" |
10 | #include "asm/fixmap.h" | 10 | #include "asm/fixmap.h" |
11 | 11 | ||
12 | #define access_ok_skas(type, addr, size) \ | 12 | /* No SKAS-specific checking. */ |
13 | ((segment_eq(get_fs(), KERNEL_DS)) || \ | 13 | #define access_ok_skas(type, addr, size) 0 |
14 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
15 | ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \ | ||
16 | ((type == VERIFY_READ ) && \ | ||
17 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
18 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
19 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) | ||
20 | 14 | ||
21 | extern int copy_from_user_skas(void *to, const void __user *from, int n); | 15 | extern int copy_from_user_skas(void *to, const void __user *from, int n); |
22 | extern int copy_to_user_skas(void __user *to, const void *from, int n); | 16 | extern int copy_to_user_skas(void __user *to, const void *from, int n); |
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 75195281081e..a5a47528dec7 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n) | |||
143 | return(0); | 143 | return(0); |
144 | } | 144 | } |
145 | 145 | ||
146 | return(access_ok_skas(VERIFY_READ, from, n) ? | 146 | return(access_ok(VERIFY_READ, from, n) ? |
147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | 147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): |
148 | n); | 148 | n); |
149 | } | 149 | } |
@@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n) | |||
164 | return(0); | 164 | return(0); |
165 | } | 165 | } |
166 | 166 | ||
167 | return(access_ok_skas(VERIFY_WRITE, to, n) ? | 167 | return(access_ok(VERIFY_WRITE, to, n) ? |
168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | 168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : |
169 | n); | 169 | n); |
170 | } | 170 | } |
@@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count) | |||
193 | return(strnlen(dst, count)); | 193 | return(strnlen(dst, count)); |
194 | } | 194 | } |
195 | 195 | ||
196 | if(!access_ok_skas(VERIFY_READ, src, 1)) | 196 | if(!access_ok(VERIFY_READ, src, 1)) |
197 | return(-EFAULT); | 197 | return(-EFAULT); |
198 | 198 | ||
199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, | 199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, |
@@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len) | |||
221 | return(0); | 221 | return(0); |
222 | } | 222 | } |
223 | 223 | ||
224 | return(access_ok_skas(VERIFY_WRITE, mem, len) ? | 224 | return(access_ok(VERIFY_WRITE, mem, len) ? |
225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); | 225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); |
226 | } | 226 | } |
227 | 227 | ||
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 95c8f8733baf..0d4c10a73607 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c | |||
@@ -95,7 +95,16 @@ survive: | |||
95 | pte = pte_offset_kernel(pmd, address); | 95 | pte = pte_offset_kernel(pmd, address); |
96 | } while(!pte_present(*pte)); | 96 | } while(!pte_present(*pte)); |
97 | err = 0; | 97 | err = 0; |
98 | /* The below warning was added in place of | ||
99 | * pte_mkyoung(); if (is_write) pte_mkdirty(); | ||
100 | * If it's triggered, we'd see normally a hang here (a clean pte is | ||
101 | * marked read-only to emulate the dirty bit). | ||
102 | * However, the generic code can mark a PTE writable but clean on a | ||
103 | * concurrent read fault, triggering this harmlessly. So comment it out. | ||
104 | */ | ||
105 | #if 0 | ||
98 | WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); | 106 | WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); |
107 | #endif | ||
99 | flush_tlb_page(vma, address); | 108 | flush_tlb_page(vma, address); |
100 | out: | 109 | out: |
101 | up_read(&mm->mmap_sem); | 110 | up_read(&mm->mmap_sem); |
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index dc2ebfa8c54f..b9bfe9c481c4 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h | |||
@@ -19,19 +19,13 @@ | |||
19 | extern unsigned long end_vm; | 19 | extern unsigned long end_vm; |
20 | extern unsigned long uml_physmem; | 20 | extern unsigned long uml_physmem; |
21 | 21 | ||
22 | #define under_task_size(addr, size) \ | ||
23 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
24 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | ||
25 | |||
26 | #define is_stack(addr, size) \ | 22 | #define is_stack(addr, size) \ |
27 | (((unsigned long) (addr) < STACK_TOP) && \ | 23 | (((unsigned long) (addr) < STACK_TOP) && \ |
28 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ | 24 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ |
29 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) | 25 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) |
30 | 26 | ||
31 | #define access_ok_tt(type, addr, size) \ | 27 | #define access_ok_tt(type, addr, size) \ |
32 | ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ | 28 | (is_stack(addr, size)) |
33 | (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ | ||
34 | (under_task_size(addr, size) || is_stack(addr, size)))) | ||
35 | 29 | ||
36 | extern unsigned long get_fault_addr(void); | 30 | extern unsigned long get_fault_addr(void); |
37 | 31 | ||
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index a72aa632972f..1cb60726567e 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | int copy_from_user_tt(void *to, const void __user *from, int n) | 9 | int copy_from_user_tt(void *to, const void __user *from, int n) |
10 | { | 10 | { |
11 | if(!access_ok_tt(VERIFY_READ, from, n)) | 11 | if(!access_ok(VERIFY_READ, from, n)) |
12 | return(n); | 12 | return(n); |
13 | 13 | ||
14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, | 14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, |
@@ -17,7 +17,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) | |||
17 | 17 | ||
18 | int copy_to_user_tt(void __user *to, const void *from, int n) | 18 | int copy_to_user_tt(void __user *to, const void *from, int n) |
19 | { | 19 | { |
20 | if(!access_ok_tt(VERIFY_WRITE, to, n)) | 20 | if(!access_ok(VERIFY_WRITE, to, n)) |
21 | return(n); | 21 | return(n); |
22 | 22 | ||
23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, | 23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, |
@@ -28,7 +28,7 @@ int strncpy_from_user_tt(char *dst, const char __user *src, int count) | |||
28 | { | 28 | { |
29 | int n; | 29 | int n; |
30 | 30 | ||
31 | if(!access_ok_tt(VERIFY_READ, src, 1)) | 31 | if(!access_ok(VERIFY_READ, src, 1)) |
32 | return(-EFAULT); | 32 | return(-EFAULT); |
33 | 33 | ||
34 | n = __do_strncpy_from_user(dst, src, count, | 34 | n = __do_strncpy_from_user(dst, src, count, |
@@ -47,7 +47,7 @@ int __clear_user_tt(void __user *mem, int len) | |||
47 | 47 | ||
48 | int clear_user_tt(void __user *mem, int len) | 48 | int clear_user_tt(void __user *mem, int len) |
49 | { | 49 | { |
50 | if(!access_ok_tt(VERIFY_WRITE, mem, len)) | 50 | if(!access_ok(VERIFY_WRITE, mem, len)) |
51 | return(len); | 51 | return(len); |
52 | 52 | ||
53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, | 53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, |
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig index 89c053b6c2c4..310865903234 100644 --- a/arch/v850/Kconfig +++ b/arch/v850/Kconfig | |||
@@ -23,6 +23,14 @@ config GENERIC_CALIBRATE_DELAY | |||
23 | bool | 23 | bool |
24 | default y | 24 | default y |
25 | 25 | ||
26 | config GENERIC_HARDIRQS | ||
27 | bool | ||
28 | default y | ||
29 | |||
30 | config GENERIC_IRQ_PROBE | ||
31 | bool | ||
32 | default y | ||
33 | |||
26 | # Turn off some random 386 crap that can affect device config | 34 | # Turn off some random 386 crap that can affect device config |
27 | config ISA | 35 | config ISA |
28 | bool | 36 | bool |
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c index 9e85969ba976..7a151c26f82e 100644 --- a/arch/v850/kernel/irq.c +++ b/arch/v850/kernel/irq.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * arch/v850/kernel/irq.c -- High-level interrupt handling | 2 | * arch/v850/kernel/irq.c -- High-level interrupt handling |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03,04 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03,04,05 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03,04 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03,04,05 Miles Bader <miles@gnu.org> |
6 | * Copyright (C) 1994-2000 Ralf Baechle | 6 | * Copyright (C) 1994-2000 Ralf Baechle |
7 | * Copyright (C) 1992 Linus Torvalds | 7 | * Copyright (C) 1992 Linus Torvalds |
8 | * | 8 | * |
@@ -27,55 +27,15 @@ | |||
27 | #include <asm/system.h> | 27 | #include <asm/system.h> |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Controller mappings for all interrupt sources: | 30 | * 'what should we do if we get a hw irq event on an illegal vector'. |
31 | * each architecture has to answer this themselves, it doesn't deserve | ||
32 | * a generic callback i think. | ||
31 | */ | 33 | */ |
32 | irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { | 34 | void ack_bad_irq(unsigned int irq) |
33 | [0 ... NR_IRQS-1] = { | ||
34 | .handler = &no_irq_type, | ||
35 | .lock = SPIN_LOCK_UNLOCKED | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * Special irq handlers. | ||
41 | */ | ||
42 | |||
43 | irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
44 | { | ||
45 | return IRQ_NONE; | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Generic no controller code | ||
50 | */ | ||
51 | |||
52 | static void enable_none(unsigned int irq) { } | ||
53 | static unsigned int startup_none(unsigned int irq) { return 0; } | ||
54 | static void disable_none(unsigned int irq) { } | ||
55 | static void ack_none(unsigned int irq) | ||
56 | { | 35 | { |
57 | /* | ||
58 | * 'what should we do if we get a hw irq event on an illegal vector'. | ||
59 | * each architecture has to answer this themselves, it doesn't deserve | ||
60 | * a generic callback i think. | ||
61 | */ | ||
62 | printk("received IRQ %d with unknown interrupt type\n", irq); | 36 | printk("received IRQ %d with unknown interrupt type\n", irq); |
63 | } | 37 | } |
64 | 38 | ||
65 | /* startup is the same as "enable", shutdown is same as "disable" */ | ||
66 | #define shutdown_none disable_none | ||
67 | #define end_none enable_none | ||
68 | |||
69 | struct hw_interrupt_type no_irq_type = { | ||
70 | .typename = "none", | ||
71 | .startup = startup_none, | ||
72 | .shutdown = shutdown_none, | ||
73 | .enable = enable_none, | ||
74 | .disable = disable_none, | ||
75 | .ack = ack_none, | ||
76 | .end = end_none | ||
77 | }; | ||
78 | |||
79 | volatile unsigned long irq_err_count, spurious_count; | 39 | volatile unsigned long irq_err_count, spurious_count; |
80 | 40 | ||
81 | /* | 41 | /* |
@@ -84,643 +44,68 @@ volatile unsigned long irq_err_count, spurious_count; | |||
84 | 44 | ||
85 | int show_interrupts(struct seq_file *p, void *v) | 45 | int show_interrupts(struct seq_file *p, void *v) |
86 | { | 46 | { |
87 | int i = *(loff_t *) v; | 47 | int irq = *(loff_t *) v; |
88 | struct irqaction * action; | ||
89 | unsigned long flags; | ||
90 | 48 | ||
91 | if (i == 0) { | 49 | if (irq == 0) { |
50 | int cpu; | ||
92 | seq_puts(p, " "); | 51 | seq_puts(p, " "); |
93 | for (i=0; i < 1 /*smp_num_cpus*/; i++) | 52 | for (cpu=0; cpu < 1 /*smp_num_cpus*/; cpu++) |
94 | seq_printf(p, "CPU%d ", i); | 53 | seq_printf(p, "CPU%d ", cpu); |
95 | seq_putc(p, '\n'); | 54 | seq_putc(p, '\n'); |
96 | } | 55 | } |
97 | 56 | ||
98 | if (i < NR_IRQS) { | 57 | if (irq < NR_IRQS) { |
99 | int j, count, num; | 58 | unsigned long flags; |
100 | const char *type_name = irq_desc[i].handler->typename; | 59 | struct irqaction *action; |
101 | spin_lock_irqsave(&irq_desc[j].lock, flags); | ||
102 | action = irq_desc[i].action; | ||
103 | if (!action) | ||
104 | goto skip; | ||
105 | 60 | ||
106 | count = 0; | 61 | spin_lock_irqsave(&irq_desc[irq].lock, flags); |
107 | num = -1; | ||
108 | for (j = 0; j < NR_IRQS; j++) | ||
109 | if (irq_desc[j].handler->typename == type_name) { | ||
110 | if (i == j) | ||
111 | num = count; | ||
112 | count++; | ||
113 | } | ||
114 | 62 | ||
115 | seq_printf(p, "%3d: ",i); | 63 | action = irq_desc[irq].action; |
116 | seq_printf(p, "%10u ", kstat_irqs(i)); | 64 | if (action) { |
117 | if (count > 1) { | 65 | int j; |
118 | int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1); | 66 | int count = 0; |
119 | seq_printf(p, " %*s%d", 14 - prec, type_name, num); | 67 | int num = -1; |
120 | } else | 68 | const char *type_name = irq_desc[irq].handler->typename; |
121 | seq_printf(p, " %14s", type_name); | 69 | |
70 | for (j = 0; j < NR_IRQS; j++) | ||
71 | if (irq_desc[j].handler->typename == type_name){ | ||
72 | if (irq == j) | ||
73 | num = count; | ||
74 | count++; | ||
75 | } | ||
76 | |||
77 | seq_printf(p, "%3d: ",irq); | ||
78 | seq_printf(p, "%10u ", kstat_irqs(irq)); | ||
79 | if (count > 1) { | ||
80 | int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1); | ||
81 | seq_printf(p, " %*s%d", 14 - prec, | ||
82 | type_name, num); | ||
83 | } else | ||
84 | seq_printf(p, " %14s", type_name); | ||
122 | 85 | ||
123 | seq_printf(p, " %s", action->name); | 86 | seq_printf(p, " %s", action->name); |
124 | for (action=action->next; action; action = action->next) | 87 | for (action=action->next; action; action = action->next) |
125 | seq_printf(p, ", %s", action->name); | 88 | seq_printf(p, ", %s", action->name); |
126 | seq_putc(p, '\n'); | 89 | seq_putc(p, '\n'); |
127 | skip: | 90 | } |
128 | spin_unlock_irqrestore(&irq_desc[j].lock, flags); | ||
129 | } else if (i == NR_IRQS) | ||
130 | seq_printf(p, "ERR: %10lu\n", irq_err_count); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * This should really return information about whether | ||
136 | * we should do bottom half handling etc. Right now we | ||
137 | * end up _always_ checking the bottom half, which is a | ||
138 | * waste of time and is not what some drivers would | ||
139 | * prefer. | ||
140 | */ | ||
141 | int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) | ||
142 | { | ||
143 | int status = 1; /* Force the "do bottom halves" bit */ | ||
144 | int ret; | ||
145 | |||
146 | if (!(action->flags & SA_INTERRUPT)) | ||
147 | local_irq_enable(); | ||
148 | |||
149 | do { | ||
150 | ret = action->handler(irq, action->dev_id, regs); | ||
151 | if (ret == IRQ_HANDLED) | ||
152 | status |= action->flags; | ||
153 | action = action->next; | ||
154 | } while (action); | ||
155 | if (status & SA_SAMPLE_RANDOM) | ||
156 | add_interrupt_randomness(irq); | ||
157 | local_irq_disable(); | ||
158 | |||
159 | return status; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Generic enable/disable code: this just calls | ||
164 | * down into the PIC-specific version for the actual | ||
165 | * hardware disable after having gotten the irq | ||
166 | * controller lock. | ||
167 | */ | ||
168 | |||
169 | /** | ||
170 | * disable_irq_nosync - disable an irq without waiting | ||
171 | * @irq: Interrupt to disable | ||
172 | * | ||
173 | * Disable the selected interrupt line. Disables of an interrupt | ||
174 | * stack. Unlike disable_irq(), this function does not ensure existing | ||
175 | * instances of the IRQ handler have completed before returning. | ||
176 | * | ||
177 | * This function may be called from IRQ context. | ||
178 | */ | ||
179 | |||
180 | void inline disable_irq_nosync(unsigned int irq) | ||
181 | { | ||
182 | irq_desc_t *desc = irq_desc + irq; | ||
183 | unsigned long flags; | ||
184 | |||
185 | spin_lock_irqsave(&desc->lock, flags); | ||
186 | if (!desc->depth++) { | ||
187 | desc->status |= IRQ_DISABLED; | ||
188 | desc->handler->disable(irq); | ||
189 | } | ||
190 | spin_unlock_irqrestore(&desc->lock, flags); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * disable_irq - disable an irq and wait for completion | ||
195 | * @irq: Interrupt to disable | ||
196 | * | ||
197 | * Disable the selected interrupt line. Disables of an interrupt | ||
198 | * stack. That is for two disables you need two enables. This | ||
199 | * function waits for any pending IRQ handlers for this interrupt | ||
200 | * to complete before returning. If you use this function while | ||
201 | * holding a resource the IRQ handler may need you will deadlock. | ||
202 | * | ||
203 | * This function may be called - with care - from IRQ context. | ||
204 | */ | ||
205 | |||
206 | void disable_irq(unsigned int irq) | ||
207 | { | ||
208 | disable_irq_nosync(irq); | ||
209 | synchronize_irq(irq); | ||
210 | } | ||
211 | 91 | ||
212 | /** | 92 | spin_unlock_irqrestore(&irq_desc[irq].lock, flags); |
213 | * enable_irq - enable interrupt handling on an irq | 93 | } else if (irq == NR_IRQS) |
214 | * @irq: Interrupt to enable | 94 | seq_printf(p, "ERR: %10lu\n", irq_err_count); |
215 | * | ||
216 | * Re-enables the processing of interrupts on this IRQ line | ||
217 | * providing no disable_irq calls are now in effect. | ||
218 | * | ||
219 | * This function may be called from IRQ context. | ||
220 | */ | ||
221 | |||
222 | void enable_irq(unsigned int irq) | ||
223 | { | ||
224 | irq_desc_t *desc = irq_desc + irq; | ||
225 | unsigned long flags; | ||
226 | 95 | ||
227 | spin_lock_irqsave(&desc->lock, flags); | 96 | return 0; |
228 | switch (desc->depth) { | ||
229 | case 1: { | ||
230 | unsigned int status = desc->status & ~IRQ_DISABLED; | ||
231 | desc->status = status; | ||
232 | if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { | ||
233 | desc->status = status | IRQ_REPLAY; | ||
234 | hw_resend_irq(desc->handler,irq); | ||
235 | } | ||
236 | desc->handler->enable(irq); | ||
237 | /* fall-through */ | ||
238 | } | ||
239 | default: | ||
240 | desc->depth--; | ||
241 | break; | ||
242 | case 0: | ||
243 | printk("enable_irq(%u) unbalanced from %p\n", irq, | ||
244 | __builtin_return_address(0)); | ||
245 | } | ||
246 | spin_unlock_irqrestore(&desc->lock, flags); | ||
247 | } | 97 | } |
248 | 98 | ||
249 | /* Handle interrupt IRQ. REGS are the registers at the time of ther | 99 | /* Handle interrupt IRQ. REGS are the registers at the time of ther |
250 | interrupt. */ | 100 | interrupt. */ |
251 | unsigned int handle_irq (int irq, struct pt_regs *regs) | 101 | unsigned int handle_irq (int irq, struct pt_regs *regs) |
252 | { | 102 | { |
253 | /* | ||
254 | * We ack quickly, we don't want the irq controller | ||
255 | * thinking we're snobs just because some other CPU has | ||
256 | * disabled global interrupts (we have already done the | ||
257 | * INT_ACK cycles, it's too late to try to pretend to the | ||
258 | * controller that we aren't taking the interrupt). | ||
259 | * | ||
260 | * 0 return value means that this irq is already being | ||
261 | * handled by some other CPU. (or is disabled) | ||
262 | */ | ||
263 | int cpu = smp_processor_id(); | ||
264 | irq_desc_t *desc = irq_desc + irq; | ||
265 | struct irqaction * action; | ||
266 | unsigned int status; | ||
267 | |||
268 | irq_enter(); | 103 | irq_enter(); |
269 | kstat_cpu(cpu).irqs[irq]++; | 104 | __do_IRQ(irq, regs); |
270 | spin_lock(&desc->lock); | ||
271 | desc->handler->ack(irq); | ||
272 | /* | ||
273 | REPLAY is when Linux resends an IRQ that was dropped earlier | ||
274 | WAITING is used by probe to mark irqs that are being tested | ||
275 | */ | ||
276 | status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); | ||
277 | status |= IRQ_PENDING; /* we _want_ to handle it */ | ||
278 | |||
279 | /* | ||
280 | * If the IRQ is disabled for whatever reason, we cannot | ||
281 | * use the action we have. | ||
282 | */ | ||
283 | action = NULL; | ||
284 | if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { | ||
285 | action = desc->action; | ||
286 | status &= ~IRQ_PENDING; /* we commit to handling */ | ||
287 | status |= IRQ_INPROGRESS; /* we are handling it */ | ||
288 | } | ||
289 | desc->status = status; | ||
290 | |||
291 | /* | ||
292 | * If there is no IRQ handler or it was disabled, exit early. | ||
293 | Since we set PENDING, if another processor is handling | ||
294 | a different instance of this same irq, the other processor | ||
295 | will take care of it. | ||
296 | */ | ||
297 | if (unlikely(!action)) | ||
298 | goto out; | ||
299 | |||
300 | /* | ||
301 | * Edge triggered interrupts need to remember | ||
302 | * pending events. | ||
303 | * This applies to any hw interrupts that allow a second | ||
304 | * instance of the same irq to arrive while we are in handle_irq | ||
305 | * or in the handler. But the code here only handles the _second_ | ||
306 | * instance of the irq, not the third or fourth. So it is mostly | ||
307 | * useful for irq hardware that does not mask cleanly in an | ||
308 | * SMP environment. | ||
309 | */ | ||
310 | for (;;) { | ||
311 | spin_unlock(&desc->lock); | ||
312 | handle_IRQ_event(irq, regs, action); | ||
313 | spin_lock(&desc->lock); | ||
314 | |||
315 | if (likely(!(desc->status & IRQ_PENDING))) | ||
316 | break; | ||
317 | desc->status &= ~IRQ_PENDING; | ||
318 | } | ||
319 | desc->status &= ~IRQ_INPROGRESS; | ||
320 | |||
321 | out: | ||
322 | /* | ||
323 | * The ->end() handler has to deal with interrupts which got | ||
324 | * disabled while the handler was running. | ||
325 | */ | ||
326 | desc->handler->end(irq); | ||
327 | spin_unlock(&desc->lock); | ||
328 | |||
329 | irq_exit(); | 105 | irq_exit(); |
330 | |||
331 | return 1; | 106 | return 1; |
332 | } | 107 | } |
333 | 108 | ||
334 | /** | ||
335 | * request_irq - allocate an interrupt line | ||
336 | * @irq: Interrupt line to allocate | ||
337 | * @handler: Function to be called when the IRQ occurs | ||
338 | * @irqflags: Interrupt type flags | ||
339 | * @devname: An ascii name for the claiming device | ||
340 | * @dev_id: A cookie passed back to the handler function | ||
341 | * | ||
342 | * This call allocates interrupt resources and enables the | ||
343 | * interrupt line and IRQ handling. From the point this | ||
344 | * call is made your handler function may be invoked. Since | ||
345 | * your handler function must clear any interrupt the board | ||
346 | * raises, you must take care both to initialise your hardware | ||
347 | * and to set up the interrupt handler in the right order. | ||
348 | * | ||
349 | * Dev_id must be globally unique. Normally the address of the | ||
350 | * device data structure is used as the cookie. Since the handler | ||
351 | * receives this value it makes sense to use it. | ||
352 | * | ||
353 | * If your interrupt is shared you must pass a non NULL dev_id | ||
354 | * as this is required when freeing the interrupt. | ||
355 | * | ||
356 | * Flags: | ||
357 | * | ||
358 | * SA_SHIRQ Interrupt is shared | ||
359 | * | ||
360 | * SA_INTERRUPT Disable local interrupts while processing | ||
361 | * | ||
362 | * SA_SAMPLE_RANDOM The interrupt can be used for entropy | ||
363 | * | ||
364 | */ | ||
365 | |||
366 | int request_irq(unsigned int irq, | ||
367 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
368 | unsigned long irqflags, | ||
369 | const char * devname, | ||
370 | void *dev_id) | ||
371 | { | ||
372 | int retval; | ||
373 | struct irqaction * action; | ||
374 | |||
375 | #if 1 | ||
376 | /* | ||
377 | * Sanity-check: shared interrupts should REALLY pass in | ||
378 | * a real dev-ID, otherwise we'll have trouble later trying | ||
379 | * to figure out which interrupt is which (messes up the | ||
380 | * interrupt freeing logic etc). | ||
381 | */ | ||
382 | if (irqflags & SA_SHIRQ) { | ||
383 | if (!dev_id) | ||
384 | printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); | ||
385 | } | ||
386 | #endif | ||
387 | |||
388 | if (irq >= NR_IRQS) | ||
389 | return -EINVAL; | ||
390 | if (!handler) | ||
391 | return -EINVAL; | ||
392 | |||
393 | action = (struct irqaction *) | ||
394 | kmalloc(sizeof(struct irqaction), GFP_KERNEL); | ||
395 | if (!action) | ||
396 | return -ENOMEM; | ||
397 | |||
398 | action->handler = handler; | ||
399 | action->flags = irqflags; | ||
400 | cpus_clear(action->mask); | ||
401 | action->name = devname; | ||
402 | action->next = NULL; | ||
403 | action->dev_id = dev_id; | ||
404 | |||
405 | retval = setup_irq(irq, action); | ||
406 | if (retval) | ||
407 | kfree(action); | ||
408 | return retval; | ||
409 | } | ||
410 | |||
411 | EXPORT_SYMBOL(request_irq); | ||
412 | |||
413 | /** | ||
414 | * free_irq - free an interrupt | ||
415 | * @irq: Interrupt line to free | ||
416 | * @dev_id: Device identity to free | ||
417 | * | ||
418 | * Remove an interrupt handler. The handler is removed and if the | ||
419 | * interrupt line is no longer in use by any driver it is disabled. | ||
420 | * On a shared IRQ the caller must ensure the interrupt is disabled | ||
421 | * on the card it drives before calling this function. The function | ||
422 | * does not return until any executing interrupts for this IRQ | ||
423 | * have completed. | ||
424 | * | ||
425 | * This function may be called from interrupt context. | ||
426 | * | ||
427 | * Bugs: Attempting to free an irq in a handler for the same irq hangs | ||
428 | * the machine. | ||
429 | */ | ||
430 | |||
431 | void free_irq(unsigned int irq, void *dev_id) | ||
432 | { | ||
433 | irq_desc_t *desc; | ||
434 | struct irqaction **p; | ||
435 | unsigned long flags; | ||
436 | |||
437 | if (irq >= NR_IRQS) | ||
438 | return; | ||
439 | |||
440 | desc = irq_desc + irq; | ||
441 | spin_lock_irqsave(&desc->lock,flags); | ||
442 | p = &desc->action; | ||
443 | for (;;) { | ||
444 | struct irqaction * action = *p; | ||
445 | if (action) { | ||
446 | struct irqaction **pp = p; | ||
447 | p = &action->next; | ||
448 | if (action->dev_id != dev_id) | ||
449 | continue; | ||
450 | |||
451 | /* Found it - now remove it from the list of entries */ | ||
452 | *pp = action->next; | ||
453 | if (!desc->action) { | ||
454 | desc->status |= IRQ_DISABLED; | ||
455 | desc->handler->shutdown(irq); | ||
456 | } | ||
457 | spin_unlock_irqrestore(&desc->lock,flags); | ||
458 | |||
459 | synchronize_irq(irq); | ||
460 | kfree(action); | ||
461 | return; | ||
462 | } | ||
463 | printk("Trying to free free IRQ%d\n",irq); | ||
464 | spin_unlock_irqrestore(&desc->lock,flags); | ||
465 | return; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | EXPORT_SYMBOL(free_irq); | ||
470 | |||
471 | /* | ||
472 | * IRQ autodetection code.. | ||
473 | * | ||
474 | * This depends on the fact that any interrupt that | ||
475 | * comes in on to an unassigned handler will get stuck | ||
476 | * with "IRQ_WAITING" cleared and the interrupt | ||
477 | * disabled. | ||
478 | */ | ||
479 | |||
480 | static DECLARE_MUTEX(probe_sem); | ||
481 | |||
482 | /** | ||
483 | * probe_irq_on - begin an interrupt autodetect | ||
484 | * | ||
485 | * Commence probing for an interrupt. The interrupts are scanned | ||
486 | * and a mask of potential interrupt lines is returned. | ||
487 | * | ||
488 | */ | ||
489 | |||
490 | unsigned long probe_irq_on(void) | ||
491 | { | ||
492 | unsigned int i; | ||
493 | irq_desc_t *desc; | ||
494 | unsigned long val; | ||
495 | unsigned long delay; | ||
496 | |||
497 | down(&probe_sem); | ||
498 | /* | ||
499 | * something may have generated an irq long ago and we want to | ||
500 | * flush such a longstanding irq before considering it as spurious. | ||
501 | */ | ||
502 | for (i = NR_IRQS-1; i > 0; i--) { | ||
503 | desc = irq_desc + i; | ||
504 | |||
505 | spin_lock_irq(&desc->lock); | ||
506 | if (!irq_desc[i].action) | ||
507 | irq_desc[i].handler->startup(i); | ||
508 | spin_unlock_irq(&desc->lock); | ||
509 | } | ||
510 | |||
511 | /* Wait for longstanding interrupts to trigger. */ | ||
512 | for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) | ||
513 | /* about 20ms delay */ barrier(); | ||
514 | |||
515 | /* | ||
516 | * enable any unassigned irqs | ||
517 | * (we must startup again here because if a longstanding irq | ||
518 | * happened in the previous stage, it may have masked itself) | ||
519 | */ | ||
520 | for (i = NR_IRQS-1; i > 0; i--) { | ||
521 | desc = irq_desc + i; | ||
522 | |||
523 | spin_lock_irq(&desc->lock); | ||
524 | if (!desc->action) { | ||
525 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; | ||
526 | if (desc->handler->startup(i)) | ||
527 | desc->status |= IRQ_PENDING; | ||
528 | } | ||
529 | spin_unlock_irq(&desc->lock); | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Wait for spurious interrupts to trigger | ||
534 | */ | ||
535 | for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) | ||
536 | /* about 100ms delay */ barrier(); | ||
537 | |||
538 | /* | ||
539 | * Now filter out any obviously spurious interrupts | ||
540 | */ | ||
541 | val = 0; | ||
542 | for (i = 0; i < NR_IRQS; i++) { | ||
543 | irq_desc_t *desc = irq_desc + i; | ||
544 | unsigned int status; | ||
545 | |||
546 | spin_lock_irq(&desc->lock); | ||
547 | status = desc->status; | ||
548 | |||
549 | if (status & IRQ_AUTODETECT) { | ||
550 | /* It triggered already - consider it spurious. */ | ||
551 | if (!(status & IRQ_WAITING)) { | ||
552 | desc->status = status & ~IRQ_AUTODETECT; | ||
553 | desc->handler->shutdown(i); | ||
554 | } else | ||
555 | if (i < 32) | ||
556 | val |= 1 << i; | ||
557 | } | ||
558 | spin_unlock_irq(&desc->lock); | ||
559 | } | ||
560 | |||
561 | return val; | ||
562 | } | ||
563 | |||
564 | EXPORT_SYMBOL(probe_irq_on); | ||
565 | |||
566 | /* | ||
567 | * Return a mask of triggered interrupts (this | ||
568 | * can handle only legacy ISA interrupts). | ||
569 | */ | ||
570 | |||
571 | /** | ||
572 | * probe_irq_mask - scan a bitmap of interrupt lines | ||
573 | * @val: mask of interrupts to consider | ||
574 | * | ||
575 | * Scan the ISA bus interrupt lines and return a bitmap of | ||
576 | * active interrupts. The interrupt probe logic state is then | ||
577 | * returned to its previous value. | ||
578 | * | ||
579 | * Note: we need to scan all the irq's even though we will | ||
580 | * only return ISA irq numbers - just so that we reset them | ||
581 | * all to a known state. | ||
582 | */ | ||
583 | unsigned int probe_irq_mask(unsigned long val) | ||
584 | { | ||
585 | int i; | ||
586 | unsigned int mask; | ||
587 | |||
588 | mask = 0; | ||
589 | for (i = 0; i < NR_IRQS; i++) { | ||
590 | irq_desc_t *desc = irq_desc + i; | ||
591 | unsigned int status; | ||
592 | |||
593 | spin_lock_irq(&desc->lock); | ||
594 | status = desc->status; | ||
595 | |||
596 | if (status & IRQ_AUTODETECT) { | ||
597 | if (i < 16 && !(status & IRQ_WAITING)) | ||
598 | mask |= 1 << i; | ||
599 | |||
600 | desc->status = status & ~IRQ_AUTODETECT; | ||
601 | desc->handler->shutdown(i); | ||
602 | } | ||
603 | spin_unlock_irq(&desc->lock); | ||
604 | } | ||
605 | up(&probe_sem); | ||
606 | |||
607 | return mask & val; | ||
608 | } | ||
609 | |||
610 | /* | ||
611 | * Return the one interrupt that triggered (this can | ||
612 | * handle any interrupt source). | ||
613 | */ | ||
614 | |||
615 | /** | ||
616 | * probe_irq_off - end an interrupt autodetect | ||
617 | * @val: mask of potential interrupts (unused) | ||
618 | * | ||
619 | * Scans the unused interrupt lines and returns the line which | ||
620 | * appears to have triggered the interrupt. If no interrupt was | ||
621 | * found then zero is returned. If more than one interrupt is | ||
622 | * found then minus the first candidate is returned to indicate | ||
623 | * their is doubt. | ||
624 | * | ||
625 | * The interrupt probe logic state is returned to its previous | ||
626 | * value. | ||
627 | * | ||
628 | * BUGS: When used in a module (which arguably shouldnt happen) | ||
629 | * nothing prevents two IRQ probe callers from overlapping. The | ||
630 | * results of this are non-optimal. | ||
631 | */ | ||
632 | |||
633 | int probe_irq_off(unsigned long val) | ||
634 | { | ||
635 | int i, irq_found, nr_irqs; | ||
636 | |||
637 | nr_irqs = 0; | ||
638 | irq_found = 0; | ||
639 | for (i = 0; i < NR_IRQS; i++) { | ||
640 | irq_desc_t *desc = irq_desc + i; | ||
641 | unsigned int status; | ||
642 | |||
643 | spin_lock_irq(&desc->lock); | ||
644 | status = desc->status; | ||
645 | |||
646 | if (status & IRQ_AUTODETECT) { | ||
647 | if (!(status & IRQ_WAITING)) { | ||
648 | if (!nr_irqs) | ||
649 | irq_found = i; | ||
650 | nr_irqs++; | ||
651 | } | ||
652 | desc->status = status & ~IRQ_AUTODETECT; | ||
653 | desc->handler->shutdown(i); | ||
654 | } | ||
655 | spin_unlock_irq(&desc->lock); | ||
656 | } | ||
657 | up(&probe_sem); | ||
658 | |||
659 | if (nr_irqs > 1) | ||
660 | irq_found = -irq_found; | ||
661 | return irq_found; | ||
662 | } | ||
663 | |||
664 | EXPORT_SYMBOL(probe_irq_off); | ||
665 | |||
666 | /* this was setup_x86_irq but it seems pretty generic */ | ||
667 | int setup_irq(unsigned int irq, struct irqaction * new) | ||
668 | { | ||
669 | int shared = 0; | ||
670 | unsigned long flags; | ||
671 | struct irqaction *old, **p; | ||
672 | irq_desc_t *desc = irq_desc + irq; | ||
673 | |||
674 | /* | ||
675 | * Some drivers like serial.c use request_irq() heavily, | ||
676 | * so we have to be careful not to interfere with a | ||
677 | * running system. | ||
678 | */ | ||
679 | if (new->flags & SA_SAMPLE_RANDOM) { | ||
680 | /* | ||
681 | * This function might sleep, we want to call it first, | ||
682 | * outside of the atomic block. | ||
683 | * Yes, this might clear the entropy pool if the wrong | ||
684 | * driver is attempted to be loaded, without actually | ||
685 | * installing a new handler, but is this really a problem, | ||
686 | * only the sysadmin is able to do this. | ||
687 | */ | ||
688 | rand_initialize_irq(irq); | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * The following block of code has to be executed atomically | ||
693 | */ | ||
694 | spin_lock_irqsave(&desc->lock,flags); | ||
695 | p = &desc->action; | ||
696 | if ((old = *p) != NULL) { | ||
697 | /* Can't share interrupts unless both agree to */ | ||
698 | if (!(old->flags & new->flags & SA_SHIRQ)) { | ||
699 | spin_unlock_irqrestore(&desc->lock,flags); | ||
700 | return -EBUSY; | ||
701 | } | ||
702 | |||
703 | /* add new interrupt at end of irq queue */ | ||
704 | do { | ||
705 | p = &old->next; | ||
706 | old = *p; | ||
707 | } while (old); | ||
708 | shared = 1; | ||
709 | } | ||
710 | |||
711 | *p = new; | ||
712 | |||
713 | if (!shared) { | ||
714 | desc->depth = 0; | ||
715 | desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); | ||
716 | desc->handler->startup(irq); | ||
717 | } | ||
718 | spin_unlock_irqrestore(&desc->lock,flags); | ||
719 | |||
720 | /* register_irq_proc(irq); */ | ||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /* Initialize irq handling for IRQs. | 109 | /* Initialize irq handling for IRQs. |
725 | BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL | 110 | BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL |
726 | to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */ | 111 | to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */ |
@@ -736,9 +121,3 @@ init_irq_handlers (int base_irq, int num, int interval, | |||
736 | base_irq += interval; | 121 | base_irq += interval; |
737 | } | 122 | } |
738 | } | 123 | } |
739 | |||
740 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) | ||
741 | void init_irq_proc(void) | ||
742 | { | ||
743 | } | ||
744 | #endif /* CONFIG_PROC_FS && CONFIG_SYSCTL */ | ||
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4cce2f6f170c..6ece645e4dbe 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -226,22 +226,42 @@ config SCHED_SMT | |||
226 | 226 | ||
227 | source "kernel/Kconfig.preempt" | 227 | source "kernel/Kconfig.preempt" |
228 | 228 | ||
229 | config K8_NUMA | 229 | config NUMA |
230 | bool "K8 NUMA support" | 230 | bool "Non Uniform Memory Access (NUMA) Support" |
231 | select NUMA | ||
232 | depends on SMP | 231 | depends on SMP |
233 | help | 232 | help |
234 | Enable NUMA (Non Unified Memory Architecture) support for | 233 | Enable NUMA (Non Uniform Memory Access) support. The kernel |
235 | AMD Opteron Multiprocessor systems. The kernel will try to allocate | 234 | will try to allocate memory used by a CPU on the local memory |
236 | memory used by a CPU on the local memory controller of the CPU | 235 | controller of the CPU and add some more NUMA awareness to the kernel. |
237 | and add some more NUMA awareness to the kernel. | 236 | This code is recommended on all multiprocessor Opteron systems. |
238 | This code is recommended on all multiprocessor Opteron systems | 237 | If the system is EM64T, you should say N unless your system is EM64T |
239 | and normally doesn't hurt on others. | 238 | NUMA. |
239 | |||
240 | config K8_NUMA | ||
241 | bool "Old style AMD Opteron NUMA detection" | ||
242 | depends on NUMA | ||
243 | default y | ||
244 | help | ||
245 | Enable K8 NUMA node topology detection. You should say Y here if | ||
246 | you have a multi processor AMD K8 system. This uses an old | ||
247 | method to read the NUMA configurtion directly from the builtin | ||
248 | Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA | ||
249 | instead, which also takes priority if both are compiled in. | ||
250 | |||
251 | # Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig. | ||
252 | |||
253 | config X86_64_ACPI_NUMA | ||
254 | bool "ACPI NUMA detection" | ||
255 | depends on NUMA | ||
256 | select ACPI | ||
257 | select ACPI_NUMA | ||
258 | default y | ||
259 | help | ||
260 | Enable ACPI SRAT based node topology detection. | ||
240 | 261 | ||
241 | config NUMA_EMU | 262 | config NUMA_EMU |
242 | bool "NUMA emulation support" | 263 | bool "NUMA emulation" |
243 | select NUMA | 264 | depends on NUMA |
244 | depends on SMP | ||
245 | help | 265 | help |
246 | Enable NUMA emulation. A flat machine will be split | 266 | Enable NUMA emulation. A flat machine will be split |
247 | into virtual nodes when booted with "numa=fake=N", where N is the | 267 | into virtual nodes when booted with "numa=fake=N", where N is the |
@@ -252,9 +272,6 @@ config ARCH_DISCONTIGMEM_ENABLE | |||
252 | depends on NUMA | 272 | depends on NUMA |
253 | default y | 273 | default y |
254 | 274 | ||
255 | config NUMA | ||
256 | bool | ||
257 | default n | ||
258 | 275 | ||
259 | config ARCH_DISCONTIGMEM_ENABLE | 276 | config ARCH_DISCONTIGMEM_ENABLE |
260 | def_bool y | 277 | def_bool y |
@@ -374,6 +391,14 @@ config X86_MCE_INTEL | |||
374 | Additional support for intel specific MCE features such as | 391 | Additional support for intel specific MCE features such as |
375 | the thermal monitor. | 392 | the thermal monitor. |
376 | 393 | ||
394 | config X86_MCE_AMD | ||
395 | bool "AMD MCE features" | ||
396 | depends on X86_MCE && X86_LOCAL_APIC | ||
397 | default y | ||
398 | help | ||
399 | Additional support for AMD specific MCE features such as | ||
400 | the DRAM Error Threshold. | ||
401 | |||
377 | config PHYSICAL_START | 402 | config PHYSICAL_START |
378 | hex "Physical address where the kernel is loaded" if EMBEDDED | 403 | hex "Physical address where the kernel is loaded" if EMBEDDED |
379 | default "0x100000" | 404 | default "0x100000" |
@@ -502,7 +527,7 @@ config IA32_EMULATION | |||
502 | left. | 527 | left. |
503 | 528 | ||
504 | config IA32_AOUT | 529 | config IA32_AOUT |
505 | bool "IA32 a.out support" | 530 | tristate "IA32 a.out support" |
506 | depends on IA32_EMULATION | 531 | depends on IA32_EMULATION |
507 | help | 532 | help |
508 | Support old a.out binaries in the 32bit emulation. | 533 | Support old a.out binaries in the 32bit emulation. |
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index d584ecc27ea1..e2c6e64a85ec 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug | |||
@@ -2,15 +2,6 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | # !SMP for now because the context switch early causes GPF in segment reloading | ||
6 | # and the GS base checking does the wrong thing then, causing a hang. | ||
7 | config CHECKING | ||
8 | bool "Additional run-time checks" | ||
9 | depends on DEBUG_KERNEL && !SMP | ||
10 | help | ||
11 | Enables some internal consistency checks for kernel debugging. | ||
12 | You should normally say N. | ||
13 | |||
14 | config INIT_DEBUG | 5 | config INIT_DEBUG |
15 | bool "Debug __init statements" | 6 | bool "Debug __init statements" |
16 | depends on DEBUG_KERNEL | 7 | depends on DEBUG_KERNEL |
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index f8db7e500fbf..5d56542fb68f 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-git11 | 3 | # Linux kernel version: 2.6.14-git7 |
4 | # Mon Sep 12 16:16:16 2005 | 4 | # Sat Nov 5 15:55:50 2005 |
5 | # | 5 | # |
6 | CONFIG_X86_64=y | 6 | CONFIG_X86_64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -35,7 +35,7 @@ CONFIG_POSIX_MQUEUE=y | |||
35 | # CONFIG_BSD_PROCESS_ACCT is not set | 35 | # CONFIG_BSD_PROCESS_ACCT is not set |
36 | CONFIG_SYSCTL=y | 36 | CONFIG_SYSCTL=y |
37 | # CONFIG_AUDIT is not set | 37 | # CONFIG_AUDIT is not set |
38 | # CONFIG_HOTPLUG is not set | 38 | CONFIG_HOTPLUG=y |
39 | CONFIG_KOBJECT_UEVENT=y | 39 | CONFIG_KOBJECT_UEVENT=y |
40 | CONFIG_IKCONFIG=y | 40 | CONFIG_IKCONFIG=y |
41 | CONFIG_IKCONFIG_PROC=y | 41 | CONFIG_IKCONFIG_PROC=y |
@@ -93,10 +93,11 @@ CONFIG_PREEMPT_NONE=y | |||
93 | # CONFIG_PREEMPT_VOLUNTARY is not set | 93 | # CONFIG_PREEMPT_VOLUNTARY is not set |
94 | # CONFIG_PREEMPT is not set | 94 | # CONFIG_PREEMPT is not set |
95 | CONFIG_PREEMPT_BKL=y | 95 | CONFIG_PREEMPT_BKL=y |
96 | CONFIG_NUMA=y | ||
96 | CONFIG_K8_NUMA=y | 97 | CONFIG_K8_NUMA=y |
98 | CONFIG_X86_64_ACPI_NUMA=y | ||
97 | # CONFIG_NUMA_EMU is not set | 99 | # CONFIG_NUMA_EMU is not set |
98 | CONFIG_ARCH_DISCONTIGMEM_ENABLE=y | 100 | CONFIG_ARCH_DISCONTIGMEM_ENABLE=y |
99 | CONFIG_NUMA=y | ||
100 | CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y | 101 | CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y |
101 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | 102 | CONFIG_ARCH_SPARSEMEM_ENABLE=y |
102 | CONFIG_SELECT_MEMORY_MODEL=y | 103 | CONFIG_SELECT_MEMORY_MODEL=y |
@@ -107,9 +108,10 @@ CONFIG_DISCONTIGMEM=y | |||
107 | CONFIG_FLAT_NODE_MEM_MAP=y | 108 | CONFIG_FLAT_NODE_MEM_MAP=y |
108 | CONFIG_NEED_MULTIPLE_NODES=y | 109 | CONFIG_NEED_MULTIPLE_NODES=y |
109 | # CONFIG_SPARSEMEM_STATIC is not set | 110 | # CONFIG_SPARSEMEM_STATIC is not set |
111 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
110 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y | 112 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y |
111 | CONFIG_HAVE_DEC_LOCK=y | ||
112 | CONFIG_NR_CPUS=32 | 113 | CONFIG_NR_CPUS=32 |
114 | CONFIG_HOTPLUG_CPU=y | ||
113 | CONFIG_HPET_TIMER=y | 115 | CONFIG_HPET_TIMER=y |
114 | CONFIG_X86_PM_TIMER=y | 116 | CONFIG_X86_PM_TIMER=y |
115 | CONFIG_HPET_EMULATE_RTC=y | 117 | CONFIG_HPET_EMULATE_RTC=y |
@@ -117,6 +119,7 @@ CONFIG_GART_IOMMU=y | |||
117 | CONFIG_SWIOTLB=y | 119 | CONFIG_SWIOTLB=y |
118 | CONFIG_X86_MCE=y | 120 | CONFIG_X86_MCE=y |
119 | CONFIG_X86_MCE_INTEL=y | 121 | CONFIG_X86_MCE_INTEL=y |
122 | CONFIG_X86_MCE_AMD=y | ||
120 | CONFIG_PHYSICAL_START=0x100000 | 123 | CONFIG_PHYSICAL_START=0x100000 |
121 | # CONFIG_KEXEC is not set | 124 | # CONFIG_KEXEC is not set |
122 | CONFIG_SECCOMP=y | 125 | CONFIG_SECCOMP=y |
@@ -136,11 +139,15 @@ CONFIG_PM=y | |||
136 | # CONFIG_PM_DEBUG is not set | 139 | # CONFIG_PM_DEBUG is not set |
137 | CONFIG_SOFTWARE_SUSPEND=y | 140 | CONFIG_SOFTWARE_SUSPEND=y |
138 | CONFIG_PM_STD_PARTITION="" | 141 | CONFIG_PM_STD_PARTITION="" |
142 | CONFIG_SUSPEND_SMP=y | ||
139 | 143 | ||
140 | # | 144 | # |
141 | # ACPI (Advanced Configuration and Power Interface) Support | 145 | # ACPI (Advanced Configuration and Power Interface) Support |
142 | # | 146 | # |
143 | CONFIG_ACPI=y | 147 | CONFIG_ACPI=y |
148 | CONFIG_ACPI_SLEEP=y | ||
149 | CONFIG_ACPI_SLEEP_PROC_FS=y | ||
150 | CONFIG_ACPI_SLEEP_PROC_SLEEP=y | ||
144 | CONFIG_ACPI_AC=y | 151 | CONFIG_ACPI_AC=y |
145 | CONFIG_ACPI_BATTERY=y | 152 | CONFIG_ACPI_BATTERY=y |
146 | CONFIG_ACPI_BUTTON=y | 153 | CONFIG_ACPI_BUTTON=y |
@@ -148,6 +155,7 @@ CONFIG_ACPI_BUTTON=y | |||
148 | CONFIG_ACPI_HOTKEY=m | 155 | CONFIG_ACPI_HOTKEY=m |
149 | CONFIG_ACPI_FAN=y | 156 | CONFIG_ACPI_FAN=y |
150 | CONFIG_ACPI_PROCESSOR=y | 157 | CONFIG_ACPI_PROCESSOR=y |
158 | CONFIG_ACPI_HOTPLUG_CPU=y | ||
151 | CONFIG_ACPI_THERMAL=y | 159 | CONFIG_ACPI_THERMAL=y |
152 | CONFIG_ACPI_NUMA=y | 160 | CONFIG_ACPI_NUMA=y |
153 | # CONFIG_ACPI_ASUS is not set | 161 | # CONFIG_ACPI_ASUS is not set |
@@ -158,7 +166,7 @@ CONFIG_ACPI_BLACKLIST_YEAR=2001 | |||
158 | CONFIG_ACPI_EC=y | 166 | CONFIG_ACPI_EC=y |
159 | CONFIG_ACPI_POWER=y | 167 | CONFIG_ACPI_POWER=y |
160 | CONFIG_ACPI_SYSTEM=y | 168 | CONFIG_ACPI_SYSTEM=y |
161 | # CONFIG_ACPI_CONTAINER is not set | 169 | CONFIG_ACPI_CONTAINER=y |
162 | 170 | ||
163 | # | 171 | # |
164 | # CPU Frequency scaling | 172 | # CPU Frequency scaling |
@@ -293,7 +301,6 @@ CONFIG_IPV6=y | |||
293 | # Network testing | 301 | # Network testing |
294 | # | 302 | # |
295 | # CONFIG_NET_PKTGEN is not set | 303 | # CONFIG_NET_PKTGEN is not set |
296 | # CONFIG_NETFILTER_NETLINK is not set | ||
297 | # CONFIG_HAMRADIO is not set | 304 | # CONFIG_HAMRADIO is not set |
298 | # CONFIG_IRDA is not set | 305 | # CONFIG_IRDA is not set |
299 | # CONFIG_BT is not set | 306 | # CONFIG_BT is not set |
@@ -312,6 +319,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y | |||
312 | # CONFIG_DEBUG_DRIVER is not set | 319 | # CONFIG_DEBUG_DRIVER is not set |
313 | 320 | ||
314 | # | 321 | # |
322 | # Connector - unified userspace <-> kernelspace linker | ||
323 | # | ||
324 | # CONFIG_CONNECTOR is not set | ||
325 | |||
326 | # | ||
315 | # Memory Technology Devices (MTD) | 327 | # Memory Technology Devices (MTD) |
316 | # | 328 | # |
317 | # CONFIG_MTD is not set | 329 | # CONFIG_MTD is not set |
@@ -354,6 +366,11 @@ CONFIG_IOSCHED_NOOP=y | |||
354 | # CONFIG_IOSCHED_AS is not set | 366 | # CONFIG_IOSCHED_AS is not set |
355 | CONFIG_IOSCHED_DEADLINE=y | 367 | CONFIG_IOSCHED_DEADLINE=y |
356 | CONFIG_IOSCHED_CFQ=y | 368 | CONFIG_IOSCHED_CFQ=y |
369 | # CONFIG_DEFAULT_AS is not set | ||
370 | CONFIG_DEFAULT_DEADLINE=y | ||
371 | # CONFIG_DEFAULT_CFQ is not set | ||
372 | # CONFIG_DEFAULT_NOOP is not set | ||
373 | CONFIG_DEFAULT_IOSCHED="cfq" | ||
357 | # CONFIG_ATA_OVER_ETH is not set | 374 | # CONFIG_ATA_OVER_ETH is not set |
358 | 375 | ||
359 | # | 376 | # |
@@ -450,6 +467,7 @@ CONFIG_BLK_DEV_SD=y | |||
450 | CONFIG_SCSI_SPI_ATTRS=y | 467 | CONFIG_SCSI_SPI_ATTRS=y |
451 | # CONFIG_SCSI_FC_ATTRS is not set | 468 | # CONFIG_SCSI_FC_ATTRS is not set |
452 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 469 | # CONFIG_SCSI_ISCSI_ATTRS is not set |
470 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
453 | 471 | ||
454 | # | 472 | # |
455 | # SCSI low-level drivers | 473 | # SCSI low-level drivers |
@@ -469,20 +487,24 @@ CONFIG_AIC79XX_DEBUG_MASK=0 | |||
469 | # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set | 487 | # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set |
470 | # CONFIG_MEGARAID_NEWGEN is not set | 488 | # CONFIG_MEGARAID_NEWGEN is not set |
471 | # CONFIG_MEGARAID_LEGACY is not set | 489 | # CONFIG_MEGARAID_LEGACY is not set |
490 | # CONFIG_MEGARAID_SAS is not set | ||
472 | CONFIG_SCSI_SATA=y | 491 | CONFIG_SCSI_SATA=y |
473 | # CONFIG_SCSI_SATA_AHCI is not set | 492 | # CONFIG_SCSI_SATA_AHCI is not set |
474 | # CONFIG_SCSI_SATA_SVW is not set | 493 | # CONFIG_SCSI_SATA_SVW is not set |
475 | CONFIG_SCSI_ATA_PIIX=y | 494 | CONFIG_SCSI_ATA_PIIX=y |
476 | # CONFIG_SCSI_SATA_MV is not set | 495 | # CONFIG_SCSI_SATA_MV is not set |
477 | # CONFIG_SCSI_SATA_NV is not set | 496 | CONFIG_SCSI_SATA_NV=y |
478 | # CONFIG_SCSI_SATA_PROMISE is not set | 497 | # CONFIG_SCSI_PDC_ADMA is not set |
479 | # CONFIG_SCSI_SATA_QSTOR is not set | 498 | # CONFIG_SCSI_SATA_QSTOR is not set |
499 | # CONFIG_SCSI_SATA_PROMISE is not set | ||
480 | # CONFIG_SCSI_SATA_SX4 is not set | 500 | # CONFIG_SCSI_SATA_SX4 is not set |
481 | # CONFIG_SCSI_SATA_SIL is not set | 501 | # CONFIG_SCSI_SATA_SIL is not set |
502 | # CONFIG_SCSI_SATA_SIL24 is not set | ||
482 | # CONFIG_SCSI_SATA_SIS is not set | 503 | # CONFIG_SCSI_SATA_SIS is not set |
483 | # CONFIG_SCSI_SATA_ULI is not set | 504 | # CONFIG_SCSI_SATA_ULI is not set |
484 | CONFIG_SCSI_SATA_VIA=y | 505 | CONFIG_SCSI_SATA_VIA=y |
485 | # CONFIG_SCSI_SATA_VITESSE is not set | 506 | # CONFIG_SCSI_SATA_VITESSE is not set |
507 | CONFIG_SCSI_SATA_INTEL_COMBINED=y | ||
486 | # CONFIG_SCSI_BUSLOGIC is not set | 508 | # CONFIG_SCSI_BUSLOGIC is not set |
487 | # CONFIG_SCSI_DMX3191D is not set | 509 | # CONFIG_SCSI_DMX3191D is not set |
488 | # CONFIG_SCSI_EATA is not set | 510 | # CONFIG_SCSI_EATA is not set |
@@ -525,6 +547,7 @@ CONFIG_BLK_DEV_DM=y | |||
525 | CONFIG_FUSION=y | 547 | CONFIG_FUSION=y |
526 | CONFIG_FUSION_SPI=y | 548 | CONFIG_FUSION_SPI=y |
527 | # CONFIG_FUSION_FC is not set | 549 | # CONFIG_FUSION_FC is not set |
550 | # CONFIG_FUSION_SAS is not set | ||
528 | CONFIG_FUSION_MAX_SGE=128 | 551 | CONFIG_FUSION_MAX_SGE=128 |
529 | # CONFIG_FUSION_CTL is not set | 552 | # CONFIG_FUSION_CTL is not set |
530 | 553 | ||
@@ -564,6 +587,7 @@ CONFIG_NET_ETHERNET=y | |||
564 | CONFIG_MII=y | 587 | CONFIG_MII=y |
565 | # CONFIG_HAPPYMEAL is not set | 588 | # CONFIG_HAPPYMEAL is not set |
566 | # CONFIG_SUNGEM is not set | 589 | # CONFIG_SUNGEM is not set |
590 | # CONFIG_CASSINI is not set | ||
567 | CONFIG_NET_VENDOR_3COM=y | 591 | CONFIG_NET_VENDOR_3COM=y |
568 | CONFIG_VORTEX=y | 592 | CONFIG_VORTEX=y |
569 | # CONFIG_TYPHOON is not set | 593 | # CONFIG_TYPHOON is not set |
@@ -740,7 +764,43 @@ CONFIG_LEGACY_PTY_COUNT=256 | |||
740 | # | 764 | # |
741 | # Watchdog Cards | 765 | # Watchdog Cards |
742 | # | 766 | # |
743 | # CONFIG_WATCHDOG is not set | 767 | CONFIG_WATCHDOG=y |
768 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
769 | |||
770 | # | ||
771 | # Watchdog Device Drivers | ||
772 | # | ||
773 | CONFIG_SOFT_WATCHDOG=y | ||
774 | # CONFIG_ACQUIRE_WDT is not set | ||
775 | # CONFIG_ADVANTECH_WDT is not set | ||
776 | # CONFIG_ALIM1535_WDT is not set | ||
777 | # CONFIG_ALIM7101_WDT is not set | ||
778 | # CONFIG_SC520_WDT is not set | ||
779 | # CONFIG_EUROTECH_WDT is not set | ||
780 | # CONFIG_IB700_WDT is not set | ||
781 | # CONFIG_IBMASR is not set | ||
782 | # CONFIG_WAFER_WDT is not set | ||
783 | # CONFIG_I6300ESB_WDT is not set | ||
784 | # CONFIG_I8XX_TCO is not set | ||
785 | # CONFIG_SC1200_WDT is not set | ||
786 | # CONFIG_60XX_WDT is not set | ||
787 | # CONFIG_SBC8360_WDT is not set | ||
788 | # CONFIG_CPU5_WDT is not set | ||
789 | # CONFIG_W83627HF_WDT is not set | ||
790 | # CONFIG_W83877F_WDT is not set | ||
791 | # CONFIG_W83977F_WDT is not set | ||
792 | # CONFIG_MACHZ_WDT is not set | ||
793 | |||
794 | # | ||
795 | # PCI-based Watchdog Cards | ||
796 | # | ||
797 | # CONFIG_PCIPCWATCHDOG is not set | ||
798 | # CONFIG_WDTPCI is not set | ||
799 | |||
800 | # | ||
801 | # USB-based Watchdog Cards | ||
802 | # | ||
803 | # CONFIG_USBPCWATCHDOG is not set | ||
744 | CONFIG_HW_RANDOM=y | 804 | CONFIG_HW_RANDOM=y |
745 | # CONFIG_NVRAM is not set | 805 | # CONFIG_NVRAM is not set |
746 | CONFIG_RTC=y | 806 | CONFIG_RTC=y |
@@ -767,6 +827,7 @@ CONFIG_MAX_RAW_DEVS=256 | |||
767 | # TPM devices | 827 | # TPM devices |
768 | # | 828 | # |
769 | # CONFIG_TCG_TPM is not set | 829 | # CONFIG_TCG_TPM is not set |
830 | # CONFIG_TELCLOCK is not set | ||
770 | 831 | ||
771 | # | 832 | # |
772 | # I2C support | 833 | # I2C support |
@@ -783,6 +844,7 @@ CONFIG_MAX_RAW_DEVS=256 | |||
783 | # | 844 | # |
784 | CONFIG_HWMON=y | 845 | CONFIG_HWMON=y |
785 | # CONFIG_HWMON_VID is not set | 846 | # CONFIG_HWMON_VID is not set |
847 | # CONFIG_SENSORS_HDAPS is not set | ||
786 | # CONFIG_HWMON_DEBUG_CHIP is not set | 848 | # CONFIG_HWMON_DEBUG_CHIP is not set |
787 | 849 | ||
788 | # | 850 | # |
@@ -886,12 +948,15 @@ CONFIG_USB_UHCI_HCD=y | |||
886 | # USB Device Class drivers | 948 | # USB Device Class drivers |
887 | # | 949 | # |
888 | # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set | 950 | # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set |
889 | # CONFIG_USB_BLUETOOTH_TTY is not set | ||
890 | # CONFIG_USB_ACM is not set | 951 | # CONFIG_USB_ACM is not set |
891 | CONFIG_USB_PRINTER=y | 952 | CONFIG_USB_PRINTER=y |
892 | 953 | ||
893 | # | 954 | # |
894 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information | 955 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' |
956 | # | ||
957 | |||
958 | # | ||
959 | # may also be needed; see USB_STORAGE Help for more information | ||
895 | # | 960 | # |
896 | CONFIG_USB_STORAGE=y | 961 | CONFIG_USB_STORAGE=y |
897 | # CONFIG_USB_STORAGE_DEBUG is not set | 962 | # CONFIG_USB_STORAGE_DEBUG is not set |
@@ -924,6 +989,7 @@ CONFIG_USB_HIDINPUT=y | |||
924 | # CONFIG_USB_XPAD is not set | 989 | # CONFIG_USB_XPAD is not set |
925 | # CONFIG_USB_ATI_REMOTE is not set | 990 | # CONFIG_USB_ATI_REMOTE is not set |
926 | # CONFIG_USB_KEYSPAN_REMOTE is not set | 991 | # CONFIG_USB_KEYSPAN_REMOTE is not set |
992 | # CONFIG_USB_APPLETOUCH is not set | ||
927 | 993 | ||
928 | # | 994 | # |
929 | # USB Imaging devices | 995 | # USB Imaging devices |
@@ -1005,7 +1071,7 @@ CONFIG_USB_MON=y | |||
1005 | # | 1071 | # |
1006 | # CONFIG_EDD is not set | 1072 | # CONFIG_EDD is not set |
1007 | # CONFIG_DELL_RBU is not set | 1073 | # CONFIG_DELL_RBU is not set |
1008 | CONFIG_DCDBAS=m | 1074 | # CONFIG_DCDBAS is not set |
1009 | 1075 | ||
1010 | # | 1076 | # |
1011 | # File systems | 1077 | # File systems |
@@ -1037,7 +1103,7 @@ CONFIG_INOTIFY=y | |||
1037 | # CONFIG_QUOTA is not set | 1103 | # CONFIG_QUOTA is not set |
1038 | CONFIG_DNOTIFY=y | 1104 | CONFIG_DNOTIFY=y |
1039 | CONFIG_AUTOFS_FS=y | 1105 | CONFIG_AUTOFS_FS=y |
1040 | # CONFIG_AUTOFS4_FS is not set | 1106 | CONFIG_AUTOFS4_FS=y |
1041 | # CONFIG_FUSE_FS is not set | 1107 | # CONFIG_FUSE_FS is not set |
1042 | 1108 | ||
1043 | # | 1109 | # |
@@ -1068,7 +1134,7 @@ CONFIG_TMPFS=y | |||
1068 | CONFIG_HUGETLBFS=y | 1134 | CONFIG_HUGETLBFS=y |
1069 | CONFIG_HUGETLB_PAGE=y | 1135 | CONFIG_HUGETLB_PAGE=y |
1070 | CONFIG_RAMFS=y | 1136 | CONFIG_RAMFS=y |
1071 | # CONFIG_RELAYFS_FS is not set | 1137 | CONFIG_RELAYFS_FS=y |
1072 | 1138 | ||
1073 | # | 1139 | # |
1074 | # Miscellaneous filesystems | 1140 | # Miscellaneous filesystems |
@@ -1186,7 +1252,9 @@ CONFIG_DETECT_SOFTLOCKUP=y | |||
1186 | # CONFIG_DEBUG_KOBJECT is not set | 1252 | # CONFIG_DEBUG_KOBJECT is not set |
1187 | # CONFIG_DEBUG_INFO is not set | 1253 | # CONFIG_DEBUG_INFO is not set |
1188 | CONFIG_DEBUG_FS=y | 1254 | CONFIG_DEBUG_FS=y |
1255 | # CONFIG_DEBUG_VM is not set | ||
1189 | # CONFIG_FRAME_POINTER is not set | 1256 | # CONFIG_FRAME_POINTER is not set |
1257 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1190 | CONFIG_INIT_DEBUG=y | 1258 | CONFIG_INIT_DEBUG=y |
1191 | # CONFIG_IOMMU_DEBUG is not set | 1259 | # CONFIG_IOMMU_DEBUG is not set |
1192 | CONFIG_KPROBES=y | 1260 | CONFIG_KPROBES=y |
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index 93c60f4aa47a..3bf58af98936 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #undef WARN_OLD | 36 | #undef WARN_OLD |
37 | #undef CORE_DUMP /* probably broken */ | 37 | #undef CORE_DUMP /* probably broken */ |
38 | 38 | ||
39 | extern int ia32_setup_arg_pages(struct linux_binprm *bprm, | ||
40 | unsigned long stack_top, int exec_stack); | ||
41 | |||
42 | static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); | 39 | static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); |
43 | static int load_aout_library(struct file*); | 40 | static int load_aout_library(struct file*); |
44 | 41 | ||
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index d9161e395978..830feb272eca 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c | |||
@@ -335,7 +335,8 @@ static void elf32_init(struct pt_regs *regs) | |||
335 | me->thread.es = __USER_DS; | 335 | me->thread.es = __USER_DS; |
336 | } | 336 | } |
337 | 337 | ||
338 | int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack) | 338 | int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, |
339 | int executable_stack) | ||
339 | { | 340 | { |
340 | unsigned long stack_base; | 341 | unsigned long stack_base; |
341 | struct vm_area_struct *mpnt; | 342 | struct vm_area_struct *mpnt; |
@@ -389,6 +390,7 @@ int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int exec | |||
389 | 390 | ||
390 | return 0; | 391 | return 0; |
391 | } | 392 | } |
393 | EXPORT_SYMBOL(ia32_setup_arg_pages); | ||
392 | 394 | ||
393 | static unsigned long | 395 | static unsigned long |
394 | elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) | 396 | elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) |
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 14328cab5d3a..fe4cbd1c4b2f 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile | |||
@@ -11,6 +11,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ | |||
11 | 11 | ||
12 | obj-$(CONFIG_X86_MCE) += mce.o | 12 | obj-$(CONFIG_X86_MCE) += mce.o |
13 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o | 13 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o |
14 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o | ||
14 | obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ | 15 | obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ |
15 | obj-$(CONFIG_ACPI) += acpi/ | 16 | obj-$(CONFIG_ACPI) += acpi/ |
16 | obj-$(CONFIG_X86_MSR) += msr.o | 17 | obj-$(CONFIG_X86_MSR) += msr.o |
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index 962ad4823b6a..c7f4fdd20f05 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c | |||
@@ -196,7 +196,7 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) | |||
196 | void __init iommu_hole_init(void) | 196 | void __init iommu_hole_init(void) |
197 | { | 197 | { |
198 | int fix, num; | 198 | int fix, num; |
199 | u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0; | 199 | u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; |
200 | u64 aper_base, last_aper_base = 0; | 200 | u64 aper_base, last_aper_base = 0; |
201 | int valid_agp = 0; | 201 | int valid_agp = 0; |
202 | 202 | ||
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index b6e7715d877f..18691ce4c759 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c | |||
@@ -833,6 +833,16 @@ int setup_profiling_timer(unsigned int multiplier) | |||
833 | return 0; | 833 | return 0; |
834 | } | 834 | } |
835 | 835 | ||
836 | #ifdef CONFIG_X86_MCE_AMD | ||
837 | void setup_threshold_lvt(unsigned long lvt_off) | ||
838 | { | ||
839 | unsigned int v = 0; | ||
840 | unsigned long reg = (lvt_off << 4) + 0x500; | ||
841 | v |= THRESHOLD_APIC_VECTOR; | ||
842 | apic_write(reg, v); | ||
843 | } | ||
844 | #endif /* CONFIG_X86_MCE_AMD */ | ||
845 | |||
836 | #undef APIC_DIVISOR | 846 | #undef APIC_DIVISOR |
837 | 847 | ||
838 | /* | 848 | /* |
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index ab3f87aaff70..17579a1a174b 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -23,8 +23,7 @@ | |||
23 | #include <asm/e820.h> | 23 | #include <asm/e820.h> |
24 | #include <asm/proto.h> | 24 | #include <asm/proto.h> |
25 | #include <asm/bootsetup.h> | 25 | #include <asm/bootsetup.h> |
26 | 26 | #include <asm/sections.h> | |
27 | extern char _end[]; | ||
28 | 27 | ||
29 | /* | 28 | /* |
30 | * PFN of last memory page. | 29 | * PFN of last memory page. |
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 7937971d1853..9ff42041bb6b 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S | |||
@@ -612,6 +612,9 @@ retint_kernel: | |||
612 | ENTRY(thermal_interrupt) | 612 | ENTRY(thermal_interrupt) |
613 | apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt | 613 | apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt |
614 | 614 | ||
615 | ENTRY(threshold_interrupt) | ||
616 | apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt | ||
617 | |||
615 | #ifdef CONFIG_SMP | 618 | #ifdef CONFIG_SMP |
616 | ENTRY(reschedule_interrupt) | 619 | ENTRY(reschedule_interrupt) |
617 | apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt | 620 | apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt |
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index b92e5f45ed46..15290968e49d 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <linux/threads.h> | 14 | #include <linux/threads.h> |
15 | #include <linux/init.h> | ||
15 | #include <asm/desc.h> | 16 | #include <asm/desc.h> |
16 | #include <asm/segment.h> | 17 | #include <asm/segment.h> |
17 | #include <asm/page.h> | 18 | #include <asm/page.h> |
@@ -70,7 +71,7 @@ startup_32: | |||
70 | movl %eax, %cr4 | 71 | movl %eax, %cr4 |
71 | 72 | ||
72 | /* Setup early boot stage 4 level pagetables */ | 73 | /* Setup early boot stage 4 level pagetables */ |
73 | movl $(init_level4_pgt - __START_KERNEL_map), %eax | 74 | movl $(boot_level4_pgt - __START_KERNEL_map), %eax |
74 | movl %eax, %cr3 | 75 | movl %eax, %cr3 |
75 | 76 | ||
76 | /* Setup EFER (Extended Feature Enable Register) */ | 77 | /* Setup EFER (Extended Feature Enable Register) */ |
@@ -113,7 +114,7 @@ startup_64: | |||
113 | movq %rax, %cr4 | 114 | movq %rax, %cr4 |
114 | 115 | ||
115 | /* Setup early boot stage 4 level pagetables. */ | 116 | /* Setup early boot stage 4 level pagetables. */ |
116 | movq $(init_level4_pgt - __START_KERNEL_map), %rax | 117 | movq $(boot_level4_pgt - __START_KERNEL_map), %rax |
117 | movq %rax, %cr3 | 118 | movq %rax, %cr3 |
118 | 119 | ||
119 | /* Check if nx is implemented */ | 120 | /* Check if nx is implemented */ |
@@ -240,20 +241,10 @@ ljumpvector: | |||
240 | ENTRY(stext) | 241 | ENTRY(stext) |
241 | ENTRY(_stext) | 242 | ENTRY(_stext) |
242 | 243 | ||
243 | /* | ||
244 | * This default setting generates an ident mapping at address 0x100000 | ||
245 | * and a mapping for the kernel that precisely maps virtual address | ||
246 | * 0xffffffff80000000 to physical address 0x000000. (always using | ||
247 | * 2Mbyte large pages provided by PAE mode) | ||
248 | */ | ||
249 | .org 0x1000 | 244 | .org 0x1000 |
250 | ENTRY(init_level4_pgt) | 245 | ENTRY(init_level4_pgt) |
251 | .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ | 246 | /* This gets initialized in x86_64_start_kernel */ |
252 | .fill 255,8,0 | 247 | .fill 512,8,0 |
253 | .quad 0x000000000000a007 + __PHYSICAL_START | ||
254 | .fill 254,8,0 | ||
255 | /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ | ||
256 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ | ||
257 | 248 | ||
258 | .org 0x2000 | 249 | .org 0x2000 |
259 | ENTRY(level3_ident_pgt) | 250 | ENTRY(level3_ident_pgt) |
@@ -350,6 +341,24 @@ ENTRY(wakeup_level4_pgt) | |||
350 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ | 341 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ |
351 | #endif | 342 | #endif |
352 | 343 | ||
344 | #ifndef CONFIG_HOTPLUG_CPU | ||
345 | __INITDATA | ||
346 | #endif | ||
347 | /* | ||
348 | * This default setting generates an ident mapping at address 0x100000 | ||
349 | * and a mapping for the kernel that precisely maps virtual address | ||
350 | * 0xffffffff80000000 to physical address 0x000000. (always using | ||
351 | * 2Mbyte large pages provided by PAE mode) | ||
352 | */ | ||
353 | .align PAGE_SIZE | ||
354 | ENTRY(boot_level4_pgt) | ||
355 | .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ | ||
356 | .fill 255,8,0 | ||
357 | .quad 0x000000000000a007 + __PHYSICAL_START | ||
358 | .fill 254,8,0 | ||
359 | /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ | ||
360 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ | ||
361 | |||
353 | .data | 362 | .data |
354 | 363 | ||
355 | .align 16 | 364 | .align 16 |
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index cf6ab147a2a5..b675c5add01e 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c | |||
@@ -19,14 +19,15 @@ | |||
19 | #include <asm/bootsetup.h> | 19 | #include <asm/bootsetup.h> |
20 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
21 | #include <asm/desc.h> | 21 | #include <asm/desc.h> |
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/sections.h> | ||
22 | 24 | ||
23 | /* Don't add a printk in there. printk relies on the PDA which is not initialized | 25 | /* Don't add a printk in there. printk relies on the PDA which is not initialized |
24 | yet. */ | 26 | yet. */ |
25 | static void __init clear_bss(void) | 27 | static void __init clear_bss(void) |
26 | { | 28 | { |
27 | extern char __bss_start[], __bss_end[]; | ||
28 | memset(__bss_start, 0, | 29 | memset(__bss_start, 0, |
29 | (unsigned long) __bss_end - (unsigned long) __bss_start); | 30 | (unsigned long) __bss_stop - (unsigned long) __bss_start); |
30 | } | 31 | } |
31 | 32 | ||
32 | #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ | 33 | #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ |
@@ -75,8 +76,6 @@ static void __init setup_boot_cpu_data(void) | |||
75 | boot_cpu_data.x86_mask = eax & 0xf; | 76 | boot_cpu_data.x86_mask = eax & 0xf; |
76 | } | 77 | } |
77 | 78 | ||
78 | extern char _end[]; | ||
79 | |||
80 | void __init x86_64_start_kernel(char * real_mode_data) | 79 | void __init x86_64_start_kernel(char * real_mode_data) |
81 | { | 80 | { |
82 | char *s; | 81 | char *s; |
@@ -86,6 +85,13 @@ void __init x86_64_start_kernel(char * real_mode_data) | |||
86 | set_intr_gate(i, early_idt_handler); | 85 | set_intr_gate(i, early_idt_handler); |
87 | asm volatile("lidt %0" :: "m" (idt_descr)); | 86 | asm volatile("lidt %0" :: "m" (idt_descr)); |
88 | clear_bss(); | 87 | clear_bss(); |
88 | |||
89 | /* | ||
90 | * switch to init_level4_pgt from boot_level4_pgt | ||
91 | */ | ||
92 | memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t)); | ||
93 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
94 | |||
89 | pda_init(0); | 95 | pda_init(0); |
90 | copy_bootdata(real_mode_data); | 96 | copy_bootdata(real_mode_data); |
91 | #ifdef CONFIG_SMP | 97 | #ifdef CONFIG_SMP |
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index c6c9791d77c1..6e5101ad3d1a 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c | |||
@@ -492,6 +492,7 @@ void invalidate_interrupt5(void); | |||
492 | void invalidate_interrupt6(void); | 492 | void invalidate_interrupt6(void); |
493 | void invalidate_interrupt7(void); | 493 | void invalidate_interrupt7(void); |
494 | void thermal_interrupt(void); | 494 | void thermal_interrupt(void); |
495 | void threshold_interrupt(void); | ||
495 | void i8254_timer_resume(void); | 496 | void i8254_timer_resume(void); |
496 | 497 | ||
497 | static void setup_timer_hardware(void) | 498 | static void setup_timer_hardware(void) |
@@ -515,7 +516,7 @@ void i8254_timer_resume(void) | |||
515 | } | 516 | } |
516 | 517 | ||
517 | static struct sysdev_class timer_sysclass = { | 518 | static struct sysdev_class timer_sysclass = { |
518 | set_kset_name("timer"), | 519 | set_kset_name("timer_pit"), |
519 | .resume = timer_resume, | 520 | .resume = timer_resume, |
520 | }; | 521 | }; |
521 | 522 | ||
@@ -580,6 +581,7 @@ void __init init_IRQ(void) | |||
580 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); | 581 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); |
581 | #endif | 582 | #endif |
582 | set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); | 583 | set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); |
584 | set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); | ||
583 | 585 | ||
584 | #ifdef CONFIG_X86_LOCAL_APIC | 586 | #ifdef CONFIG_X86_LOCAL_APIC |
585 | /* self generated IPI for local APIC timer */ | 587 | /* self generated IPI for local APIC timer */ |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index c8eee20cd519..97154ab058b4 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
@@ -57,7 +57,7 @@ int nr_ioapic_registers[MAX_IO_APICS]; | |||
57 | * Rough estimation of how many shared IRQs there are, can | 57 | * Rough estimation of how many shared IRQs there are, can |
58 | * be changed anytime. | 58 | * be changed anytime. |
59 | */ | 59 | */ |
60 | #define MAX_PLUS_SHARED_IRQS NR_IRQS | 60 | #define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS |
61 | #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) | 61 | #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) |
62 | 62 | ||
63 | /* | 63 | /* |
@@ -85,6 +85,7 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; | |||
85 | int pin; \ | 85 | int pin; \ |
86 | struct irq_pin_list *entry = irq_2_pin + irq; \ | 86 | struct irq_pin_list *entry = irq_2_pin + irq; \ |
87 | \ | 87 | \ |
88 | BUG_ON(irq >= NR_IRQS); \ | ||
88 | for (;;) { \ | 89 | for (;;) { \ |
89 | unsigned int reg; \ | 90 | unsigned int reg; \ |
90 | pin = entry->pin; \ | 91 | pin = entry->pin; \ |
@@ -127,6 +128,8 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) | |||
127 | } | 128 | } |
128 | #endif | 129 | #endif |
129 | 130 | ||
131 | static u8 gsi_2_irq[NR_IRQ_VECTORS] = { [0 ... NR_IRQ_VECTORS-1] = 0xFF }; | ||
132 | |||
130 | /* | 133 | /* |
131 | * The common case is 1:1 IRQ<->pin mappings. Sometimes there are | 134 | * The common case is 1:1 IRQ<->pin mappings. Sometimes there are |
132 | * shared ISA-space IRQs, so we have to support them. We are super | 135 | * shared ISA-space IRQs, so we have to support them. We are super |
@@ -137,6 +140,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
137 | static int first_free_entry = NR_IRQS; | 140 | static int first_free_entry = NR_IRQS; |
138 | struct irq_pin_list *entry = irq_2_pin + irq; | 141 | struct irq_pin_list *entry = irq_2_pin + irq; |
139 | 142 | ||
143 | BUG_ON(irq >= NR_IRQS); | ||
140 | while (entry->next) | 144 | while (entry->next) |
141 | entry = irq_2_pin + entry->next; | 145 | entry = irq_2_pin + entry->next; |
142 | 146 | ||
@@ -144,7 +148,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
144 | entry->next = first_free_entry; | 148 | entry->next = first_free_entry; |
145 | entry = irq_2_pin + entry->next; | 149 | entry = irq_2_pin + entry->next; |
146 | if (++first_free_entry >= PIN_MAP_SIZE) | 150 | if (++first_free_entry >= PIN_MAP_SIZE) |
147 | panic("io_apic.c: whoops"); | 151 | panic("io_apic.c: ran out of irq_2_pin entries!"); |
148 | } | 152 | } |
149 | entry->apic = apic; | 153 | entry->apic = apic; |
150 | entry->pin = pin; | 154 | entry->pin = pin; |
@@ -420,6 +424,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) | |||
420 | best_guess = irq; | 424 | best_guess = irq; |
421 | } | 425 | } |
422 | } | 426 | } |
427 | BUG_ON(best_guess >= NR_IRQS); | ||
423 | return best_guess; | 428 | return best_guess; |
424 | } | 429 | } |
425 | 430 | ||
@@ -610,6 +615,64 @@ static inline int irq_trigger(int idx) | |||
610 | return MPBIOS_trigger(idx); | 615 | return MPBIOS_trigger(idx); |
611 | } | 616 | } |
612 | 617 | ||
618 | static int next_irq = 16; | ||
619 | |||
620 | /* | ||
621 | * gsi_irq_sharing -- Name overload! "irq" can be either a legacy IRQ | ||
622 | * in the range 0-15, a linux IRQ in the range 0-223, or a GSI number | ||
623 | * from ACPI, which can reach 800 in large boxen. | ||
624 | * | ||
625 | * Compact the sparse GSI space into a sequential IRQ series and reuse | ||
626 | * vectors if possible. | ||
627 | */ | ||
628 | int gsi_irq_sharing(int gsi) | ||
629 | { | ||
630 | int i, tries, vector; | ||
631 | |||
632 | BUG_ON(gsi >= NR_IRQ_VECTORS); | ||
633 | |||
634 | if (platform_legacy_irq(gsi)) | ||
635 | return gsi; | ||
636 | |||
637 | if (gsi_2_irq[gsi] != 0xFF) | ||
638 | return (int)gsi_2_irq[gsi]; | ||
639 | |||
640 | tries = NR_IRQS; | ||
641 | try_again: | ||
642 | vector = assign_irq_vector(gsi); | ||
643 | |||
644 | /* | ||
645 | * Sharing vectors means sharing IRQs, so scan irq_vectors for previous | ||
646 | * use of vector and if found, return that IRQ. However, we never want | ||
647 | * to share legacy IRQs, which usually have a different trigger mode | ||
648 | * than PCI. | ||
649 | */ | ||
650 | for (i = 0; i < NR_IRQS; i++) | ||
651 | if (IO_APIC_VECTOR(i) == vector) | ||
652 | break; | ||
653 | if (platform_legacy_irq(i)) { | ||
654 | if (--tries >= 0) { | ||
655 | IO_APIC_VECTOR(i) = 0; | ||
656 | goto try_again; | ||
657 | } | ||
658 | panic("gsi_irq_sharing: didn't find an IRQ using vector 0x%02X for GSI %d", vector, gsi); | ||
659 | } | ||
660 | if (i < NR_IRQS) { | ||
661 | gsi_2_irq[gsi] = i; | ||
662 | printk(KERN_INFO "GSI %d sharing vector 0x%02X and IRQ %d\n", | ||
663 | gsi, vector, i); | ||
664 | return i; | ||
665 | } | ||
666 | |||
667 | i = next_irq++; | ||
668 | BUG_ON(i >= NR_IRQS); | ||
669 | gsi_2_irq[gsi] = i; | ||
670 | IO_APIC_VECTOR(i) = vector; | ||
671 | printk(KERN_INFO "GSI %d assigned vector 0x%02X and IRQ %d\n", | ||
672 | gsi, vector, i); | ||
673 | return i; | ||
674 | } | ||
675 | |||
613 | static int pin_2_irq(int idx, int apic, int pin) | 676 | static int pin_2_irq(int idx, int apic, int pin) |
614 | { | 677 | { |
615 | int irq, i; | 678 | int irq, i; |
@@ -639,6 +702,7 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
639 | while (i < apic) | 702 | while (i < apic) |
640 | irq += nr_ioapic_registers[i++]; | 703 | irq += nr_ioapic_registers[i++]; |
641 | irq += pin; | 704 | irq += pin; |
705 | irq = gsi_irq_sharing(irq); | ||
642 | break; | 706 | break; |
643 | } | 707 | } |
644 | default: | 708 | default: |
@@ -648,6 +712,7 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
648 | break; | 712 | break; |
649 | } | 713 | } |
650 | } | 714 | } |
715 | BUG_ON(irq >= NR_IRQS); | ||
651 | 716 | ||
652 | /* | 717 | /* |
653 | * PCI IRQ command line redirection. Yes, limits are hardcoded. | 718 | * PCI IRQ command line redirection. Yes, limits are hardcoded. |
@@ -663,6 +728,7 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
663 | } | 728 | } |
664 | } | 729 | } |
665 | } | 730 | } |
731 | BUG_ON(irq >= NR_IRQS); | ||
666 | return irq; | 732 | return irq; |
667 | } | 733 | } |
668 | 734 | ||
@@ -690,8 +756,8 @@ int assign_irq_vector(int irq) | |||
690 | { | 756 | { |
691 | static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; | 757 | static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; |
692 | 758 | ||
693 | BUG_ON(irq >= NR_IRQ_VECTORS); | 759 | BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS); |
694 | if (IO_APIC_VECTOR(irq) > 0) | 760 | if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) |
695 | return IO_APIC_VECTOR(irq); | 761 | return IO_APIC_VECTOR(irq); |
696 | next: | 762 | next: |
697 | current_vector += 8; | 763 | current_vector += 8; |
@@ -699,9 +765,8 @@ next: | |||
699 | goto next; | 765 | goto next; |
700 | 766 | ||
701 | if (current_vector >= FIRST_SYSTEM_VECTOR) { | 767 | if (current_vector >= FIRST_SYSTEM_VECTOR) { |
702 | offset++; | 768 | /* If we run out of vectors on large boxen, must share them. */ |
703 | if (!(offset%8)) | 769 | offset = (offset + 1) % 8; |
704 | return -ENOSPC; | ||
705 | current_vector = FIRST_DEVICE_VECTOR + offset; | 770 | current_vector = FIRST_DEVICE_VECTOR + offset; |
706 | } | 771 | } |
707 | 772 | ||
@@ -1917,6 +1982,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | |||
1917 | entry.polarity = active_high_low; | 1982 | entry.polarity = active_high_low; |
1918 | entry.mask = 1; /* Disabled (masked) */ | 1983 | entry.mask = 1; /* Disabled (masked) */ |
1919 | 1984 | ||
1985 | irq = gsi_irq_sharing(irq); | ||
1920 | /* | 1986 | /* |
1921 | * IRQs < 16 are already in the irq_2_pin[] map | 1987 | * IRQs < 16 are already in the irq_2_pin[] map |
1922 | */ | 1988 | */ |
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 69541db5ff2c..183dc6105429 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c | |||
@@ -37,7 +37,7 @@ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL }; | |||
37 | static unsigned long console_logged; | 37 | static unsigned long console_logged; |
38 | static int notify_user; | 38 | static int notify_user; |
39 | static int rip_msr; | 39 | static int rip_msr; |
40 | static int mce_bootlog; | 40 | static int mce_bootlog = 1; |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Lockless MCE logging infrastructure. | 43 | * Lockless MCE logging infrastructure. |
@@ -347,7 +347,11 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c) | |||
347 | /* disable GART TBL walk error reporting, which trips off | 347 | /* disable GART TBL walk error reporting, which trips off |
348 | incorrectly with the IOMMU & 3ware & Cerberus. */ | 348 | incorrectly with the IOMMU & 3ware & Cerberus. */ |
349 | clear_bit(10, &bank[4]); | 349 | clear_bit(10, &bank[4]); |
350 | /* Lots of broken BIOS around that don't clear them | ||
351 | by default and leave crap in there. Don't log. */ | ||
352 | mce_bootlog = 0; | ||
350 | } | 353 | } |
354 | |||
351 | } | 355 | } |
352 | 356 | ||
353 | static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | 357 | static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) |
@@ -356,6 +360,9 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | |||
356 | case X86_VENDOR_INTEL: | 360 | case X86_VENDOR_INTEL: |
357 | mce_intel_feature_init(c); | 361 | mce_intel_feature_init(c); |
358 | break; | 362 | break; |
363 | case X86_VENDOR_AMD: | ||
364 | mce_amd_feature_init(c); | ||
365 | break; | ||
359 | default: | 366 | default: |
360 | break; | 367 | break; |
361 | } | 368 | } |
@@ -495,16 +502,16 @@ static int __init mcheck_disable(char *str) | |||
495 | /* mce=off disables machine check. Note you can reenable it later | 502 | /* mce=off disables machine check. Note you can reenable it later |
496 | using sysfs. | 503 | using sysfs. |
497 | mce=TOLERANCELEVEL (number, see above) | 504 | mce=TOLERANCELEVEL (number, see above) |
498 | mce=bootlog Log MCEs from before booting. Disabled by default to work | 505 | mce=bootlog Log MCEs from before booting. Disabled by default on AMD. |
499 | around buggy BIOS that leave bogus MCEs. */ | 506 | mce=nobootlog Don't log MCEs from before booting. */ |
500 | static int __init mcheck_enable(char *str) | 507 | static int __init mcheck_enable(char *str) |
501 | { | 508 | { |
502 | if (*str == '=') | 509 | if (*str == '=') |
503 | str++; | 510 | str++; |
504 | if (!strcmp(str, "off")) | 511 | if (!strcmp(str, "off")) |
505 | mce_dont_init = 1; | 512 | mce_dont_init = 1; |
506 | else if (!strcmp(str, "bootlog")) | 513 | else if (!strcmp(str, "bootlog") || !strcmp(str,"nobootlog")) |
507 | mce_bootlog = 1; | 514 | mce_bootlog = str[0] == 'b'; |
508 | else if (isdigit(str[0])) | 515 | else if (isdigit(str[0])) |
509 | get_option(&str, &tolerant); | 516 | get_option(&str, &tolerant); |
510 | else | 517 | else |
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c new file mode 100644 index 000000000000..1f76175ace02 --- /dev/null +++ b/arch/x86_64/kernel/mce_amd.c | |||
@@ -0,0 +1,538 @@ | |||
1 | /* | ||
2 | * (c) 2005 Advanced Micro Devices, Inc. | ||
3 | * Your use of this code is subject to the terms and conditions of the | ||
4 | * GNU general public license version 2. See "COPYING" or | ||
5 | * http://www.gnu.org/licenses/gpl.html | ||
6 | * | ||
7 | * Written by Jacob Shin - AMD, Inc. | ||
8 | * | ||
9 | * Support : jacob.shin@amd.com | ||
10 | * | ||
11 | * MC4_MISC0 DRAM ECC Error Threshold available under AMD K8 Rev F. | ||
12 | * MC4_MISC0 exists per physical processor. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/cpu.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/kobject.h> | ||
21 | #include <linux/notifier.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/smp.h> | ||
24 | #include <linux/sysdev.h> | ||
25 | #include <linux/sysfs.h> | ||
26 | #include <asm/apic.h> | ||
27 | #include <asm/mce.h> | ||
28 | #include <asm/msr.h> | ||
29 | #include <asm/percpu.h> | ||
30 | |||
31 | #define PFX "mce_threshold: " | ||
32 | #define VERSION "version 1.00.9" | ||
33 | #define NR_BANKS 5 | ||
34 | #define THRESHOLD_MAX 0xFFF | ||
35 | #define INT_TYPE_APIC 0x00020000 | ||
36 | #define MASK_VALID_HI 0x80000000 | ||
37 | #define MASK_LVTOFF_HI 0x00F00000 | ||
38 | #define MASK_COUNT_EN_HI 0x00080000 | ||
39 | #define MASK_INT_TYPE_HI 0x00060000 | ||
40 | #define MASK_OVERFLOW_HI 0x00010000 | ||
41 | #define MASK_ERR_COUNT_HI 0x00000FFF | ||
42 | #define MASK_OVERFLOW 0x0001000000000000L | ||
43 | |||
44 | struct threshold_bank { | ||
45 | unsigned int cpu; | ||
46 | u8 bank; | ||
47 | u8 interrupt_enable; | ||
48 | u16 threshold_limit; | ||
49 | struct kobject kobj; | ||
50 | }; | ||
51 | |||
52 | static struct threshold_bank threshold_defaults = { | ||
53 | .interrupt_enable = 0, | ||
54 | .threshold_limit = THRESHOLD_MAX, | ||
55 | }; | ||
56 | |||
57 | #ifdef CONFIG_SMP | ||
58 | static unsigned char shared_bank[NR_BANKS] = { | ||
59 | 0, 0, 0, 0, 1 | ||
60 | }; | ||
61 | #endif | ||
62 | |||
63 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ | ||
64 | |||
65 | /* | ||
66 | * CPU Initialization | ||
67 | */ | ||
68 | |||
69 | /* must be called with correct cpu affinity */ | ||
70 | static void threshold_restart_bank(struct threshold_bank *b, | ||
71 | int reset, u16 old_limit) | ||
72 | { | ||
73 | u32 mci_misc_hi, mci_misc_lo; | ||
74 | |||
75 | rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi); | ||
76 | |||
77 | if (b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX)) | ||
78 | reset = 1; /* limit cannot be lower than err count */ | ||
79 | |||
80 | if (reset) { /* reset err count and overflow bit */ | ||
81 | mci_misc_hi = | ||
82 | (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | | ||
83 | (THRESHOLD_MAX - b->threshold_limit); | ||
84 | } else if (old_limit) { /* change limit w/o reset */ | ||
85 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + | ||
86 | (old_limit - b->threshold_limit); | ||
87 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | | ||
88 | (new_count & THRESHOLD_MAX); | ||
89 | } | ||
90 | |||
91 | b->interrupt_enable ? | ||
92 | (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : | ||
93 | (mci_misc_hi &= ~MASK_INT_TYPE_HI); | ||
94 | |||
95 | mci_misc_hi |= MASK_COUNT_EN_HI; | ||
96 | wrmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi); | ||
97 | } | ||
98 | |||
99 | void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) | ||
100 | { | ||
101 | int bank; | ||
102 | u32 mci_misc_lo, mci_misc_hi; | ||
103 | unsigned int cpu = smp_processor_id(); | ||
104 | |||
105 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
106 | rdmsr(MSR_IA32_MC0_MISC + bank * 4, mci_misc_lo, mci_misc_hi); | ||
107 | |||
108 | /* !valid, !counter present, bios locked */ | ||
109 | if (!(mci_misc_hi & MASK_VALID_HI) || | ||
110 | !(mci_misc_hi & MASK_VALID_HI >> 1) || | ||
111 | (mci_misc_hi & MASK_VALID_HI >> 2)) | ||
112 | continue; | ||
113 | |||
114 | per_cpu(bank_map, cpu) |= (1 << bank); | ||
115 | |||
116 | #ifdef CONFIG_SMP | ||
117 | if (shared_bank[bank] && cpu_core_id[cpu]) | ||
118 | continue; | ||
119 | #endif | ||
120 | |||
121 | setup_threshold_lvt((mci_misc_hi & MASK_LVTOFF_HI) >> 20); | ||
122 | threshold_defaults.cpu = cpu; | ||
123 | threshold_defaults.bank = bank; | ||
124 | threshold_restart_bank(&threshold_defaults, 0, 0); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * APIC Interrupt Handler | ||
130 | */ | ||
131 | |||
132 | /* | ||
133 | * threshold interrupt handler will service THRESHOLD_APIC_VECTOR. | ||
134 | * the interrupt goes off when error_count reaches threshold_limit. | ||
135 | * the handler will simply log mcelog w/ software defined bank number. | ||
136 | */ | ||
137 | asmlinkage void mce_threshold_interrupt(void) | ||
138 | { | ||
139 | int bank; | ||
140 | struct mce m; | ||
141 | |||
142 | ack_APIC_irq(); | ||
143 | irq_enter(); | ||
144 | |||
145 | memset(&m, 0, sizeof(m)); | ||
146 | rdtscll(m.tsc); | ||
147 | m.cpu = smp_processor_id(); | ||
148 | |||
149 | /* assume first bank caused it */ | ||
150 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
151 | m.bank = MCE_THRESHOLD_BASE + bank; | ||
152 | rdmsrl(MSR_IA32_MC0_MISC + bank * 4, m.misc); | ||
153 | |||
154 | if (m.misc & MASK_OVERFLOW) { | ||
155 | mce_log(&m); | ||
156 | goto out; | ||
157 | } | ||
158 | } | ||
159 | out: | ||
160 | irq_exit(); | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Sysfs Interface | ||
165 | */ | ||
166 | |||
167 | static struct sysdev_class threshold_sysclass = { | ||
168 | set_kset_name("threshold"), | ||
169 | }; | ||
170 | |||
171 | static DEFINE_PER_CPU(struct sys_device, device_threshold); | ||
172 | |||
173 | struct threshold_attr { | ||
174 | struct attribute attr; | ||
175 | ssize_t(*show) (struct threshold_bank *, char *); | ||
176 | ssize_t(*store) (struct threshold_bank *, const char *, size_t count); | ||
177 | }; | ||
178 | |||
179 | static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); | ||
180 | |||
181 | static cpumask_t affinity_set(unsigned int cpu) | ||
182 | { | ||
183 | cpumask_t oldmask = current->cpus_allowed; | ||
184 | cpumask_t newmask = CPU_MASK_NONE; | ||
185 | cpu_set(cpu, newmask); | ||
186 | set_cpus_allowed(current, newmask); | ||
187 | return oldmask; | ||
188 | } | ||
189 | |||
190 | static void affinity_restore(cpumask_t oldmask) | ||
191 | { | ||
192 | set_cpus_allowed(current, oldmask); | ||
193 | } | ||
194 | |||
195 | #define SHOW_FIELDS(name) \ | ||
196 | static ssize_t show_ ## name(struct threshold_bank * b, char *buf) \ | ||
197 | { \ | ||
198 | return sprintf(buf, "%lx\n", (unsigned long) b->name); \ | ||
199 | } | ||
200 | SHOW_FIELDS(interrupt_enable) | ||
201 | SHOW_FIELDS(threshold_limit) | ||
202 | |||
203 | static ssize_t store_interrupt_enable(struct threshold_bank *b, | ||
204 | const char *buf, size_t count) | ||
205 | { | ||
206 | char *end; | ||
207 | cpumask_t oldmask; | ||
208 | unsigned long new = simple_strtoul(buf, &end, 0); | ||
209 | if (end == buf) | ||
210 | return -EINVAL; | ||
211 | b->interrupt_enable = !!new; | ||
212 | |||
213 | oldmask = affinity_set(b->cpu); | ||
214 | threshold_restart_bank(b, 0, 0); | ||
215 | affinity_restore(oldmask); | ||
216 | |||
217 | return end - buf; | ||
218 | } | ||
219 | |||
220 | static ssize_t store_threshold_limit(struct threshold_bank *b, | ||
221 | const char *buf, size_t count) | ||
222 | { | ||
223 | char *end; | ||
224 | cpumask_t oldmask; | ||
225 | u16 old; | ||
226 | unsigned long new = simple_strtoul(buf, &end, 0); | ||
227 | if (end == buf) | ||
228 | return -EINVAL; | ||
229 | if (new > THRESHOLD_MAX) | ||
230 | new = THRESHOLD_MAX; | ||
231 | if (new < 1) | ||
232 | new = 1; | ||
233 | old = b->threshold_limit; | ||
234 | b->threshold_limit = new; | ||
235 | |||
236 | oldmask = affinity_set(b->cpu); | ||
237 | threshold_restart_bank(b, 0, old); | ||
238 | affinity_restore(oldmask); | ||
239 | |||
240 | return end - buf; | ||
241 | } | ||
242 | |||
243 | static ssize_t show_error_count(struct threshold_bank *b, char *buf) | ||
244 | { | ||
245 | u32 high, low; | ||
246 | cpumask_t oldmask; | ||
247 | oldmask = affinity_set(b->cpu); | ||
248 | rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, low, high); /* ignore low 32 */ | ||
249 | affinity_restore(oldmask); | ||
250 | return sprintf(buf, "%x\n", | ||
251 | (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit)); | ||
252 | } | ||
253 | |||
254 | static ssize_t store_error_count(struct threshold_bank *b, | ||
255 | const char *buf, size_t count) | ||
256 | { | ||
257 | cpumask_t oldmask; | ||
258 | oldmask = affinity_set(b->cpu); | ||
259 | threshold_restart_bank(b, 1, 0); | ||
260 | affinity_restore(oldmask); | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | #define THRESHOLD_ATTR(_name,_mode,_show,_store) { \ | ||
265 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
266 | .show = _show, \ | ||
267 | .store = _store, \ | ||
268 | }; | ||
269 | |||
270 | #define ATTR_FIELDS(name) \ | ||
271 | static struct threshold_attr name = \ | ||
272 | THRESHOLD_ATTR(name, 0644, show_## name, store_## name) | ||
273 | |||
274 | ATTR_FIELDS(interrupt_enable); | ||
275 | ATTR_FIELDS(threshold_limit); | ||
276 | ATTR_FIELDS(error_count); | ||
277 | |||
278 | static struct attribute *default_attrs[] = { | ||
279 | &interrupt_enable.attr, | ||
280 | &threshold_limit.attr, | ||
281 | &error_count.attr, | ||
282 | NULL | ||
283 | }; | ||
284 | |||
285 | #define to_bank(k) container_of(k,struct threshold_bank,kobj) | ||
286 | #define to_attr(a) container_of(a,struct threshold_attr,attr) | ||
287 | |||
288 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | ||
289 | { | ||
290 | struct threshold_bank *b = to_bank(kobj); | ||
291 | struct threshold_attr *a = to_attr(attr); | ||
292 | ssize_t ret; | ||
293 | ret = a->show ? a->show(b, buf) : -EIO; | ||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | static ssize_t store(struct kobject *kobj, struct attribute *attr, | ||
298 | const char *buf, size_t count) | ||
299 | { | ||
300 | struct threshold_bank *b = to_bank(kobj); | ||
301 | struct threshold_attr *a = to_attr(attr); | ||
302 | ssize_t ret; | ||
303 | ret = a->store ? a->store(b, buf, count) : -EIO; | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static struct sysfs_ops threshold_ops = { | ||
308 | .show = show, | ||
309 | .store = store, | ||
310 | }; | ||
311 | |||
312 | static struct kobj_type threshold_ktype = { | ||
313 | .sysfs_ops = &threshold_ops, | ||
314 | .default_attrs = default_attrs, | ||
315 | }; | ||
316 | |||
317 | /* symlinks sibling shared banks to first core. first core owns dir/files. */ | ||
318 | static __cpuinit int threshold_create_bank(unsigned int cpu, int bank) | ||
319 | { | ||
320 | int err = 0; | ||
321 | struct threshold_bank *b = 0; | ||
322 | |||
323 | #ifdef CONFIG_SMP | ||
324 | if (cpu_core_id[cpu] && shared_bank[bank]) { /* symlink */ | ||
325 | char name[16]; | ||
326 | unsigned lcpu = first_cpu(cpu_core_map[cpu]); | ||
327 | if (cpu_core_id[lcpu]) | ||
328 | goto out; /* first core not up yet */ | ||
329 | |||
330 | b = per_cpu(threshold_banks, lcpu)[bank]; | ||
331 | if (!b) | ||
332 | goto out; | ||
333 | sprintf(name, "bank%i", bank); | ||
334 | err = sysfs_create_link(&per_cpu(device_threshold, cpu).kobj, | ||
335 | &b->kobj, name); | ||
336 | if (err) | ||
337 | goto out; | ||
338 | per_cpu(threshold_banks, cpu)[bank] = b; | ||
339 | goto out; | ||
340 | } | ||
341 | #endif | ||
342 | |||
343 | b = kmalloc(sizeof(struct threshold_bank), GFP_KERNEL); | ||
344 | if (!b) { | ||
345 | err = -ENOMEM; | ||
346 | goto out; | ||
347 | } | ||
348 | memset(b, 0, sizeof(struct threshold_bank)); | ||
349 | |||
350 | b->cpu = cpu; | ||
351 | b->bank = bank; | ||
352 | b->interrupt_enable = 0; | ||
353 | b->threshold_limit = THRESHOLD_MAX; | ||
354 | kobject_set_name(&b->kobj, "bank%i", bank); | ||
355 | b->kobj.parent = &per_cpu(device_threshold, cpu).kobj; | ||
356 | b->kobj.ktype = &threshold_ktype; | ||
357 | |||
358 | err = kobject_register(&b->kobj); | ||
359 | if (err) { | ||
360 | kfree(b); | ||
361 | goto out; | ||
362 | } | ||
363 | per_cpu(threshold_banks, cpu)[bank] = b; | ||
364 | out: | ||
365 | return err; | ||
366 | } | ||
367 | |||
368 | /* create dir/files for all valid threshold banks */ | ||
369 | static __cpuinit int threshold_create_device(unsigned int cpu) | ||
370 | { | ||
371 | int bank; | ||
372 | int err = 0; | ||
373 | |||
374 | per_cpu(device_threshold, cpu).id = cpu; | ||
375 | per_cpu(device_threshold, cpu).cls = &threshold_sysclass; | ||
376 | err = sysdev_register(&per_cpu(device_threshold, cpu)); | ||
377 | if (err) | ||
378 | goto out; | ||
379 | |||
380 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
381 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
382 | continue; | ||
383 | err = threshold_create_bank(cpu, bank); | ||
384 | if (err) | ||
385 | goto out; | ||
386 | } | ||
387 | out: | ||
388 | return err; | ||
389 | } | ||
390 | |||
391 | #ifdef CONFIG_HOTPLUG_CPU | ||
392 | /* | ||
393 | * let's be hotplug friendly. | ||
394 | * in case of multiple core processors, the first core always takes ownership | ||
395 | * of shared sysfs dir/files, and rest of the cores will be symlinked to it. | ||
396 | */ | ||
397 | |||
398 | /* cpu hotplug call removes all symlinks before first core dies */ | ||
399 | static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank) | ||
400 | { | ||
401 | struct threshold_bank *b; | ||
402 | char name[16]; | ||
403 | |||
404 | b = per_cpu(threshold_banks, cpu)[bank]; | ||
405 | if (!b) | ||
406 | return; | ||
407 | if (shared_bank[bank] && atomic_read(&b->kobj.kref.refcount) > 2) { | ||
408 | sprintf(name, "bank%i", bank); | ||
409 | sysfs_remove_link(&per_cpu(device_threshold, cpu).kobj, name); | ||
410 | per_cpu(threshold_banks, cpu)[bank] = 0; | ||
411 | } else { | ||
412 | kobject_unregister(&b->kobj); | ||
413 | kfree(per_cpu(threshold_banks, cpu)[bank]); | ||
414 | } | ||
415 | } | ||
416 | |||
417 | static __cpuinit void threshold_remove_device(unsigned int cpu) | ||
418 | { | ||
419 | int bank; | ||
420 | |||
421 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
422 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
423 | continue; | ||
424 | threshold_remove_bank(cpu, bank); | ||
425 | } | ||
426 | sysdev_unregister(&per_cpu(device_threshold, cpu)); | ||
427 | } | ||
428 | |||
429 | /* link all existing siblings when first core comes up */ | ||
430 | static __cpuinit int threshold_create_symlinks(unsigned int cpu) | ||
431 | { | ||
432 | int bank, err = 0; | ||
433 | unsigned int lcpu = 0; | ||
434 | |||
435 | if (cpu_core_id[cpu]) | ||
436 | return 0; | ||
437 | for_each_cpu_mask(lcpu, cpu_core_map[cpu]) { | ||
438 | if (lcpu == cpu) | ||
439 | continue; | ||
440 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
441 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
442 | continue; | ||
443 | if (!shared_bank[bank]) | ||
444 | continue; | ||
445 | err = threshold_create_bank(lcpu, bank); | ||
446 | } | ||
447 | } | ||
448 | return err; | ||
449 | } | ||
450 | |||
451 | /* remove all symlinks before first core dies. */ | ||
452 | static __cpuinit void threshold_remove_symlinks(unsigned int cpu) | ||
453 | { | ||
454 | int bank; | ||
455 | unsigned int lcpu = 0; | ||
456 | if (cpu_core_id[cpu]) | ||
457 | return; | ||
458 | for_each_cpu_mask(lcpu, cpu_core_map[cpu]) { | ||
459 | if (lcpu == cpu) | ||
460 | continue; | ||
461 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
462 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
463 | continue; | ||
464 | if (!shared_bank[bank]) | ||
465 | continue; | ||
466 | threshold_remove_bank(lcpu, bank); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | #else /* !CONFIG_HOTPLUG_CPU */ | ||
471 | static __cpuinit void threshold_create_symlinks(unsigned int cpu) | ||
472 | { | ||
473 | } | ||
474 | static __cpuinit void threshold_remove_symlinks(unsigned int cpu) | ||
475 | { | ||
476 | } | ||
477 | static void threshold_remove_device(unsigned int cpu) | ||
478 | { | ||
479 | } | ||
480 | #endif | ||
481 | |||
482 | /* get notified when a cpu comes on/off */ | ||
483 | static __cpuinit int threshold_cpu_callback(struct notifier_block *nfb, | ||
484 | unsigned long action, void *hcpu) | ||
485 | { | ||
486 | /* cpu was unsigned int to begin with */ | ||
487 | unsigned int cpu = (unsigned long)hcpu; | ||
488 | |||
489 | if (cpu >= NR_CPUS) | ||
490 | goto out; | ||
491 | |||
492 | switch (action) { | ||
493 | case CPU_ONLINE: | ||
494 | threshold_create_device(cpu); | ||
495 | threshold_create_symlinks(cpu); | ||
496 | break; | ||
497 | case CPU_DOWN_PREPARE: | ||
498 | threshold_remove_symlinks(cpu); | ||
499 | break; | ||
500 | case CPU_DOWN_FAILED: | ||
501 | threshold_create_symlinks(cpu); | ||
502 | break; | ||
503 | case CPU_DEAD: | ||
504 | threshold_remove_device(cpu); | ||
505 | break; | ||
506 | default: | ||
507 | break; | ||
508 | } | ||
509 | out: | ||
510 | return NOTIFY_OK; | ||
511 | } | ||
512 | |||
513 | static struct notifier_block threshold_cpu_notifier = { | ||
514 | .notifier_call = threshold_cpu_callback, | ||
515 | }; | ||
516 | |||
517 | static __init int threshold_init_device(void) | ||
518 | { | ||
519 | int err; | ||
520 | int lcpu = 0; | ||
521 | |||
522 | err = sysdev_class_register(&threshold_sysclass); | ||
523 | if (err) | ||
524 | goto out; | ||
525 | |||
526 | /* to hit CPUs online before the notifier is up */ | ||
527 | for_each_online_cpu(lcpu) { | ||
528 | err = threshold_create_device(lcpu); | ||
529 | if (err) | ||
530 | goto out; | ||
531 | } | ||
532 | register_cpu_notifier(&threshold_cpu_notifier); | ||
533 | |||
534 | out: | ||
535 | return err; | ||
536 | } | ||
537 | |||
538 | device_initcall(threshold_init_device); | ||
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index f16d38d09daf..1105250bf02c 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c | |||
@@ -42,7 +42,7 @@ int acpi_found_madt; | |||
42 | * Various Linux-internal data structures created from the | 42 | * Various Linux-internal data structures created from the |
43 | * MP-table. | 43 | * MP-table. |
44 | */ | 44 | */ |
45 | int apic_version [MAX_APICS]; | 45 | unsigned char apic_version [MAX_APICS]; |
46 | unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; | 46 | unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; |
47 | int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; | 47 | int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; |
48 | 48 | ||
@@ -65,7 +65,9 @@ unsigned long mp_lapic_addr = 0; | |||
65 | /* Processor that is doing the boot up */ | 65 | /* Processor that is doing the boot up */ |
66 | unsigned int boot_cpu_id = -1U; | 66 | unsigned int boot_cpu_id = -1U; |
67 | /* Internal processor count */ | 67 | /* Internal processor count */ |
68 | static unsigned int num_processors = 0; | 68 | unsigned int num_processors __initdata = 0; |
69 | |||
70 | unsigned disabled_cpus __initdata; | ||
69 | 71 | ||
70 | /* Bitmask of physically existing CPUs */ | 72 | /* Bitmask of physically existing CPUs */ |
71 | physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE; | 73 | physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE; |
@@ -106,11 +108,14 @@ static int __init mpf_checksum(unsigned char *mp, int len) | |||
106 | 108 | ||
107 | static void __init MP_processor_info (struct mpc_config_processor *m) | 109 | static void __init MP_processor_info (struct mpc_config_processor *m) |
108 | { | 110 | { |
109 | int ver, cpu; | 111 | int cpu; |
112 | unsigned char ver; | ||
110 | static int found_bsp=0; | 113 | static int found_bsp=0; |
111 | 114 | ||
112 | if (!(m->mpc_cpuflag & CPU_ENABLED)) | 115 | if (!(m->mpc_cpuflag & CPU_ENABLED)) { |
116 | disabled_cpus++; | ||
113 | return; | 117 | return; |
118 | } | ||
114 | 119 | ||
115 | printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n", | 120 | printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n", |
116 | m->mpc_apicid, | 121 | m->mpc_apicid, |
@@ -129,12 +134,14 @@ static void __init MP_processor_info (struct mpc_config_processor *m) | |||
129 | } | 134 | } |
130 | 135 | ||
131 | cpu = num_processors++; | 136 | cpu = num_processors++; |
132 | 137 | ||
133 | if (m->mpc_apicid > MAX_APICS) { | 138 | #if MAX_APICS < 255 |
139 | if ((int)m->mpc_apicid > MAX_APICS) { | ||
134 | printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", | 140 | printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", |
135 | m->mpc_apicid, MAX_APICS); | 141 | m->mpc_apicid, MAX_APICS); |
136 | return; | 142 | return; |
137 | } | 143 | } |
144 | #endif | ||
138 | ver = m->mpc_apicver; | 145 | ver = m->mpc_apicver; |
139 | 146 | ||
140 | physid_set(m->mpc_apicid, phys_cpu_present_map); | 147 | physid_set(m->mpc_apicid, phys_cpu_present_map); |
@@ -218,7 +225,7 @@ static void __init MP_intsrc_info (struct mpc_config_intsrc *m) | |||
218 | m->mpc_irqtype, m->mpc_irqflag & 3, | 225 | m->mpc_irqtype, m->mpc_irqflag & 3, |
219 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, | 226 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, |
220 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); | 227 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); |
221 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | 228 | if (++mp_irq_entries >= MAX_IRQ_SOURCES) |
222 | panic("Max # of irq sources exceeded!!\n"); | 229 | panic("Max # of irq sources exceeded!!\n"); |
223 | } | 230 | } |
224 | 231 | ||
@@ -549,7 +556,7 @@ void __init get_smp_config (void) | |||
549 | * Read the physical hardware table. Anything here will | 556 | * Read the physical hardware table. Anything here will |
550 | * override the defaults. | 557 | * override the defaults. |
551 | */ | 558 | */ |
552 | if (!smp_read_mpc((void *)(unsigned long)mpf->mpf_physptr)) { | 559 | if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) { |
553 | smp_found_config = 0; | 560 | smp_found_config = 0; |
554 | printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); | 561 | printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); |
555 | printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); | 562 | printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); |
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 88be97c96987..2e28e855ec3c 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c | |||
@@ -220,6 +220,12 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | |||
220 | uses the normal dma_mask for alloc_coherent. */ | 220 | uses the normal dma_mask for alloc_coherent. */ |
221 | dma_mask &= *dev->dma_mask; | 221 | dma_mask &= *dev->dma_mask; |
222 | 222 | ||
223 | /* Why <=? Even when the mask is smaller than 4GB it is often larger | ||
224 | than 16MB and in this case we have a chance of finding fitting memory | ||
225 | in the next higher zone first. If not retry with true GFP_DMA. -AK */ | ||
226 | if (dma_mask <= 0xffffffff) | ||
227 | gfp |= GFP_DMA32; | ||
228 | |||
223 | again: | 229 | again: |
224 | memory = dma_alloc_pages(dev, gfp, get_order(size)); | 230 | memory = dma_alloc_pages(dev, gfp, get_order(size)); |
225 | if (memory == NULL) | 231 | if (memory == NULL) |
@@ -245,7 +251,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | |||
245 | } | 251 | } |
246 | 252 | ||
247 | if (!(gfp & GFP_DMA)) { | 253 | if (!(gfp & GFP_DMA)) { |
248 | gfp |= GFP_DMA; | 254 | gfp = (gfp & ~GFP_DMA32) | GFP_DMA; |
249 | goto again; | 255 | goto again; |
250 | } | 256 | } |
251 | return NULL; | 257 | return NULL; |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 59be85d9a4bc..5afd63e8cef7 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -144,7 +144,8 @@ void cpu_idle_wait(void) | |||
144 | do { | 144 | do { |
145 | ssleep(1); | 145 | ssleep(1); |
146 | for_each_online_cpu(cpu) { | 146 | for_each_online_cpu(cpu) { |
147 | if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu)) | 147 | if (cpu_isset(cpu, map) && |
148 | !per_cpu(cpu_idle_state, cpu)) | ||
148 | cpu_clear(cpu, map); | 149 | cpu_clear(cpu, map); |
149 | } | 150 | } |
150 | cpus_and(map, map, cpu_online_map); | 151 | cpus_and(map, map, cpu_online_map); |
@@ -275,7 +276,8 @@ void __show_regs(struct pt_regs * regs) | |||
275 | system_utsname.version); | 276 | system_utsname.version); |
276 | printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip); | 277 | printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip); |
277 | printk_address(regs->rip); | 278 | printk_address(regs->rip); |
278 | printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags); | 279 | printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, |
280 | regs->eflags); | ||
279 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", | 281 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", |
280 | regs->rax, regs->rbx, regs->rcx); | 282 | regs->rax, regs->rbx, regs->rcx); |
281 | printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", | 283 | printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", |
@@ -427,15 +429,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
427 | struct pt_regs * childregs; | 429 | struct pt_regs * childregs; |
428 | struct task_struct *me = current; | 430 | struct task_struct *me = current; |
429 | 431 | ||
430 | childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; | 432 | childregs = ((struct pt_regs *) |
431 | 433 | (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; | |
432 | *childregs = *regs; | 434 | *childregs = *regs; |
433 | 435 | ||
434 | childregs->rax = 0; | 436 | childregs->rax = 0; |
435 | childregs->rsp = rsp; | 437 | childregs->rsp = rsp; |
436 | if (rsp == ~0UL) { | 438 | if (rsp == ~0UL) |
437 | childregs->rsp = (unsigned long)childregs; | 439 | childregs->rsp = (unsigned long)childregs; |
438 | } | ||
439 | 440 | ||
440 | p->thread.rsp = (unsigned long) childregs; | 441 | p->thread.rsp = (unsigned long) childregs; |
441 | p->thread.rsp0 = (unsigned long) (childregs+1); | 442 | p->thread.rsp0 = (unsigned long) (childregs+1); |
@@ -457,7 +458,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
457 | p->thread.io_bitmap_max = 0; | 458 | p->thread.io_bitmap_max = 0; |
458 | return -ENOMEM; | 459 | return -ENOMEM; |
459 | } | 460 | } |
460 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, IO_BITMAP_BYTES); | 461 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, |
462 | IO_BITMAP_BYTES); | ||
461 | } | 463 | } |
462 | 464 | ||
463 | /* | 465 | /* |
@@ -494,7 +496,8 @@ out: | |||
494 | * - fold all the options into a flag word and test it with a single test. | 496 | * - fold all the options into a flag word and test it with a single test. |
495 | * - could test fs/gs bitsliced | 497 | * - could test fs/gs bitsliced |
496 | */ | 498 | */ |
497 | struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *next_p) | 499 | struct task_struct * |
500 | __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | ||
498 | { | 501 | { |
499 | struct thread_struct *prev = &prev_p->thread, | 502 | struct thread_struct *prev = &prev_p->thread, |
500 | *next = &next_p->thread; | 503 | *next = &next_p->thread; |
@@ -565,7 +568,8 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct * | |||
565 | prev->userrsp = read_pda(oldrsp); | 568 | prev->userrsp = read_pda(oldrsp); |
566 | write_pda(oldrsp, next->userrsp); | 569 | write_pda(oldrsp, next->userrsp); |
567 | write_pda(pcurrent, next_p); | 570 | write_pda(pcurrent, next_p); |
568 | write_pda(kernelstack, (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); | 571 | write_pda(kernelstack, |
572 | (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); | ||
569 | 573 | ||
570 | /* | 574 | /* |
571 | * Now maybe reload the debug registers | 575 | * Now maybe reload the debug registers |
@@ -646,7 +650,9 @@ asmlinkage long sys_fork(struct pt_regs *regs) | |||
646 | return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL); | 650 | return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL); |
647 | } | 651 | } |
648 | 652 | ||
649 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | 653 | asmlinkage long |
654 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
655 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
650 | { | 656 | { |
651 | if (!newsp) | 657 | if (!newsp) |
652 | newsp = regs->rsp; | 658 | newsp = regs->rsp; |
@@ -682,7 +688,8 @@ unsigned long get_wchan(struct task_struct *p) | |||
682 | return 0; | 688 | return 0; |
683 | fp = *(u64 *)(p->thread.rsp); | 689 | fp = *(u64 *)(p->thread.rsp); |
684 | do { | 690 | do { |
685 | if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) | 691 | if (fp < (unsigned long)stack || |
692 | fp > (unsigned long)stack+THREAD_SIZE) | ||
686 | return 0; | 693 | return 0; |
687 | rip = *(u64 *)(fp+8); | 694 | rip = *(u64 *)(fp+8); |
688 | if (!in_sched_functions(rip)) | 695 | if (!in_sched_functions(rip)) |
@@ -717,8 +724,8 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
717 | task->thread.gsindex = 0; | 724 | task->thread.gsindex = 0; |
718 | task->thread.gs = addr; | 725 | task->thread.gs = addr; |
719 | if (doit) { | 726 | if (doit) { |
720 | load_gs_index(0); | 727 | load_gs_index(0); |
721 | ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); | 728 | ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); |
722 | } | 729 | } |
723 | } | 730 | } |
724 | put_cpu(); | 731 | put_cpu(); |
@@ -735,7 +742,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
735 | set_32bit_tls(task, FS_TLS, addr); | 742 | set_32bit_tls(task, FS_TLS, addr); |
736 | if (doit) { | 743 | if (doit) { |
737 | load_TLS(&task->thread, cpu); | 744 | load_TLS(&task->thread, cpu); |
738 | asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL)); | 745 | asm volatile("movl %0,%%fs" :: "r"(FS_TLS_SEL)); |
739 | } | 746 | } |
740 | task->thread.fsindex = FS_TLS_SEL; | 747 | task->thread.fsindex = FS_TLS_SEL; |
741 | task->thread.fs = 0; | 748 | task->thread.fs = 0; |
@@ -745,8 +752,8 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
745 | if (doit) { | 752 | if (doit) { |
746 | /* set the selector to 0 to not confuse | 753 | /* set the selector to 0 to not confuse |
747 | __switch_to */ | 754 | __switch_to */ |
748 | asm volatile("movl %0,%%fs" :: "r" (0)); | 755 | asm volatile("movl %0,%%fs" :: "r" (0)); |
749 | ret = checking_wrmsrl(MSR_FS_BASE, addr); | 756 | ret = checking_wrmsrl(MSR_FS_BASE, addr); |
750 | } | 757 | } |
751 | } | 758 | } |
752 | put_cpu(); | 759 | put_cpu(); |
@@ -755,9 +762,9 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
755 | unsigned long base; | 762 | unsigned long base; |
756 | if (task->thread.fsindex == FS_TLS_SEL) | 763 | if (task->thread.fsindex == FS_TLS_SEL) |
757 | base = read_32bit_tls(task, FS_TLS); | 764 | base = read_32bit_tls(task, FS_TLS); |
758 | else if (doit) { | 765 | else if (doit) |
759 | rdmsrl(MSR_FS_BASE, base); | 766 | rdmsrl(MSR_FS_BASE, base); |
760 | } else | 767 | else |
761 | base = task->thread.fs; | 768 | base = task->thread.fs; |
762 | ret = put_user(base, (unsigned long __user *)addr); | 769 | ret = put_user(base, (unsigned long __user *)addr); |
763 | break; | 770 | break; |
@@ -766,9 +773,9 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
766 | unsigned long base; | 773 | unsigned long base; |
767 | if (task->thread.gsindex == GS_TLS_SEL) | 774 | if (task->thread.gsindex == GS_TLS_SEL) |
768 | base = read_32bit_tls(task, GS_TLS); | 775 | base = read_32bit_tls(task, GS_TLS); |
769 | else if (doit) { | 776 | else if (doit) |
770 | rdmsrl(MSR_KERNEL_GS_BASE, base); | 777 | rdmsrl(MSR_KERNEL_GS_BASE, base); |
771 | } else | 778 | else |
772 | base = task->thread.gs; | 779 | base = task->thread.gs; |
773 | ret = put_user(base, (unsigned long __user *)addr); | 780 | ret = put_user(base, (unsigned long __user *)addr); |
774 | break; | 781 | break; |
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index 47f95687905f..75235ed2b31b 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c | |||
@@ -77,6 +77,7 @@ static inline void kb_wait(void) | |||
77 | 77 | ||
78 | void machine_shutdown(void) | 78 | void machine_shutdown(void) |
79 | { | 79 | { |
80 | unsigned long flags; | ||
80 | /* Stop the cpus and apics */ | 81 | /* Stop the cpus and apics */ |
81 | #ifdef CONFIG_SMP | 82 | #ifdef CONFIG_SMP |
82 | int reboot_cpu_id; | 83 | int reboot_cpu_id; |
@@ -98,7 +99,7 @@ void machine_shutdown(void) | |||
98 | smp_send_stop(); | 99 | smp_send_stop(); |
99 | #endif | 100 | #endif |
100 | 101 | ||
101 | local_irq_disable(); | 102 | local_irq_save(flags); |
102 | 103 | ||
103 | #ifndef CONFIG_SMP | 104 | #ifndef CONFIG_SMP |
104 | disable_local_APIC(); | 105 | disable_local_APIC(); |
@@ -106,7 +107,7 @@ void machine_shutdown(void) | |||
106 | 107 | ||
107 | disable_IO_APIC(); | 108 | disable_IO_APIC(); |
108 | 109 | ||
109 | local_irq_enable(); | 110 | local_irq_restore(flags); |
110 | } | 111 | } |
111 | 112 | ||
112 | void machine_emergency_restart(void) | 113 | void machine_emergency_restart(void) |
@@ -120,7 +121,7 @@ void machine_emergency_restart(void) | |||
120 | /* Could also try the reset bit in the Hammer NB */ | 121 | /* Could also try the reset bit in the Hammer NB */ |
121 | switch (reboot_type) { | 122 | switch (reboot_type) { |
122 | case BOOT_KBD: | 123 | case BOOT_KBD: |
123 | for (i=0; i<100; i++) { | 124 | for (i=0; i<10; i++) { |
124 | kb_wait(); | 125 | kb_wait(); |
125 | udelay(50); | 126 | udelay(50); |
126 | outb(0xfe,0x64); /* pulse reset low */ | 127 | outb(0xfe,0x64); /* pulse reset low */ |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index da0bc3e7bdf5..750e01dcbdf4 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <asm/setup.h> | 60 | #include <asm/setup.h> |
61 | #include <asm/mach_apic.h> | 61 | #include <asm/mach_apic.h> |
62 | #include <asm/numa.h> | 62 | #include <asm/numa.h> |
63 | #include <asm/sections.h> | ||
63 | 64 | ||
64 | /* | 65 | /* |
65 | * Machine setup.. | 66 | * Machine setup.. |
@@ -103,7 +104,6 @@ struct edid_info edid_info; | |||
103 | struct e820map e820; | 104 | struct e820map e820; |
104 | 105 | ||
105 | extern int root_mountflags; | 106 | extern int root_mountflags; |
106 | extern char _text, _etext, _edata, _end; | ||
107 | 107 | ||
108 | char command_line[COMMAND_LINE_SIZE]; | 108 | char command_line[COMMAND_LINE_SIZE]; |
109 | 109 | ||
@@ -412,7 +412,6 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
412 | { | 412 | { |
413 | unsigned long bootmap_size, bootmap; | 413 | unsigned long bootmap_size, bootmap; |
414 | 414 | ||
415 | memory_present(0, start_pfn, end_pfn); | ||
416 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; | 415 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; |
417 | bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); | 416 | bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); |
418 | if (bootmap == -1L) | 417 | if (bootmap == -1L) |
@@ -571,6 +570,8 @@ void __init setup_arch(char **cmdline_p) | |||
571 | 570 | ||
572 | init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); | 571 | init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); |
573 | 572 | ||
573 | zap_low_mappings(0); | ||
574 | |||
574 | #ifdef CONFIG_ACPI | 575 | #ifdef CONFIG_ACPI |
575 | /* | 576 | /* |
576 | * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). | 577 | * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). |
@@ -657,8 +658,6 @@ void __init setup_arch(char **cmdline_p) | |||
657 | } | 658 | } |
658 | #endif | 659 | #endif |
659 | 660 | ||
660 | sparse_init(); | ||
661 | |||
662 | paging_init(); | 661 | paging_init(); |
663 | 662 | ||
664 | check_ioapic(); | 663 | check_ioapic(); |
@@ -793,7 +792,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
793 | #endif | 792 | #endif |
794 | 793 | ||
795 | bits = 0; | 794 | bits = 0; |
796 | while ((1 << bits) < c->x86_num_cores) | 795 | while ((1 << bits) < c->x86_max_cores) |
797 | bits++; | 796 | bits++; |
798 | 797 | ||
799 | /* Low order bits define the core id (index of core in socket) */ | 798 | /* Low order bits define the core id (index of core in socket) */ |
@@ -823,10 +822,10 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
823 | if (!node_online(node)) | 822 | if (!node_online(node)) |
824 | node = nearby_node(apicid); | 823 | node = nearby_node(apicid); |
825 | } | 824 | } |
826 | cpu_to_node[cpu] = node; | 825 | numa_set_node(cpu, node); |
827 | 826 | ||
828 | printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", | 827 | printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", |
829 | cpu, c->x86_num_cores, node, cpu_core_id[cpu]); | 828 | cpu, c->x86_max_cores, node, cpu_core_id[cpu]); |
830 | #endif | 829 | #endif |
831 | #endif | 830 | #endif |
832 | } | 831 | } |
@@ -875,9 +874,9 @@ static int __init init_amd(struct cpuinfo_x86 *c) | |||
875 | display_cacheinfo(c); | 874 | display_cacheinfo(c); |
876 | 875 | ||
877 | if (c->extended_cpuid_level >= 0x80000008) { | 876 | if (c->extended_cpuid_level >= 0x80000008) { |
878 | c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; | 877 | c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; |
879 | if (c->x86_num_cores & (c->x86_num_cores - 1)) | 878 | if (c->x86_max_cores & (c->x86_max_cores - 1)) |
880 | c->x86_num_cores = 1; | 879 | c->x86_max_cores = 1; |
881 | 880 | ||
882 | amd_detect_cmp(c); | 881 | amd_detect_cmp(c); |
883 | } | 882 | } |
@@ -889,54 +888,44 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
889 | { | 888 | { |
890 | #ifdef CONFIG_SMP | 889 | #ifdef CONFIG_SMP |
891 | u32 eax, ebx, ecx, edx; | 890 | u32 eax, ebx, ecx, edx; |
892 | int index_msb, tmp; | 891 | int index_msb, core_bits; |
893 | int cpu = smp_processor_id(); | 892 | int cpu = smp_processor_id(); |
894 | 893 | ||
894 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
895 | |||
896 | c->apicid = phys_pkg_id(0); | ||
897 | |||
895 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 898 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
896 | return; | 899 | return; |
897 | 900 | ||
898 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
899 | smp_num_siblings = (ebx & 0xff0000) >> 16; | 901 | smp_num_siblings = (ebx & 0xff0000) >> 16; |
900 | 902 | ||
901 | if (smp_num_siblings == 1) { | 903 | if (smp_num_siblings == 1) { |
902 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); | 904 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); |
903 | } else if (smp_num_siblings > 1) { | 905 | } else if (smp_num_siblings > 1 ) { |
904 | index_msb = 31; | 906 | |
905 | /* | ||
906 | * At this point we only support two siblings per | ||
907 | * processor package. | ||
908 | */ | ||
909 | if (smp_num_siblings > NR_CPUS) { | 907 | if (smp_num_siblings > NR_CPUS) { |
910 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); | 908 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); |
911 | smp_num_siblings = 1; | 909 | smp_num_siblings = 1; |
912 | return; | 910 | return; |
913 | } | 911 | } |
914 | tmp = smp_num_siblings; | 912 | |
915 | while ((tmp & 0x80000000 ) == 0) { | 913 | index_msb = get_count_order(smp_num_siblings); |
916 | tmp <<=1 ; | ||
917 | index_msb--; | ||
918 | } | ||
919 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
920 | index_msb++; | ||
921 | phys_proc_id[cpu] = phys_pkg_id(index_msb); | 914 | phys_proc_id[cpu] = phys_pkg_id(index_msb); |
922 | 915 | ||
923 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | 916 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", |
924 | phys_proc_id[cpu]); | 917 | phys_proc_id[cpu]); |
925 | 918 | ||
926 | smp_num_siblings = smp_num_siblings / c->x86_num_cores; | 919 | smp_num_siblings = smp_num_siblings / c->x86_max_cores; |
927 | 920 | ||
928 | tmp = smp_num_siblings; | 921 | index_msb = get_count_order(smp_num_siblings) ; |
929 | index_msb = 31; | ||
930 | while ((tmp & 0x80000000) == 0) { | ||
931 | tmp <<=1 ; | ||
932 | index_msb--; | ||
933 | } | ||
934 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
935 | index_msb++; | ||
936 | 922 | ||
937 | cpu_core_id[cpu] = phys_pkg_id(index_msb); | 923 | core_bits = get_count_order(c->x86_max_cores); |
938 | 924 | ||
939 | if (c->x86_num_cores > 1) | 925 | cpu_core_id[cpu] = phys_pkg_id(index_msb) & |
926 | ((1 << core_bits) - 1); | ||
927 | |||
928 | if (c->x86_max_cores > 1) | ||
940 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | 929 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", |
941 | cpu_core_id[cpu]); | 930 | cpu_core_id[cpu]); |
942 | } | 931 | } |
@@ -975,7 +964,7 @@ static void srat_detect_node(void) | |||
975 | node = apicid_to_node[hard_smp_processor_id()]; | 964 | node = apicid_to_node[hard_smp_processor_id()]; |
976 | if (node == NUMA_NO_NODE) | 965 | if (node == NUMA_NO_NODE) |
977 | node = 0; | 966 | node = 0; |
978 | cpu_to_node[cpu] = node; | 967 | numa_set_node(cpu, node); |
979 | 968 | ||
980 | if (acpi_numa > 0) | 969 | if (acpi_numa > 0) |
981 | printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node); | 970 | printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node); |
@@ -993,13 +982,18 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
993 | unsigned eax = cpuid_eax(0x80000008); | 982 | unsigned eax = cpuid_eax(0x80000008); |
994 | c->x86_virt_bits = (eax >> 8) & 0xff; | 983 | c->x86_virt_bits = (eax >> 8) & 0xff; |
995 | c->x86_phys_bits = eax & 0xff; | 984 | c->x86_phys_bits = eax & 0xff; |
985 | /* CPUID workaround for Intel 0F34 CPU */ | ||
986 | if (c->x86_vendor == X86_VENDOR_INTEL && | ||
987 | c->x86 == 0xF && c->x86_model == 0x3 && | ||
988 | c->x86_mask == 0x4) | ||
989 | c->x86_phys_bits = 36; | ||
996 | } | 990 | } |
997 | 991 | ||
998 | if (c->x86 == 15) | 992 | if (c->x86 == 15) |
999 | c->x86_cache_alignment = c->x86_clflush_size * 2; | 993 | c->x86_cache_alignment = c->x86_clflush_size * 2; |
1000 | if (c->x86 >= 15) | 994 | if (c->x86 >= 15) |
1001 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); | 995 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); |
1002 | c->x86_num_cores = intel_num_cpu_cores(c); | 996 | c->x86_max_cores = intel_num_cpu_cores(c); |
1003 | 997 | ||
1004 | srat_detect_node(); | 998 | srat_detect_node(); |
1005 | } | 999 | } |
@@ -1037,7 +1031,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
1037 | c->x86_model_id[0] = '\0'; /* Unset */ | 1031 | c->x86_model_id[0] = '\0'; /* Unset */ |
1038 | c->x86_clflush_size = 64; | 1032 | c->x86_clflush_size = 64; |
1039 | c->x86_cache_alignment = c->x86_clflush_size; | 1033 | c->x86_cache_alignment = c->x86_clflush_size; |
1040 | c->x86_num_cores = 1; | 1034 | c->x86_max_cores = 1; |
1041 | c->extended_cpuid_level = 0; | 1035 | c->extended_cpuid_level = 0; |
1042 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 1036 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
1043 | 1037 | ||
@@ -1060,10 +1054,10 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
1060 | c->x86 = (tfms >> 8) & 0xf; | 1054 | c->x86 = (tfms >> 8) & 0xf; |
1061 | c->x86_model = (tfms >> 4) & 0xf; | 1055 | c->x86_model = (tfms >> 4) & 0xf; |
1062 | c->x86_mask = tfms & 0xf; | 1056 | c->x86_mask = tfms & 0xf; |
1063 | if (c->x86 == 0xf) { | 1057 | if (c->x86 == 0xf) |
1064 | c->x86 += (tfms >> 20) & 0xff; | 1058 | c->x86 += (tfms >> 20) & 0xff; |
1059 | if (c->x86 >= 0x6) | ||
1065 | c->x86_model += ((tfms >> 16) & 0xF) << 4; | 1060 | c->x86_model += ((tfms >> 16) & 0xF) << 4; |
1066 | } | ||
1067 | if (c->x86_capability[0] & (1<<19)) | 1061 | if (c->x86_capability[0] & (1<<19)) |
1068 | c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; | 1062 | c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; |
1069 | } else { | 1063 | } else { |
@@ -1271,13 +1265,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1271 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); | 1265 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); |
1272 | 1266 | ||
1273 | #ifdef CONFIG_SMP | 1267 | #ifdef CONFIG_SMP |
1274 | if (smp_num_siblings * c->x86_num_cores > 1) { | 1268 | if (smp_num_siblings * c->x86_max_cores > 1) { |
1275 | int cpu = c - cpu_data; | 1269 | int cpu = c - cpu_data; |
1276 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]); | 1270 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]); |
1277 | seq_printf(m, "siblings\t: %d\n", | 1271 | seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu])); |
1278 | c->x86_num_cores * smp_num_siblings); | ||
1279 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]); | 1272 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]); |
1280 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | 1273 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); |
1281 | } | 1274 | } |
1282 | #endif | 1275 | #endif |
1283 | 1276 | ||
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 79190891fbc5..06dc354375c3 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c | |||
@@ -141,7 +141,6 @@ void pda_init(int cpu) | |||
141 | panic("cannot allocate irqstack for cpu %d", cpu); | 141 | panic("cannot allocate irqstack for cpu %d", cpu); |
142 | } | 142 | } |
143 | 143 | ||
144 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
145 | 144 | ||
146 | pda->irqstackptr += IRQSTACKSIZE-64; | 145 | pda->irqstackptr += IRQSTACKSIZE-64; |
147 | } | 146 | } |
@@ -197,6 +196,7 @@ void __cpuinit cpu_init (void) | |||
197 | /* CPU 0 is initialised in head64.c */ | 196 | /* CPU 0 is initialised in head64.c */ |
198 | if (cpu != 0) { | 197 | if (cpu != 0) { |
199 | pda_init(cpu); | 198 | pda_init(cpu); |
199 | zap_low_mappings(cpu); | ||
200 | } else | 200 | } else |
201 | estacks = boot_exception_stacks; | 201 | estacks = boot_exception_stacks; |
202 | 202 | ||
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index d642fbf3da29..5876df116c92 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c | |||
@@ -110,6 +110,15 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned | |||
110 | COPY(r14); | 110 | COPY(r14); |
111 | COPY(r15); | 111 | COPY(r15); |
112 | 112 | ||
113 | /* Kernel saves and restores only the CS segment register on signals, | ||
114 | * which is the bare minimum needed to allow mixed 32/64-bit code. | ||
115 | * App's signal handler can save/restore other segments if needed. */ | ||
116 | { | ||
117 | unsigned cs; | ||
118 | err |= __get_user(cs, &sc->cs); | ||
119 | regs->cs = cs | 3; /* Force into user mode */ | ||
120 | } | ||
121 | |||
113 | { | 122 | { |
114 | unsigned int tmpflags; | 123 | unsigned int tmpflags; |
115 | err |= __get_user(tmpflags, &sc->eflags); | 124 | err |= __get_user(tmpflags, &sc->eflags); |
@@ -187,6 +196,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo | |||
187 | { | 196 | { |
188 | int err = 0; | 197 | int err = 0; |
189 | 198 | ||
199 | err |= __put_user(regs->cs, &sc->cs); | ||
190 | err |= __put_user(0, &sc->gs); | 200 | err |= __put_user(0, &sc->gs); |
191 | err |= __put_user(0, &sc->fs); | 201 | err |= __put_user(0, &sc->fs); |
192 | 202 | ||
@@ -318,7 +328,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
318 | 328 | ||
319 | regs->rsp = (unsigned long)frame; | 329 | regs->rsp = (unsigned long)frame; |
320 | 330 | ||
331 | /* Set up the CS register to run signal handlers in 64-bit mode, | ||
332 | even if the handler happens to be interrupting 32-bit code. */ | ||
333 | regs->cs = __USER_CS; | ||
334 | |||
335 | /* This, by contrast, has nothing to do with segment registers - | ||
336 | see include/asm-x86_64/uaccess.h for details. */ | ||
321 | set_fs(USER_DS); | 337 | set_fs(USER_DS); |
338 | |||
322 | regs->eflags &= ~TF_MASK; | 339 | regs->eflags &= ~TF_MASK; |
323 | if (test_thread_flag(TIF_SINGLESTEP)) | 340 | if (test_thread_flag(TIF_SINGLESTEP)) |
324 | ptrace_notify(SIGTRAP); | 341 | ptrace_notify(SIGTRAP); |
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 9db9dda161b4..cfc3d9dccbd9 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <asm/proto.h> | 28 | #include <asm/proto.h> |
29 | #include <asm/apicdef.h> | 29 | #include <asm/apicdef.h> |
30 | 30 | ||
31 | #define __cpuinit __init | ||
32 | |||
33 | /* | 31 | /* |
34 | * Smarter SMP flushing macros. | 32 | * Smarter SMP flushing macros. |
35 | * c/o Linus Torvalds. | 33 | * c/o Linus Torvalds. |
@@ -452,13 +450,14 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | |||
452 | 450 | ||
453 | void smp_stop_cpu(void) | 451 | void smp_stop_cpu(void) |
454 | { | 452 | { |
453 | unsigned long flags; | ||
455 | /* | 454 | /* |
456 | * Remove this CPU: | 455 | * Remove this CPU: |
457 | */ | 456 | */ |
458 | cpu_clear(smp_processor_id(), cpu_online_map); | 457 | cpu_clear(smp_processor_id(), cpu_online_map); |
459 | local_irq_disable(); | 458 | local_irq_save(flags); |
460 | disable_local_APIC(); | 459 | disable_local_APIC(); |
461 | local_irq_enable(); | 460 | local_irq_restore(flags); |
462 | } | 461 | } |
463 | 462 | ||
464 | static void smp_really_stop_cpu(void *dummy) | 463 | static void smp_really_stop_cpu(void *dummy) |
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index c4e59bbdc187..683c33f7b967 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c | |||
@@ -64,6 +64,7 @@ | |||
64 | int smp_num_siblings = 1; | 64 | int smp_num_siblings = 1; |
65 | /* Package ID of each logical CPU */ | 65 | /* Package ID of each logical CPU */ |
66 | u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; | 66 | u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
67 | /* core ID of each logical CPU */ | ||
67 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; | 68 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
68 | 69 | ||
69 | /* Bitmask of currently online CPUs */ | 70 | /* Bitmask of currently online CPUs */ |
@@ -87,7 +88,10 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; | |||
87 | /* Set when the idlers are all forked */ | 88 | /* Set when the idlers are all forked */ |
88 | int smp_threads_ready; | 89 | int smp_threads_ready; |
89 | 90 | ||
91 | /* representing HT siblings of each logical CPU */ | ||
90 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 92 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
93 | |||
94 | /* representing HT and core siblings of each logical CPU */ | ||
91 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 95 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
92 | EXPORT_SYMBOL(cpu_core_map); | 96 | EXPORT_SYMBOL(cpu_core_map); |
93 | 97 | ||
@@ -434,30 +438,59 @@ void __cpuinit smp_callin(void) | |||
434 | cpu_set(cpuid, cpu_callin_map); | 438 | cpu_set(cpuid, cpu_callin_map); |
435 | } | 439 | } |
436 | 440 | ||
441 | /* representing cpus for which sibling maps can be computed */ | ||
442 | static cpumask_t cpu_sibling_setup_map; | ||
443 | |||
437 | static inline void set_cpu_sibling_map(int cpu) | 444 | static inline void set_cpu_sibling_map(int cpu) |
438 | { | 445 | { |
439 | int i; | 446 | int i; |
447 | struct cpuinfo_x86 *c = cpu_data; | ||
448 | |||
449 | cpu_set(cpu, cpu_sibling_setup_map); | ||
440 | 450 | ||
441 | if (smp_num_siblings > 1) { | 451 | if (smp_num_siblings > 1) { |
442 | for_each_cpu(i) { | 452 | for_each_cpu_mask(i, cpu_sibling_setup_map) { |
443 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | 453 | if (phys_proc_id[cpu] == phys_proc_id[i] && |
454 | cpu_core_id[cpu] == cpu_core_id[i]) { | ||
444 | cpu_set(i, cpu_sibling_map[cpu]); | 455 | cpu_set(i, cpu_sibling_map[cpu]); |
445 | cpu_set(cpu, cpu_sibling_map[i]); | 456 | cpu_set(cpu, cpu_sibling_map[i]); |
457 | cpu_set(i, cpu_core_map[cpu]); | ||
458 | cpu_set(cpu, cpu_core_map[i]); | ||
446 | } | 459 | } |
447 | } | 460 | } |
448 | } else { | 461 | } else { |
449 | cpu_set(cpu, cpu_sibling_map[cpu]); | 462 | cpu_set(cpu, cpu_sibling_map[cpu]); |
450 | } | 463 | } |
451 | 464 | ||
452 | if (current_cpu_data.x86_num_cores > 1) { | 465 | if (current_cpu_data.x86_max_cores == 1) { |
453 | for_each_cpu(i) { | ||
454 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
455 | cpu_set(i, cpu_core_map[cpu]); | ||
456 | cpu_set(cpu, cpu_core_map[i]); | ||
457 | } | ||
458 | } | ||
459 | } else { | ||
460 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 466 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
467 | c[cpu].booted_cores = 1; | ||
468 | return; | ||
469 | } | ||
470 | |||
471 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | ||
472 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
473 | cpu_set(i, cpu_core_map[cpu]); | ||
474 | cpu_set(cpu, cpu_core_map[i]); | ||
475 | /* | ||
476 | * Does this new cpu bringup a new core? | ||
477 | */ | ||
478 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) { | ||
479 | /* | ||
480 | * for each core in package, increment | ||
481 | * the booted_cores for this new cpu | ||
482 | */ | ||
483 | if (first_cpu(cpu_sibling_map[i]) == i) | ||
484 | c[cpu].booted_cores++; | ||
485 | /* | ||
486 | * increment the core count for all | ||
487 | * the other cpus in this package | ||
488 | */ | ||
489 | if (i != cpu) | ||
490 | c[i].booted_cores++; | ||
491 | } else if (i != cpu && !c[cpu].booted_cores) | ||
492 | c[cpu].booted_cores = c[i].booted_cores; | ||
493 | } | ||
461 | } | 494 | } |
462 | } | 495 | } |
463 | 496 | ||
@@ -879,6 +912,9 @@ static __init void disable_smp(void) | |||
879 | } | 912 | } |
880 | 913 | ||
881 | #ifdef CONFIG_HOTPLUG_CPU | 914 | #ifdef CONFIG_HOTPLUG_CPU |
915 | |||
916 | int additional_cpus __initdata = -1; | ||
917 | |||
882 | /* | 918 | /* |
883 | * cpu_possible_map should be static, it cannot change as cpu's | 919 | * cpu_possible_map should be static, it cannot change as cpu's |
884 | * are onlined, or offlined. The reason is per-cpu data-structures | 920 | * are onlined, or offlined. The reason is per-cpu data-structures |
@@ -887,14 +923,38 @@ static __init void disable_smp(void) | |||
887 | * cpu_present_map on the other hand can change dynamically. | 923 | * cpu_present_map on the other hand can change dynamically. |
888 | * In case when cpu_hotplug is not compiled, then we resort to current | 924 | * In case when cpu_hotplug is not compiled, then we resort to current |
889 | * behaviour, which is cpu_possible == cpu_present. | 925 | * behaviour, which is cpu_possible == cpu_present. |
890 | * If cpu-hotplug is supported, then we need to preallocate for all | ||
891 | * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range. | ||
892 | * - Ashok Raj | 926 | * - Ashok Raj |
927 | * | ||
928 | * Three ways to find out the number of additional hotplug CPUs: | ||
929 | * - If the BIOS specified disabled CPUs in ACPI/mptables use that. | ||
930 | * - otherwise use half of the available CPUs or 2, whatever is more. | ||
931 | * - The user can overwrite it with additional_cpus=NUM | ||
932 | * We do this because additional CPUs waste a lot of memory. | ||
933 | * -AK | ||
893 | */ | 934 | */ |
894 | __init void prefill_possible_map(void) | 935 | __init void prefill_possible_map(void) |
895 | { | 936 | { |
896 | int i; | 937 | int i; |
897 | for (i = 0; i < NR_CPUS; i++) | 938 | int possible; |
939 | |||
940 | if (additional_cpus == -1) { | ||
941 | if (disabled_cpus > 0) { | ||
942 | additional_cpus = disabled_cpus; | ||
943 | } else { | ||
944 | additional_cpus = num_processors / 2; | ||
945 | if (additional_cpus == 0) | ||
946 | additional_cpus = 2; | ||
947 | } | ||
948 | } | ||
949 | possible = num_processors + additional_cpus; | ||
950 | if (possible > NR_CPUS) | ||
951 | possible = NR_CPUS; | ||
952 | |||
953 | printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n", | ||
954 | possible, | ||
955 | max_t(int, possible - num_processors, 0)); | ||
956 | |||
957 | for (i = 0; i < possible; i++) | ||
898 | cpu_set(i, cpu_possible_map); | 958 | cpu_set(i, cpu_possible_map); |
899 | } | 959 | } |
900 | #endif | 960 | #endif |
@@ -965,6 +1025,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
965 | nmi_watchdog_default(); | 1025 | nmi_watchdog_default(); |
966 | current_cpu_data = boot_cpu_data; | 1026 | current_cpu_data = boot_cpu_data; |
967 | current_thread_info()->cpu = 0; /* needed? */ | 1027 | current_thread_info()->cpu = 0; /* needed? */ |
1028 | set_cpu_sibling_map(0); | ||
968 | 1029 | ||
969 | if (smp_sanity_check(max_cpus) < 0) { | 1030 | if (smp_sanity_check(max_cpus) < 0) { |
970 | printk(KERN_INFO "SMP disabled\n"); | 1031 | printk(KERN_INFO "SMP disabled\n"); |
@@ -1008,8 +1069,6 @@ void __init smp_prepare_boot_cpu(void) | |||
1008 | int me = smp_processor_id(); | 1069 | int me = smp_processor_id(); |
1009 | cpu_set(me, cpu_online_map); | 1070 | cpu_set(me, cpu_online_map); |
1010 | cpu_set(me, cpu_callout_map); | 1071 | cpu_set(me, cpu_callout_map); |
1011 | cpu_set(0, cpu_sibling_map[0]); | ||
1012 | cpu_set(0, cpu_core_map[0]); | ||
1013 | per_cpu(cpu_state, me) = CPU_ONLINE; | 1072 | per_cpu(cpu_state, me) = CPU_ONLINE; |
1014 | } | 1073 | } |
1015 | 1074 | ||
@@ -1062,9 +1121,6 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
1062 | */ | 1121 | */ |
1063 | void __init smp_cpus_done(unsigned int max_cpus) | 1122 | void __init smp_cpus_done(unsigned int max_cpus) |
1064 | { | 1123 | { |
1065 | #ifndef CONFIG_HOTPLUG_CPU | ||
1066 | zap_low_mappings(); | ||
1067 | #endif | ||
1068 | smp_cleanup_boot(); | 1124 | smp_cleanup_boot(); |
1069 | 1125 | ||
1070 | #ifdef CONFIG_X86_IO_APIC | 1126 | #ifdef CONFIG_X86_IO_APIC |
@@ -1081,15 +1137,24 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
1081 | static void remove_siblinginfo(int cpu) | 1137 | static void remove_siblinginfo(int cpu) |
1082 | { | 1138 | { |
1083 | int sibling; | 1139 | int sibling; |
1140 | struct cpuinfo_x86 *c = cpu_data; | ||
1084 | 1141 | ||
1142 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) { | ||
1143 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1144 | /* | ||
1145 | * last thread sibling in this cpu core going down | ||
1146 | */ | ||
1147 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) | ||
1148 | c[sibling].booted_cores--; | ||
1149 | } | ||
1150 | |||
1085 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) | 1151 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) |
1086 | cpu_clear(cpu, cpu_sibling_map[sibling]); | 1152 | cpu_clear(cpu, cpu_sibling_map[sibling]); |
1087 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) | ||
1088 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1089 | cpus_clear(cpu_sibling_map[cpu]); | 1153 | cpus_clear(cpu_sibling_map[cpu]); |
1090 | cpus_clear(cpu_core_map[cpu]); | 1154 | cpus_clear(cpu_core_map[cpu]); |
1091 | phys_proc_id[cpu] = BAD_APICID; | 1155 | phys_proc_id[cpu] = BAD_APICID; |
1092 | cpu_core_id[cpu] = BAD_APICID; | 1156 | cpu_core_id[cpu] = BAD_APICID; |
1157 | cpu_clear(cpu, cpu_sibling_setup_map); | ||
1093 | } | 1158 | } |
1094 | 1159 | ||
1095 | void remove_cpu_from_maps(void) | 1160 | void remove_cpu_from_maps(void) |
@@ -1153,6 +1218,12 @@ void __cpu_die(unsigned int cpu) | |||
1153 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | 1218 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); |
1154 | } | 1219 | } |
1155 | 1220 | ||
1221 | static __init int setup_additional_cpus(char *s) | ||
1222 | { | ||
1223 | return get_option(&s, &additional_cpus); | ||
1224 | } | ||
1225 | __setup("additional_cpus=", setup_additional_cpus); | ||
1226 | |||
1156 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 1227 | #else /* ... !CONFIG_HOTPLUG_CPU */ |
1157 | 1228 | ||
1158 | int __cpu_disable(void) | 1229 | int __cpu_disable(void) |
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c index cc7821c68851..6449ea8fe756 100644 --- a/arch/x86_64/kernel/sys_x86_64.c +++ b/arch/x86_64/kernel/sys_x86_64.c | |||
@@ -154,17 +154,3 @@ asmlinkage long sys_uname(struct new_utsname __user * name) | |||
154 | err |= copy_to_user(&name->machine, "i686", 5); | 154 | err |= copy_to_user(&name->machine, "i686", 5); |
155 | return err ? -EFAULT : 0; | 155 | return err ? -EFAULT : 0; |
156 | } | 156 | } |
157 | |||
158 | asmlinkage long sys_time64(long __user * tloc) | ||
159 | { | ||
160 | struct timeval now; | ||
161 | int i; | ||
162 | |||
163 | do_gettimeofday(&now); | ||
164 | i = now.tv_sec; | ||
165 | if (tloc) { | ||
166 | if (put_user(i,tloc)) | ||
167 | i = -EFAULT; | ||
168 | } | ||
169 | return i; | ||
170 | } | ||
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index b5e09e6b5536..bf337f493189 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -428,19 +428,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, | |||
428 | { | 428 | { |
429 | conditional_sti(regs); | 429 | conditional_sti(regs); |
430 | 430 | ||
431 | #ifdef CONFIG_CHECKING | ||
432 | { | ||
433 | unsigned long gs; | ||
434 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
435 | rdmsrl(MSR_GS_BASE, gs); | ||
436 | if (gs != (unsigned long)pda) { | ||
437 | wrmsrl(MSR_GS_BASE, pda); | ||
438 | printk("%s: wrong gs %lx expected %p rip %lx\n", str, gs, pda, | ||
439 | regs->rip); | ||
440 | } | ||
441 | } | ||
442 | #endif | ||
443 | |||
444 | if (user_mode(regs)) { | 431 | if (user_mode(regs)) { |
445 | struct task_struct *tsk = current; | 432 | struct task_struct *tsk = current; |
446 | 433 | ||
@@ -513,20 +500,6 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, | |||
513 | { | 500 | { |
514 | conditional_sti(regs); | 501 | conditional_sti(regs); |
515 | 502 | ||
516 | #ifdef CONFIG_CHECKING | ||
517 | { | ||
518 | unsigned long gs; | ||
519 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
520 | rdmsrl(MSR_GS_BASE, gs); | ||
521 | if (gs != (unsigned long)pda) { | ||
522 | wrmsrl(MSR_GS_BASE, pda); | ||
523 | oops_in_progress++; | ||
524 | printk("general protection handler: wrong gs %lx expected %p\n", gs, pda); | ||
525 | oops_in_progress--; | ||
526 | } | ||
527 | } | ||
528 | #endif | ||
529 | |||
530 | if (user_mode(regs)) { | 503 | if (user_mode(regs)) { |
531 | struct task_struct *tsk = current; | 504 | struct task_struct *tsk = current; |
532 | 505 | ||
@@ -665,19 +638,6 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, | |||
665 | struct task_struct *tsk = current; | 638 | struct task_struct *tsk = current; |
666 | siginfo_t info; | 639 | siginfo_t info; |
667 | 640 | ||
668 | #ifdef CONFIG_CHECKING | ||
669 | { | ||
670 | /* RED-PEN interaction with debugger - could destroy gs */ | ||
671 | unsigned long gs; | ||
672 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
673 | rdmsrl(MSR_GS_BASE, gs); | ||
674 | if (gs != (unsigned long)pda) { | ||
675 | wrmsrl(MSR_GS_BASE, pda); | ||
676 | printk("debug handler: wrong gs %lx expected %p\n", gs, pda); | ||
677 | } | ||
678 | } | ||
679 | #endif | ||
680 | |||
681 | get_debugreg(condition, 6); | 641 | get_debugreg(condition, 6); |
682 | 642 | ||
683 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, | 643 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, |
@@ -888,6 +848,10 @@ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) | |||
888 | { | 848 | { |
889 | } | 849 | } |
890 | 850 | ||
851 | asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void) | ||
852 | { | ||
853 | } | ||
854 | |||
891 | /* | 855 | /* |
892 | * 'math_state_restore()' saves the current math information in the | 856 | * 'math_state_restore()' saves the current math information in the |
893 | * old math state array, and gets the new ones from the current task | 857 | * old math state array, and gets the new ones from the current task |
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 6dd642cad2ef..58b19215b4b3 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S | |||
@@ -50,7 +50,7 @@ SECTIONS | |||
50 | *(.bss.page_aligned) | 50 | *(.bss.page_aligned) |
51 | *(.bss) | 51 | *(.bss) |
52 | } | 52 | } |
53 | __bss_end = .; | 53 | __bss_stop = .; |
54 | 54 | ||
55 | . = ALIGN(PAGE_SIZE); | 55 | . = ALIGN(PAGE_SIZE); |
56 | . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); | 56 | . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); |
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index fd99ddd009bc..4a54221e10bc 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c | |||
@@ -203,3 +203,6 @@ EXPORT_SYMBOL(flush_tlb_page); | |||
203 | #endif | 203 | #endif |
204 | 204 | ||
205 | EXPORT_SYMBOL(cpu_khz); | 205 | EXPORT_SYMBOL(cpu_khz); |
206 | |||
207 | EXPORT_SYMBOL(load_gs_index); | ||
208 | |||
diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S index 30a9da458c15..43d9fa136180 100644 --- a/arch/x86_64/lib/clear_page.S +++ b/arch/x86_64/lib/clear_page.S | |||
@@ -5,46 +5,8 @@ | |||
5 | .globl clear_page | 5 | .globl clear_page |
6 | .p2align 4 | 6 | .p2align 4 |
7 | clear_page: | 7 | clear_page: |
8 | xorl %eax,%eax | ||
9 | movl $4096/64,%ecx | ||
10 | .p2align 4 | ||
11 | .Lloop: | ||
12 | decl %ecx | ||
13 | #define PUT(x) movq %rax,x*8(%rdi) | ||
14 | movq %rax,(%rdi) | ||
15 | PUT(1) | ||
16 | PUT(2) | ||
17 | PUT(3) | ||
18 | PUT(4) | ||
19 | PUT(5) | ||
20 | PUT(6) | ||
21 | PUT(7) | ||
22 | leaq 64(%rdi),%rdi | ||
23 | jnz .Lloop | ||
24 | nop | ||
25 | ret | ||
26 | clear_page_end: | ||
27 | |||
28 | /* C stepping K8 run faster using the string instructions. | ||
29 | It is also a lot simpler. Use this when possible */ | ||
30 | |||
31 | #include <asm/cpufeature.h> | ||
32 | |||
33 | .section .altinstructions,"a" | ||
34 | .align 8 | ||
35 | .quad clear_page | ||
36 | .quad clear_page_c | ||
37 | .byte X86_FEATURE_K8_C | ||
38 | .byte clear_page_end-clear_page | ||
39 | .byte clear_page_c_end-clear_page_c | ||
40 | .previous | ||
41 | |||
42 | .section .altinstr_replacement,"ax" | ||
43 | clear_page_c: | ||
44 | movl $4096/8,%ecx | 8 | movl $4096/8,%ecx |
45 | xorl %eax,%eax | 9 | xorl %eax,%eax |
46 | rep | 10 | rep |
47 | stosq | 11 | stosq |
48 | ret | 12 | ret |
49 | clear_page_c_end: | ||
50 | .previous | ||
diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S index dd3aa47b6bf5..621a19769406 100644 --- a/arch/x86_64/lib/copy_page.S +++ b/arch/x86_64/lib/copy_page.S | |||
@@ -8,94 +8,7 @@ | |||
8 | .globl copy_page | 8 | .globl copy_page |
9 | .p2align 4 | 9 | .p2align 4 |
10 | copy_page: | 10 | copy_page: |
11 | subq $3*8,%rsp | ||
12 | movq %rbx,(%rsp) | ||
13 | movq %r12,1*8(%rsp) | ||
14 | movq %r13,2*8(%rsp) | ||
15 | |||
16 | movl $(4096/64)-5,%ecx | ||
17 | .p2align 4 | ||
18 | .Loop64: | ||
19 | dec %rcx | ||
20 | |||
21 | movq (%rsi), %rax | ||
22 | movq 8 (%rsi), %rbx | ||
23 | movq 16 (%rsi), %rdx | ||
24 | movq 24 (%rsi), %r8 | ||
25 | movq 32 (%rsi), %r9 | ||
26 | movq 40 (%rsi), %r10 | ||
27 | movq 48 (%rsi), %r11 | ||
28 | movq 56 (%rsi), %r12 | ||
29 | |||
30 | prefetcht0 5*64(%rsi) | ||
31 | |||
32 | movq %rax, (%rdi) | ||
33 | movq %rbx, 8 (%rdi) | ||
34 | movq %rdx, 16 (%rdi) | ||
35 | movq %r8, 24 (%rdi) | ||
36 | movq %r9, 32 (%rdi) | ||
37 | movq %r10, 40 (%rdi) | ||
38 | movq %r11, 48 (%rdi) | ||
39 | movq %r12, 56 (%rdi) | ||
40 | |||
41 | leaq 64 (%rsi), %rsi | ||
42 | leaq 64 (%rdi), %rdi | ||
43 | |||
44 | jnz .Loop64 | ||
45 | |||
46 | movl $5,%ecx | ||
47 | .p2align 4 | ||
48 | .Loop2: | ||
49 | decl %ecx | ||
50 | |||
51 | movq (%rsi), %rax | ||
52 | movq 8 (%rsi), %rbx | ||
53 | movq 16 (%rsi), %rdx | ||
54 | movq 24 (%rsi), %r8 | ||
55 | movq 32 (%rsi), %r9 | ||
56 | movq 40 (%rsi), %r10 | ||
57 | movq 48 (%rsi), %r11 | ||
58 | movq 56 (%rsi), %r12 | ||
59 | |||
60 | movq %rax, (%rdi) | ||
61 | movq %rbx, 8 (%rdi) | ||
62 | movq %rdx, 16 (%rdi) | ||
63 | movq %r8, 24 (%rdi) | ||
64 | movq %r9, 32 (%rdi) | ||
65 | movq %r10, 40 (%rdi) | ||
66 | movq %r11, 48 (%rdi) | ||
67 | movq %r12, 56 (%rdi) | ||
68 | |||
69 | leaq 64(%rdi),%rdi | ||
70 | leaq 64(%rsi),%rsi | ||
71 | |||
72 | jnz .Loop2 | ||
73 | |||
74 | movq (%rsp),%rbx | ||
75 | movq 1*8(%rsp),%r12 | ||
76 | movq 2*8(%rsp),%r13 | ||
77 | addq $3*8,%rsp | ||
78 | ret | ||
79 | |||
80 | /* C stepping K8 run faster using the string copy instructions. | ||
81 | It is also a lot simpler. Use this when possible */ | ||
82 | |||
83 | #include <asm/cpufeature.h> | ||
84 | |||
85 | .section .altinstructions,"a" | ||
86 | .align 8 | ||
87 | .quad copy_page | ||
88 | .quad copy_page_c | ||
89 | .byte X86_FEATURE_K8_C | ||
90 | .byte copy_page_c_end-copy_page_c | ||
91 | .byte copy_page_c_end-copy_page_c | ||
92 | .previous | ||
93 | |||
94 | .section .altinstr_replacement,"ax" | ||
95 | copy_page_c: | ||
96 | movl $4096/8,%ecx | 11 | movl $4096/8,%ecx |
97 | rep | 12 | rep |
98 | movsq | 13 | movsq |
99 | ret | 14 | ret |
100 | copy_page_c_end: | ||
101 | .previous | ||
diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S index c6c46494fef5..92dd80544602 100644 --- a/arch/x86_64/lib/memcpy.S +++ b/arch/x86_64/lib/memcpy.S | |||
@@ -11,6 +11,8 @@ | |||
11 | * | 11 | * |
12 | * Output: | 12 | * Output: |
13 | * rax original destination | 13 | * rax original destination |
14 | * | ||
15 | * TODO: check best memcpy for PSC | ||
14 | */ | 16 | */ |
15 | 17 | ||
16 | .globl __memcpy | 18 | .globl __memcpy |
@@ -18,95 +20,6 @@ | |||
18 | .p2align 4 | 20 | .p2align 4 |
19 | __memcpy: | 21 | __memcpy: |
20 | memcpy: | 22 | memcpy: |
21 | pushq %rbx | ||
22 | movq %rdi,%rax | ||
23 | |||
24 | movl %edx,%ecx | ||
25 | shrl $6,%ecx | ||
26 | jz .Lhandle_tail | ||
27 | |||
28 | .p2align 4 | ||
29 | .Lloop_64: | ||
30 | decl %ecx | ||
31 | |||
32 | movq (%rsi),%r11 | ||
33 | movq 8(%rsi),%r8 | ||
34 | |||
35 | movq %r11,(%rdi) | ||
36 | movq %r8,1*8(%rdi) | ||
37 | |||
38 | movq 2*8(%rsi),%r9 | ||
39 | movq 3*8(%rsi),%r10 | ||
40 | |||
41 | movq %r9,2*8(%rdi) | ||
42 | movq %r10,3*8(%rdi) | ||
43 | |||
44 | movq 4*8(%rsi),%r11 | ||
45 | movq 5*8(%rsi),%r8 | ||
46 | |||
47 | movq %r11,4*8(%rdi) | ||
48 | movq %r8,5*8(%rdi) | ||
49 | |||
50 | movq 6*8(%rsi),%r9 | ||
51 | movq 7*8(%rsi),%r10 | ||
52 | |||
53 | movq %r9,6*8(%rdi) | ||
54 | movq %r10,7*8(%rdi) | ||
55 | |||
56 | leaq 64(%rsi),%rsi | ||
57 | leaq 64(%rdi),%rdi | ||
58 | jnz .Lloop_64 | ||
59 | |||
60 | .Lhandle_tail: | ||
61 | movl %edx,%ecx | ||
62 | andl $63,%ecx | ||
63 | shrl $3,%ecx | ||
64 | jz .Lhandle_7 | ||
65 | .p2align 4 | ||
66 | .Lloop_8: | ||
67 | decl %ecx | ||
68 | movq (%rsi),%r8 | ||
69 | movq %r8,(%rdi) | ||
70 | leaq 8(%rdi),%rdi | ||
71 | leaq 8(%rsi),%rsi | ||
72 | jnz .Lloop_8 | ||
73 | |||
74 | .Lhandle_7: | ||
75 | movl %edx,%ecx | ||
76 | andl $7,%ecx | ||
77 | jz .Lende | ||
78 | .p2align 4 | ||
79 | .Lloop_1: | ||
80 | movb (%rsi),%r8b | ||
81 | movb %r8b,(%rdi) | ||
82 | incq %rdi | ||
83 | incq %rsi | ||
84 | decl %ecx | ||
85 | jnz .Lloop_1 | ||
86 | |||
87 | .Lende: | ||
88 | popq %rbx | ||
89 | ret | ||
90 | .Lfinal: | ||
91 | |||
92 | /* C stepping K8 run faster using the string copy instructions. | ||
93 | It is also a lot simpler. Use this when possible */ | ||
94 | |||
95 | .section .altinstructions,"a" | ||
96 | .align 8 | ||
97 | .quad memcpy | ||
98 | .quad memcpy_c | ||
99 | .byte X86_FEATURE_K8_C | ||
100 | .byte .Lfinal-memcpy | ||
101 | .byte memcpy_c_end-memcpy_c | ||
102 | .previous | ||
103 | |||
104 | .section .altinstr_replacement,"ax" | ||
105 | /* rdi destination | ||
106 | * rsi source | ||
107 | * rdx count | ||
108 | */ | ||
109 | memcpy_c: | ||
110 | movq %rdi,%rax | 23 | movq %rdi,%rax |
111 | movl %edx,%ecx | 24 | movl %edx,%ecx |
112 | shrl $3,%ecx | 25 | shrl $3,%ecx |
@@ -117,5 +30,3 @@ memcpy_c: | |||
117 | rep | 30 | rep |
118 | movsb | 31 | movsb |
119 | ret | 32 | ret |
120 | memcpy_c_end: | ||
121 | .previous | ||
diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S index 4b4c40638640..2aa48f24ed1e 100644 --- a/arch/x86_64/lib/memset.S +++ b/arch/x86_64/lib/memset.S | |||
@@ -13,98 +13,6 @@ | |||
13 | .p2align 4 | 13 | .p2align 4 |
14 | memset: | 14 | memset: |
15 | __memset: | 15 | __memset: |
16 | movq %rdi,%r10 | ||
17 | movq %rdx,%r11 | ||
18 | |||
19 | /* expand byte value */ | ||
20 | movzbl %sil,%ecx | ||
21 | movabs $0x0101010101010101,%rax | ||
22 | mul %rcx /* with rax, clobbers rdx */ | ||
23 | |||
24 | /* align dst */ | ||
25 | movl %edi,%r9d | ||
26 | andl $7,%r9d | ||
27 | jnz .Lbad_alignment | ||
28 | .Lafter_bad_alignment: | ||
29 | |||
30 | movl %r11d,%ecx | ||
31 | shrl $6,%ecx | ||
32 | jz .Lhandle_tail | ||
33 | |||
34 | .p2align 4 | ||
35 | .Lloop_64: | ||
36 | decl %ecx | ||
37 | movq %rax,(%rdi) | ||
38 | movq %rax,8(%rdi) | ||
39 | movq %rax,16(%rdi) | ||
40 | movq %rax,24(%rdi) | ||
41 | movq %rax,32(%rdi) | ||
42 | movq %rax,40(%rdi) | ||
43 | movq %rax,48(%rdi) | ||
44 | movq %rax,56(%rdi) | ||
45 | leaq 64(%rdi),%rdi | ||
46 | jnz .Lloop_64 | ||
47 | |||
48 | /* Handle tail in loops. The loops should be faster than hard | ||
49 | to predict jump tables. */ | ||
50 | .p2align 4 | ||
51 | .Lhandle_tail: | ||
52 | movl %r11d,%ecx | ||
53 | andl $63&(~7),%ecx | ||
54 | jz .Lhandle_7 | ||
55 | shrl $3,%ecx | ||
56 | .p2align 4 | ||
57 | .Lloop_8: | ||
58 | decl %ecx | ||
59 | movq %rax,(%rdi) | ||
60 | leaq 8(%rdi),%rdi | ||
61 | jnz .Lloop_8 | ||
62 | |||
63 | .Lhandle_7: | ||
64 | movl %r11d,%ecx | ||
65 | andl $7,%ecx | ||
66 | jz .Lende | ||
67 | .p2align 4 | ||
68 | .Lloop_1: | ||
69 | decl %ecx | ||
70 | movb %al,(%rdi) | ||
71 | leaq 1(%rdi),%rdi | ||
72 | jnz .Lloop_1 | ||
73 | |||
74 | .Lende: | ||
75 | movq %r10,%rax | ||
76 | ret | ||
77 | |||
78 | .Lbad_alignment: | ||
79 | cmpq $7,%r11 | ||
80 | jbe .Lhandle_7 | ||
81 | movq %rax,(%rdi) /* unaligned store */ | ||
82 | movq $8,%r8 | ||
83 | subq %r9,%r8 | ||
84 | addq %r8,%rdi | ||
85 | subq %r8,%r11 | ||
86 | jmp .Lafter_bad_alignment | ||
87 | |||
88 | /* C stepping K8 run faster using the string instructions. | ||
89 | It is also a lot simpler. Use this when possible */ | ||
90 | |||
91 | #include <asm/cpufeature.h> | ||
92 | |||
93 | .section .altinstructions,"a" | ||
94 | .align 8 | ||
95 | .quad memset | ||
96 | .quad memset_c | ||
97 | .byte X86_FEATURE_K8_C | ||
98 | .byte memset_c_end-memset_c | ||
99 | .byte memset_c_end-memset_c | ||
100 | .previous | ||
101 | |||
102 | .section .altinstr_replacement,"ax" | ||
103 | /* rdi destination | ||
104 | * rsi value | ||
105 | * rdx count | ||
106 | */ | ||
107 | memset_c: | ||
108 | movq %rdi,%r9 | 16 | movq %rdi,%r9 |
109 | movl %edx,%r8d | 17 | movl %edx,%r8d |
110 | andl $7,%r8d | 18 | andl $7,%r8d |
@@ -121,5 +29,3 @@ memset_c: | |||
121 | stosb | 29 | stosb |
122 | movq %r9,%rax | 30 | movq %r9,%rax |
123 | ret | 31 | ret |
124 | memset_c_end: | ||
125 | .previous | ||
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index b75b872ec154..3a63707a698b 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c | |||
@@ -308,18 +308,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
308 | unsigned long flags; | 308 | unsigned long flags; |
309 | siginfo_t info; | 309 | siginfo_t info; |
310 | 310 | ||
311 | #ifdef CONFIG_CHECKING | ||
312 | { | ||
313 | unsigned long gs; | ||
314 | struct x8664_pda *pda = cpu_pda + stack_smp_processor_id(); | ||
315 | rdmsrl(MSR_GS_BASE, gs); | ||
316 | if (gs != (unsigned long)pda) { | ||
317 | wrmsrl(MSR_GS_BASE, pda); | ||
318 | printk("page_fault: wrong gs %lx expected %p\n", gs, pda); | ||
319 | } | ||
320 | } | ||
321 | #endif | ||
322 | |||
323 | /* get the address */ | 311 | /* get the address */ |
324 | __asm__("movq %%cr2,%0":"=r" (address)); | 312 | __asm__("movq %%cr2,%0":"=r" (address)); |
325 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 313 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, |
@@ -571,3 +559,10 @@ do_sigbus: | |||
571 | force_sig_info(SIGBUS, &info, tsk); | 559 | force_sig_info(SIGBUS, &info, tsk); |
572 | return; | 560 | return; |
573 | } | 561 | } |
562 | |||
563 | static int __init enable_pagefaulttrace(char *str) | ||
564 | { | ||
565 | page_fault_trace = 1; | ||
566 | return 0; | ||
567 | } | ||
568 | __setup("pagefaulttrace", enable_pagefaulttrace); | ||
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index e60a1a848de8..286f6a624c3a 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
25 | #include <linux/pci.h> | ||
25 | 26 | ||
26 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
@@ -36,16 +37,13 @@ | |||
36 | #include <asm/mmu_context.h> | 37 | #include <asm/mmu_context.h> |
37 | #include <asm/proto.h> | 38 | #include <asm/proto.h> |
38 | #include <asm/smp.h> | 39 | #include <asm/smp.h> |
40 | #include <asm/sections.h> | ||
39 | 41 | ||
40 | #ifndef Dprintk | 42 | #ifndef Dprintk |
41 | #define Dprintk(x...) | 43 | #define Dprintk(x...) |
42 | #endif | 44 | #endif |
43 | 45 | ||
44 | #ifdef CONFIG_GART_IOMMU | 46 | static unsigned long dma_reserve __initdata; |
45 | extern int swiotlb; | ||
46 | #endif | ||
47 | |||
48 | extern char _stext[]; | ||
49 | 47 | ||
50 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 48 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
51 | 49 | ||
@@ -86,9 +84,6 @@ void show_mem(void) | |||
86 | 84 | ||
87 | /* References to section boundaries */ | 85 | /* References to section boundaries */ |
88 | 86 | ||
89 | extern char _text, _etext, _edata, __bss_start, _end[]; | ||
90 | extern char __init_begin, __init_end; | ||
91 | |||
92 | int after_bootmem; | 87 | int after_bootmem; |
93 | 88 | ||
94 | static void *spp_getpage(void) | 89 | static void *spp_getpage(void) |
@@ -308,42 +303,81 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) | |||
308 | table_end<<PAGE_SHIFT); | 303 | table_end<<PAGE_SHIFT); |
309 | } | 304 | } |
310 | 305 | ||
311 | extern struct x8664_pda cpu_pda[NR_CPUS]; | 306 | void __cpuinit zap_low_mappings(int cpu) |
307 | { | ||
308 | if (cpu == 0) { | ||
309 | pgd_t *pgd = pgd_offset_k(0UL); | ||
310 | pgd_clear(pgd); | ||
311 | } else { | ||
312 | /* | ||
313 | * For AP's, zap the low identity mappings by changing the cr3 | ||
314 | * to init_level4_pgt and doing local flush tlb all | ||
315 | */ | ||
316 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
317 | } | ||
318 | __flush_tlb_all(); | ||
319 | } | ||
312 | 320 | ||
313 | /* Assumes all CPUs still execute in init_mm */ | 321 | /* Compute zone sizes for the DMA and DMA32 zones in a node. */ |
314 | void zap_low_mappings(void) | 322 | __init void |
323 | size_zones(unsigned long *z, unsigned long *h, | ||
324 | unsigned long start_pfn, unsigned long end_pfn) | ||
315 | { | 325 | { |
316 | pgd_t *pgd = pgd_offset_k(0UL); | 326 | int i; |
317 | pgd_clear(pgd); | 327 | unsigned long w; |
318 | flush_tlb_all(); | 328 | |
329 | for (i = 0; i < MAX_NR_ZONES; i++) | ||
330 | z[i] = 0; | ||
331 | |||
332 | if (start_pfn < MAX_DMA_PFN) | ||
333 | z[ZONE_DMA] = MAX_DMA_PFN - start_pfn; | ||
334 | if (start_pfn < MAX_DMA32_PFN) { | ||
335 | unsigned long dma32_pfn = MAX_DMA32_PFN; | ||
336 | if (dma32_pfn > end_pfn) | ||
337 | dma32_pfn = end_pfn; | ||
338 | z[ZONE_DMA32] = dma32_pfn - start_pfn; | ||
339 | } | ||
340 | z[ZONE_NORMAL] = end_pfn - start_pfn; | ||
341 | |||
342 | /* Remove lower zones from higher ones. */ | ||
343 | w = 0; | ||
344 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
345 | if (z[i]) | ||
346 | z[i] -= w; | ||
347 | w += z[i]; | ||
348 | } | ||
349 | |||
350 | /* Compute holes */ | ||
351 | w = 0; | ||
352 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
353 | unsigned long s = w; | ||
354 | w += z[i]; | ||
355 | h[i] = e820_hole_size(s, w); | ||
356 | } | ||
357 | |||
358 | /* Add the space pace needed for mem_map to the holes too. */ | ||
359 | for (i = 0; i < MAX_NR_ZONES; i++) | ||
360 | h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE; | ||
361 | |||
362 | /* The 16MB DMA zone has the kernel and other misc mappings. | ||
363 | Account them too */ | ||
364 | if (h[ZONE_DMA]) { | ||
365 | h[ZONE_DMA] += dma_reserve; | ||
366 | if (h[ZONE_DMA] >= z[ZONE_DMA]) { | ||
367 | printk(KERN_WARNING | ||
368 | "Kernel too large and filling up ZONE_DMA?\n"); | ||
369 | h[ZONE_DMA] = z[ZONE_DMA]; | ||
370 | } | ||
371 | } | ||
319 | } | 372 | } |
320 | 373 | ||
321 | #ifndef CONFIG_NUMA | 374 | #ifndef CONFIG_NUMA |
322 | void __init paging_init(void) | 375 | void __init paging_init(void) |
323 | { | 376 | { |
324 | { | 377 | unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; |
325 | unsigned long zones_size[MAX_NR_ZONES]; | 378 | size_zones(zones, holes, 0, end_pfn); |
326 | unsigned long holes[MAX_NR_ZONES]; | 379 | free_area_init_node(0, NODE_DATA(0), zones, |
327 | unsigned int max_dma; | 380 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); |
328 | |||
329 | memset(zones_size, 0, sizeof(zones_size)); | ||
330 | memset(holes, 0, sizeof(holes)); | ||
331 | |||
332 | max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
333 | |||
334 | if (end_pfn < max_dma) { | ||
335 | zones_size[ZONE_DMA] = end_pfn; | ||
336 | holes[ZONE_DMA] = e820_hole_size(0, end_pfn); | ||
337 | } else { | ||
338 | zones_size[ZONE_DMA] = max_dma; | ||
339 | holes[ZONE_DMA] = e820_hole_size(0, max_dma); | ||
340 | zones_size[ZONE_NORMAL] = end_pfn - max_dma; | ||
341 | holes[ZONE_NORMAL] = e820_hole_size(max_dma, end_pfn); | ||
342 | } | ||
343 | free_area_init_node(0, NODE_DATA(0), zones_size, | ||
344 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); | ||
345 | } | ||
346 | return; | ||
347 | } | 381 | } |
348 | #endif | 382 | #endif |
349 | 383 | ||
@@ -438,19 +472,16 @@ void __init mem_init(void) | |||
438 | datasize >> 10, | 472 | datasize >> 10, |
439 | initsize >> 10); | 473 | initsize >> 10); |
440 | 474 | ||
475 | #ifdef CONFIG_SMP | ||
441 | /* | 476 | /* |
442 | * Subtle. SMP is doing its boot stuff late (because it has to | 477 | * Sync boot_level4_pgt mappings with the init_level4_pgt |
443 | * fork idle threads) - but it also needs low mappings for the | 478 | * except for the low identity mappings which are already zapped |
444 | * protected-mode entry to work. We zap these entries only after | 479 | * in init_level4_pgt. This sync-up is essential for AP's bringup |
445 | * the WP-bit has been tested. | ||
446 | */ | 480 | */ |
447 | #ifndef CONFIG_SMP | 481 | memcpy(boot_level4_pgt+1, init_level4_pgt+1, (PTRS_PER_PGD-1)*sizeof(pgd_t)); |
448 | zap_low_mappings(); | ||
449 | #endif | 482 | #endif |
450 | } | 483 | } |
451 | 484 | ||
452 | extern char __initdata_begin[], __initdata_end[]; | ||
453 | |||
454 | void free_initmem(void) | 485 | void free_initmem(void) |
455 | { | 486 | { |
456 | unsigned long addr; | 487 | unsigned long addr; |
@@ -464,7 +495,7 @@ void free_initmem(void) | |||
464 | totalram_pages++; | 495 | totalram_pages++; |
465 | } | 496 | } |
466 | memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); | 497 | memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); |
467 | printk ("Freeing unused kernel memory: %luk freed\n", (&__init_end - &__init_begin) >> 10); | 498 | printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10); |
468 | } | 499 | } |
469 | 500 | ||
470 | #ifdef CONFIG_BLK_DEV_INITRD | 501 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -491,6 +522,8 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | |||
491 | #else | 522 | #else |
492 | reserve_bootmem(phys, len); | 523 | reserve_bootmem(phys, len); |
493 | #endif | 524 | #endif |
525 | if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) | ||
526 | dma_reserve += len / PAGE_SIZE; | ||
494 | } | 527 | } |
495 | 528 | ||
496 | int kern_addr_valid(unsigned long addr) | 529 | int kern_addr_valid(unsigned long addr) |
@@ -532,10 +565,6 @@ extern int exception_trace, page_fault_trace; | |||
532 | static ctl_table debug_table2[] = { | 565 | static ctl_table debug_table2[] = { |
533 | { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL, | 566 | { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL, |
534 | proc_dointvec }, | 567 | proc_dointvec }, |
535 | #ifdef CONFIG_CHECKING | ||
536 | { 100, "page-fault-trace", &page_fault_trace, sizeof(int), 0644, NULL, | ||
537 | proc_dointvec }, | ||
538 | #endif | ||
539 | { 0, } | 568 | { 0, } |
540 | }; | 569 | }; |
541 | 570 | ||
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 65417b040c1b..a5663e0bb01c 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c | |||
@@ -108,6 +108,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) | |||
108 | limit >>= 16; | 108 | limit >>= 16; |
109 | limit <<= 24; | 109 | limit <<= 24; |
110 | limit |= (1<<24)-1; | 110 | limit |= (1<<24)-1; |
111 | limit++; | ||
111 | 112 | ||
112 | if (limit > end_pfn << PAGE_SHIFT) | 113 | if (limit > end_pfn << PAGE_SHIFT) |
113 | limit = end_pfn << PAGE_SHIFT; | 114 | limit = end_pfn << PAGE_SHIFT; |
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 214803821001..a828a01739cc 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -38,38 +38,57 @@ cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; | |||
38 | 38 | ||
39 | int numa_off __initdata; | 39 | int numa_off __initdata; |
40 | 40 | ||
41 | int __init compute_hash_shift(struct node *nodes, int numnodes) | 41 | |
42 | /* | ||
43 | * Given a shift value, try to populate memnodemap[] | ||
44 | * Returns : | ||
45 | * 1 if OK | ||
46 | * 0 if memnodmap[] too small (of shift too small) | ||
47 | * -1 if node overlap or lost ram (shift too big) | ||
48 | */ | ||
49 | static int __init populate_memnodemap( | ||
50 | const struct node *nodes, int numnodes, int shift) | ||
42 | { | 51 | { |
43 | int i; | 52 | int i; |
44 | int shift = 20; | 53 | int res = -1; |
45 | unsigned long addr,maxend=0; | 54 | unsigned long addr, end; |
46 | |||
47 | for (i = 0; i < numnodes; i++) | ||
48 | if ((nodes[i].start != nodes[i].end) && (nodes[i].end > maxend)) | ||
49 | maxend = nodes[i].end; | ||
50 | 55 | ||
51 | while ((1UL << shift) < (maxend / NODEMAPSIZE)) | 56 | memset(memnodemap, 0xff, sizeof(memnodemap)); |
52 | shift++; | ||
53 | |||
54 | printk (KERN_DEBUG"Using %d for the hash shift. Max adder is %lx \n", | ||
55 | shift,maxend); | ||
56 | memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); | ||
57 | for (i = 0; i < numnodes; i++) { | 57 | for (i = 0; i < numnodes; i++) { |
58 | if (nodes[i].start == nodes[i].end) | 58 | addr = nodes[i].start; |
59 | end = nodes[i].end; | ||
60 | if (addr >= end) | ||
59 | continue; | 61 | continue; |
60 | for (addr = nodes[i].start; | 62 | if ((end >> shift) >= NODEMAPSIZE) |
61 | addr < nodes[i].end; | 63 | return 0; |
62 | addr += (1UL << shift)) { | 64 | do { |
63 | if (memnodemap[addr >> shift] != 0xff) { | 65 | if (memnodemap[addr >> shift] != 0xff) |
64 | printk(KERN_INFO | ||
65 | "Your memory is not aligned you need to rebuild your kernel " | ||
66 | "with a bigger NODEMAPSIZE shift=%d adder=%lu\n", | ||
67 | shift,addr); | ||
68 | return -1; | 66 | return -1; |
69 | } | ||
70 | memnodemap[addr >> shift] = i; | 67 | memnodemap[addr >> shift] = i; |
71 | } | 68 | addr += (1 << shift); |
69 | } while (addr < end); | ||
70 | res = 1; | ||
72 | } | 71 | } |
72 | return res; | ||
73 | } | ||
74 | |||
75 | int __init compute_hash_shift(struct node *nodes, int numnodes) | ||
76 | { | ||
77 | int shift = 20; | ||
78 | |||
79 | while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0) | ||
80 | shift++; | ||
81 | |||
82 | printk(KERN_DEBUG "Using %d for the hash shift.\n", | ||
83 | shift); | ||
84 | |||
85 | if (populate_memnodemap(nodes, numnodes, shift) != 1) { | ||
86 | printk(KERN_INFO | ||
87 | "Your memory is not aligned you need to rebuild your kernel " | ||
88 | "with a bigger NODEMAPSIZE shift=%d\n", | ||
89 | shift); | ||
90 | return -1; | ||
91 | } | ||
73 | return shift; | 92 | return shift; |
74 | } | 93 | } |
75 | 94 | ||
@@ -94,7 +113,6 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
94 | start_pfn = start >> PAGE_SHIFT; | 113 | start_pfn = start >> PAGE_SHIFT; |
95 | end_pfn = end >> PAGE_SHIFT; | 114 | end_pfn = end >> PAGE_SHIFT; |
96 | 115 | ||
97 | memory_present(nodeid, start_pfn, end_pfn); | ||
98 | nodedata_phys = find_e820_area(start, end, pgdat_size); | 116 | nodedata_phys = find_e820_area(start, end, pgdat_size); |
99 | if (nodedata_phys == -1L) | 117 | if (nodedata_phys == -1L) |
100 | panic("Cannot find memory pgdat in node %d\n", nodeid); | 118 | panic("Cannot find memory pgdat in node %d\n", nodeid); |
@@ -132,29 +150,14 @@ void __init setup_node_zones(int nodeid) | |||
132 | unsigned long start_pfn, end_pfn; | 150 | unsigned long start_pfn, end_pfn; |
133 | unsigned long zones[MAX_NR_ZONES]; | 151 | unsigned long zones[MAX_NR_ZONES]; |
134 | unsigned long holes[MAX_NR_ZONES]; | 152 | unsigned long holes[MAX_NR_ZONES]; |
135 | unsigned long dma_end_pfn; | ||
136 | 153 | ||
137 | memset(zones, 0, sizeof(unsigned long) * MAX_NR_ZONES); | 154 | start_pfn = node_start_pfn(nodeid); |
138 | memset(holes, 0, sizeof(unsigned long) * MAX_NR_ZONES); | 155 | end_pfn = node_end_pfn(nodeid); |
139 | 156 | ||
140 | start_pfn = node_start_pfn(nodeid); | 157 | Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", |
141 | end_pfn = node_end_pfn(nodeid); | 158 | nodeid, start_pfn, end_pfn); |
142 | 159 | ||
143 | Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); | 160 | size_zones(zones, holes, start_pfn, end_pfn); |
144 | |||
145 | /* All nodes > 0 have a zero length zone DMA */ | ||
146 | dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
147 | if (start_pfn < dma_end_pfn) { | ||
148 | zones[ZONE_DMA] = dma_end_pfn - start_pfn; | ||
149 | holes[ZONE_DMA] = e820_hole_size(start_pfn, dma_end_pfn); | ||
150 | zones[ZONE_NORMAL] = end_pfn - dma_end_pfn; | ||
151 | holes[ZONE_NORMAL] = e820_hole_size(dma_end_pfn, end_pfn); | ||
152 | |||
153 | } else { | ||
154 | zones[ZONE_NORMAL] = end_pfn - start_pfn; | ||
155 | holes[ZONE_NORMAL] = e820_hole_size(start_pfn, end_pfn); | ||
156 | } | ||
157 | |||
158 | free_area_init_node(nodeid, NODE_DATA(nodeid), zones, | 161 | free_area_init_node(nodeid, NODE_DATA(nodeid), zones, |
159 | start_pfn, holes); | 162 | start_pfn, holes); |
160 | } | 163 | } |
@@ -171,7 +174,7 @@ void __init numa_init_array(void) | |||
171 | for (i = 0; i < NR_CPUS; i++) { | 174 | for (i = 0; i < NR_CPUS; i++) { |
172 | if (cpu_to_node[i] != NUMA_NO_NODE) | 175 | if (cpu_to_node[i] != NUMA_NO_NODE) |
173 | continue; | 176 | continue; |
174 | cpu_to_node[i] = rr; | 177 | numa_set_node(i, rr); |
175 | rr = next_node(rr, node_online_map); | 178 | rr = next_node(rr, node_online_map); |
176 | if (rr == MAX_NUMNODES) | 179 | if (rr == MAX_NUMNODES) |
177 | rr = first_node(node_online_map); | 180 | rr = first_node(node_online_map); |
@@ -205,8 +208,6 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) | |||
205 | if (i == numa_fake-1) | 208 | if (i == numa_fake-1) |
206 | sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start; | 209 | sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start; |
207 | nodes[i].end = nodes[i].start + sz; | 210 | nodes[i].end = nodes[i].start + sz; |
208 | if (i != numa_fake-1) | ||
209 | nodes[i].end--; | ||
210 | printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", | 211 | printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", |
211 | i, | 212 | i, |
212 | nodes[i].start, nodes[i].end, | 213 | nodes[i].start, nodes[i].end, |
@@ -257,7 +258,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
257 | nodes_clear(node_online_map); | 258 | nodes_clear(node_online_map); |
258 | node_set_online(0); | 259 | node_set_online(0); |
259 | for (i = 0; i < NR_CPUS; i++) | 260 | for (i = 0; i < NR_CPUS; i++) |
260 | cpu_to_node[i] = 0; | 261 | numa_set_node(i, 0); |
261 | node_to_cpumask[0] = cpumask_of_cpu(0); | 262 | node_to_cpumask[0] = cpumask_of_cpu(0); |
262 | setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); | 263 | setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); |
263 | } | 264 | } |
@@ -267,6 +268,12 @@ __cpuinit void numa_add_cpu(int cpu) | |||
267 | set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); | 268 | set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); |
268 | } | 269 | } |
269 | 270 | ||
271 | void __cpuinit numa_set_node(int cpu, int node) | ||
272 | { | ||
273 | cpu_pda[cpu].nodenumber = node; | ||
274 | cpu_to_node[cpu] = node; | ||
275 | } | ||
276 | |||
270 | unsigned long __init numa_free_all_bootmem(void) | 277 | unsigned long __init numa_free_all_bootmem(void) |
271 | { | 278 | { |
272 | int i; | 279 | int i; |
@@ -277,9 +284,26 @@ unsigned long __init numa_free_all_bootmem(void) | |||
277 | return pages; | 284 | return pages; |
278 | } | 285 | } |
279 | 286 | ||
287 | #ifdef CONFIG_SPARSEMEM | ||
288 | static void __init arch_sparse_init(void) | ||
289 | { | ||
290 | int i; | ||
291 | |||
292 | for_each_online_node(i) | ||
293 | memory_present(i, node_start_pfn(i), node_end_pfn(i)); | ||
294 | |||
295 | sparse_init(); | ||
296 | } | ||
297 | #else | ||
298 | #define arch_sparse_init() do {} while (0) | ||
299 | #endif | ||
300 | |||
280 | void __init paging_init(void) | 301 | void __init paging_init(void) |
281 | { | 302 | { |
282 | int i; | 303 | int i; |
304 | |||
305 | arch_sparse_init(); | ||
306 | |||
283 | for_each_online_node(i) { | 307 | for_each_online_node(i) { |
284 | setup_node_zones(i); | 308 | setup_node_zones(i); |
285 | } | 309 | } |
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 4b2e844c15a7..33340bd1e328 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -71,8 +71,6 @@ static __init void cutoff_node(int i, unsigned long start, unsigned long end) | |||
71 | nd->start = nd->end; | 71 | nd->start = nd->end; |
72 | } | 72 | } |
73 | if (nd->end > end) { | 73 | if (nd->end > end) { |
74 | if (!(end & 0xfff)) | ||
75 | end--; | ||
76 | nd->end = end; | 74 | nd->end = end; |
77 | if (nd->start > nd->end) | 75 | if (nd->start > nd->end) |
78 | nd->start = nd->end; | 76 | nd->start = nd->end; |
@@ -166,8 +164,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
166 | if (nd->end < end) | 164 | if (nd->end < end) |
167 | nd->end = end; | 165 | nd->end = end; |
168 | } | 166 | } |
169 | if (!(nd->end & 0xfff)) | ||
170 | nd->end--; | ||
171 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, | 167 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, |
172 | nd->start, nd->end); | 168 | nd->start, nd->end); |
173 | } | 169 | } |
@@ -203,7 +199,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
203 | if (cpu_to_node[i] == NUMA_NO_NODE) | 199 | if (cpu_to_node[i] == NUMA_NO_NODE) |
204 | continue; | 200 | continue; |
205 | if (!node_isset(cpu_to_node[i], nodes_parsed)) | 201 | if (!node_isset(cpu_to_node[i], nodes_parsed)) |
206 | cpu_to_node[i] = NUMA_NO_NODE; | 202 | numa_set_node(i, NUMA_NO_NODE); |
207 | } | 203 | } |
208 | numa_init_array(); | 204 | numa_init_array(); |
209 | return 0; | 205 | return 0; |