[SPARC64]: Hypervisor TSB context switching.
authorDavid S. Miller <davem@sunset.davemloft.net>
Fri, 10 Feb 2006 01:21:53 +0000 (17:21 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 20 Mar 2006 09:12:06 +0000 (01:12 -0800)
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc64/kernel/tsb.S
arch/sparc64/mm/tsb.c
include/asm-sparc64/mmu.h
include/asm-sparc64/mmu_context.h

index c848c88..a53ec6f 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <asm/tsb.h>
+#include <asm/hypervisor.h>
 
        .text
        .align  32
@@ -233,6 +234,7 @@ tsb_flush:
         * %o1: TSB register value
         * %o2: TSB virtual address
         * %o3: TSB mapping locked PTE
+        * %o4: Hypervisor TSB descriptor physical address
         *
         * We have to run this whole thing with interrupts
         * disabled so that the current cpu doesn't change
@@ -251,30 +253,40 @@ __tsb_context_switch:
        add     %g2, %g1, %g2
        stx     %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR]
 
-661:   mov     TSB_REG, %g1
-       stxa    %o1, [%g1] ASI_DMMU
-       .section .sun4v_2insn_patch, "ax"
-       .word   661b
+       sethi   %hi(tlb_type), %g1
+       lduw    [%g1 + %lo(tlb_type)], %g1
+       cmp     %g1, 3
+       bne,pt  %icc, 1f
+        nop
+
+       /* Hypervisor TSB switch. */
        mov     SCRATCHPAD_UTSBREG1, %g1
        stxa    %o1, [%g1] ASI_SCRATCHPAD
-       .previous
+       mov     -1, %g2
+       mov     SCRATCHPAD_UTSBREG2, %g1
+       stxa    %g2, [%g1] ASI_SCRATCHPAD
 
-       membar  #Sync
+       mov     HV_FAST_MMU_TSB_CTXNON0, %o0
+       mov     1, %o1
+       mov     %o4, %o2
+       ta      HV_FAST_TRAP
+
+       ba,pt   %xcc, 9f
+        nop
 
-661:   stxa    %o1, [%g1] ASI_IMMU
+       /* SUN4U TSB switch.  */
+1:     mov     TSB_REG, %g1
+       stxa    %o1, [%g1] ASI_DMMU
+       membar  #Sync
+       stxa    %o1, [%g1] ASI_IMMU
        membar  #Sync
-       .section .sun4v_2insn_patch, "ax"
-       .word   661b
-       nop
-       nop
-       .previous
 
-       brz     %o2, 9f
+2:     brz     %o2, 9f
         nop
 
-       sethi   %hi(sparc64_highest_unlocked_tlb_ent), %o4
+       sethi   %hi(sparc64_highest_unlocked_tlb_ent), %g2
        mov     TLB_TAG_ACCESS, %g1
-       lduw    [%o4 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2
+       lduw    [%g2 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2
        stxa    %o2, [%g1] ASI_DMMU
        membar  #Sync
        sllx    %g2, 3, %g2
index 2cc8e65..6ae2a5a 100644 (file)
@@ -149,7 +149,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes)
                BUG();
        };
 
-       if (tlb_type == cheetah_plus) {
+       if (tlb_type == cheetah_plus || tlb_type == hypervisor) {
                /* Physical mapping, no locked TLB entry for TSB.  */
                tsb_reg |= tsb_paddr;
 
@@ -166,6 +166,52 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes)
                mm->context.tsb_map_pte = tte;
        }
 
+       /* Setup the Hypervisor TSB descriptor.  */
+       if (tlb_type == hypervisor) {
+               struct hv_tsb_descr *hp = &mm->context.tsb_descr;
+
+               switch (PAGE_SIZE) {
+               case 8192:
+               default:
+                       hp->pgsz_idx = HV_PGSZ_IDX_8K;
+                       break;
+
+               case 64 * 1024:
+                       hp->pgsz_idx = HV_PGSZ_IDX_64K;
+                       break;
+
+               case 512 * 1024:
+                       hp->pgsz_idx = HV_PGSZ_IDX_512K;
+                       break;
+
+               case 4 * 1024 * 1024:
+                       hp->pgsz_idx = HV_PGSZ_IDX_4MB;
+                       break;
+               };
+               hp->assoc = 1;
+               hp->num_ttes = tsb_bytes / 16;
+               hp->ctx_idx = 0;
+               switch (PAGE_SIZE) {
+               case 8192:
+               default:
+                       hp->pgsz_mask = HV_PGSZ_MASK_8K;
+                       break;
+
+               case 64 * 1024:
+                       hp->pgsz_mask = HV_PGSZ_MASK_64K;
+                       break;
+
+               case 512 * 1024:
+                       hp->pgsz_mask = HV_PGSZ_MASK_512K;
+                       break;
+
+               case 4 * 1024 * 1024:
+                       hp->pgsz_mask = HV_PGSZ_MASK_4MB;
+                       break;
+               };
+               hp->tsb_base = tsb_paddr;
+               hp->resv = 0;
+       }
 }
 
 /* The page tables are locked against modifications while this
index 55e6227..473d990 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <asm/page.h>
 #include <asm/const.h>
+#include <asm/hypervisor.h>
 
 /*
  * For the 8k pagesize kernel, use only 10 hw context bits to optimize some
@@ -101,13 +102,14 @@ extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte
 extern void tsb_flush(unsigned long ent, unsigned long tag);
 
 typedef struct {
-       unsigned long   sparc64_ctx_val;
-       struct tsb      *tsb;
-       unsigned long   tsb_rss_limit;
-       unsigned long   tsb_nentries;
-       unsigned long   tsb_reg_val;
-       unsigned long   tsb_map_vaddr;
-       unsigned long   tsb_map_pte;
+       unsigned long           sparc64_ctx_val;
+       struct tsb              *tsb;
+       unsigned long           tsb_rss_limit;
+       unsigned long           tsb_nentries;
+       unsigned long           tsb_reg_val;
+       unsigned long           tsb_map_vaddr;
+       unsigned long           tsb_map_pte;
+       struct hv_tsb_descr     tsb_descr;
 } mm_context_t;
 
 #endif /* !__ASSEMBLY__ */
index 2760353..eb660b1 100644 (file)
@@ -22,14 +22,18 @@ extern void get_new_mmu_context(struct mm_struct *mm);
 extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 extern void destroy_context(struct mm_struct *mm);
 
-extern void __tsb_context_switch(unsigned long pgd_pa, unsigned long tsb_reg,
-                                unsigned long tsb_vaddr, unsigned long tsb_pte);
+extern void __tsb_context_switch(unsigned long pgd_pa,
+                                unsigned long tsb_reg,
+                                unsigned long tsb_vaddr,
+                                unsigned long tsb_pte,
+                                unsigned long tsb_descr_pa);
 
 static inline void tsb_context_switch(struct mm_struct *mm)
 {
        __tsb_context_switch(__pa(mm->pgd), mm->context.tsb_reg_val,
                             mm->context.tsb_map_vaddr,
-                            mm->context.tsb_map_pte);
+                            mm->context.tsb_map_pte,
+                            __pa(&mm->context.tsb_descr));
 }
 
 extern void tsb_grow(struct mm_struct *mm, unsigned long mm_rss, gfp_t gfp_flags);