diff options
| -rw-r--r-- | arch/parisc/Kconfig | 2 | ||||
| -rw-r--r-- | arch/parisc/Makefile | 21 | ||||
| -rw-r--r-- | arch/parisc/include/asm/hardirq.h | 9 | ||||
| -rw-r--r-- | arch/parisc/include/asm/processor.h | 3 | ||||
| -rw-r--r-- | arch/parisc/kernel/entry.S | 155 | ||||
| -rw-r--r-- | arch/parisc/kernel/irq.c | 101 | ||||
| -rw-r--r-- | arch/parisc/mm/init.c | 4 |
7 files changed, 194 insertions, 101 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index cad060f288cf..6507dabdd5dd 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
| @@ -245,7 +245,7 @@ config SMP | |||
| 245 | 245 | ||
| 246 | config IRQSTACKS | 246 | config IRQSTACKS |
| 247 | bool "Use separate kernel stacks when processing interrupts" | 247 | bool "Use separate kernel stacks when processing interrupts" |
| 248 | default n | 248 | default y |
| 249 | help | 249 | help |
| 250 | If you say Y here the kernel will use separate kernel stacks | 250 | If you say Y here the kernel will use separate kernel stacks |
| 251 | for handling hard and soft interrupts. This can help avoid | 251 | for handling hard and soft interrupts. This can help avoid |
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 2f967cc6649e..197690068f88 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile | |||
| @@ -23,24 +23,21 @@ NM = sh $(srctree)/arch/parisc/nm | |||
| 23 | CHECKFLAGS += -D__hppa__=1 | 23 | CHECKFLAGS += -D__hppa__=1 |
| 24 | LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) | 24 | LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) |
| 25 | 25 | ||
| 26 | MACHINE := $(shell uname -m) | ||
| 27 | NATIVE := $(if $(filter parisc%,$(MACHINE)),1,0) | ||
| 28 | |||
| 29 | ifdef CONFIG_64BIT | 26 | ifdef CONFIG_64BIT |
| 30 | UTS_MACHINE := parisc64 | 27 | UTS_MACHINE := parisc64 |
| 31 | CHECKFLAGS += -D__LP64__=1 -m64 | 28 | CHECKFLAGS += -D__LP64__=1 -m64 |
| 32 | WIDTH := 64 | 29 | CC_ARCHES = hppa64 |
| 33 | else # 32-bit | 30 | else # 32-bit |
| 34 | WIDTH := | 31 | CC_ARCHES = hppa hppa2.0 hppa1.1 |
| 35 | endif | 32 | endif |
| 36 | 33 | ||
| 37 | # attempt to help out folks who are cross-compiling | 34 | ifneq ($(SUBARCH),$(UTS_MACHINE)) |
| 38 | ifeq ($(NATIVE),1) | 35 | ifeq ($(CROSS_COMPILE),) |
| 39 | CROSS_COMPILE := hppa$(WIDTH)-linux- | 36 | CC_SUFFIXES = linux linux-gnu unknown-linux-gnu |
| 40 | else | 37 | CROSS_COMPILE := $(call cc-cross-prefix, \ |
| 41 | ifeq ($(CROSS_COMPILE),) | 38 | $(foreach a,$(CC_ARCHES), \ |
| 42 | CROSS_COMPILE := hppa$(WIDTH)-linux-gnu- | 39 | $(foreach s,$(CC_SUFFIXES),$(a)-$(s)-))) |
| 43 | endif | 40 | endif |
| 44 | endif | 41 | endif |
| 45 | 42 | ||
| 46 | OBJCOPY_FLAGS =-O binary -R .note -R .comment -S | 43 | OBJCOPY_FLAGS =-O binary -R .note -R .comment -S |
diff --git a/arch/parisc/include/asm/hardirq.h b/arch/parisc/include/asm/hardirq.h index 12373c4dabab..c19f7138ba48 100644 --- a/arch/parisc/include/asm/hardirq.h +++ b/arch/parisc/include/asm/hardirq.h | |||
| @@ -11,10 +11,18 @@ | |||
| 11 | #include <linux/threads.h> | 11 | #include <linux/threads.h> |
| 12 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
| 13 | 13 | ||
| 14 | #ifdef CONFIG_IRQSTACKS | ||
| 15 | #define __ARCH_HAS_DO_SOFTIRQ | ||
| 16 | #endif | ||
| 17 | |||
| 14 | typedef struct { | 18 | typedef struct { |
| 15 | unsigned int __softirq_pending; | 19 | unsigned int __softirq_pending; |
| 16 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | 20 | #ifdef CONFIG_DEBUG_STACKOVERFLOW |
| 17 | unsigned int kernel_stack_usage; | 21 | unsigned int kernel_stack_usage; |
| 22 | #ifdef CONFIG_IRQSTACKS | ||
| 23 | unsigned int irq_stack_usage; | ||
| 24 | unsigned int irq_stack_counter; | ||
| 25 | #endif | ||
| 18 | #endif | 26 | #endif |
| 19 | #ifdef CONFIG_SMP | 27 | #ifdef CONFIG_SMP |
| 20 | unsigned int irq_resched_count; | 28 | unsigned int irq_resched_count; |
| @@ -28,6 +36,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); | |||
| 28 | #define __ARCH_IRQ_STAT | 36 | #define __ARCH_IRQ_STAT |
| 29 | #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) | 37 | #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) |
| 30 | #define inc_irq_stat(member) this_cpu_inc(irq_stat.member) | 38 | #define inc_irq_stat(member) this_cpu_inc(irq_stat.member) |
| 39 | #define __inc_irq_stat(member) __this_cpu_inc(irq_stat.member) | ||
| 31 | #define local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending) | 40 | #define local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending) |
| 32 | 41 | ||
| 33 | #define __ARCH_SET_SOFTIRQ_PENDING | 42 | #define __ARCH_SET_SOFTIRQ_PENDING |
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 064015547d1e..cfbc43929cf6 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h | |||
| @@ -63,10 +63,13 @@ | |||
| 63 | */ | 63 | */ |
| 64 | #ifdef __KERNEL__ | 64 | #ifdef __KERNEL__ |
| 65 | 65 | ||
| 66 | #include <linux/spinlock_types.h> | ||
| 67 | |||
| 66 | #define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */ | 68 | #define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */ |
| 67 | 69 | ||
| 68 | union irq_stack_union { | 70 | union irq_stack_union { |
| 69 | unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)]; | 71 | unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)]; |
| 72 | raw_spinlock_t lock; | ||
| 70 | }; | 73 | }; |
| 71 | 74 | ||
| 72 | DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); | 75 | DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 4bb96ad9b0b1..ae27cb6ce19a 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
| @@ -452,9 +452,41 @@ | |||
| 452 | L2_ptep \pgd,\pte,\index,\va,\fault | 452 | L2_ptep \pgd,\pte,\index,\va,\fault |
| 453 | .endm | 453 | .endm |
| 454 | 454 | ||
| 455 | /* Acquire pa_dbit_lock lock. */ | ||
| 456 | .macro dbit_lock spc,tmp,tmp1 | ||
| 457 | #ifdef CONFIG_SMP | ||
| 458 | cmpib,COND(=),n 0,\spc,2f | ||
| 459 | load32 PA(pa_dbit_lock),\tmp | ||
| 460 | 1: LDCW 0(\tmp),\tmp1 | ||
| 461 | cmpib,COND(=) 0,\tmp1,1b | ||
| 462 | nop | ||
| 463 | 2: | ||
| 464 | #endif | ||
| 465 | .endm | ||
| 466 | |||
| 467 | /* Release pa_dbit_lock lock without reloading lock address. */ | ||
| 468 | .macro dbit_unlock0 spc,tmp | ||
| 469 | #ifdef CONFIG_SMP | ||
| 470 | or,COND(=) %r0,\spc,%r0 | ||
| 471 | stw \spc,0(\tmp) | ||
| 472 | #endif | ||
| 473 | .endm | ||
| 474 | |||
| 475 | /* Release pa_dbit_lock lock. */ | ||
| 476 | .macro dbit_unlock1 spc,tmp | ||
| 477 | #ifdef CONFIG_SMP | ||
| 478 | load32 PA(pa_dbit_lock),\tmp | ||
| 479 | dbit_unlock0 \spc,\tmp | ||
| 480 | #endif | ||
| 481 | .endm | ||
| 482 | |||
| 455 | /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and | 483 | /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and |
| 456 | * don't needlessly dirty the cache line if it was already set */ | 484 | * don't needlessly dirty the cache line if it was already set */ |
| 457 | .macro update_ptep ptep,pte,tmp,tmp1 | 485 | .macro update_ptep spc,ptep,pte,tmp,tmp1 |
| 486 | #ifdef CONFIG_SMP | ||
| 487 | or,COND(=) %r0,\spc,%r0 | ||
| 488 | LDREG 0(\ptep),\pte | ||
| 489 | #endif | ||
| 458 | ldi _PAGE_ACCESSED,\tmp1 | 490 | ldi _PAGE_ACCESSED,\tmp1 |
| 459 | or \tmp1,\pte,\tmp | 491 | or \tmp1,\pte,\tmp |
| 460 | and,COND(<>) \tmp1,\pte,%r0 | 492 | and,COND(<>) \tmp1,\pte,%r0 |
| @@ -463,7 +495,11 @@ | |||
| 463 | 495 | ||
| 464 | /* Set the dirty bit (and accessed bit). No need to be | 496 | /* Set the dirty bit (and accessed bit). No need to be |
| 465 | * clever, this is only used from the dirty fault */ | 497 | * clever, this is only used from the dirty fault */ |
| 466 | .macro update_dirty ptep,pte,tmp | 498 | .macro update_dirty spc,ptep,pte,tmp |
| 499 | #ifdef CONFIG_SMP | ||
| 500 | or,COND(=) %r0,\spc,%r0 | ||
| 501 | LDREG 0(\ptep),\pte | ||
| 502 | #endif | ||
| 467 | ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp | 503 | ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp |
| 468 | or \tmp,\pte,\pte | 504 | or \tmp,\pte,\pte |
| 469 | STREG \pte,0(\ptep) | 505 | STREG \pte,0(\ptep) |
| @@ -1111,11 +1147,13 @@ dtlb_miss_20w: | |||
| 1111 | 1147 | ||
| 1112 | L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w | 1148 | L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w |
| 1113 | 1149 | ||
| 1114 | update_ptep ptp,pte,t0,t1 | 1150 | dbit_lock spc,t0,t1 |
| 1151 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1115 | 1152 | ||
| 1116 | make_insert_tlb spc,pte,prot | 1153 | make_insert_tlb spc,pte,prot |
| 1117 | 1154 | ||
| 1118 | idtlbt pte,prot | 1155 | idtlbt pte,prot |
| 1156 | dbit_unlock1 spc,t0 | ||
| 1119 | 1157 | ||
| 1120 | rfir | 1158 | rfir |
| 1121 | nop | 1159 | nop |
| @@ -1135,11 +1173,13 @@ nadtlb_miss_20w: | |||
| 1135 | 1173 | ||
| 1136 | L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w | 1174 | L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w |
| 1137 | 1175 | ||
| 1138 | update_ptep ptp,pte,t0,t1 | 1176 | dbit_lock spc,t0,t1 |
| 1177 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1139 | 1178 | ||
| 1140 | make_insert_tlb spc,pte,prot | 1179 | make_insert_tlb spc,pte,prot |
| 1141 | 1180 | ||
| 1142 | idtlbt pte,prot | 1181 | idtlbt pte,prot |
| 1182 | dbit_unlock1 spc,t0 | ||
| 1143 | 1183 | ||
| 1144 | rfir | 1184 | rfir |
| 1145 | nop | 1185 | nop |
| @@ -1161,7 +1201,8 @@ dtlb_miss_11: | |||
| 1161 | 1201 | ||
| 1162 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 | 1202 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 |
| 1163 | 1203 | ||
| 1164 | update_ptep ptp,pte,t0,t1 | 1204 | dbit_lock spc,t0,t1 |
| 1205 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1165 | 1206 | ||
| 1166 | make_insert_tlb_11 spc,pte,prot | 1207 | make_insert_tlb_11 spc,pte,prot |
| 1167 | 1208 | ||
| @@ -1172,6 +1213,7 @@ dtlb_miss_11: | |||
| 1172 | idtlbp prot,(%sr1,va) | 1213 | idtlbp prot,(%sr1,va) |
| 1173 | 1214 | ||
| 1174 | mtsp t0, %sr1 /* Restore sr1 */ | 1215 | mtsp t0, %sr1 /* Restore sr1 */ |
| 1216 | dbit_unlock1 spc,t0 | ||
| 1175 | 1217 | ||
| 1176 | rfir | 1218 | rfir |
| 1177 | nop | 1219 | nop |
| @@ -1192,7 +1234,8 @@ nadtlb_miss_11: | |||
| 1192 | 1234 | ||
| 1193 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 | 1235 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 |
| 1194 | 1236 | ||
| 1195 | update_ptep ptp,pte,t0,t1 | 1237 | dbit_lock spc,t0,t1 |
| 1238 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1196 | 1239 | ||
| 1197 | make_insert_tlb_11 spc,pte,prot | 1240 | make_insert_tlb_11 spc,pte,prot |
| 1198 | 1241 | ||
| @@ -1204,6 +1247,7 @@ nadtlb_miss_11: | |||
| 1204 | idtlbp prot,(%sr1,va) | 1247 | idtlbp prot,(%sr1,va) |
| 1205 | 1248 | ||
| 1206 | mtsp t0, %sr1 /* Restore sr1 */ | 1249 | mtsp t0, %sr1 /* Restore sr1 */ |
| 1250 | dbit_unlock1 spc,t0 | ||
| 1207 | 1251 | ||
| 1208 | rfir | 1252 | rfir |
| 1209 | nop | 1253 | nop |
| @@ -1224,13 +1268,15 @@ dtlb_miss_20: | |||
| 1224 | 1268 | ||
| 1225 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 | 1269 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 |
| 1226 | 1270 | ||
| 1227 | update_ptep ptp,pte,t0,t1 | 1271 | dbit_lock spc,t0,t1 |
| 1272 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1228 | 1273 | ||
| 1229 | make_insert_tlb spc,pte,prot | 1274 | make_insert_tlb spc,pte,prot |
| 1230 | 1275 | ||
| 1231 | f_extend pte,t0 | 1276 | f_extend pte,t0 |
| 1232 | 1277 | ||
| 1233 | idtlbt pte,prot | 1278 | idtlbt pte,prot |
| 1279 | dbit_unlock1 spc,t0 | ||
| 1234 | 1280 | ||
| 1235 | rfir | 1281 | rfir |
| 1236 | nop | 1282 | nop |
| @@ -1250,13 +1296,15 @@ nadtlb_miss_20: | |||
| 1250 | 1296 | ||
| 1251 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 | 1297 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 |
| 1252 | 1298 | ||
| 1253 | update_ptep ptp,pte,t0,t1 | 1299 | dbit_lock spc,t0,t1 |
| 1300 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1254 | 1301 | ||
| 1255 | make_insert_tlb spc,pte,prot | 1302 | make_insert_tlb spc,pte,prot |
| 1256 | 1303 | ||
| 1257 | f_extend pte,t0 | 1304 | f_extend pte,t0 |
| 1258 | 1305 | ||
| 1259 | idtlbt pte,prot | 1306 | idtlbt pte,prot |
| 1307 | dbit_unlock1 spc,t0 | ||
| 1260 | 1308 | ||
| 1261 | rfir | 1309 | rfir |
| 1262 | nop | 1310 | nop |
| @@ -1357,11 +1405,13 @@ itlb_miss_20w: | |||
| 1357 | 1405 | ||
| 1358 | L3_ptep ptp,pte,t0,va,itlb_fault | 1406 | L3_ptep ptp,pte,t0,va,itlb_fault |
| 1359 | 1407 | ||
| 1360 | update_ptep ptp,pte,t0,t1 | 1408 | dbit_lock spc,t0,t1 |
| 1409 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1361 | 1410 | ||
| 1362 | make_insert_tlb spc,pte,prot | 1411 | make_insert_tlb spc,pte,prot |
| 1363 | 1412 | ||
| 1364 | iitlbt pte,prot | 1413 | iitlbt pte,prot |
| 1414 | dbit_unlock1 spc,t0 | ||
| 1365 | 1415 | ||
| 1366 | rfir | 1416 | rfir |
| 1367 | nop | 1417 | nop |
| @@ -1379,11 +1429,13 @@ naitlb_miss_20w: | |||
| 1379 | 1429 | ||
| 1380 | L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w | 1430 | L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w |
| 1381 | 1431 | ||
| 1382 | update_ptep ptp,pte,t0,t1 | 1432 | dbit_lock spc,t0,t1 |
| 1433 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1383 | 1434 | ||
| 1384 | make_insert_tlb spc,pte,prot | 1435 | make_insert_tlb spc,pte,prot |
| 1385 | 1436 | ||
| 1386 | iitlbt pte,prot | 1437 | iitlbt pte,prot |
| 1438 | dbit_unlock1 spc,t0 | ||
| 1387 | 1439 | ||
| 1388 | rfir | 1440 | rfir |
| 1389 | nop | 1441 | nop |
| @@ -1405,7 +1457,8 @@ itlb_miss_11: | |||
| 1405 | 1457 | ||
| 1406 | L2_ptep ptp,pte,t0,va,itlb_fault | 1458 | L2_ptep ptp,pte,t0,va,itlb_fault |
| 1407 | 1459 | ||
| 1408 | update_ptep ptp,pte,t0,t1 | 1460 | dbit_lock spc,t0,t1 |
| 1461 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1409 | 1462 | ||
| 1410 | make_insert_tlb_11 spc,pte,prot | 1463 | make_insert_tlb_11 spc,pte,prot |
| 1411 | 1464 | ||
| @@ -1416,6 +1469,7 @@ itlb_miss_11: | |||
| 1416 | iitlbp prot,(%sr1,va) | 1469 | iitlbp prot,(%sr1,va) |
| 1417 | 1470 | ||
| 1418 | mtsp t0, %sr1 /* Restore sr1 */ | 1471 | mtsp t0, %sr1 /* Restore sr1 */ |
| 1472 | dbit_unlock1 spc,t0 | ||
| 1419 | 1473 | ||
| 1420 | rfir | 1474 | rfir |
| 1421 | nop | 1475 | nop |
| @@ -1427,7 +1481,8 @@ naitlb_miss_11: | |||
| 1427 | 1481 | ||
| 1428 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 | 1482 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 |
| 1429 | 1483 | ||
| 1430 | update_ptep ptp,pte,t0,t1 | 1484 | dbit_lock spc,t0,t1 |
| 1485 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1431 | 1486 | ||
| 1432 | make_insert_tlb_11 spc,pte,prot | 1487 | make_insert_tlb_11 spc,pte,prot |
| 1433 | 1488 | ||
| @@ -1438,6 +1493,7 @@ naitlb_miss_11: | |||
| 1438 | iitlbp prot,(%sr1,va) | 1493 | iitlbp prot,(%sr1,va) |
| 1439 | 1494 | ||
| 1440 | mtsp t0, %sr1 /* Restore sr1 */ | 1495 | mtsp t0, %sr1 /* Restore sr1 */ |
| 1496 | dbit_unlock1 spc,t0 | ||
| 1441 | 1497 | ||
| 1442 | rfir | 1498 | rfir |
| 1443 | nop | 1499 | nop |
| @@ -1459,13 +1515,15 @@ itlb_miss_20: | |||
| 1459 | 1515 | ||
| 1460 | L2_ptep ptp,pte,t0,va,itlb_fault | 1516 | L2_ptep ptp,pte,t0,va,itlb_fault |
| 1461 | 1517 | ||
| 1462 | update_ptep ptp,pte,t0,t1 | 1518 | dbit_lock spc,t0,t1 |
| 1519 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1463 | 1520 | ||
| 1464 | make_insert_tlb spc,pte,prot | 1521 | make_insert_tlb spc,pte,prot |
| 1465 | 1522 | ||
| 1466 | f_extend pte,t0 | 1523 | f_extend pte,t0 |
| 1467 | 1524 | ||
| 1468 | iitlbt pte,prot | 1525 | iitlbt pte,prot |
| 1526 | dbit_unlock1 spc,t0 | ||
| 1469 | 1527 | ||
| 1470 | rfir | 1528 | rfir |
| 1471 | nop | 1529 | nop |
| @@ -1477,13 +1535,15 @@ naitlb_miss_20: | |||
| 1477 | 1535 | ||
| 1478 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 | 1536 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 |
| 1479 | 1537 | ||
| 1480 | update_ptep ptp,pte,t0,t1 | 1538 | dbit_lock spc,t0,t1 |
| 1539 | update_ptep spc,ptp,pte,t0,t1 | ||
| 1481 | 1540 | ||
| 1482 | make_insert_tlb spc,pte,prot | 1541 | make_insert_tlb spc,pte,prot |
| 1483 | 1542 | ||
| 1484 | f_extend pte,t0 | 1543 | f_extend pte,t0 |
| 1485 | 1544 | ||
| 1486 | iitlbt pte,prot | 1545 | iitlbt pte,prot |
| 1546 | dbit_unlock1 spc,t0 | ||
| 1487 | 1547 | ||
| 1488 | rfir | 1548 | rfir |
| 1489 | nop | 1549 | nop |
| @@ -1507,29 +1567,13 @@ dbit_trap_20w: | |||
| 1507 | 1567 | ||
| 1508 | L3_ptep ptp,pte,t0,va,dbit_fault | 1568 | L3_ptep ptp,pte,t0,va,dbit_fault |
| 1509 | 1569 | ||
| 1510 | #ifdef CONFIG_SMP | 1570 | dbit_lock spc,t0,t1 |
| 1511 | cmpib,COND(=),n 0,spc,dbit_nolock_20w | 1571 | update_dirty spc,ptp,pte,t1 |
| 1512 | load32 PA(pa_dbit_lock),t0 | ||
| 1513 | |||
| 1514 | dbit_spin_20w: | ||
| 1515 | LDCW 0(t0),t1 | ||
| 1516 | cmpib,COND(=) 0,t1,dbit_spin_20w | ||
| 1517 | nop | ||
| 1518 | |||
| 1519 | dbit_nolock_20w: | ||
| 1520 | #endif | ||
| 1521 | update_dirty ptp,pte,t1 | ||
| 1522 | 1572 | ||
| 1523 | make_insert_tlb spc,pte,prot | 1573 | make_insert_tlb spc,pte,prot |
| 1524 | 1574 | ||
| 1525 | idtlbt pte,prot | 1575 | idtlbt pte,prot |
| 1526 | #ifdef CONFIG_SMP | 1576 | dbit_unlock0 spc,t0 |
| 1527 | cmpib,COND(=),n 0,spc,dbit_nounlock_20w | ||
| 1528 | ldi 1,t1 | ||
| 1529 | stw t1,0(t0) | ||
| 1530 | |||
| 1531 | dbit_nounlock_20w: | ||
| 1532 | #endif | ||
| 1533 | 1577 | ||
| 1534 | rfir | 1578 | rfir |
| 1535 | nop | 1579 | nop |
| @@ -1543,18 +1587,8 @@ dbit_trap_11: | |||
| 1543 | 1587 | ||
| 1544 | L2_ptep ptp,pte,t0,va,dbit_fault | 1588 | L2_ptep ptp,pte,t0,va,dbit_fault |
| 1545 | 1589 | ||
| 1546 | #ifdef CONFIG_SMP | 1590 | dbit_lock spc,t0,t1 |
| 1547 | cmpib,COND(=),n 0,spc,dbit_nolock_11 | 1591 | update_dirty spc,ptp,pte,t1 |
| 1548 | load32 PA(pa_dbit_lock),t0 | ||
| 1549 | |||
| 1550 | dbit_spin_11: | ||
| 1551 | LDCW 0(t0),t1 | ||
| 1552 | cmpib,= 0,t1,dbit_spin_11 | ||
| 1553 | nop | ||
| 1554 | |||
| 1555 | dbit_nolock_11: | ||
| 1556 | #endif | ||
| 1557 | update_dirty ptp,pte,t1 | ||
| 1558 | 1592 | ||
| 1559 | make_insert_tlb_11 spc,pte,prot | 1593 | make_insert_tlb_11 spc,pte,prot |
| 1560 | 1594 | ||
| @@ -1565,13 +1599,7 @@ dbit_nolock_11: | |||
| 1565 | idtlbp prot,(%sr1,va) | 1599 | idtlbp prot,(%sr1,va) |
| 1566 | 1600 | ||
| 1567 | mtsp t1, %sr1 /* Restore sr1 */ | 1601 | mtsp t1, %sr1 /* Restore sr1 */ |
| 1568 | #ifdef CONFIG_SMP | 1602 | dbit_unlock0 spc,t0 |
| 1569 | cmpib,COND(=),n 0,spc,dbit_nounlock_11 | ||
| 1570 | ldi 1,t1 | ||
| 1571 | stw t1,0(t0) | ||
| 1572 | |||
| 1573 | dbit_nounlock_11: | ||
| 1574 | #endif | ||
| 1575 | 1603 | ||
| 1576 | rfir | 1604 | rfir |
| 1577 | nop | 1605 | nop |
| @@ -1583,32 +1611,15 @@ dbit_trap_20: | |||
| 1583 | 1611 | ||
| 1584 | L2_ptep ptp,pte,t0,va,dbit_fault | 1612 | L2_ptep ptp,pte,t0,va,dbit_fault |
| 1585 | 1613 | ||
| 1586 | #ifdef CONFIG_SMP | 1614 | dbit_lock spc,t0,t1 |
| 1587 | cmpib,COND(=),n 0,spc,dbit_nolock_20 | 1615 | update_dirty spc,ptp,pte,t1 |
| 1588 | load32 PA(pa_dbit_lock),t0 | ||
| 1589 | |||
| 1590 | dbit_spin_20: | ||
| 1591 | LDCW 0(t0),t1 | ||
| 1592 | cmpib,= 0,t1,dbit_spin_20 | ||
| 1593 | nop | ||
| 1594 | |||
| 1595 | dbit_nolock_20: | ||
| 1596 | #endif | ||
| 1597 | update_dirty ptp,pte,t1 | ||
| 1598 | 1616 | ||
| 1599 | make_insert_tlb spc,pte,prot | 1617 | make_insert_tlb spc,pte,prot |
| 1600 | 1618 | ||
| 1601 | f_extend pte,t1 | 1619 | f_extend pte,t1 |
| 1602 | 1620 | ||
| 1603 | idtlbt pte,prot | 1621 | idtlbt pte,prot |
| 1604 | 1622 | dbit_unlock0 spc,t0 | |
| 1605 | #ifdef CONFIG_SMP | ||
| 1606 | cmpib,COND(=),n 0,spc,dbit_nounlock_20 | ||
| 1607 | ldi 1,t1 | ||
| 1608 | stw t1,0(t0) | ||
| 1609 | |||
| 1610 | dbit_nounlock_20: | ||
| 1611 | #endif | ||
| 1612 | 1623 | ||
| 1613 | rfir | 1624 | rfir |
| 1614 | nop | 1625 | nop |
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index e255db0bb761..55237a70e197 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c | |||
| @@ -166,22 +166,32 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
| 166 | seq_printf(p, "%*s: ", prec, "STK"); | 166 | seq_printf(p, "%*s: ", prec, "STK"); |
| 167 | for_each_online_cpu(j) | 167 | for_each_online_cpu(j) |
| 168 | seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage); | 168 | seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage); |
| 169 | seq_printf(p, " Kernel stack usage\n"); | 169 | seq_puts(p, " Kernel stack usage\n"); |
| 170 | # ifdef CONFIG_IRQSTACKS | ||
| 171 | seq_printf(p, "%*s: ", prec, "IST"); | ||
| 172 | for_each_online_cpu(j) | ||
| 173 | seq_printf(p, "%10u ", irq_stats(j)->irq_stack_usage); | ||
| 174 | seq_puts(p, " Interrupt stack usage\n"); | ||
| 175 | seq_printf(p, "%*s: ", prec, "ISC"); | ||
| 176 | for_each_online_cpu(j) | ||
| 177 | seq_printf(p, "%10u ", irq_stats(j)->irq_stack_counter); | ||
| 178 | seq_puts(p, " Interrupt stack usage counter\n"); | ||
| 179 | # endif | ||
| 170 | #endif | 180 | #endif |
| 171 | #ifdef CONFIG_SMP | 181 | #ifdef CONFIG_SMP |
| 172 | seq_printf(p, "%*s: ", prec, "RES"); | 182 | seq_printf(p, "%*s: ", prec, "RES"); |
| 173 | for_each_online_cpu(j) | 183 | for_each_online_cpu(j) |
| 174 | seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); | 184 | seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); |
| 175 | seq_printf(p, " Rescheduling interrupts\n"); | 185 | seq_puts(p, " Rescheduling interrupts\n"); |
| 176 | seq_printf(p, "%*s: ", prec, "CAL"); | 186 | seq_printf(p, "%*s: ", prec, "CAL"); |
| 177 | for_each_online_cpu(j) | 187 | for_each_online_cpu(j) |
| 178 | seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); | 188 | seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); |
| 179 | seq_printf(p, " Function call interrupts\n"); | 189 | seq_puts(p, " Function call interrupts\n"); |
| 180 | #endif | 190 | #endif |
| 181 | seq_printf(p, "%*s: ", prec, "TLB"); | 191 | seq_printf(p, "%*s: ", prec, "TLB"); |
| 182 | for_each_online_cpu(j) | 192 | for_each_online_cpu(j) |
| 183 | seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); | 193 | seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); |
| 184 | seq_printf(p, " TLB shootdowns\n"); | 194 | seq_puts(p, " TLB shootdowns\n"); |
| 185 | return 0; | 195 | return 0; |
| 186 | } | 196 | } |
| 187 | 197 | ||
| @@ -378,6 +388,7 @@ static inline void stack_overflow_check(struct pt_regs *regs) | |||
| 378 | unsigned long sp = regs->gr[30]; | 388 | unsigned long sp = regs->gr[30]; |
| 379 | unsigned long stack_usage; | 389 | unsigned long stack_usage; |
| 380 | unsigned int *last_usage; | 390 | unsigned int *last_usage; |
| 391 | int cpu = smp_processor_id(); | ||
| 381 | 392 | ||
| 382 | /* if sr7 != 0, we interrupted a userspace process which we do not want | 393 | /* if sr7 != 0, we interrupted a userspace process which we do not want |
| 383 | * to check for stack overflow. We will only check the kernel stack. */ | 394 | * to check for stack overflow. We will only check the kernel stack. */ |
| @@ -386,7 +397,31 @@ static inline void stack_overflow_check(struct pt_regs *regs) | |||
| 386 | 397 | ||
| 387 | /* calculate kernel stack usage */ | 398 | /* calculate kernel stack usage */ |
| 388 | stack_usage = sp - stack_start; | 399 | stack_usage = sp - stack_start; |
| 389 | last_usage = &per_cpu(irq_stat.kernel_stack_usage, smp_processor_id()); | 400 | #ifdef CONFIG_IRQSTACKS |
| 401 | if (likely(stack_usage <= THREAD_SIZE)) | ||
| 402 | goto check_kernel_stack; /* found kernel stack */ | ||
| 403 | |||
| 404 | /* check irq stack usage */ | ||
| 405 | stack_start = (unsigned long) &per_cpu(irq_stack_union, cpu).stack; | ||
| 406 | stack_usage = sp - stack_start; | ||
| 407 | |||
| 408 | last_usage = &per_cpu(irq_stat.irq_stack_usage, cpu); | ||
| 409 | if (unlikely(stack_usage > *last_usage)) | ||
| 410 | *last_usage = stack_usage; | ||
| 411 | |||
| 412 | if (likely(stack_usage < (IRQ_STACK_SIZE - STACK_MARGIN))) | ||
| 413 | return; | ||
| 414 | |||
| 415 | pr_emerg("stackcheck: %s will most likely overflow irq stack " | ||
| 416 | "(sp:%lx, stk bottom-top:%lx-%lx)\n", | ||
| 417 | current->comm, sp, stack_start, stack_start + IRQ_STACK_SIZE); | ||
| 418 | goto panic_check; | ||
| 419 | |||
| 420 | check_kernel_stack: | ||
| 421 | #endif | ||
| 422 | |||
| 423 | /* check kernel stack usage */ | ||
| 424 | last_usage = &per_cpu(irq_stat.kernel_stack_usage, cpu); | ||
| 390 | 425 | ||
| 391 | if (unlikely(stack_usage > *last_usage)) | 426 | if (unlikely(stack_usage > *last_usage)) |
| 392 | *last_usage = stack_usage; | 427 | *last_usage = stack_usage; |
| @@ -398,31 +433,69 @@ static inline void stack_overflow_check(struct pt_regs *regs) | |||
| 398 | "(sp:%lx, stk bottom-top:%lx-%lx)\n", | 433 | "(sp:%lx, stk bottom-top:%lx-%lx)\n", |
| 399 | current->comm, sp, stack_start, stack_start + THREAD_SIZE); | 434 | current->comm, sp, stack_start, stack_start + THREAD_SIZE); |
| 400 | 435 | ||
| 436 | #ifdef CONFIG_IRQSTACKS | ||
| 437 | panic_check: | ||
| 438 | #endif | ||
| 401 | if (sysctl_panic_on_stackoverflow) | 439 | if (sysctl_panic_on_stackoverflow) |
| 402 | panic("low stack detected by irq handler - check messages\n"); | 440 | panic("low stack detected by irq handler - check messages\n"); |
| 403 | #endif | 441 | #endif |
| 404 | } | 442 | } |
| 405 | 443 | ||
| 406 | #ifdef CONFIG_IRQSTACKS | 444 | #ifdef CONFIG_IRQSTACKS |
| 407 | DEFINE_PER_CPU(union irq_stack_union, irq_stack_union); | 445 | DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = { |
| 446 | .lock = __RAW_SPIN_LOCK_UNLOCKED((irq_stack_union).lock) | ||
| 447 | }; | ||
| 408 | 448 | ||
| 409 | static void execute_on_irq_stack(void *func, unsigned long param1) | 449 | static void execute_on_irq_stack(void *func, unsigned long param1) |
| 410 | { | 450 | { |
| 411 | unsigned long *irq_stack_start; | 451 | union irq_stack_union *union_ptr; |
| 412 | unsigned long irq_stack; | 452 | unsigned long irq_stack; |
| 413 | int cpu = smp_processor_id(); | 453 | raw_spinlock_t *irq_stack_in_use; |
| 414 | 454 | ||
| 415 | irq_stack_start = &per_cpu(irq_stack_union, cpu).stack[0]; | 455 | union_ptr = &per_cpu(irq_stack_union, smp_processor_id()); |
| 416 | irq_stack = (unsigned long) irq_stack_start; | 456 | irq_stack = (unsigned long) &union_ptr->stack; |
| 417 | irq_stack = ALIGN(irq_stack, 16); /* align for stack frame usage */ | 457 | irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.lock), |
| 458 | 64); /* align for stack frame usage */ | ||
| 418 | 459 | ||
| 419 | BUG_ON(*irq_stack_start); /* report bug if we were called recursive. */ | 460 | /* We may be called recursive. If we are already using the irq stack, |
| 420 | *irq_stack_start = 1; | 461 | * just continue to use it. Use spinlocks to serialize |
| 462 | * the irq stack usage. | ||
| 463 | */ | ||
| 464 | irq_stack_in_use = &union_ptr->lock; | ||
| 465 | if (!raw_spin_trylock(irq_stack_in_use)) { | ||
| 466 | void (*direct_call)(unsigned long p1) = func; | ||
| 467 | |||
| 468 | /* We are using the IRQ stack already. | ||
| 469 | * Do direct call on current stack. */ | ||
| 470 | direct_call(param1); | ||
| 471 | return; | ||
| 472 | } | ||
| 421 | 473 | ||
| 422 | /* This is where we switch to the IRQ stack. */ | 474 | /* This is where we switch to the IRQ stack. */ |
| 423 | call_on_stack(param1, func, irq_stack); | 475 | call_on_stack(param1, func, irq_stack); |
| 424 | 476 | ||
| 425 | *irq_stack_start = 0; | 477 | __inc_irq_stat(irq_stack_counter); |
| 478 | |||
| 479 | /* free up irq stack usage. */ | ||
| 480 | do_raw_spin_unlock(irq_stack_in_use); | ||
| 481 | } | ||
| 482 | |||
| 483 | asmlinkage void do_softirq(void) | ||
| 484 | { | ||
| 485 | __u32 pending; | ||
| 486 | unsigned long flags; | ||
| 487 | |||
| 488 | if (in_interrupt()) | ||
| 489 | return; | ||
| 490 | |||
| 491 | local_irq_save(flags); | ||
| 492 | |||
| 493 | pending = local_softirq_pending(); | ||
| 494 | |||
| 495 | if (pending) | ||
| 496 | execute_on_irq_stack(__do_softirq, 0); | ||
| 497 | |||
| 498 | local_irq_restore(flags); | ||
| 426 | } | 499 | } |
| 427 | #endif /* CONFIG_IRQSTACKS */ | 500 | #endif /* CONFIG_IRQSTACKS */ |
| 428 | 501 | ||
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index ce939ac8622b..1c965642068b 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
| @@ -1069,7 +1069,7 @@ void flush_tlb_all(void) | |||
| 1069 | { | 1069 | { |
| 1070 | int do_recycle; | 1070 | int do_recycle; |
| 1071 | 1071 | ||
| 1072 | inc_irq_stat(irq_tlb_count); | 1072 | __inc_irq_stat(irq_tlb_count); |
| 1073 | do_recycle = 0; | 1073 | do_recycle = 0; |
| 1074 | spin_lock(&sid_lock); | 1074 | spin_lock(&sid_lock); |
| 1075 | if (dirty_space_ids > RECYCLE_THRESHOLD) { | 1075 | if (dirty_space_ids > RECYCLE_THRESHOLD) { |
| @@ -1090,7 +1090,7 @@ void flush_tlb_all(void) | |||
| 1090 | #else | 1090 | #else |
| 1091 | void flush_tlb_all(void) | 1091 | void flush_tlb_all(void) |
| 1092 | { | 1092 | { |
| 1093 | inc_irq_stat(irq_tlb_count); | 1093 | __inc_irq_stat(irq_tlb_count); |
| 1094 | spin_lock(&sid_lock); | 1094 | spin_lock(&sid_lock); |
| 1095 | flush_tlb_all_local(NULL); | 1095 | flush_tlb_all_local(NULL); |
| 1096 | recycle_sids(); | 1096 | recycle_sids(); |
