aboutsummaryrefslogtreecommitdiff
path: root/arch/sparc64/mm
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-06 23:44:37 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 01:11:52 -0800
commitd257d5da39a78b32721ca84b2ba7f461f2f7ed7f (patch)
treeac28d377688ebe13a4d38e05f4ff65ba73d8652a /arch/sparc64/mm
parent840aaef8db32572b6d11e0d5cb5e6efcbc812000 (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')
-rw-r--r--arch/sparc64/mm/init.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index ab50cd9618f..e9aac424877 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)
static void __init tsb_phys_patch(void)
{
+ struct tsb_ldquad_phys_patch_entry *pquad;
struct tsb_phys_patch_entry *p;
+ pquad = &__tsb_ldquad_phys_patch;
+ while (pquad < &__tsb_ldquad_phys_patch_end) {
+ unsigned long addr = pquad->addr;
+
+ if (tlb_type == hypervisor)
+ *(unsigned int *) addr = pquad->sun4v_insn;
+ else
+ *(unsigned int *) addr = pquad->sun4u_insn;
+ wmb();
+ __asm__ __volatile__("flush %0"
+ : /* no outputs */
+ : "r" (addr));
+
+ pquad++;
+ }
+
p = &__tsb_phys_patch;
while (p < &__tsb_phys_patch_end) {
unsigned long addr = p->addr;
@@ -1069,6 +1086,7 @@ static void __init tsb_phys_patch(void)
/* paging_init() sets up the page tables */
extern void cheetah_ecache_flush_init(void);
+extern void sun4v_patch_tlb_handlers(void);
static unsigned long last_valid_pfn;
pgd_t swapper_pg_dir[2048];
@@ -1078,9 +1096,13 @@ void __init paging_init(void)
unsigned long end_pfn, pages_avail, shift;
unsigned long real_end, i;
- if (tlb_type == cheetah_plus)
+ if (tlb_type == cheetah_plus ||
+ tlb_type == hypervisor)
tsb_phys_patch();
+ if (tlb_type == hypervisor)
+ sun4v_patch_tlb_handlers();
+
/* Find available physical memory... */
read_obp_memory("available", &pavail[0], &pavail_ents);