aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/Kconfig23
-rw-r--r--arch/ia64/hp/common/sba_iommu.c10
-rw-r--r--arch/ia64/hp/sim/simserial.c3
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c11
-rw-r--r--arch/ia64/kernel/crash.c245
-rw-r--r--arch/ia64/kernel/efi.c71
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c1
-rw-r--r--arch/ia64/kernel/iosapic.c21
-rw-r--r--arch/ia64/kernel/kprobes.c2
-rw-r--r--arch/ia64/kernel/machine_kexec.c133
-rw-r--r--arch/ia64/kernel/mca.c5
-rw-r--r--arch/ia64/kernel/palinfo.c22
-rw-r--r--arch/ia64/kernel/perfmon.c3
-rw-r--r--arch/ia64/kernel/perfmon_montecito.h12
-rw-r--r--arch/ia64/kernel/relocate_kernel.S334
-rw-r--r--arch/ia64/kernel/setup.c38
-rw-r--r--arch/ia64/kernel/smp.c28
-rw-r--r--arch/ia64/lib/ip_fast_csum.S58
-rw-r--r--arch/ia64/pci/pci.c3
-rw-r--r--arch/ia64/sn/kernel/irq.c18
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c4
-rw-r--r--arch/ia64/sn/kernel/setup.c8
24 files changed, 1008 insertions, 48 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 683b12c6f76c..75d839715b2f 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -434,6 +434,29 @@ config IA64_ESI
434 434
435source "drivers/sn/Kconfig" 435source "drivers/sn/Kconfig"
436 436
437config KEXEC
438 bool "kexec system call (EXPERIMENTAL)"
439 depends on EXPERIMENTAL && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
440 help
441 kexec is a system call that implements the ability to shutdown your
442 current kernel, and to start another kernel. It is like a reboot
443 but it is indepedent of the system firmware. And like a reboot
444 you can start any kernel with it, not just Linux.
445
446 The name comes from the similiarity to the exec system call.
447
448 It is an ongoing process to be certain the hardware in a machine
449 is properly shutdown, so do not be surprised if this code does not
450 initially work for you. It may help to enable device hotplugging
451 support. As of this writing the exact hardware interface is
452 strongly in flux, so no good recommendation can be made.
453
454config CRASH_DUMP
455 bool "kernel crash dumps (EXPERIMENTAL)"
456 depends on EXPERIMENTAL && IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
457 help
458 Generate crash dump after being started by kexec.
459
437source "drivers/firmware/Kconfig" 460source "drivers/firmware/Kconfig"
438 461
439source "fs/Kconfig.binfmt" 462source "fs/Kconfig.binfmt"
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 14691cda05c3..ce49fe3a3b56 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1672,15 +1672,13 @@ ioc_sac_init(struct ioc *ioc)
1672 * SAC (single address cycle) addressable, so allocate a 1672 * SAC (single address cycle) addressable, so allocate a
1673 * pseudo-device to enforce that. 1673 * pseudo-device to enforce that.
1674 */ 1674 */
1675 sac = kmalloc(sizeof(*sac), GFP_KERNEL); 1675 sac = kzalloc(sizeof(*sac), GFP_KERNEL);
1676 if (!sac) 1676 if (!sac)
1677 panic(PFX "Couldn't allocate struct pci_dev"); 1677 panic(PFX "Couldn't allocate struct pci_dev");
1678 memset(sac, 0, sizeof(*sac));
1679 1678
1680 controller = kmalloc(sizeof(*controller), GFP_KERNEL); 1679 controller = kzalloc(sizeof(*controller), GFP_KERNEL);
1681 if (!controller) 1680 if (!controller)
1682 panic(PFX "Couldn't allocate struct pci_controller"); 1681 panic(PFX "Couldn't allocate struct pci_controller");
1683 memset(controller, 0, sizeof(*controller));
1684 1682
1685 controller->iommu = ioc; 1683 controller->iommu = ioc;
1686 sac->sysdata = controller; 1684 sac->sysdata = controller;
@@ -1737,12 +1735,10 @@ ioc_init(u64 hpa, void *handle)
1737 struct ioc *ioc; 1735 struct ioc *ioc;
1738 struct ioc_iommu *info; 1736 struct ioc_iommu *info;
1739 1737
1740 ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); 1738 ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
1741 if (!ioc) 1739 if (!ioc)
1742 return NULL; 1740 return NULL;
1743 1741
1744 memset(ioc, 0, sizeof(*ioc));
1745
1746 ioc->next = ioc_list; 1742 ioc->next = ioc_list;
1747 ioc_list = ioc; 1743 ioc_list = ioc;
1748 1744
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index b62f0c4d2c7c..1f16ebb9a800 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -684,12 +684,11 @@ static int get_async_struct(int line, struct async_struct **ret_info)
684 *ret_info = sstate->info; 684 *ret_info = sstate->info;
685 return 0; 685 return 0;
686 } 686 }
687 info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); 687 info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
688 if (!info) { 688 if (!info) {
689 sstate->count--; 689 sstate->count--;
690 return -ENOMEM; 690 return -ENOMEM;
691 } 691 }
692 memset(info, 0, sizeof(struct async_struct));
693 init_waitqueue_head(&info->open_wait); 692 init_waitqueue_head(&info->open_wait);
694 init_waitqueue_head(&info->close_wait); 693 init_waitqueue_head(&info->close_wait);
695 init_waitqueue_head(&info->delta_msr_wait); 694 init_waitqueue_head(&info->delta_msr_wait);
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index cfa099b04cda..8ae384eb5357 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
28obj-$(CONFIG_CPU_FREQ) += cpufreq/ 28obj-$(CONFIG_CPU_FREQ) += cpufreq/
29obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o 29obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
30obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o 30obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
31obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
31obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o 32obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
32obj-$(CONFIG_AUDIT) += audit.o 33obj-$(CONFIG_AUDIT) += audit.o
33obj-$(CONFIG_PCI_MSI) += msi_ia64.o 34obj-$(CONFIG_PCI_MSI) += msi_ia64.o
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index 86faf221a070..088f130197ae 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -68,7 +68,8 @@ processor_get_pstate (
68 68
69 dprintk("processor_get_pstate\n"); 69 dprintk("processor_get_pstate\n");
70 70
71 retval = ia64_pal_get_pstate(&pstate_index); 71 retval = ia64_pal_get_pstate(&pstate_index,
72 PAL_GET_PSTATE_TYPE_INSTANT);
72 *value = (u32) pstate_index; 73 *value = (u32) pstate_index;
73 74
74 if (retval) 75 if (retval)
@@ -91,7 +92,7 @@ extract_clock (
91 dprintk("extract_clock\n"); 92 dprintk("extract_clock\n");
92 93
93 for (i = 0; i < data->acpi_data.state_count; i++) { 94 for (i = 0; i < data->acpi_data.state_count; i++) {
94 if (value >= data->acpi_data.states[i].control) 95 if (value == data->acpi_data.states[i].status)
95 return data->acpi_data.states[i].core_frequency; 96 return data->acpi_data.states[i].core_frequency;
96 } 97 }
97 return data->acpi_data.states[i-1].core_frequency; 98 return data->acpi_data.states[i-1].core_frequency;
@@ -117,11 +118,7 @@ processor_get_freq (
117 goto migrate_end; 118 goto migrate_end;
118 } 119 }
119 120
120 /* 121 /* processor_get_pstate gets the instantaneous frequency */
121 * processor_get_pstate gets the average frequency since the
122 * last get. So, do two PAL_get_freq()...
123 */
124 ret = processor_get_pstate(&value);
125 ret = processor_get_pstate(&value); 122 ret = processor_get_pstate(&value);
126 123
127 if (ret) { 124 if (ret) {
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
new file mode 100644
index 000000000000..0aabedf95dad
--- /dev/null
+++ b/arch/ia64/kernel/crash.c
@@ -0,0 +1,245 @@
1/*
2 * arch/ia64/kernel/crash.c
3 *
4 * Architecture specific (ia64) functions for kexec based crash dumps.
5 *
6 * Created by: Khalid Aziz <khalid.aziz@hp.com>
7 * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
8 * Copyright (C) 2005 Intel Corp Zou Nan hai <nanhai.zou@intel.com>
9 *
10 */
11#include <linux/smp.h>
12#include <linux/delay.h>
13#include <linux/crash_dump.h>
14#include <linux/bootmem.h>
15#include <linux/kexec.h>
16#include <linux/elfcore.h>
17#include <linux/sysctl.h>
18#include <linux/init.h>
19
20#include <asm/kdebug.h>
21#include <asm/mca.h>
22#include <asm/uaccess.h>
23
24int kdump_status[NR_CPUS];
25atomic_t kdump_cpu_freezed;
26atomic_t kdump_in_progress;
27int kdump_on_init = 1;
28ssize_t
29copy_oldmem_page(unsigned long pfn, char *buf,
30 size_t csize, unsigned long offset, int userbuf)
31{
32 void *vaddr;
33
34 if (!csize)
35 return 0;
36 vaddr = __va(pfn<<PAGE_SHIFT);
37 if (userbuf) {
38 if (copy_to_user(buf, (vaddr + offset), csize)) {
39 return -EFAULT;
40 }
41 } else
42 memcpy(buf, (vaddr + offset), csize);
43 return csize;
44}
45
46static inline Elf64_Word
47*append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
48 size_t data_len)
49{
50 struct elf_note *note = (struct elf_note *)buf;
51 note->n_namesz = strlen(name) + 1;
52 note->n_descsz = data_len;
53 note->n_type = type;
54 buf += (sizeof(*note) + 3)/4;
55 memcpy(buf, name, note->n_namesz);
56 buf += (note->n_namesz + 3)/4;
57 memcpy(buf, data, data_len);
58 buf += (data_len + 3)/4;
59 return buf;
60}
61
62static void
63final_note(void *buf)
64{
65 memset(buf, 0, sizeof(struct elf_note));
66}
67
68extern void ia64_dump_cpu_regs(void *);
69
70static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
71
72void
73crash_save_this_cpu()
74{
75 void *buf;
76 unsigned long cfm, sof, sol;
77
78 int cpu = smp_processor_id();
79 struct elf_prstatus *prstatus = &per_cpu(elf_prstatus, cpu);
80
81 elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
82 memset(prstatus, 0, sizeof(*prstatus));
83 prstatus->pr_pid = current->pid;
84
85 ia64_dump_cpu_regs(dst);
86 cfm = dst[43];
87 sol = (cfm >> 7) & 0x7f;
88 sof = cfm & 0x7f;
89 dst[46] = (unsigned long)ia64_rse_skip_regs((unsigned long *)dst[46],
90 sof - sol);
91
92 buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
93 if (!buf)
94 return;
95 buf = append_elf_note(buf, "CORE", NT_PRSTATUS, prstatus,
96 sizeof(*prstatus));
97 final_note(buf);
98}
99
100static int
101kdump_wait_cpu_freeze(void)
102{
103 int cpu_num = num_online_cpus() - 1;
104 int timeout = 1000;
105 while(timeout-- > 0) {
106 if (atomic_read(&kdump_cpu_freezed) == cpu_num)
107 return 0;
108 udelay(1000);
109 }
110 return 1;
111}
112
113void
114machine_crash_shutdown(struct pt_regs *pt)
115{
116 /* This function is only called after the system
117 * has paniced or is otherwise in a critical state.
118 * The minimum amount of code to allow a kexec'd kernel
119 * to run successfully needs to happen here.
120 *
121 * In practice this means shooting down the other cpus in
122 * an SMP system.
123 */
124 kexec_disable_iosapic();
125#ifdef CONFIG_SMP
126 kdump_smp_send_stop();
127 if (kdump_wait_cpu_freeze() && kdump_on_init) {
128 //not all cpu response to IPI, send INIT to freeze them
129 kdump_smp_send_init();
130 }
131#endif
132}
133
134static void
135machine_kdump_on_init(void)
136{
137 local_irq_disable();
138 kexec_disable_iosapic();
139 machine_kexec(ia64_kimage);
140}
141
142void
143kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
144{
145 int cpuid;
146 local_irq_disable();
147 cpuid = smp_processor_id();
148 crash_save_this_cpu();
149 current->thread.ksp = (__u64)info->sw - 16;
150 atomic_inc(&kdump_cpu_freezed);
151 kdump_status[cpuid] = 1;
152 mb();
153 if (cpuid == 0) {
154 for (;;)
155 cpu_relax();
156 } else
157 ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]);
158}
159
160static int
161kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
162{
163 struct ia64_mca_notify_die *nd;
164 struct die_args *args = data;
165
166 if (!kdump_on_init)
167 return NOTIFY_DONE;
168
169 if (val != DIE_INIT_MONARCH_ENTER &&
170 val != DIE_INIT_SLAVE_ENTER &&
171 val != DIE_MCA_RENDZVOUS_LEAVE &&
172 val != DIE_MCA_MONARCH_LEAVE)
173 return NOTIFY_DONE;
174
175 nd = (struct ia64_mca_notify_die *)args->err;
176 /* Reason code 1 means machine check rendezous*/
177 if ((val == DIE_INIT_MONARCH_ENTER || DIE_INIT_SLAVE_ENTER) &&
178 nd->sos->rv_rc == 1)
179 return NOTIFY_DONE;
180
181 switch (val) {
182 case DIE_INIT_MONARCH_ENTER:
183 machine_kdump_on_init();
184 break;
185 case DIE_INIT_SLAVE_ENTER:
186 unw_init_running(kdump_cpu_freeze, NULL);
187 break;
188 case DIE_MCA_RENDZVOUS_LEAVE:
189 if (atomic_read(&kdump_in_progress))
190 unw_init_running(kdump_cpu_freeze, NULL);
191 break;
192 case DIE_MCA_MONARCH_LEAVE:
193 /* die_register->signr indicate if MCA is recoverable */
194 if (!args->signr)
195 machine_kdump_on_init();
196 break;
197 }
198 return NOTIFY_DONE;
199}
200
201#ifdef CONFIG_SYSCTL
202static ctl_table kdump_on_init_table[] = {
203 {
204 .ctl_name = CTL_UNNUMBERED,
205 .procname = "kdump_on_init",
206 .data = &kdump_on_init,
207 .maxlen = sizeof(int),
208 .mode = 0644,
209 .proc_handler = &proc_dointvec,
210 },
211 { .ctl_name = 0 }
212};
213
214static ctl_table sys_table[] = {
215 {
216 .ctl_name = CTL_KERN,
217 .procname = "kernel",
218 .mode = 0555,
219 .child = kdump_on_init_table,
220 },
221 { .ctl_name = 0 }
222};
223#endif
224
225static int
226machine_crash_setup(void)
227{
228 char *from = strstr(saved_command_line, "elfcorehdr=");
229 static struct notifier_block kdump_init_notifier_nb = {
230 .notifier_call = kdump_init_notifier,
231 };
232 int ret;
233 if (from)
234 elfcorehdr_addr = memparse(from+11, &from);
235 saved_max_pfn = (unsigned long)-1;
236 if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
237 return ret;
238#ifdef CONFIG_SYSCTL
239 register_sysctl_table(sys_table, 0);
240#endif
241 return 0;
242}
243
244__initcall(machine_crash_setup);
245
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index bb8770a177b5..0b25a7d4e1e4 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -26,6 +26,7 @@
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/time.h> 27#include <linux/time.h>
28#include <linux/efi.h> 28#include <linux/efi.h>
29#include <linux/kexec.h>
29 30
30#include <asm/io.h> 31#include <asm/io.h>
31#include <asm/kregs.h> 32#include <asm/kregs.h>
@@ -41,7 +42,7 @@ extern efi_status_t efi_call_phys (void *, ...);
41struct efi efi; 42struct efi efi;
42EXPORT_SYMBOL(efi); 43EXPORT_SYMBOL(efi);
43static efi_runtime_services_t *runtime; 44static efi_runtime_services_t *runtime;
44static unsigned long mem_limit = ~0UL, max_addr = ~0UL; 45static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
45 46
46#define efi_call_virt(f, args...) (*(f))(args) 47#define efi_call_virt(f, args...) (*(f))(args)
47 48
@@ -224,7 +225,7 @@ efi_gettimeofday (struct timespec *ts)
224} 225}
225 226
226static int 227static int
227is_available_memory (efi_memory_desc_t *md) 228is_memory_available (efi_memory_desc_t *md)
228{ 229{
229 if (!(md->attribute & EFI_MEMORY_WB)) 230 if (!(md->attribute & EFI_MEMORY_WB))
230 return 0; 231 return 0;
@@ -421,6 +422,8 @@ efi_init (void)
421 mem_limit = memparse(cp + 4, &cp); 422 mem_limit = memparse(cp + 4, &cp);
422 } else if (memcmp(cp, "max_addr=", 9) == 0) { 423 } else if (memcmp(cp, "max_addr=", 9) == 0) {
423 max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); 424 max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
425 } else if (memcmp(cp, "min_addr=", 9) == 0) {
426 min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp));
424 } else { 427 } else {
425 while (*cp != ' ' && *cp) 428 while (*cp != ' ' && *cp)
426 ++cp; 429 ++cp;
@@ -428,6 +431,8 @@ efi_init (void)
428 ++cp; 431 ++cp;
429 } 432 }
430 } 433 }
434 if (min_addr != 0UL)
435 printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20);
431 if (max_addr != ~0UL) 436 if (max_addr != ~0UL)
432 printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); 437 printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20);
433 438
@@ -887,14 +892,15 @@ find_memmap_space (void)
887 } 892 }
888 contig_high = GRANULEROUNDDOWN(contig_high); 893 contig_high = GRANULEROUNDDOWN(contig_high);
889 } 894 }
890 if (!is_available_memory(md) || md->type == EFI_LOADER_DATA) 895 if (!is_memory_available(md) || md->type == EFI_LOADER_DATA)
891 continue; 896 continue;
892 897
893 /* Round ends inward to granule boundaries */ 898 /* Round ends inward to granule boundaries */
894 as = max(contig_low, md->phys_addr); 899 as = max(contig_low, md->phys_addr);
895 ae = min(contig_high, efi_md_end(md)); 900 ae = min(contig_high, efi_md_end(md));
896 901
897 /* keep within max_addr= command line arg */ 902 /* keep within max_addr= and min_addr= command line arg */
903 as = max(as, min_addr);
898 ae = min(ae, max_addr); 904 ae = min(ae, max_addr);
899 if (ae <= as) 905 if (ae <= as)
900 continue; 906 continue;
@@ -962,7 +968,7 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
962 } 968 }
963 contig_high = GRANULEROUNDDOWN(contig_high); 969 contig_high = GRANULEROUNDDOWN(contig_high);
964 } 970 }
965 if (!is_available_memory(md)) 971 if (!is_memory_available(md))
966 continue; 972 continue;
967 973
968 /* 974 /*
@@ -1004,7 +1010,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
1004 } else 1010 } else
1005 ae = efi_md_end(md); 1011 ae = efi_md_end(md);
1006 1012
1007 /* keep within max_addr= command line arg */ 1013 /* keep within max_addr= and min_addr= command line arg */
1014 as = max(as, min_addr);
1008 ae = min(ae, max_addr); 1015 ae = min(ae, max_addr);
1009 if (ae <= as) 1016 if (ae <= as)
1010 continue; 1017 continue;
@@ -1116,6 +1123,58 @@ efi_initialize_iomem_resources(struct resource *code_resource,
1116 */ 1123 */
1117 insert_resource(res, code_resource); 1124 insert_resource(res, code_resource);
1118 insert_resource(res, data_resource); 1125 insert_resource(res, data_resource);
1126#ifdef CONFIG_KEXEC
1127 insert_resource(res, &efi_memmap_res);
1128 insert_resource(res, &boot_param_res);
1129 if (crashk_res.end > crashk_res.start)
1130 insert_resource(res, &crashk_res);
1131#endif
1119 } 1132 }
1120 } 1133 }
1121} 1134}
1135
1136#ifdef CONFIG_KEXEC
1137/* find a block of memory aligned to 64M exclude reserved regions
1138 rsvd_regions are sorted
1139 */
1140unsigned long
1141kdump_find_rsvd_region (unsigned long size,
1142 struct rsvd_region *r, int n)
1143{
1144 int i;
1145 u64 start, end;
1146 u64 alignment = 1UL << _PAGE_SIZE_64M;
1147 void *efi_map_start, *efi_map_end, *p;
1148 efi_memory_desc_t *md;
1149 u64 efi_desc_size;
1150
1151 efi_map_start = __va(ia64_boot_param->efi_memmap);
1152 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
1153 efi_desc_size = ia64_boot_param->efi_memdesc_size;
1154
1155 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
1156 md = p;
1157 if (!efi_wb(md))
1158 continue;
1159 start = ALIGN(md->phys_addr, alignment);
1160 end = efi_md_end(md);
1161 for (i = 0; i < n; i++) {
1162 if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
1163 if (__pa(r[i].start) > start + size)
1164 return start;
1165 start = ALIGN(__pa(r[i].end), alignment);
1166 if (i < n-1 && __pa(r[i+1].start) < start + size)
1167 continue;
1168 else
1169 break;
1170 }
1171 }
1172 if (end > start + size)
1173 return start;
1174 }
1175
1176 printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n",
1177 size);
1178 return ~0UL;
1179}
1180#endif
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 3390b7c5a63f..15234ed3a341 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1575,7 +1575,7 @@ sys_call_table:
1575 data8 sys_mq_timedreceive // 1265 1575 data8 sys_mq_timedreceive // 1265
1576 data8 sys_mq_notify 1576 data8 sys_mq_notify
1577 data8 sys_mq_getsetattr 1577 data8 sys_mq_getsetattr
1578 data8 sys_ni_syscall // reserved for kexec_load 1578 data8 sys_kexec_load
1579 data8 sys_ni_syscall // reserved for vserver 1579 data8 sys_ni_syscall // reserved for vserver
1580 data8 sys_waitid // 1270 1580 data8 sys_waitid // 1270
1581 data8 sys_add_key 1581 data8 sys_add_key
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index 879c1817bd1c..bd17190bebb6 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -14,6 +14,7 @@ EXPORT_SYMBOL(strlen);
14 14
15#include <asm/checksum.h> 15#include <asm/checksum.h>
16EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */ 16EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */
17EXPORT_SYMBOL(csum_ipv6_magic);
17 18
18#include <asm/semaphore.h> 19#include <asm/semaphore.h>
19EXPORT_SYMBOL(__down); 20EXPORT_SYMBOL(__down);
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 60d64950e3c2..0fc5fb7865cf 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -288,6 +288,27 @@ nop (unsigned int irq)
288 /* do nothing... */ 288 /* do nothing... */
289} 289}
290 290
291
292#ifdef CONFIG_KEXEC
293void
294kexec_disable_iosapic(void)
295{
296 struct iosapic_intr_info *info;
297 struct iosapic_rte_info *rte;
298 u8 vec = 0;
299 for (info = iosapic_intr_info; info <
300 iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) {
301 list_for_each_entry(rte, &info->rtes,
302 rte_list) {
303 iosapic_write(rte->addr,
304 IOSAPIC_RTE_LOW(rte->rte_index),
305 IOSAPIC_MASK|vec);
306 iosapic_eoi(rte->addr, vec);
307 }
308 }
309}
310#endif
311
291static void 312static void
292mask_irq (unsigned int irq) 313mask_irq (unsigned int irq)
293{ 314{
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 4d592ee9300b..76e778951e20 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -851,7 +851,7 @@ static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
851 return; 851 return;
852 } 852 }
853 } while (unw_unwind(info) >= 0); 853 } while (unw_unwind(info) >= 0);
854 lp->bsp = 0; 854 lp->bsp = NULL;
855 lp->cfm = 0; 855 lp->cfm = 0;
856 return; 856 return;
857} 857}
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
new file mode 100644
index 000000000000..468233fa2cee
--- /dev/null
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -0,0 +1,133 @@
1/*
2 * arch/ia64/kernel/machine_kexec.c
3 *
4 * Handle transition of Linux booting another kernel
5 * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.
6 * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
7 * Copyright (C) 2006 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
8 *
9 * This source code is licensed under the GNU General Public License,
10 * Version 2. See the file COPYING for more details.
11 */
12
13#include <linux/mm.h>
14#include <linux/kexec.h>
15#include <linux/cpu.h>
16#include <linux/irq.h>
17#include <asm/mmu_context.h>
18#include <asm/setup.h>
19#include <asm/delay.h>
20#include <asm/meminit.h>
21
22typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long,
23 struct ia64_boot_param *, unsigned long);
24
25struct kimage *ia64_kimage;
26
27struct resource efi_memmap_res = {
28 .name = "EFI Memory Map",
29 .start = 0,
30 .end = 0,
31 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
32};
33
34struct resource boot_param_res = {
35 .name = "Boot parameter",
36 .start = 0,
37 .end = 0,
38 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
39};
40
41
42/*
43 * Do what every setup is needed on image and the
44 * reboot code buffer to allow us to avoid allocations
45 * later.
46 */
47int machine_kexec_prepare(struct kimage *image)
48{
49 void *control_code_buffer;
50 const unsigned long *func;
51
52 func = (unsigned long *)&relocate_new_kernel;
53 /* Pre-load control code buffer to minimize work in kexec path */
54 control_code_buffer = page_address(image->control_code_page);
55 memcpy((void *)control_code_buffer, (const void *)func[0],
56 relocate_new_kernel_size);
57 flush_icache_range((unsigned long)control_code_buffer,
58 (unsigned long)control_code_buffer + relocate_new_kernel_size);
59 ia64_kimage = image;
60
61 return 0;
62}
63
64void machine_kexec_cleanup(struct kimage *image)
65{
66}
67
68void machine_shutdown(void)
69{
70 int cpu;
71
72 for_each_online_cpu(cpu) {
73 if (cpu != smp_processor_id())
74 cpu_down(cpu);
75 }
76 kexec_disable_iosapic();
77}
78
79/*
80 * Do not allocate memory (or fail in any way) in machine_kexec().
81 * We are past the point of no return, committed to rebooting now.
82 */
83extern void *efi_get_pal_addr(void);
84static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
85{
86 struct kimage *image = arg;
87 relocate_new_kernel_t rnk;
88 void *pal_addr = efi_get_pal_addr();
89 unsigned long code_addr = (unsigned long)page_address(image->control_code_page);
90 unsigned long vector;
91 int ii;
92
93 if (image->type == KEXEC_TYPE_CRASH) {
94 crash_save_this_cpu();
95 current->thread.ksp = (__u64)info->sw - 16;
96 }
97
98 /* Interrupts aren't acceptable while we reboot */
99 local_irq_disable();
100
101 /* Mask CMC and Performance Monitor interrupts */
102 ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
103 ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
104
105 /* Mask ITV and Local Redirect Registers */
106 ia64_set_itv(1 << 16);
107 ia64_set_lrr0(1 << 16);
108 ia64_set_lrr1(1 << 16);
109
110 /* terminate possible nested in-service interrupts */
111 for (ii = 0; ii < 16; ii++)
112 ia64_eoi();
113
114 /* unmask TPR and clear any pending interrupts */
115 ia64_setreg(_IA64_REG_CR_TPR, 0);
116 ia64_srlz_d();
117 vector = ia64_get_ivr();
118 while (vector != IA64_SPURIOUS_INT_VECTOR) {
119 ia64_eoi();
120 vector = ia64_get_ivr();
121 }
122 platform_kernel_launch_event();
123 rnk = (relocate_new_kernel_t)&code_addr;
124 (*rnk)(image->head, image->start, ia64_boot_param,
125 GRANULEROUNDDOWN((unsigned long) pal_addr));
126 BUG();
127}
128
129void machine_kexec(struct kimage *image)
130{
131 unw_init_running(ia64_machine_kexec, image);
132 for(;;);
133}
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 6bedd97570ca..87c1c4f42872 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -82,6 +82,7 @@
82#include <asm/system.h> 82#include <asm/system.h>
83#include <asm/sal.h> 83#include <asm/sal.h>
84#include <asm/mca.h> 84#include <asm/mca.h>
85#include <asm/kexec.h>
85 86
86#include <asm/irq.h> 87#include <asm/irq.h>
87#include <asm/hw_irq.h> 88#include <asm/hw_irq.h>
@@ -1238,6 +1239,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
1238 } else { 1239 } else {
1239 /* Dump buffered message to console */ 1240 /* Dump buffered message to console */
1240 ia64_mlogbuf_finish(1); 1241 ia64_mlogbuf_finish(1);
1242#ifdef CONFIG_CRASH_DUMP
1243 atomic_set(&kdump_in_progress, 1);
1244 monarch_cpu = -1;
1245#endif
1241 } 1246 }
1242 if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover) 1247 if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
1243 == NOTIFY_STOP) 1248 == NOTIFY_STOP)
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index c4c10a0b99d9..a71df9ae0397 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -16,6 +16,7 @@
16 * 02/05/2001 S.Eranian fixed module support 16 * 02/05/2001 S.Eranian fixed module support
17 * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes 17 * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes
18 * 03/24/2004 Ashok Raj updated to work with CPU Hotplug 18 * 03/24/2004 Ashok Raj updated to work with CPU Hotplug
19 * 10/26/2006 Russ Anderson updated processor features to rev 2.2 spec
19 */ 20 */
20#include <linux/types.h> 21#include <linux/types.h>
21#include <linux/errno.h> 22#include <linux/errno.h>
@@ -314,13 +315,20 @@ vm_info(char *page)
314 "Protection Key Registers(PKR) : %d\n" 315 "Protection Key Registers(PKR) : %d\n"
315 "Implemented bits in PKR.key : %d\n" 316 "Implemented bits in PKR.key : %d\n"
316 "Hash Tag ID : 0x%x\n" 317 "Hash Tag ID : 0x%x\n"
317 "Size of RR.rid : %d\n", 318 "Size of RR.rid : %d\n"
319 "Max Purges : ",
318 vm_info_1.pal_vm_info_1_s.phys_add_size, 320 vm_info_1.pal_vm_info_1_s.phys_add_size,
319 vm_info_2.pal_vm_info_2_s.impl_va_msb+1, 321 vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
320 vm_info_1.pal_vm_info_1_s.max_pkr+1, 322 vm_info_1.pal_vm_info_1_s.max_pkr+1,
321 vm_info_1.pal_vm_info_1_s.key_size, 323 vm_info_1.pal_vm_info_1_s.key_size,
322 vm_info_1.pal_vm_info_1_s.hash_tag_id, 324 vm_info_1.pal_vm_info_1_s.hash_tag_id,
323 vm_info_2.pal_vm_info_2_s.rid_size); 325 vm_info_2.pal_vm_info_2_s.rid_size);
326 if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES)
327 p += sprintf(p, "unlimited\n");
328 else
329 p += sprintf(p, "%d\n",
330 vm_info_2.pal_vm_info_2_s.max_purges ?
331 vm_info_2.pal_vm_info_2_s.max_purges : 1);
324 } 332 }
325 333
326 if (ia64_pal_mem_attrib(&attrib) == 0) { 334 if (ia64_pal_mem_attrib(&attrib) == 0) {
@@ -467,7 +475,11 @@ static const char *proc_features[]={
467 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL, 475 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
468 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 476 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
469 NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL, 477 NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,
470 NULL,NULL,NULL,NULL,NULL, 478 "Unimplemented instruction address fault",
479 "INIT, PMI, and LINT pins",
480 "Simple unimplemented instr addresses",
481 "Variable P-state performance",
482 "Virtual machine features implemented",
471 "XIP,XPSR,XFS implemented", 483 "XIP,XPSR,XFS implemented",
472 "XR1-XR3 implemented", 484 "XR1-XR3 implemented",
473 "Disable dynamic predicate prediction", 485 "Disable dynamic predicate prediction",
@@ -475,7 +487,11 @@ static const char *proc_features[]={
475 "Disable dynamic data cache prefetch", 487 "Disable dynamic data cache prefetch",
476 "Disable dynamic inst cache prefetch", 488 "Disable dynamic inst cache prefetch",
477 "Disable dynamic branch prediction", 489 "Disable dynamic branch prediction",
478 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 490 NULL, NULL, NULL, NULL,
491 "Disable P-states",
492 "Enable MCA on Data Poisoning",
493 "Enable vmsw instruction",
494 "Enable extern environmental notification",
479 "Disable BINIT on processor time-out", 495 "Disable BINIT on processor time-out",
480 "Disable dynamic power management (DPM)", 496 "Disable dynamic power management (DPM)",
481 "Disable coherency", 497 "Disable coherency",
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index e2321536ee4c..dbb28164b19b 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -853,9 +853,8 @@ pfm_context_alloc(void)
853 * allocate context descriptor 853 * allocate context descriptor
854 * must be able to free with interrupts disabled 854 * must be able to free with interrupts disabled
855 */ 855 */
856 ctx = kmalloc(sizeof(pfm_context_t), GFP_KERNEL); 856 ctx = kzalloc(sizeof(pfm_context_t), GFP_KERNEL);
857 if (ctx) { 857 if (ctx) {
858 memset(ctx, 0, sizeof(pfm_context_t));
859 DPRINT(("alloc ctx @%p\n", ctx)); 858 DPRINT(("alloc ctx @%p\n", ctx));
860 } 859 }
861 return ctx; 860 return ctx;
diff --git a/arch/ia64/kernel/perfmon_montecito.h b/arch/ia64/kernel/perfmon_montecito.h
index cd06ac6a686c..7f8da4c7ca67 100644
--- a/arch/ia64/kernel/perfmon_montecito.h
+++ b/arch/ia64/kernel/perfmon_montecito.h
@@ -45,16 +45,16 @@ static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={
45/* pmc29 */ { PFM_REG_NOTIMPL, }, 45/* pmc29 */ { PFM_REG_NOTIMPL, },
46/* pmc30 */ { PFM_REG_NOTIMPL, }, 46/* pmc30 */ { PFM_REG_NOTIMPL, },
47/* pmc31 */ { PFM_REG_NOTIMPL, }, 47/* pmc31 */ { PFM_REG_NOTIMPL, },
48/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 48/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffffUL, 0x30f01ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
49/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 49/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
50/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 50/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffffUL, 0xf01ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
51/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 51/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
52/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 52/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
53/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}}, 53/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}},
54/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 54/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
55/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, 55/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
56/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}}, 56/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}},
57/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, 57/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefeUL, 0x1e00018181818UL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
58/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, 58/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
59 { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ 59 { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */
60}; 60};
@@ -185,7 +185,7 @@ pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cn
185 DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded)); 185 DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded));
186 186
187 if (cnum == 41 && is_loaded 187 if (cnum == 41 && is_loaded
188 && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) { 188 && (tmpval & 0x1e00000000000UL) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) {
189 189
190 DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval)); 190 DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval));
191 191
diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..ae473e3f2a0d
--- /dev/null
+++ b/arch/ia64/kernel/relocate_kernel.S
@@ -0,0 +1,334 @@
1/*
2 * arch/ia64/kernel/relocate_kernel.S
3 *
4 * Relocate kexec'able kernel and start it
5 *
6 * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
7 * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
8 * Copyright (C) 2005 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
9 *
10 * This source code is licensed under the GNU General Public License,
11 * Version 2. See the file COPYING for more details.
12 */
13#include <asm/asmmacro.h>
14#include <asm/kregs.h>
15#include <asm/page.h>
16#include <asm/pgtable.h>
17#include <asm/mca_asm.h>
18
19 /* Must be relocatable PIC code callable as a C function
20 */
21GLOBAL_ENTRY(relocate_new_kernel)
22 .prologue
23 alloc r31=ar.pfs,4,0,0,0
24 .body
25.reloc_entry:
26{
27 rsm psr.i| psr.ic
28 mov r2=ip
29}
30 ;;
31{
32 flushrs // must be first insn in group
33 srlz.i
34}
35 ;;
36 dep r2=0,r2,61,3 //to physical address
37 ;;
38 //first switch to physical mode
39 add r3=1f-.reloc_entry, r2
40 movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC
41 mov ar.rsc=0 // put RSE in enforced lazy mode
42 ;;
43 add sp=(memory_stack_end - 16 - .reloc_entry),r2
44 add r8=(register_stack - .reloc_entry),r2
45 ;;
46 mov r18=ar.rnat
47 mov ar.bspstore=r8
48 ;;
49 mov cr.ipsr=r16
50 mov cr.iip=r3
51 mov cr.ifs=r0
52 srlz.i
53 ;;
54 mov ar.rnat=r18
55 rfi
56 ;;
571:
58 //physical mode code begin
59 mov b6=in1
60 dep r28=0,in2,61,3 //to physical address
61
62 // purge all TC entries
63#define O(member) IA64_CPUINFO_##member##_OFFSET
64 GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2
65 ;;
66 addl r17=O(PTCE_STRIDE),r2
67 addl r2=O(PTCE_BASE),r2
68 ;;
69 ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base
70 ld4 r19=[r2],4 // r19=ptce_count[0]
71 ld4 r21=[r17],4 // r21=ptce_stride[0]
72 ;;
73 ld4 r20=[r2] // r20=ptce_count[1]
74 ld4 r22=[r17] // r22=ptce_stride[1]
75 mov r24=r0
76 ;;
77 adds r20=-1,r20
78 ;;
79#undef O
802:
81 cmp.ltu p6,p7=r24,r19
82(p7) br.cond.dpnt.few 4f
83 mov ar.lc=r20
843:
85 ptc.e r18
86 ;;
87 add r18=r22,r18
88 br.cloop.sptk.few 3b
89 ;;
90 add r18=r21,r18
91 add r24=1,r24
92 ;;
93 br.sptk.few 2b
944:
95 srlz.i
96 ;;
97 //purge TR entry for kernel text and data
98 movl r16=KERNEL_START
99 mov r18=KERNEL_TR_PAGE_SHIFT<<2
100 ;;
101 ptr.i r16, r18
102 ptr.d r16, r18
103 ;;
104 srlz.i
105 ;;
106
107 // purge TR entry for percpu data
108 movl r16=PERCPU_ADDR
109 mov r18=PERCPU_PAGE_SHIFT<<2
110 ;;
111 ptr.d r16,r18
112 ;;
113 srlz.d
114 ;;
115
116 // purge TR entry for pal code
117 mov r16=in3
118 mov r18=IA64_GRANULE_SHIFT<<2
119 ;;
120 ptr.i r16,r18
121 ;;
122 srlz.i
123 ;;
124
125 // purge TR entry for stack
126 mov r16=IA64_KR(CURRENT_STACK)
127 ;;
128 shl r16=r16,IA64_GRANULE_SHIFT
129 movl r19=PAGE_OFFSET
130 ;;
131 add r16=r19,r16
132 mov r18=IA64_GRANULE_SHIFT<<2
133 ;;
134 ptr.d r16,r18
135 ;;
136 srlz.i
137 ;;
138
139 //copy segments
140 movl r16=PAGE_MASK
141 mov r30=in0 // in0 is page_list
142 br.sptk.few .dest_page
143 ;;
144.loop:
145 ld8 r30=[in0], 8;;
146.dest_page:
147 tbit.z p0, p6=r30, 0;; // 0x1 dest page
148(p6) and r17=r30, r16
149(p6) br.cond.sptk.few .loop;;
150
151 tbit.z p0, p6=r30, 1;; // 0x2 indirect page
152(p6) and in0=r30, r16
153(p6) br.cond.sptk.few .loop;;
154
155 tbit.z p0, p6=r30, 2;; // 0x4 end flag
156(p6) br.cond.sptk.few .end_loop;;
157
158 tbit.z p6, p0=r30, 3;; // 0x8 source page
159(p6) br.cond.sptk.few .loop
160
161 and r18=r30, r16
162
163 // simple copy page, may optimize later
164 movl r14=PAGE_SIZE/8 - 1;;
165 mov ar.lc=r14;;
1661:
167 ld8 r14=[r18], 8;;
168 st8 [r17]=r14;;
169 fc.i r17
170 add r17=8, r17
171 br.ctop.sptk.few 1b
172 br.sptk.few .loop
173 ;;
174
175.end_loop:
176 sync.i // for fc.i
177 ;;
178 srlz.i
179 ;;
180 srlz.d
181 ;;
182 br.call.sptk.many b0=b6;;
183
184.align 32
185memory_stack:
186 .fill 8192, 1, 0
187memory_stack_end:
188register_stack:
189 .fill 8192, 1, 0
190register_stack_end:
191relocate_new_kernel_end:
192END(relocate_new_kernel)
193
194.global relocate_new_kernel_size
195relocate_new_kernel_size:
196 data8 relocate_new_kernel_end - relocate_new_kernel
197
198GLOBAL_ENTRY(ia64_dump_cpu_regs)
199 .prologue
200 alloc loc0=ar.pfs,1,2,0,0
201 .body
202 mov ar.rsc=0 // put RSE in enforced lazy mode
203 add loc1=4*8, in0 // save r4 and r5 first
204 ;;
205{
206 flushrs // flush dirty regs to backing store
207 srlz.i
208}
209 st8 [loc1]=r4, 8
210 ;;
211 st8 [loc1]=r5, 8
212 ;;
213 add loc1=32*8, in0
214 mov r4=ar.rnat
215 ;;
216 st8 [in0]=r0, 8 // r0
217 st8 [loc1]=r4, 8 // rnat
218 mov r5=pr
219 ;;
220 st8 [in0]=r1, 8 // r1
221 st8 [loc1]=r5, 8 // pr
222 mov r4=b0
223 ;;
224 st8 [in0]=r2, 8 // r2
225 st8 [loc1]=r4, 8 // b0
226 mov r5=b1;
227 ;;
228 st8 [in0]=r3, 24 // r3
229 st8 [loc1]=r5, 8 // b1
230 mov r4=b2
231 ;;
232 st8 [in0]=r6, 8 // r6
233 st8 [loc1]=r4, 8 // b2
234 mov r5=b3
235 ;;
236 st8 [in0]=r7, 8 // r7
237 st8 [loc1]=r5, 8 // b3
238 mov r4=b4
239 ;;
240 st8 [in0]=r8, 8 // r8
241 st8 [loc1]=r4, 8 // b4
242 mov r5=b5
243 ;;
244 st8 [in0]=r9, 8 // r9
245 st8 [loc1]=r5, 8 // b5
246 mov r4=b6
247 ;;
248 st8 [in0]=r10, 8 // r10
249 st8 [loc1]=r5, 8 // b6
250 mov r5=b7
251 ;;
252 st8 [in0]=r11, 8 // r11
253 st8 [loc1]=r5, 8 // b7
254 mov r4=b0
255 ;;
256 st8 [in0]=r12, 8 // r12
257 st8 [loc1]=r4, 8 // ip
258 mov r5=loc0
259 ;;
260 st8 [in0]=r13, 8 // r13
261 extr.u r5=r5, 0, 38 // ar.pfs.pfm
262 mov r4=r0 // user mask
263 ;;
264 st8 [in0]=r14, 8 // r14
265 st8 [loc1]=r5, 8 // cfm
266 ;;
267 st8 [in0]=r15, 8 // r15
268 st8 [loc1]=r4, 8 // user mask
269 mov r5=ar.rsc
270 ;;
271 st8 [in0]=r16, 8 // r16
272 st8 [loc1]=r5, 8 // ar.rsc
273 mov r4=ar.bsp
274 ;;
275 st8 [in0]=r17, 8 // r17
276 st8 [loc1]=r4, 8 // ar.bsp
277 mov r5=ar.bspstore
278 ;;
279 st8 [in0]=r18, 8 // r18
280 st8 [loc1]=r5, 8 // ar.bspstore
281 mov r4=ar.rnat
282 ;;
283 st8 [in0]=r19, 8 // r19
284 st8 [loc1]=r4, 8 // ar.rnat
285 mov r5=ar.ccv
286 ;;
287 st8 [in0]=r20, 8 // r20
288 st8 [loc1]=r5, 8 // ar.ccv
289 mov r4=ar.unat
290 ;;
291 st8 [in0]=r21, 8 // r21
292 st8 [loc1]=r4, 8 // ar.unat
293 mov r5 = ar.fpsr
294 ;;
295 st8 [in0]=r22, 8 // r22
296 st8 [loc1]=r5, 8 // ar.fpsr
297 mov r4 = ar.unat
298 ;;
299 st8 [in0]=r23, 8 // r23
300 st8 [loc1]=r4, 8 // unat
301 mov r5 = ar.fpsr
302 ;;
303 st8 [in0]=r24, 8 // r24
304 st8 [loc1]=r5, 8 // fpsr
305 mov r4 = ar.pfs
306 ;;
307 st8 [in0]=r25, 8 // r25
308 st8 [loc1]=r4, 8 // ar.pfs
309 mov r5 = ar.lc
310 ;;
311 st8 [in0]=r26, 8 // r26
312 st8 [loc1]=r5, 8 // ar.lc
313 mov r4 = ar.ec
314 ;;
315 st8 [in0]=r27, 8 // r27
316 st8 [loc1]=r4, 8 // ar.ec
317 mov r5 = ar.csd
318 ;;
319 st8 [in0]=r28, 8 // r28
320 st8 [loc1]=r5, 8 // ar.csd
321 mov r4 = ar.ssd
322 ;;
323 st8 [in0]=r29, 8 // r29
324 st8 [loc1]=r4, 8 // ar.ssd
325 ;;
326 st8 [in0]=r30, 8 // r30
327 ;;
328 st8 [in0]=r31, 8 // r31
329 mov ar.pfs=loc0
330 ;;
331 br.ret.sptk.many rp
332END(ia64_dump_cpu_regs)
333
334
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index d10404a41756..14e1200376a9 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -43,6 +43,8 @@
43#include <linux/initrd.h> 43#include <linux/initrd.h>
44#include <linux/pm.h> 44#include <linux/pm.h>
45#include <linux/cpufreq.h> 45#include <linux/cpufreq.h>
46#include <linux/kexec.h>
47#include <linux/crash_dump.h>
46 48
47#include <asm/ia32.h> 49#include <asm/ia32.h>
48#include <asm/machvec.h> 50#include <asm/machvec.h>
@@ -252,6 +254,41 @@ reserve_memory (void)
252 efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end); 254 efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
253 n++; 255 n++;
254 256
257#ifdef CONFIG_KEXEC
258 /* crashkernel=size@offset specifies the size to reserve for a crash
259 * kernel.(offset is ingored for keep compatibility with other archs)
260 * By reserving this memory we guarantee that linux never set's it
261 * up as a DMA target.Useful for holding code to do something
262 * appropriate after a kernel panic.
263 */
264 {
265 char *from = strstr(saved_command_line, "crashkernel=");
266 unsigned long base, size;
267 if (from) {
268 size = memparse(from + 12, &from);
269 if (size) {
270 sort_regions(rsvd_region, n);
271 base = kdump_find_rsvd_region(size,
272 rsvd_region, n);
273 if (base != ~0UL) {
274 rsvd_region[n].start =
275 (unsigned long)__va(base);
276 rsvd_region[n].end =
277 (unsigned long)__va(base + size);
278 n++;
279 crashk_res.start = base;
280 crashk_res.end = base + size - 1;
281 }
282 }
283 }
284 efi_memmap_res.start = ia64_boot_param->efi_memmap;
285 efi_memmap_res.end = efi_memmap_res.start +
286 ia64_boot_param->efi_memmap_size;
287 boot_param_res.start = __pa(ia64_boot_param);
288 boot_param_res.end = boot_param_res.start +
289 sizeof(*ia64_boot_param);
290 }
291#endif
255 /* end of memory marker */ 292 /* end of memory marker */
256 rsvd_region[n].start = ~0UL; 293 rsvd_region[n].start = ~0UL;
257 rsvd_region[n].end = ~0UL; 294 rsvd_region[n].end = ~0UL;
@@ -263,6 +300,7 @@ reserve_memory (void)
263 sort_regions(rsvd_region, num_rsvd_regions); 300 sort_regions(rsvd_region, num_rsvd_regions);
264} 301}
265 302
303
266/** 304/**
267 * find_initrd - get initrd parameters from the boot parameter structure 305 * find_initrd - get initrd parameters from the boot parameter structure
268 * 306 *
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 6ab95ceaf9d4..b1b9aa4364b9 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -30,6 +30,7 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/efi.h> 31#include <linux/efi.h>
32#include <linux/bitops.h> 32#include <linux/bitops.h>
33#include <linux/kexec.h>
33 34
34#include <asm/atomic.h> 35#include <asm/atomic.h>
35#include <asm/current.h> 36#include <asm/current.h>
@@ -66,6 +67,7 @@ static volatile struct call_data_struct *call_data;
66 67
67#define IPI_CALL_FUNC 0 68#define IPI_CALL_FUNC 0
68#define IPI_CPU_STOP 1 69#define IPI_CPU_STOP 1
70#define IPI_KDUMP_CPU_STOP 3
69 71
70/* This needs to be cacheline aligned because it is written to by *other* CPUs. */ 72/* This needs to be cacheline aligned because it is written to by *other* CPUs. */
71static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; 73static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
@@ -155,7 +157,11 @@ handle_IPI (int irq, void *dev_id)
155 case IPI_CPU_STOP: 157 case IPI_CPU_STOP:
156 stop_this_cpu(); 158 stop_this_cpu();
157 break; 159 break;
158 160#ifdef CONFIG_CRASH_DUMP
161 case IPI_KDUMP_CPU_STOP:
162 unw_init_running(kdump_cpu_freeze, NULL);
163 break;
164#endif
159 default: 165 default:
160 printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); 166 printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
161 break; 167 break;
@@ -213,6 +219,26 @@ send_IPI_self (int op)
213 send_IPI_single(smp_processor_id(), op); 219 send_IPI_single(smp_processor_id(), op);
214} 220}
215 221
222#ifdef CONFIG_CRASH_DUMP
223void
224kdump_smp_send_stop()
225{
226 send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
227}
228
229void
230kdump_smp_send_init()
231{
232 unsigned int cpu, self_cpu;
233 self_cpu = smp_processor_id();
234 for_each_online_cpu(cpu) {
235 if (cpu != self_cpu) {
236 if(kdump_status[cpu] == 0)
237 platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
238 }
239 }
240}
241#endif
216/* 242/*
217 * Called with preeemption disabled. 243 * Called with preeemption disabled.
218 */ 244 */
diff --git a/arch/ia64/lib/ip_fast_csum.S b/arch/ia64/lib/ip_fast_csum.S
index 19674ca2acfc..1f86aeb2c948 100644
--- a/arch/ia64/lib/ip_fast_csum.S
+++ b/arch/ia64/lib/ip_fast_csum.S
@@ -8,8 +8,8 @@
8 * in0: address of buffer to checksum (char *) 8 * in0: address of buffer to checksum (char *)
9 * in1: length of the buffer (int) 9 * in1: length of the buffer (int)
10 * 10 *
11 * Copyright (C) 2002 Intel Corp. 11 * Copyright (C) 2002, 2006 Intel Corp.
12 * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com> 12 * Copyright (C) 2002, 2006 Ken Chen <kenneth.w.chen@intel.com>
13 */ 13 */
14 14
15#include <asm/asmmacro.h> 15#include <asm/asmmacro.h>
@@ -25,6 +25,9 @@
25 25
26#define in0 r32 26#define in0 r32
27#define in1 r33 27#define in1 r33
28#define in2 r34
29#define in3 r35
30#define in4 r36
28#define ret0 r8 31#define ret0 r8
29 32
30GLOBAL_ENTRY(ip_fast_csum) 33GLOBAL_ENTRY(ip_fast_csum)
@@ -65,8 +68,9 @@ GLOBAL_ENTRY(ip_fast_csum)
65 zxt2 r20=r20 68 zxt2 r20=r20
66 ;; 69 ;;
67 add r20=ret0,r20 70 add r20=ret0,r20
71 mov r9=0xffff
68 ;; 72 ;;
69 andcm ret0=-1,r20 73 andcm ret0=r9,r20
70 .restore sp // reset frame state 74 .restore sp // reset frame state
71 br.ret.sptk.many b0 75 br.ret.sptk.many b0
72 ;; 76 ;;
@@ -88,3 +92,51 @@ GLOBAL_ENTRY(ip_fast_csum)
88 mov b0=r34 92 mov b0=r34
89 br.ret.sptk.many b0 93 br.ret.sptk.many b0
90END(ip_fast_csum) 94END(ip_fast_csum)
95
96GLOBAL_ENTRY(csum_ipv6_magic)
97 ld4 r20=[in0],4
98 ld4 r21=[in1],4
99 dep r15=in3,in2,32,16
100 ;;
101 ld4 r22=[in0],4
102 ld4 r23=[in1],4
103 mux1 r15=r15,@rev
104 ;;
105 ld4 r24=[in0],4
106 ld4 r25=[in1],4
107 shr.u r15=r15,16
108 add r16=r20,r21
109 add r17=r22,r23
110 ;;
111 ld4 r26=[in0],4
112 ld4 r27=[in1],4
113 add r18=r24,r25
114 add r8=r16,r17
115 ;;
116 add r19=r26,r27
117 add r8=r8,r18
118 ;;
119 add r8=r8,r19
120 add r15=r15,in4
121 ;;
122 add r8=r8,r15
123 ;;
124 shr.u r10=r8,32 // now fold sum into short
125 zxt4 r11=r8
126 ;;
127 add r8=r10,r11
128 ;;
129 shr.u r10=r8,16 // yeah, keep it rolling
130 zxt2 r11=r8
131 ;;
132 add r8=r10,r11
133 ;;
134 shr.u r10=r8,16 // three times lucky
135 zxt2 r11=r8
136 ;;
137 add r8=r10,r11
138 mov r9=0xffff
139 ;;
140 andcm r8=r9,r8
141 br.ret.sptk.many b0
142END(csum_ipv6_magic)
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index eb92cef9cd0d..474d179966dc 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -125,11 +125,10 @@ alloc_pci_controller (int seg)
125{ 125{
126 struct pci_controller *controller; 126 struct pci_controller *controller;
127 127
128 controller = kmalloc(sizeof(*controller), GFP_KERNEL); 128 controller = kzalloc(sizeof(*controller), GFP_KERNEL);
129 if (!controller) 129 if (!controller)
130 return NULL; 130 return NULL;
131 131
132 memset(controller, 0, sizeof(*controller));
133 controller->segment = seg; 132 controller->segment = seg;
134 controller->node = -1; 133 controller->node = -1;
135 return controller; 134 return controller;
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 0b49459a878a..8c5bee01eaa2 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -117,7 +117,10 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
117 nasid_t nasid, int slice) 117 nasid_t nasid, int slice)
118{ 118{
119 int vector; 119 int vector;
120 int cpuid;
121#ifdef CONFIG_SMP
120 int cpuphys; 122 int cpuphys;
123#endif
121 int64_t bridge; 124 int64_t bridge;
122 int local_widget, status; 125 int local_widget, status;
123 nasid_t local_nasid; 126 nasid_t local_nasid;
@@ -146,7 +149,6 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
146 vector = sn_irq_info->irq_irq; 149 vector = sn_irq_info->irq_irq;
147 /* Free the old PROM new_irq_info structure */ 150 /* Free the old PROM new_irq_info structure */
148 sn_intr_free(local_nasid, local_widget, new_irq_info); 151 sn_intr_free(local_nasid, local_widget, new_irq_info);
149 /* Update kernels new_irq_info with new target info */
150 unregister_intr_pda(new_irq_info); 152 unregister_intr_pda(new_irq_info);
151 153
152 /* allocate a new PROM new_irq_info struct */ 154 /* allocate a new PROM new_irq_info struct */
@@ -160,8 +162,10 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
160 return NULL; 162 return NULL;
161 } 163 }
162 164
163 cpuphys = nasid_slice_to_cpuid(nasid, slice); 165 /* Update kernels new_irq_info with new target info */
164 new_irq_info->irq_cpuid = cpuphys; 166 cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid,
167 new_irq_info->irq_slice);
168 new_irq_info->irq_cpuid = cpuid;
165 register_intr_pda(new_irq_info); 169 register_intr_pda(new_irq_info);
166 170
167 pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; 171 pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
@@ -180,6 +184,7 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
180 call_rcu(&sn_irq_info->rcu, sn_irq_info_free); 184 call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
181 185
182#ifdef CONFIG_SMP 186#ifdef CONFIG_SMP
187 cpuphys = cpu_physical_id(cpuid);
183 set_irq_affinity_info((vector & 0xff), cpuphys, 0); 188 set_irq_affinity_info((vector & 0xff), cpuphys, 0);
184#endif 189#endif
185 190
@@ -299,6 +304,9 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
299 nasid_t nasid = sn_irq_info->irq_nasid; 304 nasid_t nasid = sn_irq_info->irq_nasid;
300 int slice = sn_irq_info->irq_slice; 305 int slice = sn_irq_info->irq_slice;
301 int cpu = nasid_slice_to_cpuid(nasid, slice); 306 int cpu = nasid_slice_to_cpuid(nasid, slice);
307#ifdef CONFIG_SMP
308 int cpuphys;
309#endif
302 310
303 pci_dev_get(pci_dev); 311 pci_dev_get(pci_dev);
304 sn_irq_info->irq_cpuid = cpu; 312 sn_irq_info->irq_cpuid = cpu;
@@ -311,6 +319,10 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
311 spin_unlock(&sn_irq_info_lock); 319 spin_unlock(&sn_irq_info_lock);
312 320
313 register_intr_pda(sn_irq_info); 321 register_intr_pda(sn_irq_info);
322#ifdef CONFIG_SMP
323 cpuphys = cpu_physical_id(cpu);
324 set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
325#endif
314} 326}
315 327
316void sn_irq_unfixup(struct pci_dev *pci_dev) 328void sn_irq_unfixup(struct pci_dev *pci_dev)
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 6ffd1f850d41..b3a435fd70fb 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -136,10 +136,6 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
136 */ 136 */
137 msg.data = 0x100 + irq; 137 msg.data = 0x100 + irq;
138 138
139#ifdef CONFIG_SMP
140 set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0);
141#endif
142
143 write_msi_msg(irq, &msg); 139 write_msi_msg(irq, &msg);
144 set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); 140 set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
145 141
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 1d009f93244d..a934ad069425 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -769,5 +769,13 @@ int sn_prom_feature_available(int id)
769 return 0; 769 return 0;
770 return test_bit(id, sn_prom_features); 770 return test_bit(id, sn_prom_features);
771} 771}
772
773void
774sn_kernel_launch_event(void)
775{
776 /* ignore status until we understand possible failure, if any*/
777 if (ia64_sn_kernel_launch_event())
778 printk(KERN_ERR "KEXEC is not supported in this PROM, Please update the PROM.\n");
779}
772EXPORT_SYMBOL(sn_prom_feature_available); 780EXPORT_SYMBOL(sn_prom_feature_available);
773 781