aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-09-22 00:49:32 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-09-22 00:49:32 -0400
commit1ac4f5ebaa496a23ab4a148c9864d7e30a6c6cd3 (patch)
tree1ab1e111f596b8c66c741e63f14d721cb1818c7a
parent059deb693ec191e563ec69533d24f3feff0b78cd (diff)
[SPARC64]: Remove ktlb.S instruction patching.
This was kind of ugly, and actually buggy. The bug was that we didn't handle a machine with memory starting > 4GB. If the 'prompmd' was allocated in physical memory > 4GB we'd croak because the obp_iaddr_patch and obp_daddr_patch things only supported a 32-bit physical address. So fix this by just loading the appropriate values from two variables in the kernel image, which is locked into the TLB and thus accesses to them can't cause a recursive TLB miss. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/ktlb.S31
-rw-r--r--arch/sparc64/mm/init.c32
2 files changed, 24 insertions, 39 deletions
diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S
index b7176792c9a2..a591bc0ebc7b 100644
--- a/arch/sparc64/kernel/ktlb.S
+++ b/arch/sparc64/kernel/ktlb.S
@@ -15,8 +15,6 @@
15 .text 15 .text
16 .align 32 16 .align 32
17 17
18 .globl sparc64_vpte_patchme1
19 .globl sparc64_vpte_patchme2
20/* 18/*
21 * On a second level vpte miss, check whether the original fault is to the OBP 19 * On a second level vpte miss, check whether the original fault is to the OBP
22 * range (note that this is only possible for instruction miss, data misses to 20 * range (note that this is only possible for instruction miss, data misses to
@@ -33,18 +31,17 @@ sparc64_vpte_nucleus:
33 */ 31 */
34 sethi %hi(LOW_OBP_ADDRESS), %g5 32 sethi %hi(LOW_OBP_ADDRESS), %g5
35 cmp %g4, %g5 33 cmp %g4, %g5
36 blu,pn %xcc, sparc64_vpte_patchme1 34 blu,pn %xcc, kern_vpte
37 mov 0x1, %g5 35 mov 0x1, %g5
38 sllx %g5, 32, %g5 36 sllx %g5, 32, %g5
39 cmp %g4, %g5 37 cmp %g4, %g5
40 blu,pn %xcc, obp_iaddr_patch 38 blu,pn %xcc, vpte_insn_obp
41 nop 39 nop
42 40
43 /* These two instructions are patched by paginig_init(). */ 41 /* These two instructions are patched by paginig_init(). */
44sparc64_vpte_patchme1: 42kern_vpte:
45 sethi %hi(0), %g5 43 sethi %hi(swapper_pgd_zero), %g5
46sparc64_vpte_patchme2: 44 lduw [%g5 + %lo(swapper_pgd_zero)], %g5
47 or %g5, %lo(0), %g5
48 45
49 /* With kernel PGD in %g5, branch back into dtlb_backend. */ 46 /* With kernel PGD in %g5, branch back into dtlb_backend. */
50 ba,pt %xcc, sparc64_kpte_continue 47 ba,pt %xcc, sparc64_kpte_continue
@@ -60,11 +57,9 @@ vpte_noent:
60 stxa %g4, [%g1 + %g1] ASI_DMMU 57 stxa %g4, [%g1 + %g1] ASI_DMMU
61 done 58 done
62 59
63 .globl obp_iaddr_patch 60vpte_insn_obp:
64obp_iaddr_patch: 61 sethi %hi(prom_pmd_phys), %g5
65 /* These two instructions patched by inherit_prom_mappings(). */ 62 ldx [%g5 + %lo(prom_pmd_phys)], %g5
66 sethi %hi(0), %g5
67 or %g5, %lo(0), %g5
68 63
69 /* Behave as if we are at TL0. */ 64 /* Behave as if we are at TL0. */
70 wrpr %g0, 1, %tl 65 wrpr %g0, 1, %tl
@@ -100,11 +95,9 @@ obp_iaddr_patch:
100 stxa %g5, [%g0] ASI_ITLB_DATA_IN 95 stxa %g5, [%g0] ASI_ITLB_DATA_IN
101 retry 96 retry
102 97
103 .globl obp_daddr_patch 98kvmap_do_obp:
104obp_daddr_patch: 99 sethi %hi(prom_pmd_phys), %g5
105 /* These two instructions patched by inherit_prom_mappings(). */ 100 ldx [%g5 + %lo(prom_pmd_phys)], %g5
106 sethi %hi(0), %g5
107 or %g5, %lo(0), %g5
108 101
109 /* Get PMD offset. */ 102 /* Get PMD offset. */
110 srlx %g4, 23, %g6 103 srlx %g4, 23, %g6
@@ -159,7 +152,7 @@ kvmap_check_obp:
159 mov 0x1, %g5 152 mov 0x1, %g5
160 sllx %g5, 32, %g5 153 sllx %g5, 32, %g5
161 cmp %g4, %g5 154 cmp %g4, %g5
162 blu,pn %xcc, obp_daddr_patch 155 blu,pn %xcc, kvmap_do_obp
163 nop 156 nop
164 157
165kvmap_vmalloc_addr: 158kvmap_vmalloc_addr:
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index fdb1ebb308c9..aaf9a3eee997 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -20,6 +20,7 @@
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/seq_file.h> 21#include <linux/seq_file.h>
22#include <linux/kprobes.h> 22#include <linux/kprobes.h>
23#include <linux/cache.h>
23 24
24#include <asm/head.h> 25#include <asm/head.h>
25#include <asm/system.h> 26#include <asm/system.h>
@@ -45,10 +46,10 @@ struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
45unsigned long *sparc64_valid_addr_bitmap; 46unsigned long *sparc64_valid_addr_bitmap;
46 47
47/* Ugly, but necessary... -DaveM */ 48/* Ugly, but necessary... -DaveM */
48unsigned long phys_base; 49unsigned long phys_base __read_mostly;
49unsigned long kern_base; 50unsigned long kern_base __read_mostly;
50unsigned long kern_size; 51unsigned long kern_size __read_mostly;
51unsigned long pfn_base; 52unsigned long pfn_base __read_mostly;
52 53
53/* This is even uglier. We have a problem where the kernel may not be 54/* This is even uglier. We have a problem where the kernel may not be
54 * located at phys_base. However, initial __alloc_bootmem() calls need to 55 * located at phys_base. However, initial __alloc_bootmem() calls need to
@@ -73,7 +74,7 @@ extern unsigned long sparc_ramdisk_image64;
73extern unsigned int sparc_ramdisk_image; 74extern unsigned int sparc_ramdisk_image;
74extern unsigned int sparc_ramdisk_size; 75extern unsigned int sparc_ramdisk_size;
75 76
76struct page *mem_map_zero; 77struct page *mem_map_zero __read_mostly;
77 78
78int bigkernel = 0; 79int bigkernel = 0;
79 80
@@ -318,6 +319,10 @@ extern void register_prom_callbacks(void);
318/* Exported for SMP bootup purposes. */ 319/* Exported for SMP bootup purposes. */
319unsigned long kern_locked_tte_data; 320unsigned long kern_locked_tte_data;
320 321
322/* Exported for kernel TLB miss handling in ktlb.S */
323unsigned long prom_pmd_phys __read_mostly;
324unsigned int swapper_pgd_zero __read_mostly;
325
321void __init early_pgtable_allocfail(char *type) 326void __init early_pgtable_allocfail(char *type)
322{ 327{
323 prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type); 328 prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
@@ -364,7 +369,6 @@ static void inherit_prom_mappings(void)
364 pmd_t *pmdp; 369 pmd_t *pmdp;
365 pte_t *ptep; 370 pte_t *ptep;
366 int node, n, i, tsz; 371 int node, n, i, tsz;
367 extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2];
368 372
369 node = prom_finddevice("/virtual-memory"); 373 node = prom_finddevice("/virtual-memory");
370 n = prom_getproplen(node, "translations"); 374 n = prom_getproplen(node, "translations");
@@ -434,13 +438,7 @@ static void inherit_prom_mappings(void)
434 } 438 }
435 } 439 }
436 } 440 }
437 phys_page = __pa(prompmd); 441 prom_pmd_phys = __pa(prompmd);
438 obp_iaddr_patch[0] |= (phys_page >> 10);
439 obp_iaddr_patch[1] |= (phys_page & 0x3ff);
440 flushi((long)&obp_iaddr_patch[0]);
441 obp_daddr_patch[0] |= (phys_page >> 10);
442 obp_daddr_patch[1] |= (phys_page & 0x3ff);
443 flushi((long)&obp_daddr_patch[0]);
444 442
445 /* Now fixup OBP's idea about where we really are mapped. */ 443 /* Now fixup OBP's idea about where we really are mapped. */
446 prom_printf("Remapping the kernel... "); 444 prom_printf("Remapping the kernel... ");
@@ -1407,8 +1405,6 @@ static unsigned long last_valid_pfn;
1407void __init paging_init(void) 1405void __init paging_init(void)
1408{ 1406{
1409 extern pmd_t swapper_pmd_dir[1024]; 1407 extern pmd_t swapper_pmd_dir[1024];
1410 extern unsigned int sparc64_vpte_patchme1[1];
1411 extern unsigned int sparc64_vpte_patchme2[1];
1412 unsigned long alias_base = kern_base + PAGE_OFFSET; 1408 unsigned long alias_base = kern_base + PAGE_OFFSET;
1413 unsigned long second_alias_page = 0; 1409 unsigned long second_alias_page = 0;
1414 unsigned long pt, flags, end_pfn, pages_avail; 1410 unsigned long pt, flags, end_pfn, pages_avail;
@@ -1502,11 +1498,7 @@ void __init paging_init(void)
1502 pud_set(pud_offset(&swapper_pg_dir[0], 0), 1498 pud_set(pud_offset(&swapper_pg_dir[0], 0),
1503 swapper_pmd_dir + (shift / sizeof(pgd_t))); 1499 swapper_pmd_dir + (shift / sizeof(pgd_t)));
1504 1500
1505 sparc64_vpte_patchme1[0] |= 1501 swapper_pgd_zero = pgd_val(init_mm.pgd[0]);
1506 (((unsigned long)pgd_val(init_mm.pgd[0])) >> 10);
1507 sparc64_vpte_patchme2[0] |=
1508 (((unsigned long)pgd_val(init_mm.pgd[0])) & 0x3ff);
1509 flushi((long)&sparc64_vpte_patchme1[0]);
1510 1502
1511 /* Setup bootmem... */ 1503 /* Setup bootmem... */
1512 pages_avail = 0; 1504 pages_avail = 0;