diff options
Diffstat (limited to 'arch/sparc64')
| -rw-r--r-- | arch/sparc64/kernel/entry.S | 12 | ||||
| -rw-r--r-- | arch/sparc64/kernel/smp.c | 19 | ||||
| -rw-r--r-- | arch/sparc64/mm/init.c | 29 |
3 files changed, 45 insertions, 15 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index c9b0d7af64..ea257e8283 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
| @@ -2593,3 +2593,15 @@ sun4v_mmustat_info: | |||
| 2593 | retl | 2593 | retl |
| 2594 | nop | 2594 | nop |
| 2595 | .size sun4v_mmustat_info, .-sun4v_mmustat_info | 2595 | .size sun4v_mmustat_info, .-sun4v_mmustat_info |
| 2596 | |||
| 2597 | .globl sun4v_mmu_demap_all | ||
| 2598 | .type sun4v_mmu_demap_all,#function | ||
| 2599 | sun4v_mmu_demap_all: | ||
| 2600 | clr %o0 | ||
| 2601 | clr %o1 | ||
| 2602 | mov HV_MMU_ALL, %o2 | ||
| 2603 | mov HV_FAST_MMU_DEMAP_ALL, %o5 | ||
| 2604 | ta HV_FAST_TRAP | ||
| 2605 | retl | ||
| 2606 | nop | ||
| 2607 | .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all | ||
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 894b506f96..c39944927f 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
| @@ -476,7 +476,7 @@ static inline void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, cpuma | |||
| 476 | */ | 476 | */ |
| 477 | static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) | 477 | static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) |
| 478 | { | 478 | { |
| 479 | u64 pstate, ver; | 479 | u64 pstate, ver, busy_mask; |
| 480 | int nack_busy_id, is_jbus, need_more; | 480 | int nack_busy_id, is_jbus, need_more; |
| 481 | 481 | ||
| 482 | if (cpus_empty(mask)) | 482 | if (cpus_empty(mask)) |
| @@ -508,14 +508,20 @@ retry: | |||
| 508 | "i" (ASI_INTR_W)); | 508 | "i" (ASI_INTR_W)); |
| 509 | 509 | ||
| 510 | nack_busy_id = 0; | 510 | nack_busy_id = 0; |
| 511 | busy_mask = 0; | ||
| 511 | { | 512 | { |
| 512 | int i; | 513 | int i; |
| 513 | 514 | ||
| 514 | for_each_cpu_mask(i, mask) { | 515 | for_each_cpu_mask(i, mask) { |
| 515 | u64 target = (i << 14) | 0x70; | 516 | u64 target = (i << 14) | 0x70; |
| 516 | 517 | ||
| 517 | if (!is_jbus) | 518 | if (is_jbus) { |
| 519 | busy_mask |= (0x1UL << (i * 2)); | ||
| 520 | } else { | ||
| 518 | target |= (nack_busy_id << 24); | 521 | target |= (nack_busy_id << 24); |
| 522 | busy_mask |= (0x1UL << | ||
| 523 | (nack_busy_id * 2)); | ||
| 524 | } | ||
| 519 | __asm__ __volatile__( | 525 | __asm__ __volatile__( |
| 520 | "stxa %%g0, [%0] %1\n\t" | 526 | "stxa %%g0, [%0] %1\n\t" |
| 521 | "membar #Sync\n\t" | 527 | "membar #Sync\n\t" |
| @@ -531,15 +537,16 @@ retry: | |||
| 531 | 537 | ||
| 532 | /* Now, poll for completion. */ | 538 | /* Now, poll for completion. */ |
| 533 | { | 539 | { |
| 534 | u64 dispatch_stat; | 540 | u64 dispatch_stat, nack_mask; |
| 535 | long stuck; | 541 | long stuck; |
| 536 | 542 | ||
| 537 | stuck = 100000 * nack_busy_id; | 543 | stuck = 100000 * nack_busy_id; |
| 544 | nack_mask = busy_mask << 1; | ||
| 538 | do { | 545 | do { |
| 539 | __asm__ __volatile__("ldxa [%%g0] %1, %0" | 546 | __asm__ __volatile__("ldxa [%%g0] %1, %0" |
| 540 | : "=r" (dispatch_stat) | 547 | : "=r" (dispatch_stat) |
| 541 | : "i" (ASI_INTR_DISPATCH_STAT)); | 548 | : "i" (ASI_INTR_DISPATCH_STAT)); |
| 542 | if (dispatch_stat == 0UL) { | 549 | if (!(dispatch_stat & (busy_mask | nack_mask))) { |
| 543 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" | 550 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" |
| 544 | : : "r" (pstate)); | 551 | : : "r" (pstate)); |
| 545 | if (unlikely(need_more)) { | 552 | if (unlikely(need_more)) { |
| @@ -556,12 +563,12 @@ retry: | |||
| 556 | } | 563 | } |
| 557 | if (!--stuck) | 564 | if (!--stuck) |
| 558 | break; | 565 | break; |
| 559 | } while (dispatch_stat & 0x5555555555555555UL); | 566 | } while (dispatch_stat & busy_mask); |
| 560 | 567 | ||
| 561 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" | 568 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" |
| 562 | : : "r" (pstate)); | 569 | : : "r" (pstate)); |
| 563 | 570 | ||
| 564 | if ((dispatch_stat & ~(0x5555555555555555UL)) == 0) { | 571 | if (dispatch_stat & busy_mask) { |
| 565 | /* Busy bits will not clear, continue instead | 572 | /* Busy bits will not clear, continue instead |
| 566 | * of freezing up on this cpu. | 573 | * of freezing up on this cpu. |
| 567 | */ | 574 | */ |
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index e18ccf8522..fbeb55d71e 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
| @@ -1133,14 +1133,9 @@ static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) | |||
| 1133 | } | 1133 | } |
| 1134 | } | 1134 | } |
| 1135 | 1135 | ||
| 1136 | static void __init kernel_physical_mapping_init(void) | 1136 | static void __init init_kpte_bitmap(void) |
| 1137 | { | 1137 | { |
| 1138 | unsigned long i; | 1138 | unsigned long i; |
| 1139 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
| 1140 | unsigned long mem_alloced = 0UL; | ||
| 1141 | #endif | ||
| 1142 | |||
| 1143 | read_obp_memory("reg", &pall[0], &pall_ents); | ||
| 1144 | 1139 | ||
| 1145 | for (i = 0; i < pall_ents; i++) { | 1140 | for (i = 0; i < pall_ents; i++) { |
| 1146 | unsigned long phys_start, phys_end; | 1141 | unsigned long phys_start, phys_end; |
| @@ -1149,14 +1144,24 @@ static void __init kernel_physical_mapping_init(void) | |||
| 1149 | phys_end = phys_start + pall[i].reg_size; | 1144 | phys_end = phys_start + pall[i].reg_size; |
| 1150 | 1145 | ||
| 1151 | mark_kpte_bitmap(phys_start, phys_end); | 1146 | mark_kpte_bitmap(phys_start, phys_end); |
| 1147 | } | ||
| 1148 | } | ||
| 1152 | 1149 | ||
| 1150 | static void __init kernel_physical_mapping_init(void) | ||
| 1151 | { | ||
| 1153 | #ifdef CONFIG_DEBUG_PAGEALLOC | 1152 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 1153 | unsigned long i, mem_alloced = 0UL; | ||
| 1154 | |||
| 1155 | for (i = 0; i < pall_ents; i++) { | ||
| 1156 | unsigned long phys_start, phys_end; | ||
| 1157 | |||
| 1158 | phys_start = pall[i].phys_addr; | ||
| 1159 | phys_end = phys_start + pall[i].reg_size; | ||
| 1160 | |||
| 1154 | mem_alloced += kernel_map_range(phys_start, phys_end, | 1161 | mem_alloced += kernel_map_range(phys_start, phys_end, |
| 1155 | PAGE_KERNEL); | 1162 | PAGE_KERNEL); |
| 1156 | #endif | ||
| 1157 | } | 1163 | } |
| 1158 | 1164 | ||
| 1159 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
| 1160 | printk("Allocated %ld bytes for kernel page tables.\n", | 1165 | printk("Allocated %ld bytes for kernel page tables.\n", |
| 1161 | mem_alloced); | 1166 | mem_alloced); |
| 1162 | 1167 | ||
| @@ -1398,6 +1403,10 @@ void __init paging_init(void) | |||
| 1398 | 1403 | ||
| 1399 | inherit_prom_mappings(); | 1404 | inherit_prom_mappings(); |
| 1400 | 1405 | ||
| 1406 | read_obp_memory("reg", &pall[0], &pall_ents); | ||
| 1407 | |||
| 1408 | init_kpte_bitmap(); | ||
| 1409 | |||
| 1401 | /* Ok, we can use our TLB miss and window trap handlers safely. */ | 1410 | /* Ok, we can use our TLB miss and window trap handlers safely. */ |
| 1402 | setup_tba(); | 1411 | setup_tba(); |
| 1403 | 1412 | ||
| @@ -1904,7 +1913,9 @@ void __flush_tlb_all(void) | |||
| 1904 | "wrpr %0, %1, %%pstate" | 1913 | "wrpr %0, %1, %%pstate" |
| 1905 | : "=r" (pstate) | 1914 | : "=r" (pstate) |
| 1906 | : "i" (PSTATE_IE)); | 1915 | : "i" (PSTATE_IE)); |
| 1907 | if (tlb_type == spitfire) { | 1916 | if (tlb_type == hypervisor) { |
| 1917 | sun4v_mmu_demap_all(); | ||
| 1918 | } else if (tlb_type == spitfire) { | ||
| 1908 | for (i = 0; i < 64; i++) { | 1919 | for (i = 0; i < 64; i++) { |
| 1909 | /* Spitfire Errata #32 workaround */ | 1920 | /* Spitfire Errata #32 workaround */ |
| 1910 | /* NOTE: Always runs on spitfire, so no | 1921 | /* NOTE: Always runs on spitfire, so no |
