diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-07 02:44:37 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:11:52 -0500 |
commit | d257d5da39a78b32721ca84b2ba7f461f2f7ed7f (patch) | |
tree | ac28d377688ebe13a4d38e05f4ff65ba73d8652a /arch/sparc64/mm/init.c | |
parent | 840aaef8db32572b6d11e0d5cb5e6efcbc812000 (diff) |
[SPARC64]: Initial sun4v TLB miss handling infrastructure.
Things are a little tricky because, unlike sun4u, we have
to:
1) do a hypervisor trap to do the TLB load.
2) do the TSB lookup calculations by hand
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/mm/init.c')
-rw-r--r-- | arch/sparc64/mm/init.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index ab50cd9618f3..e9aac424877f 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
@@ -1050,8 +1050,25 @@ unsigned long __init find_ecache_flush_span(unsigned long size) | |||
1050 | 1050 | ||
1051 | static void __init tsb_phys_patch(void) | 1051 | static void __init tsb_phys_patch(void) |
1052 | { | 1052 | { |
1053 | struct tsb_ldquad_phys_patch_entry *pquad; | ||
1053 | struct tsb_phys_patch_entry *p; | 1054 | struct tsb_phys_patch_entry *p; |
1054 | 1055 | ||
1056 | pquad = &__tsb_ldquad_phys_patch; | ||
1057 | while (pquad < &__tsb_ldquad_phys_patch_end) { | ||
1058 | unsigned long addr = pquad->addr; | ||
1059 | |||
1060 | if (tlb_type == hypervisor) | ||
1061 | *(unsigned int *) addr = pquad->sun4v_insn; | ||
1062 | else | ||
1063 | *(unsigned int *) addr = pquad->sun4u_insn; | ||
1064 | wmb(); | ||
1065 | __asm__ __volatile__("flush %0" | ||
1066 | : /* no outputs */ | ||
1067 | : "r" (addr)); | ||
1068 | |||
1069 | pquad++; | ||
1070 | } | ||
1071 | |||
1055 | p = &__tsb_phys_patch; | 1072 | p = &__tsb_phys_patch; |
1056 | while (p < &__tsb_phys_patch_end) { | 1073 | while (p < &__tsb_phys_patch_end) { |
1057 | unsigned long addr = p->addr; | 1074 | unsigned long addr = p->addr; |
@@ -1069,6 +1086,7 @@ static void __init tsb_phys_patch(void) | |||
1069 | /* paging_init() sets up the page tables */ | 1086 | /* paging_init() sets up the page tables */ |
1070 | 1087 | ||
1071 | extern void cheetah_ecache_flush_init(void); | 1088 | extern void cheetah_ecache_flush_init(void); |
1089 | extern void sun4v_patch_tlb_handlers(void); | ||
1072 | 1090 | ||
1073 | static unsigned long last_valid_pfn; | 1091 | static unsigned long last_valid_pfn; |
1074 | pgd_t swapper_pg_dir[2048]; | 1092 | pgd_t swapper_pg_dir[2048]; |
@@ -1078,9 +1096,13 @@ void __init paging_init(void) | |||
1078 | unsigned long end_pfn, pages_avail, shift; | 1096 | unsigned long end_pfn, pages_avail, shift; |
1079 | unsigned long real_end, i; | 1097 | unsigned long real_end, i; |
1080 | 1098 | ||
1081 | if (tlb_type == cheetah_plus) | 1099 | if (tlb_type == cheetah_plus || |
1100 | tlb_type == hypervisor) | ||
1082 | tsb_phys_patch(); | 1101 | tsb_phys_patch(); |
1083 | 1102 | ||
1103 | if (tlb_type == hypervisor) | ||
1104 | sun4v_patch_tlb_handlers(); | ||
1105 | |||
1084 | /* Find available physical memory... */ | 1106 | /* Find available physical memory... */ |
1085 | read_obp_memory("available", &pavail[0], &pavail_ents); | 1107 | read_obp_memory("available", &pavail[0], &pavail_ents); |
1086 | 1108 | ||