diff options
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/acpi.c | 19 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 26 | ||||
-rw-r--r-- | arch/ia64/kernel/init_task.c | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/ivt.S | 84 | ||||
-rw-r--r-- | arch/ia64/kernel/minstate.h | 46 | ||||
-rw-r--r-- | arch/ia64/kernel/palinfo.c | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/patch.c | 23 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 16 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 25 | ||||
-rw-r--r-- | arch/ia64/kernel/sal.c | 11 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 40 | ||||
-rw-r--r-- | arch/ia64/kernel/vmlinux.lds.S | 7 |
12 files changed, 228 insertions, 76 deletions
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 19709a079635..43687cc60dfb 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
@@ -117,7 +117,10 @@ acpi_get_sysname(void) | |||
117 | if (!strcmp(hdr->oem_id, "HP")) { | 117 | if (!strcmp(hdr->oem_id, "HP")) { |
118 | return "hpzx1"; | 118 | return "hpzx1"; |
119 | } else if (!strcmp(hdr->oem_id, "SGI")) { | 119 | } else if (!strcmp(hdr->oem_id, "SGI")) { |
120 | return "sn2"; | 120 | if (!strcmp(hdr->oem_table_id + 4, "UV")) |
121 | return "uv"; | ||
122 | else | ||
123 | return "sn2"; | ||
121 | } | 124 | } |
122 | 125 | ||
123 | return "dig"; | 126 | return "dig"; |
@@ -130,6 +133,8 @@ acpi_get_sysname(void) | |||
130 | return "hpzx1_swiotlb"; | 133 | return "hpzx1_swiotlb"; |
131 | # elif defined (CONFIG_IA64_SGI_SN2) | 134 | # elif defined (CONFIG_IA64_SGI_SN2) |
132 | return "sn2"; | 135 | return "sn2"; |
136 | # elif defined (CONFIG_IA64_SGI_UV) | ||
137 | return "uv"; | ||
133 | # elif defined (CONFIG_IA64_DIG) | 138 | # elif defined (CONFIG_IA64_DIG) |
134 | return "dig"; | 139 | return "dig"; |
135 | # else | 140 | # else |
@@ -460,7 +465,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | |||
460 | printk(KERN_ERR | 465 | printk(KERN_ERR |
461 | "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", | 466 | "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", |
462 | len, slit->header.length); | 467 | len, slit->header.length); |
463 | memset(numa_slit, 10, sizeof(numa_slit)); | ||
464 | return; | 468 | return; |
465 | } | 469 | } |
466 | slit_table = slit; | 470 | slit_table = slit; |
@@ -569,8 +573,14 @@ void __init acpi_numa_arch_fixup(void) | |||
569 | printk(KERN_INFO "Number of memory chunks in system = %d\n", | 573 | printk(KERN_INFO "Number of memory chunks in system = %d\n", |
570 | num_node_memblks); | 574 | num_node_memblks); |
571 | 575 | ||
572 | if (!slit_table) | 576 | if (!slit_table) { |
577 | for (i = 0; i < MAX_NUMNODES; i++) | ||
578 | for (j = 0; j < MAX_NUMNODES; j++) | ||
579 | node_distance(i, j) = i == j ? LOCAL_DISTANCE : | ||
580 | REMOTE_DISTANCE; | ||
573 | return; | 581 | return; |
582 | } | ||
583 | |||
574 | memset(numa_slit, -1, sizeof(numa_slit)); | 584 | memset(numa_slit, -1, sizeof(numa_slit)); |
575 | for (i = 0; i < slit_table->locality_count; i++) { | 585 | for (i = 0; i < slit_table->locality_count; i++) { |
576 | if (!pxm_bit_test(i)) | 586 | if (!pxm_bit_test(i)) |
@@ -622,6 +632,9 @@ void acpi_unregister_gsi(u32 gsi) | |||
622 | if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM) | 632 | if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM) |
623 | return; | 633 | return; |
624 | 634 | ||
635 | if (has_8259 && gsi < 16) | ||
636 | return; | ||
637 | |||
625 | iosapic_unregister_intr(gsi); | 638 | iosapic_unregister_intr(gsi); |
626 | } | 639 | } |
627 | 640 | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index e49ad8c5dc69..ca2bb95726de 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1156,6 +1156,9 @@ skip_rbs_switch: | |||
1156 | * r31 = current->thread_info->flags | 1156 | * r31 = current->thread_info->flags |
1157 | * On exit: | 1157 | * On exit: |
1158 | * p6 = TRUE if work-pending-check needs to be redone | 1158 | * p6 = TRUE if work-pending-check needs to be redone |
1159 | * | ||
1160 | * Interrupts are disabled on entry, reenabled depend on work, and | ||
1161 | * disabled on exit. | ||
1159 | */ | 1162 | */ |
1160 | .work_pending_syscall: | 1163 | .work_pending_syscall: |
1161 | add r2=-8,r2 | 1164 | add r2=-8,r2 |
@@ -1164,16 +1167,16 @@ skip_rbs_switch: | |||
1164 | st8 [r2]=r8 | 1167 | st8 [r2]=r8 |
1165 | st8 [r3]=r10 | 1168 | st8 [r3]=r10 |
1166 | .work_pending: | 1169 | .work_pending: |
1167 | tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? | 1170 | tbit.z p6,p0=r31,TIF_NEED_RESCHED // is resched not needed? |
1168 | (p6) br.cond.sptk.few .notify | 1171 | (p6) br.cond.sptk.few .notify |
1169 | #ifdef CONFIG_PREEMPT | 1172 | #ifdef CONFIG_PREEMPT |
1170 | (pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 | 1173 | (pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 |
1171 | ;; | 1174 | ;; |
1172 | (pKStk) st4 [r20]=r21 | 1175 | (pKStk) st4 [r20]=r21 |
1173 | ssm psr.i // enable interrupts | ||
1174 | #endif | 1176 | #endif |
1177 | ssm psr.i // enable interrupts | ||
1175 | br.call.spnt.many rp=schedule | 1178 | br.call.spnt.many rp=schedule |
1176 | .ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 | 1179 | .ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 (re-check) |
1177 | rsm psr.i // disable interrupts | 1180 | rsm psr.i // disable interrupts |
1178 | ;; | 1181 | ;; |
1179 | #ifdef CONFIG_PREEMPT | 1182 | #ifdef CONFIG_PREEMPT |
@@ -1182,13 +1185,13 @@ skip_rbs_switch: | |||
1182 | (pKStk) st4 [r20]=r0 // preempt_count() <- 0 | 1185 | (pKStk) st4 [r20]=r0 // preempt_count() <- 0 |
1183 | #endif | 1186 | #endif |
1184 | (pLvSys)br.cond.sptk.few .work_pending_syscall_end | 1187 | (pLvSys)br.cond.sptk.few .work_pending_syscall_end |
1185 | br.cond.sptk.many .work_processed_kernel // re-check | 1188 | br.cond.sptk.many .work_processed_kernel |
1186 | 1189 | ||
1187 | .notify: | 1190 | .notify: |
1188 | (pUStk) br.call.spnt.many rp=notify_resume_user | 1191 | (pUStk) br.call.spnt.many rp=notify_resume_user |
1189 | .ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 | 1192 | .ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 (don't re-check) |
1190 | (pLvSys)br.cond.sptk.few .work_pending_syscall_end | 1193 | (pLvSys)br.cond.sptk.few .work_pending_syscall_end |
1191 | br.cond.sptk.many .work_processed_kernel // don't re-check | 1194 | br.cond.sptk.many .work_processed_kernel |
1192 | 1195 | ||
1193 | .work_pending_syscall_end: | 1196 | .work_pending_syscall_end: |
1194 | adds r2=PT(R8)+16,r12 | 1197 | adds r2=PT(R8)+16,r12 |
@@ -1196,7 +1199,7 @@ skip_rbs_switch: | |||
1196 | ;; | 1199 | ;; |
1197 | ld8 r8=[r2] | 1200 | ld8 r8=[r2] |
1198 | ld8 r10=[r3] | 1201 | ld8 r10=[r3] |
1199 | br.cond.sptk.many .work_processed_syscall // re-check | 1202 | br.cond.sptk.many .work_processed_syscall |
1200 | 1203 | ||
1201 | END(ia64_leave_kernel) | 1204 | END(ia64_leave_kernel) |
1202 | 1205 | ||
@@ -1234,9 +1237,12 @@ GLOBAL_ENTRY(ia64_invoke_schedule_tail) | |||
1234 | END(ia64_invoke_schedule_tail) | 1237 | END(ia64_invoke_schedule_tail) |
1235 | 1238 | ||
1236 | /* | 1239 | /* |
1237 | * Setup stack and call do_notify_resume_user(). Note that pSys and pNonSys need to | 1240 | * Setup stack and call do_notify_resume_user(), keeping interrupts |
1238 | * be set up by the caller. We declare 8 input registers so the system call | 1241 | * disabled. |
1239 | * args get preserved, in case we need to restart a system call. | 1242 | * |
1243 | * Note that pSys and pNonSys need to be set up by the caller. | ||
1244 | * We declare 8 input registers so the system call args get preserved, | ||
1245 | * in case we need to restart a system call. | ||
1240 | */ | 1246 | */ |
1241 | ENTRY(notify_resume_user) | 1247 | ENTRY(notify_resume_user) |
1242 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | 1248 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) |
diff --git a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c index bc8efcad28b8..9d7e1c66faf4 100644 --- a/arch/ia64/kernel/init_task.c +++ b/arch/ia64/kernel/init_task.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
19 | 19 | ||
20 | static struct fs_struct init_fs = INIT_FS; | 20 | static struct fs_struct init_fs = INIT_FS; |
21 | static struct files_struct init_files = INIT_FILES; | ||
22 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 21 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
23 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 22 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
24 | struct mm_struct init_mm = INIT_MM(init_mm); | 23 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 6678c49daba3..80b44ea052d7 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S | |||
@@ -1076,48 +1076,6 @@ END(ia64_syscall_setup) | |||
1076 | DBG_FAULT(15) | 1076 | DBG_FAULT(15) |
1077 | FAULT(15) | 1077 | FAULT(15) |
1078 | 1078 | ||
1079 | /* | ||
1080 | * Squatting in this space ... | ||
1081 | * | ||
1082 | * This special case dispatcher for illegal operation faults allows preserved | ||
1083 | * registers to be modified through a callback function (asm only) that is handed | ||
1084 | * back from the fault handler in r8. Up to three arguments can be passed to the | ||
1085 | * callback function by returning an aggregate with the callback as its first | ||
1086 | * element, followed by the arguments. | ||
1087 | */ | ||
1088 | ENTRY(dispatch_illegal_op_fault) | ||
1089 | .prologue | ||
1090 | .body | ||
1091 | SAVE_MIN_WITH_COVER | ||
1092 | ssm psr.ic | PSR_DEFAULT_BITS | ||
1093 | ;; | ||
1094 | srlz.i // guarantee that interruption collection is on | ||
1095 | ;; | ||
1096 | (p15) ssm psr.i // restore psr.i | ||
1097 | adds r3=8,r2 // set up second base pointer for SAVE_REST | ||
1098 | ;; | ||
1099 | alloc r14=ar.pfs,0,0,1,0 // must be first in insn group | ||
1100 | mov out0=ar.ec | ||
1101 | ;; | ||
1102 | SAVE_REST | ||
1103 | PT_REGS_UNWIND_INFO(0) | ||
1104 | ;; | ||
1105 | br.call.sptk.many rp=ia64_illegal_op_fault | ||
1106 | .ret0: ;; | ||
1107 | alloc r14=ar.pfs,0,0,3,0 // must be first in insn group | ||
1108 | mov out0=r9 | ||
1109 | mov out1=r10 | ||
1110 | mov out2=r11 | ||
1111 | movl r15=ia64_leave_kernel | ||
1112 | ;; | ||
1113 | mov rp=r15 | ||
1114 | mov b6=r8 | ||
1115 | ;; | ||
1116 | cmp.ne p6,p0=0,r8 | ||
1117 | (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel | ||
1118 | br.sptk.many ia64_leave_kernel | ||
1119 | END(dispatch_illegal_op_fault) | ||
1120 | |||
1121 | .org ia64_ivt+0x4000 | 1079 | .org ia64_ivt+0x4000 |
1122 | ///////////////////////////////////////////////////////////////////////////////////////// | 1080 | ///////////////////////////////////////////////////////////////////////////////////////// |
1123 | // 0x4000 Entry 16 (size 64 bundles) Reserved | 1081 | // 0x4000 Entry 16 (size 64 bundles) Reserved |
@@ -1715,6 +1673,48 @@ END(ia32_interrupt) | |||
1715 | DBG_FAULT(67) | 1673 | DBG_FAULT(67) |
1716 | FAULT(67) | 1674 | FAULT(67) |
1717 | 1675 | ||
1676 | /* | ||
1677 | * Squatting in this space ... | ||
1678 | * | ||
1679 | * This special case dispatcher for illegal operation faults allows preserved | ||
1680 | * registers to be modified through a callback function (asm only) that is handed | ||
1681 | * back from the fault handler in r8. Up to three arguments can be passed to the | ||
1682 | * callback function by returning an aggregate with the callback as its first | ||
1683 | * element, followed by the arguments. | ||
1684 | */ | ||
1685 | ENTRY(dispatch_illegal_op_fault) | ||
1686 | .prologue | ||
1687 | .body | ||
1688 | SAVE_MIN_WITH_COVER | ||
1689 | ssm psr.ic | PSR_DEFAULT_BITS | ||
1690 | ;; | ||
1691 | srlz.i // guarantee that interruption collection is on | ||
1692 | ;; | ||
1693 | (p15) ssm psr.i // restore psr.i | ||
1694 | adds r3=8,r2 // set up second base pointer for SAVE_REST | ||
1695 | ;; | ||
1696 | alloc r14=ar.pfs,0,0,1,0 // must be first in insn group | ||
1697 | mov out0=ar.ec | ||
1698 | ;; | ||
1699 | SAVE_REST | ||
1700 | PT_REGS_UNWIND_INFO(0) | ||
1701 | ;; | ||
1702 | br.call.sptk.many rp=ia64_illegal_op_fault | ||
1703 | .ret0: ;; | ||
1704 | alloc r14=ar.pfs,0,0,3,0 // must be first in insn group | ||
1705 | mov out0=r9 | ||
1706 | mov out1=r10 | ||
1707 | mov out2=r11 | ||
1708 | movl r15=ia64_leave_kernel | ||
1709 | ;; | ||
1710 | mov rp=r15 | ||
1711 | mov b6=r8 | ||
1712 | ;; | ||
1713 | cmp.ne p6,p0=0,r8 | ||
1714 | (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel | ||
1715 | br.sptk.many ia64_leave_kernel | ||
1716 | END(dispatch_illegal_op_fault) | ||
1717 | |||
1718 | #ifdef CONFIG_IA32_SUPPORT | 1718 | #ifdef CONFIG_IA32_SUPPORT |
1719 | 1719 | ||
1720 | /* | 1720 | /* |
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index 7c548ac52bbc..74b6d670aaef 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h | |||
@@ -15,6 +15,9 @@ | |||
15 | #define ACCOUNT_SYS_ENTER | 15 | #define ACCOUNT_SYS_ENTER |
16 | #endif | 16 | #endif |
17 | 17 | ||
18 | .section ".data.patch.rse", "a" | ||
19 | .previous | ||
20 | |||
18 | /* | 21 | /* |
19 | * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves | 22 | * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves |
20 | * the minimum state necessary that allows us to turn psr.ic back | 23 | * the minimum state necessary that allows us to turn psr.ic back |
@@ -40,7 +43,7 @@ | |||
40 | * Note that psr.ic is NOT turned on by this macro. This is so that | 43 | * Note that psr.ic is NOT turned on by this macro. This is so that |
41 | * we can pass interruption state as arguments to a handler. | 44 | * we can pass interruption state as arguments to a handler. |
42 | */ | 45 | */ |
43 | #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \ | 46 | #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA,WORKAROUND) \ |
44 | mov r16=IA64_KR(CURRENT); /* M */ \ | 47 | mov r16=IA64_KR(CURRENT); /* M */ \ |
45 | mov r27=ar.rsc; /* M */ \ | 48 | mov r27=ar.rsc; /* M */ \ |
46 | mov r20=r1; /* A */ \ | 49 | mov r20=r1; /* A */ \ |
@@ -87,6 +90,7 @@ | |||
87 | tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ | 90 | tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ |
88 | mov r29=b0 \ | 91 | mov r29=b0 \ |
89 | ;; \ | 92 | ;; \ |
93 | WORKAROUND; \ | ||
90 | adds r16=PT(R8),r1; /* initialize first base pointer */ \ | 94 | adds r16=PT(R8),r1; /* initialize first base pointer */ \ |
91 | adds r17=PT(R9),r1; /* initialize second base pointer */ \ | 95 | adds r17=PT(R9),r1; /* initialize second base pointer */ \ |
92 | (pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ | 96 | (pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ |
@@ -206,6 +210,40 @@ | |||
206 | st8 [r25]=r10; /* ar.ssd */ \ | 210 | st8 [r25]=r10; /* ar.ssd */ \ |
207 | ;; | 211 | ;; |
208 | 212 | ||
209 | #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs,) | 213 | #define RSE_WORKAROUND \ |
210 | #define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19) | 214 | (pUStk) extr.u r17=r18,3,6; \ |
211 | #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, ) | 215 | (pUStk) sub r16=r18,r22; \ |
216 | [1:](pKStk) br.cond.sptk.many 1f; \ | ||
217 | .xdata4 ".data.patch.rse",1b-. \ | ||
218 | ;; \ | ||
219 | cmp.ge p6,p7 = 33,r17; \ | ||
220 | ;; \ | ||
221 | (p6) mov r17=0x310; \ | ||
222 | (p7) mov r17=0x308; \ | ||
223 | ;; \ | ||
224 | cmp.leu p1,p0=r16,r17; \ | ||
225 | (p1) br.cond.sptk.many 1f; \ | ||
226 | dep.z r17=r26,0,62; \ | ||
227 | movl r16=2f; \ | ||
228 | ;; \ | ||
229 | mov ar.pfs=r17; \ | ||
230 | dep r27=r0,r27,16,14; \ | ||
231 | mov b0=r16; \ | ||
232 | ;; \ | ||
233 | br.ret.sptk b0; \ | ||
234 | ;; \ | ||
235 | 2: \ | ||
236 | mov ar.rsc=r0 \ | ||
237 | ;; \ | ||
238 | flushrs; \ | ||
239 | ;; \ | ||
240 | mov ar.bspstore=r22 \ | ||
241 | ;; \ | ||
242 | mov r18=ar.bsp; \ | ||
243 | ;; \ | ||
244 | 1: \ | ||
245 | .pred.rel "mutex", pKStk, pUStk | ||
246 | |||
247 | #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs, , RSE_WORKAROUND) | ||
248 | #define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND) | ||
249 | #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, , ) | ||
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 4547a2092af9..9dc00f7fe10e 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c | |||
@@ -900,12 +900,6 @@ static void | |||
900 | palinfo_smp_call(void *info) | 900 | palinfo_smp_call(void *info) |
901 | { | 901 | { |
902 | palinfo_smp_data_t *data = (palinfo_smp_data_t *)info; | 902 | palinfo_smp_data_t *data = (palinfo_smp_data_t *)info; |
903 | if (data == NULL) { | ||
904 | printk(KERN_ERR "palinfo: data pointer is NULL\n"); | ||
905 | data->ret = 0; /* no output */ | ||
906 | return; | ||
907 | } | ||
908 | /* does this actual call */ | ||
909 | data->ret = (*data->func)(data->page); | 903 | data->ret = (*data->func)(data->page); |
910 | } | 904 | } |
911 | 905 | ||
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c index e0dca8743dbb..b83b2c516008 100644 --- a/arch/ia64/kernel/patch.c +++ b/arch/ia64/kernel/patch.c | |||
@@ -115,6 +115,29 @@ ia64_patch_vtop (unsigned long start, unsigned long end) | |||
115 | ia64_srlz_i(); | 115 | ia64_srlz_i(); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | ||
119 | * Disable the RSE workaround by turning the conditional branch | ||
120 | * that we tagged in each place the workaround was used into an | ||
121 | * unconditional branch. | ||
122 | */ | ||
123 | void __init | ||
124 | ia64_patch_rse (unsigned long start, unsigned long end) | ||
125 | { | ||
126 | s32 *offp = (s32 *) start; | ||
127 | u64 ip, *b; | ||
128 | |||
129 | while (offp < (s32 *) end) { | ||
130 | ip = (u64) offp + *offp; | ||
131 | |||
132 | b = (u64 *)(ip & -16); | ||
133 | b[1] &= ~0xf800000L; | ||
134 | ia64_fc((void *) ip); | ||
135 | ++offp; | ||
136 | } | ||
137 | ia64_sync_i(); | ||
138 | ia64_srlz_i(); | ||
139 | } | ||
140 | |||
118 | void __init | 141 | void __init |
119 | ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) | 142 | ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) |
120 | { | 143 | { |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index c1ad27de2dd2..71d05133f556 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -5013,12 +5013,13 @@ pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs) | |||
5013 | } | 5013 | } |
5014 | 5014 | ||
5015 | static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds); | 5015 | static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds); |
5016 | |||
5016 | /* | 5017 | /* |
5017 | * pfm_handle_work() can be called with interrupts enabled | 5018 | * pfm_handle_work() can be called with interrupts enabled |
5018 | * (TIF_NEED_RESCHED) or disabled. The down_interruptible | 5019 | * (TIF_NEED_RESCHED) or disabled. The down_interruptible |
5019 | * call may sleep, therefore we must re-enable interrupts | 5020 | * call may sleep, therefore we must re-enable interrupts |
5020 | * to avoid deadlocks. It is safe to do so because this function | 5021 | * to avoid deadlocks. It is safe to do so because this function |
5021 | * is called ONLY when returning to user level (PUStk=1), in which case | 5022 | * is called ONLY when returning to user level (pUStk=1), in which case |
5022 | * there is no risk of kernel stack overflow due to deep | 5023 | * there is no risk of kernel stack overflow due to deep |
5023 | * interrupt nesting. | 5024 | * interrupt nesting. |
5024 | */ | 5025 | */ |
@@ -5034,7 +5035,8 @@ pfm_handle_work(void) | |||
5034 | 5035 | ||
5035 | ctx = PFM_GET_CTX(current); | 5036 | ctx = PFM_GET_CTX(current); |
5036 | if (ctx == NULL) { | 5037 | if (ctx == NULL) { |
5037 | printk(KERN_ERR "perfmon: [%d] has no PFM context\n", task_pid_nr(current)); | 5038 | printk(KERN_ERR "perfmon: [%d] has no PFM context\n", |
5039 | task_pid_nr(current)); | ||
5038 | return; | 5040 | return; |
5039 | } | 5041 | } |
5040 | 5042 | ||
@@ -5058,11 +5060,12 @@ pfm_handle_work(void) | |||
5058 | /* | 5060 | /* |
5059 | * must be done before we check for simple-reset mode | 5061 | * must be done before we check for simple-reset mode |
5060 | */ | 5062 | */ |
5061 | if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) goto do_zombie; | 5063 | if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) |
5062 | 5064 | goto do_zombie; | |
5063 | 5065 | ||
5064 | //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking; | 5066 | //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking; |
5065 | if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking; | 5067 | if (reason == PFM_TRAP_REASON_RESET) |
5068 | goto skip_blocking; | ||
5066 | 5069 | ||
5067 | /* | 5070 | /* |
5068 | * restore interrupt mask to what it was on entry. | 5071 | * restore interrupt mask to what it was on entry. |
@@ -5110,7 +5113,8 @@ do_zombie: | |||
5110 | /* | 5113 | /* |
5111 | * in case of interruption of down() we don't restart anything | 5114 | * in case of interruption of down() we don't restart anything |
5112 | */ | 5115 | */ |
5113 | if (ret < 0) goto nothing_to_do; | 5116 | if (ret < 0) |
5117 | goto nothing_to_do; | ||
5114 | 5118 | ||
5115 | skip_blocking: | 5119 | skip_blocking: |
5116 | pfm_resume_after_ovfl(ctx, ovfl_regs, regs); | 5120 | pfm_resume_after_ovfl(ctx, ovfl_regs, regs); |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 58dcfac5ea88..a3a34b4eb038 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -167,11 +167,18 @@ void tsk_clear_notify_resume(struct task_struct *tsk) | |||
167 | clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); | 167 | clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* | ||
171 | * do_notify_resume_user(): | ||
172 | * Called from notify_resume_user at entry.S, with interrupts disabled. | ||
173 | */ | ||
170 | void | 174 | void |
171 | do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall) | 175 | do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) |
172 | { | 176 | { |
173 | if (fsys_mode(current, &scr->pt)) { | 177 | if (fsys_mode(current, &scr->pt)) { |
174 | /* defer signal-handling etc. until we return to privilege-level 0. */ | 178 | /* |
179 | * defer signal-handling etc. until we return to | ||
180 | * privilege-level 0. | ||
181 | */ | ||
175 | if (!ia64_psr(&scr->pt)->lp) | 182 | if (!ia64_psr(&scr->pt)->lp) |
176 | ia64_psr(&scr->pt)->lp = 1; | 183 | ia64_psr(&scr->pt)->lp = 1; |
177 | return; | 184 | return; |
@@ -179,16 +186,26 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall | |||
179 | 186 | ||
180 | #ifdef CONFIG_PERFMON | 187 | #ifdef CONFIG_PERFMON |
181 | if (current->thread.pfm_needs_checking) | 188 | if (current->thread.pfm_needs_checking) |
189 | /* | ||
190 | * Note: pfm_handle_work() allow us to call it with interrupts | ||
191 | * disabled, and may enable interrupts within the function. | ||
192 | */ | ||
182 | pfm_handle_work(); | 193 | pfm_handle_work(); |
183 | #endif | 194 | #endif |
184 | 195 | ||
185 | /* deal with pending signal delivery */ | 196 | /* deal with pending signal delivery */ |
186 | if (test_thread_flag(TIF_SIGPENDING)) | 197 | if (test_thread_flag(TIF_SIGPENDING)) { |
198 | local_irq_enable(); /* force interrupt enable */ | ||
187 | ia64_do_signal(scr, in_syscall); | 199 | ia64_do_signal(scr, in_syscall); |
200 | } | ||
188 | 201 | ||
189 | /* copy user rbs to kernel rbs */ | 202 | /* copy user rbs to kernel rbs */ |
190 | if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) | 203 | if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) { |
204 | local_irq_enable(); /* force interrupt enable */ | ||
191 | ia64_sync_krbs(); | 205 | ia64_sync_krbs(); |
206 | } | ||
207 | |||
208 | local_irq_disable(); /* force interrupt disable */ | ||
192 | } | 209 | } |
193 | 210 | ||
194 | static int pal_halt = 1; | 211 | static int pal_halt = 1; |
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index a3022dc48ef8..7e0259709c04 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c | |||
@@ -229,6 +229,14 @@ static void __init sal_desc_ap_wakeup(void *p) { } | |||
229 | */ | 229 | */ |
230 | static int sal_cache_flush_drops_interrupts; | 230 | static int sal_cache_flush_drops_interrupts; |
231 | 231 | ||
232 | static int __init | ||
233 | force_pal_cache_flush(char *str) | ||
234 | { | ||
235 | sal_cache_flush_drops_interrupts = 1; | ||
236 | return 0; | ||
237 | } | ||
238 | early_param("force_pal_cache_flush", force_pal_cache_flush); | ||
239 | |||
232 | void __init | 240 | void __init |
233 | check_sal_cache_flush (void) | 241 | check_sal_cache_flush (void) |
234 | { | 242 | { |
@@ -237,6 +245,9 @@ check_sal_cache_flush (void) | |||
237 | u64 vector, cache_type = 3; | 245 | u64 vector, cache_type = 3; |
238 | struct ia64_sal_retval isrv; | 246 | struct ia64_sal_retval isrv; |
239 | 247 | ||
248 | if (sal_cache_flush_drops_interrupts) | ||
249 | return; | ||
250 | |||
240 | cpu = get_cpu(); | 251 | cpu = get_cpu(); |
241 | local_irq_save(flags); | 252 | local_irq_save(flags); |
242 | 253 | ||
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 5015ca1275ca..f48a809c686d 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -239,6 +239,25 @@ __initcall(register_memory); | |||
239 | 239 | ||
240 | 240 | ||
241 | #ifdef CONFIG_KEXEC | 241 | #ifdef CONFIG_KEXEC |
242 | |||
243 | /* | ||
244 | * This function checks if the reserved crashkernel is allowed on the specific | ||
245 | * IA64 machine flavour. Machines without an IO TLB use swiotlb and require | ||
246 | * some memory below 4 GB (i.e. in 32 bit area), see the implementation of | ||
247 | * lib/swiotlb.c. The hpzx1 architecture has an IO TLB but cannot use that | ||
248 | * in kdump case. See the comment in sba_init() in sba_iommu.c. | ||
249 | * | ||
250 | * So, the only machvec that really supports loading the kdump kernel | ||
251 | * over 4 GB is "sn2". | ||
252 | */ | ||
253 | static int __init check_crashkernel_memory(unsigned long pbase, size_t size) | ||
254 | { | ||
255 | if (ia64_platform_is("sn2") || ia64_platform_is("uv")) | ||
256 | return 1; | ||
257 | else | ||
258 | return pbase < (1UL << 32); | ||
259 | } | ||
260 | |||
242 | static void __init setup_crashkernel(unsigned long total, int *n) | 261 | static void __init setup_crashkernel(unsigned long total, int *n) |
243 | { | 262 | { |
244 | unsigned long long base = 0, size = 0; | 263 | unsigned long long base = 0, size = 0; |
@@ -252,6 +271,16 @@ static void __init setup_crashkernel(unsigned long total, int *n) | |||
252 | base = kdump_find_rsvd_region(size, | 271 | base = kdump_find_rsvd_region(size, |
253 | rsvd_region, *n); | 272 | rsvd_region, *n); |
254 | } | 273 | } |
274 | |||
275 | if (!check_crashkernel_memory(base, size)) { | ||
276 | pr_warning("crashkernel: There would be kdump memory " | ||
277 | "at %ld GB but this is unusable because it " | ||
278 | "must\nbe below 4 GB. Change the memory " | ||
279 | "configuration of the machine.\n", | ||
280 | (unsigned long)(base >> 30)); | ||
281 | return; | ||
282 | } | ||
283 | |||
255 | if (base != ~0UL) { | 284 | if (base != ~0UL) { |
256 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " | 285 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " |
257 | "for crashkernel (System RAM: %ldMB)\n", | 286 | "for crashkernel (System RAM: %ldMB)\n", |
@@ -531,6 +560,17 @@ setup_arch (char **cmdline_p) | |||
531 | /* process SAL system table: */ | 560 | /* process SAL system table: */ |
532 | ia64_sal_init(__va(efi.sal_systab)); | 561 | ia64_sal_init(__va(efi.sal_systab)); |
533 | 562 | ||
563 | #ifdef CONFIG_ITANIUM | ||
564 | ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); | ||
565 | #else | ||
566 | { | ||
567 | u64 num_phys_stacked; | ||
568 | |||
569 | if (ia64_pal_rse_info(&num_phys_stacked, 0) == 0 && num_phys_stacked > 96) | ||
570 | ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); | ||
571 | } | ||
572 | #endif | ||
573 | |||
534 | #ifdef CONFIG_SMP | 574 | #ifdef CONFIG_SMP |
535 | cpu_physical_id(0) = hard_smp_processor_id(); | 575 | cpu_physical_id(0) = hard_smp_processor_id(); |
536 | #endif | 576 | #endif |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 80622acc95de..5929ab10a289 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -156,6 +156,13 @@ SECTIONS | |||
156 | __end___vtop_patchlist = .; | 156 | __end___vtop_patchlist = .; |
157 | } | 157 | } |
158 | 158 | ||
159 | .data.patch.rse : AT(ADDR(.data.patch.rse) - LOAD_OFFSET) | ||
160 | { | ||
161 | __start___rse_patchlist = .; | ||
162 | *(.data.patch.rse) | ||
163 | __end___rse_patchlist = .; | ||
164 | } | ||
165 | |||
159 | .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET) | 166 | .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET) |
160 | { | 167 | { |
161 | __start___mckinley_e9_bundles = .; | 168 | __start___mckinley_e9_bundles = .; |