1*b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 2a88b5ba8SSam Ravnborg/* tsb.S: Sparc64 TSB table handling. 3a88b5ba8SSam Ravnborg * 4a88b5ba8SSam Ravnborg * Copyright (C) 2006 David S. Miller <davem@davemloft.net> 5a88b5ba8SSam Ravnborg */ 6a88b5ba8SSam Ravnborg 7a88b5ba8SSam Ravnborg 8a88b5ba8SSam Ravnborg#include <asm/tsb.h> 9a88b5ba8SSam Ravnborg#include <asm/hypervisor.h> 10a88b5ba8SSam Ravnborg#include <asm/page.h> 11a88b5ba8SSam Ravnborg#include <asm/cpudata.h> 12a88b5ba8SSam Ravnborg#include <asm/mmu.h> 13a88b5ba8SSam Ravnborg 14a88b5ba8SSam Ravnborg .text 15a88b5ba8SSam Ravnborg .align 32 16a88b5ba8SSam Ravnborg 17a88b5ba8SSam Ravnborg /* Invoked from TLB miss handler, we are in the 18a88b5ba8SSam Ravnborg * MMU global registers and they are setup like 19a88b5ba8SSam Ravnborg * this: 20a88b5ba8SSam Ravnborg * 21a88b5ba8SSam Ravnborg * %g1: TSB entry pointer 22a88b5ba8SSam Ravnborg * %g2: available temporary 23a88b5ba8SSam Ravnborg * %g3: FAULT_CODE_{D,I}TLB 24a88b5ba8SSam Ravnborg * %g4: available temporary 25a88b5ba8SSam Ravnborg * %g5: available temporary 26a88b5ba8SSam Ravnborg * %g6: TAG TARGET 27a88b5ba8SSam Ravnborg * %g7: available temporary, will be loaded by us with 28a88b5ba8SSam Ravnborg * the physical address base of the linux page 29a88b5ba8SSam Ravnborg * tables for the current address space 30a88b5ba8SSam Ravnborg */ 31a88b5ba8SSam Ravnborgtsb_miss_dtlb: 32a88b5ba8SSam Ravnborg mov TLB_TAG_ACCESS, %g4 33a88b5ba8SSam Ravnborg ldxa [%g4] ASI_DMMU, %g4 344f6deb8cSDavid S. Miller srlx %g4, PAGE_SHIFT, %g4 354f6deb8cSDavid S. Miller ba,pt %xcc, tsb_miss_page_table_walk 364f6deb8cSDavid S. Miller sllx %g4, PAGE_SHIFT, %g4 37a88b5ba8SSam Ravnborg 38a88b5ba8SSam Ravnborgtsb_miss_itlb: 39a88b5ba8SSam Ravnborg mov TLB_TAG_ACCESS, %g4 40a88b5ba8SSam Ravnborg ldxa [%g4] ASI_IMMU, %g4 414f6deb8cSDavid S. Miller srlx %g4, PAGE_SHIFT, %g4 424f6deb8cSDavid S. Miller ba,pt %xcc, tsb_miss_page_table_walk 434f6deb8cSDavid S. Miller sllx %g4, PAGE_SHIFT, %g4 44a88b5ba8SSam Ravnborg 45a88b5ba8SSam Ravnborg /* At this point we have: 46a88b5ba8SSam Ravnborg * %g1 -- PAGE_SIZE TSB entry address 47a88b5ba8SSam Ravnborg * %g3 -- FAULT_CODE_{D,I}TLB 48a88b5ba8SSam Ravnborg * %g4 -- missing virtual address 49a88b5ba8SSam Ravnborg * %g6 -- TAG TARGET (vaddr >> 22) 50a88b5ba8SSam Ravnborg */ 51a88b5ba8SSam Ravnborgtsb_miss_page_table_walk: 52a88b5ba8SSam Ravnborg TRAP_LOAD_TRAP_BLOCK(%g7, %g5) 53a88b5ba8SSam Ravnborg 54a88b5ba8SSam Ravnborg /* Before committing to a full page table walk, 55a88b5ba8SSam Ravnborg * check the huge page TSB. 56a88b5ba8SSam Ravnborg */ 579e695d2eSDavid Miller#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 58a88b5ba8SSam Ravnborg 59a88b5ba8SSam Ravnborg661: ldx [%g7 + TRAP_PER_CPU_TSB_HUGE], %g5 60a88b5ba8SSam Ravnborg nop 61a88b5ba8SSam Ravnborg .section .sun4v_2insn_patch, "ax" 62a88b5ba8SSam Ravnborg .word 661b 63a88b5ba8SSam Ravnborg mov SCRATCHPAD_UTSBREG2, %g5 64a88b5ba8SSam Ravnborg ldxa [%g5] ASI_SCRATCHPAD, %g5 65a88b5ba8SSam Ravnborg .previous 66a88b5ba8SSam Ravnborg 67a88b5ba8SSam Ravnborg cmp %g5, -1 68a88b5ba8SSam Ravnborg be,pt %xcc, 80f 69a88b5ba8SSam Ravnborg nop 70a88b5ba8SSam Ravnborg 71a88b5ba8SSam Ravnborg /* We need an aligned pair of registers containing 2 values 72a88b5ba8SSam Ravnborg * which can be easily rematerialized. %g6 and %g7 foot the 73a88b5ba8SSam Ravnborg * bill just nicely. We'll save %g6 away into %g2 for the 74a88b5ba8SSam Ravnborg * huge page TSB TAG comparison. 75a88b5ba8SSam Ravnborg * 76a88b5ba8SSam Ravnborg * Perform a huge page TSB lookup. 77a88b5ba8SSam Ravnborg */ 78a88b5ba8SSam Ravnborg mov %g6, %g2 79a88b5ba8SSam Ravnborg and %g5, 0x7, %g6 80a88b5ba8SSam Ravnborg mov 512, %g7 81a88b5ba8SSam Ravnborg andn %g5, 0x7, %g5 82a88b5ba8SSam Ravnborg sllx %g7, %g6, %g7 8337b3a8ffSDavid S. Miller srlx %g4, REAL_HPAGE_SHIFT, %g6 84a88b5ba8SSam Ravnborg sub %g7, 1, %g7 85a88b5ba8SSam Ravnborg and %g6, %g7, %g6 86a88b5ba8SSam Ravnborg sllx %g6, 4, %g6 87a88b5ba8SSam Ravnborg add %g5, %g6, %g5 88a88b5ba8SSam Ravnborg 89a88b5ba8SSam Ravnborg TSB_LOAD_QUAD(%g5, %g6) 90a88b5ba8SSam Ravnborg cmp %g6, %g2 91a88b5ba8SSam Ravnborg be,a,pt %xcc, tsb_tlb_reload 92a88b5ba8SSam Ravnborg mov %g7, %g5 93a88b5ba8SSam Ravnborg 94a88b5ba8SSam Ravnborg /* No match, remember the huge page TSB entry address, 95a88b5ba8SSam Ravnborg * and restore %g6 and %g7. 96a88b5ba8SSam Ravnborg */ 97a88b5ba8SSam Ravnborg TRAP_LOAD_TRAP_BLOCK(%g7, %g6) 98a88b5ba8SSam Ravnborg srlx %g4, 22, %g6 99a88b5ba8SSam Ravnborg80: stx %g5, [%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP] 100a88b5ba8SSam Ravnborg 101a88b5ba8SSam Ravnborg#endif 102a88b5ba8SSam Ravnborg 103a88b5ba8SSam Ravnborg ldx [%g7 + TRAP_PER_CPU_PGD_PADDR], %g7 104a88b5ba8SSam Ravnborg 105a88b5ba8SSam Ravnborg /* At this point we have: 106a88b5ba8SSam Ravnborg * %g1 -- TSB entry address 107a88b5ba8SSam Ravnborg * %g3 -- FAULT_CODE_{D,I}TLB 108a88b5ba8SSam Ravnborg * %g4 -- missing virtual address 109a88b5ba8SSam Ravnborg * %g6 -- TAG TARGET (vaddr >> 22) 110a88b5ba8SSam Ravnborg * %g7 -- page table physical address 111a88b5ba8SSam Ravnborg * 112a88b5ba8SSam Ravnborg * We know that both the base PAGE_SIZE TSB and the HPAGE_SIZE 113a88b5ba8SSam Ravnborg * TSB both lack a matching entry. 114a88b5ba8SSam Ravnborg */ 115a88b5ba8SSam Ravnborgtsb_miss_page_table_walk_sun4v_fastpath: 116a88b5ba8SSam Ravnborg USER_PGTABLE_WALK_TL1(%g4, %g7, %g5, %g2, tsb_do_fault) 117a88b5ba8SSam Ravnborg 1189e695d2eSDavid Miller /* Valid PTE is now in %g5. */ 119a88b5ba8SSam Ravnborg 1209e695d2eSDavid Miller#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 121df7b2155SNitin Gupta sethi %uhi(_PAGE_PMD_HUGE | _PAGE_PUD_HUGE), %g7 122a88b5ba8SSam Ravnborg sllx %g7, 32, %g7 123a88b5ba8SSam Ravnborg 124c7d9f77dSNitin Gupta andcc %g5, %g7, %g0 125c7d9f77dSNitin Gupta be,pt %xcc, 60f 126a88b5ba8SSam Ravnborg nop 127a88b5ba8SSam Ravnborg 128a88b5ba8SSam Ravnborg /* It is a huge page, use huge page TSB entry address we 1290fbebed6SDavid S. Miller * calculated above. If the huge page TSB has not been 1300fbebed6SDavid S. Miller * allocated, setup a trap stack and call hugetlb_setup() 1310fbebed6SDavid S. Miller * to do so, then return from the trap to replay the TLB 1320fbebed6SDavid S. Miller * miss. 1330fbebed6SDavid S. Miller * 1340fbebed6SDavid S. Miller * This is necessary to handle the case of transparent huge 1350fbebed6SDavid S. Miller * pages where we don't really have a non-atomic context 1360fbebed6SDavid S. Miller * in which to allocate the hugepage TSB hash table. When 1370fbebed6SDavid S. Miller * the 'mm' faults in the hugepage for the first time, we 1380fbebed6SDavid S. Miller * thus handle it here. This also makes sure that we can 1390fbebed6SDavid S. Miller * allocate the TSB hash table on the correct NUMA node. 140a88b5ba8SSam Ravnborg */ 141a88b5ba8SSam Ravnborg TRAP_LOAD_TRAP_BLOCK(%g7, %g2) 1420fbebed6SDavid S. Miller ldx [%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP], %g1 1430fbebed6SDavid S. Miller cmp %g1, -1 1440fbebed6SDavid S. Miller bne,pt %xcc, 60f 1450fbebed6SDavid S. Miller nop 1460fbebed6SDavid S. Miller 1470fbebed6SDavid S. Miller661: rdpr %pstate, %g5 1480fbebed6SDavid S. Miller wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate 1490fbebed6SDavid S. Miller .section .sun4v_2insn_patch, "ax" 1500fbebed6SDavid S. Miller .word 661b 1510fbebed6SDavid S. Miller SET_GL(1) 1520fbebed6SDavid S. Miller nop 1530fbebed6SDavid S. Miller .previous 1540fbebed6SDavid S. Miller 15584bd6d8bSDavid S. Miller rdpr %tl, %g7 15684bd6d8bSDavid S. Miller cmp %g7, 1 1570fbebed6SDavid S. Miller bne,pn %xcc, winfix_trampoline 15884bd6d8bSDavid S. Miller mov %g3, %g4 1590fbebed6SDavid S. Miller ba,pt %xcc, etrap 1600fbebed6SDavid S. Miller rd %pc, %g7 1610fbebed6SDavid S. Miller call hugetlb_setup 1620fbebed6SDavid S. Miller add %sp, PTREGS_OFF, %o0 1630fbebed6SDavid S. Miller ba,pt %xcc, rtrap 1640fbebed6SDavid S. Miller nop 1650fbebed6SDavid S. Miller 166a88b5ba8SSam Ravnborg60: 167a88b5ba8SSam Ravnborg#endif 168a88b5ba8SSam Ravnborg 169a88b5ba8SSam Ravnborg /* At this point we have: 170a88b5ba8SSam Ravnborg * %g1 -- TSB entry address 171a88b5ba8SSam Ravnborg * %g3 -- FAULT_CODE_{D,I}TLB 172a88b5ba8SSam Ravnborg * %g5 -- valid PTE 173a88b5ba8SSam Ravnborg * %g6 -- TAG TARGET (vaddr >> 22) 174a88b5ba8SSam Ravnborg */ 175a88b5ba8SSam Ravnborgtsb_reload: 176a88b5ba8SSam Ravnborg TSB_LOCK_TAG(%g1, %g2, %g7) 177a88b5ba8SSam Ravnborg TSB_WRITE(%g1, %g5, %g6) 178a88b5ba8SSam Ravnborg 179a88b5ba8SSam Ravnborg /* Finally, load TLB and return from trap. */ 180a88b5ba8SSam Ravnborgtsb_tlb_reload: 181a88b5ba8SSam Ravnborg cmp %g3, FAULT_CODE_DTLB 182a88b5ba8SSam Ravnborg bne,pn %xcc, tsb_itlb_load 183a88b5ba8SSam Ravnborg nop 184a88b5ba8SSam Ravnborg 185a88b5ba8SSam Ravnborgtsb_dtlb_load: 186a88b5ba8SSam Ravnborg 187a88b5ba8SSam Ravnborg661: stxa %g5, [%g0] ASI_DTLB_DATA_IN 188a88b5ba8SSam Ravnborg retry 189a88b5ba8SSam Ravnborg .section .sun4v_2insn_patch, "ax" 190a88b5ba8SSam Ravnborg .word 661b 191a88b5ba8SSam Ravnborg nop 192a88b5ba8SSam Ravnborg nop 193a88b5ba8SSam Ravnborg .previous 194a88b5ba8SSam Ravnborg 195a88b5ba8SSam Ravnborg /* For sun4v the ASI_DTLB_DATA_IN store and the retry 196a88b5ba8SSam Ravnborg * instruction get nop'd out and we get here to branch 197a88b5ba8SSam Ravnborg * to the sun4v tlb load code. The registers are setup 198a88b5ba8SSam Ravnborg * as follows: 199a88b5ba8SSam Ravnborg * 200a88b5ba8SSam Ravnborg * %g4: vaddr 201a88b5ba8SSam Ravnborg * %g5: PTE 202a88b5ba8SSam Ravnborg * %g6: TAG 203a88b5ba8SSam Ravnborg * 204a88b5ba8SSam Ravnborg * The sun4v TLB load wants the PTE in %g3 so we fix that 205a88b5ba8SSam Ravnborg * up here. 206a88b5ba8SSam Ravnborg */ 207a88b5ba8SSam Ravnborg ba,pt %xcc, sun4v_dtlb_load 208a88b5ba8SSam Ravnborg mov %g5, %g3 209a88b5ba8SSam Ravnborg 210a88b5ba8SSam Ravnborgtsb_itlb_load: 211a88b5ba8SSam Ravnborg /* Executable bit must be set. */ 2121f474646SDavid S. Miller661: sethi %hi(_PAGE_EXEC_4U), %g4 2131f474646SDavid S. Miller andcc %g5, %g4, %g0 2141f474646SDavid S. Miller .section .sun4v_2insn_patch, "ax" 215a88b5ba8SSam Ravnborg .word 661b 216a88b5ba8SSam Ravnborg andcc %g5, _PAGE_EXEC_4V, %g0 2171f474646SDavid S. Miller nop 218a88b5ba8SSam Ravnborg .previous 219a88b5ba8SSam Ravnborg 220a88b5ba8SSam Ravnborg be,pn %xcc, tsb_do_fault 221a88b5ba8SSam Ravnborg nop 222a88b5ba8SSam Ravnborg 223a88b5ba8SSam Ravnborg661: stxa %g5, [%g0] ASI_ITLB_DATA_IN 224a88b5ba8SSam Ravnborg retry 225a88b5ba8SSam Ravnborg .section .sun4v_2insn_patch, "ax" 226a88b5ba8SSam Ravnborg .word 661b 227a88b5ba8SSam Ravnborg nop 228a88b5ba8SSam Ravnborg nop 229a88b5ba8SSam Ravnborg .previous 230a88b5ba8SSam Ravnborg 231a88b5ba8SSam Ravnborg /* For sun4v the ASI_ITLB_DATA_IN store and the retry 232a88b5ba8SSam Ravnborg * instruction get nop'd out and we get here to branch 233a88b5ba8SSam Ravnborg * to the sun4v tlb load code. The registers are setup 234a88b5ba8SSam Ravnborg * as follows: 235a88b5ba8SSam Ravnborg * 236a88b5ba8SSam Ravnborg * %g4: vaddr 237a88b5ba8SSam Ravnborg * %g5: PTE 238a88b5ba8SSam Ravnborg * %g6: TAG 239a88b5ba8SSam Ravnborg * 240a88b5ba8SSam Ravnborg * The sun4v TLB load wants the PTE in %g3 so we fix that 241a88b5ba8SSam Ravnborg * up here. 242a88b5ba8SSam Ravnborg */ 243a88b5ba8SSam Ravnborg ba,pt %xcc, sun4v_itlb_load 244a88b5ba8SSam Ravnborg mov %g5, %g3 245a88b5ba8SSam Ravnborg 246a88b5ba8SSam Ravnborg /* No valid entry in the page tables, do full fault 247a88b5ba8SSam Ravnborg * processing. 248a88b5ba8SSam Ravnborg */ 249a88b5ba8SSam Ravnborg 250a88b5ba8SSam Ravnborg .globl tsb_do_fault 251a88b5ba8SSam Ravnborgtsb_do_fault: 252a88b5ba8SSam Ravnborg cmp %g3, FAULT_CODE_DTLB 253a88b5ba8SSam Ravnborg 254a88b5ba8SSam Ravnborg661: rdpr %pstate, %g5 255a88b5ba8SSam Ravnborg wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate 256a88b5ba8SSam Ravnborg .section .sun4v_2insn_patch, "ax" 257a88b5ba8SSam Ravnborg .word 661b 258a88b5ba8SSam Ravnborg SET_GL(1) 259a88b5ba8SSam Ravnborg ldxa [%g0] ASI_SCRATCHPAD, %g4 260a88b5ba8SSam Ravnborg .previous 261a88b5ba8SSam Ravnborg 262a88b5ba8SSam Ravnborg bne,pn %xcc, tsb_do_itlb_fault 263a88b5ba8SSam Ravnborg nop 264a88b5ba8SSam Ravnborg 265a88b5ba8SSam Ravnborgtsb_do_dtlb_fault: 266a88b5ba8SSam Ravnborg rdpr %tl, %g3 267a88b5ba8SSam Ravnborg cmp %g3, 1 268a88b5ba8SSam Ravnborg 269a88b5ba8SSam Ravnborg661: mov TLB_TAG_ACCESS, %g4 270a88b5ba8SSam Ravnborg ldxa [%g4] ASI_DMMU, %g5 271a88b5ba8SSam Ravnborg .section .sun4v_2insn_patch, "ax" 272a88b5ba8SSam Ravnborg .word 661b 273a88b5ba8SSam Ravnborg ldx [%g4 + HV_FAULT_D_ADDR_OFFSET], %g5 274a88b5ba8SSam Ravnborg nop 275a88b5ba8SSam Ravnborg .previous 276a88b5ba8SSam Ravnborg 2774f6deb8cSDavid S. Miller /* Clear context ID bits. */ 2784f6deb8cSDavid S. Miller srlx %g5, PAGE_SHIFT, %g5 2794f6deb8cSDavid S. Miller sllx %g5, PAGE_SHIFT, %g5 2804f6deb8cSDavid S. Miller 281a88b5ba8SSam Ravnborg be,pt %xcc, sparc64_realfault_common 282a88b5ba8SSam Ravnborg mov FAULT_CODE_DTLB, %g4 283a88b5ba8SSam Ravnborg ba,pt %xcc, winfix_trampoline 284a88b5ba8SSam Ravnborg nop 285a88b5ba8SSam Ravnborg 286a88b5ba8SSam Ravnborgtsb_do_itlb_fault: 287a88b5ba8SSam Ravnborg rdpr %tpc, %g5 288a88b5ba8SSam Ravnborg ba,pt %xcc, sparc64_realfault_common 289a88b5ba8SSam Ravnborg mov FAULT_CODE_ITLB, %g4 290a88b5ba8SSam Ravnborg 291a88b5ba8SSam Ravnborg .globl sparc64_realfault_common 292a88b5ba8SSam Ravnborgsparc64_realfault_common: 293a88b5ba8SSam Ravnborg /* fault code in %g4, fault address in %g5, etrap will 294a88b5ba8SSam Ravnborg * preserve these two values in %l4 and %l5 respectively 295a88b5ba8SSam Ravnborg */ 296a88b5ba8SSam Ravnborg ba,pt %xcc, etrap ! Save trap state 297a88b5ba8SSam Ravnborg1: rd %pc, %g7 ! ... 298a88b5ba8SSam Ravnborg stb %l4, [%g6 + TI_FAULT_CODE] ! Save fault code 299a88b5ba8SSam Ravnborg stx %l5, [%g6 + TI_FAULT_ADDR] ! Save fault address 300a88b5ba8SSam Ravnborg call do_sparc64_fault ! Call fault handler 301a88b5ba8SSam Ravnborg add %sp, PTREGS_OFF, %o0 ! Compute pt_regs arg 302a88b5ba8SSam Ravnborg ba,pt %xcc, rtrap ! Restore cpu state 303a88b5ba8SSam Ravnborg nop ! Delay slot (fill me) 304a88b5ba8SSam Ravnborg 305a88b5ba8SSam Ravnborgwinfix_trampoline: 306a88b5ba8SSam Ravnborg rdpr %tpc, %g3 ! Prepare winfixup TNPC 307a88b5ba8SSam Ravnborg or %g3, 0x7c, %g3 ! Compute branch offset 308a88b5ba8SSam Ravnborg wrpr %g3, %tnpc ! Write it into TNPC 309a88b5ba8SSam Ravnborg done ! Trap return 310a88b5ba8SSam Ravnborg 311a88b5ba8SSam Ravnborg /* Insert an entry into the TSB. 312a88b5ba8SSam Ravnborg * 313a88b5ba8SSam Ravnborg * %o0: TSB entry pointer (virt or phys address) 314a88b5ba8SSam Ravnborg * %o1: tag 315a88b5ba8SSam Ravnborg * %o2: pte 316a88b5ba8SSam Ravnborg */ 317a88b5ba8SSam Ravnborg .align 32 318a88b5ba8SSam Ravnborg .globl __tsb_insert 319a88b5ba8SSam Ravnborg__tsb_insert: 320a88b5ba8SSam Ravnborg rdpr %pstate, %o5 321a88b5ba8SSam Ravnborg wrpr %o5, PSTATE_IE, %pstate 322a88b5ba8SSam Ravnborg TSB_LOCK_TAG(%o0, %g2, %g3) 323a88b5ba8SSam Ravnborg TSB_WRITE(%o0, %o2, %o1) 324a88b5ba8SSam Ravnborg wrpr %o5, %pstate 325a88b5ba8SSam Ravnborg retl 326a88b5ba8SSam Ravnborg nop 327a88b5ba8SSam Ravnborg .size __tsb_insert, .-__tsb_insert 328a88b5ba8SSam Ravnborg 329a88b5ba8SSam Ravnborg /* Flush the given TSB entry if it has the matching 330a88b5ba8SSam Ravnborg * tag. 331a88b5ba8SSam Ravnborg * 332a88b5ba8SSam Ravnborg * %o0: TSB entry pointer (virt or phys address) 333a88b5ba8SSam Ravnborg * %o1: tag 334a88b5ba8SSam Ravnborg */ 335a88b5ba8SSam Ravnborg .align 32 336a88b5ba8SSam Ravnborg .globl tsb_flush 337a88b5ba8SSam Ravnborg .type tsb_flush,#function 338a88b5ba8SSam Ravnborgtsb_flush: 339a88b5ba8SSam Ravnborg sethi %hi(TSB_TAG_LOCK_HIGH), %g2 340a88b5ba8SSam Ravnborg1: TSB_LOAD_TAG(%o0, %g1) 341a88b5ba8SSam Ravnborg srlx %g1, 32, %o3 342a88b5ba8SSam Ravnborg andcc %o3, %g2, %g0 343a88b5ba8SSam Ravnborg bne,pn %icc, 1b 344a88b5ba8SSam Ravnborg nop 345a88b5ba8SSam Ravnborg cmp %g1, %o1 346a88b5ba8SSam Ravnborg mov 1, %o3 347a88b5ba8SSam Ravnborg bne,pt %xcc, 2f 348a88b5ba8SSam Ravnborg sllx %o3, TSB_TAG_INVALID_BIT, %o3 349a88b5ba8SSam Ravnborg TSB_CAS_TAG(%o0, %g1, %o3) 350a88b5ba8SSam Ravnborg cmp %g1, %o3 351a88b5ba8SSam Ravnborg bne,pn %xcc, 1b 352a88b5ba8SSam Ravnborg nop 353a88b5ba8SSam Ravnborg2: retl 354a88b5ba8SSam Ravnborg nop 355a88b5ba8SSam Ravnborg .size tsb_flush, .-tsb_flush 356a88b5ba8SSam Ravnborg 357a88b5ba8SSam Ravnborg /* Reload MMU related context switch state at 358a88b5ba8SSam Ravnborg * schedule() time. 359a88b5ba8SSam Ravnborg * 360a88b5ba8SSam Ravnborg * %o0: page table physical address 361a88b5ba8SSam Ravnborg * %o1: TSB base config pointer 362a88b5ba8SSam Ravnborg * %o2: TSB huge config pointer, or NULL if none 363a88b5ba8SSam Ravnborg * %o3: Hypervisor TSB descriptor physical address 364fc290a11SRob Gardner * %o4: Secondary context to load, if non-zero 365a88b5ba8SSam Ravnborg * 366a88b5ba8SSam Ravnborg * We have to run this whole thing with interrupts 367a88b5ba8SSam Ravnborg * disabled so that the current cpu doesn't change 368a88b5ba8SSam Ravnborg * due to preemption. 369a88b5ba8SSam Ravnborg */ 370a88b5ba8SSam Ravnborg .align 32 371a88b5ba8SSam Ravnborg .globl __tsb_context_switch 372a88b5ba8SSam Ravnborg .type __tsb_context_switch,#function 373a88b5ba8SSam Ravnborg__tsb_context_switch: 374a88b5ba8SSam Ravnborg rdpr %pstate, %g1 375a88b5ba8SSam Ravnborg wrpr %g1, PSTATE_IE, %pstate 376a88b5ba8SSam Ravnborg 377fc290a11SRob Gardner brz,pn %o4, 1f 378fc290a11SRob Gardner mov SECONDARY_CONTEXT, %o5 379fc290a11SRob Gardner 380fc290a11SRob Gardner661: stxa %o4, [%o5] ASI_DMMU 381fc290a11SRob Gardner .section .sun4v_1insn_patch, "ax" 382fc290a11SRob Gardner .word 661b 383fc290a11SRob Gardner stxa %o4, [%o5] ASI_MMU 384fc290a11SRob Gardner .previous 385fc290a11SRob Gardner flush %g6 386fc290a11SRob Gardner 387fc290a11SRob Gardner1: 388a88b5ba8SSam Ravnborg TRAP_LOAD_TRAP_BLOCK(%g2, %g3) 389a88b5ba8SSam Ravnborg 390a88b5ba8SSam Ravnborg stx %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR] 391a88b5ba8SSam Ravnborg 392a88b5ba8SSam Ravnborg ldx [%o1 + TSB_CONFIG_REG_VAL], %o0 393a88b5ba8SSam Ravnborg brz,pt %o2, 1f 394a88b5ba8SSam Ravnborg mov -1, %g3 395a88b5ba8SSam Ravnborg 396a88b5ba8SSam Ravnborg ldx [%o2 + TSB_CONFIG_REG_VAL], %g3 397a88b5ba8SSam Ravnborg 398a88b5ba8SSam Ravnborg1: stx %g3, [%g2 + TRAP_PER_CPU_TSB_HUGE] 399a88b5ba8SSam Ravnborg 400a88b5ba8SSam Ravnborg sethi %hi(tlb_type), %g2 401a88b5ba8SSam Ravnborg lduw [%g2 + %lo(tlb_type)], %g2 402a88b5ba8SSam Ravnborg cmp %g2, 3 403a88b5ba8SSam Ravnborg bne,pt %icc, 50f 404a88b5ba8SSam Ravnborg nop 405a88b5ba8SSam Ravnborg 406a88b5ba8SSam Ravnborg /* Hypervisor TSB switch. */ 407a88b5ba8SSam Ravnborg mov SCRATCHPAD_UTSBREG1, %o5 408a88b5ba8SSam Ravnborg stxa %o0, [%o5] ASI_SCRATCHPAD 409a88b5ba8SSam Ravnborg mov SCRATCHPAD_UTSBREG2, %o5 410a88b5ba8SSam Ravnborg stxa %g3, [%o5] ASI_SCRATCHPAD 411a88b5ba8SSam Ravnborg 412a88b5ba8SSam Ravnborg mov 2, %o0 413a88b5ba8SSam Ravnborg cmp %g3, -1 414a88b5ba8SSam Ravnborg move %xcc, 1, %o0 415a88b5ba8SSam Ravnborg 416a88b5ba8SSam Ravnborg mov HV_FAST_MMU_TSB_CTXNON0, %o5 417a88b5ba8SSam Ravnborg mov %o3, %o1 418a88b5ba8SSam Ravnborg ta HV_FAST_TRAP 419a88b5ba8SSam Ravnborg 420a88b5ba8SSam Ravnborg /* Finish up. */ 421a88b5ba8SSam Ravnborg ba,pt %xcc, 9f 422a88b5ba8SSam Ravnborg nop 423a88b5ba8SSam Ravnborg 424a88b5ba8SSam Ravnborg /* SUN4U TSB switch. */ 425a88b5ba8SSam Ravnborg50: mov TSB_REG, %o5 426a88b5ba8SSam Ravnborg stxa %o0, [%o5] ASI_DMMU 427a88b5ba8SSam Ravnborg membar #Sync 428a88b5ba8SSam Ravnborg stxa %o0, [%o5] ASI_IMMU 429a88b5ba8SSam Ravnborg membar #Sync 430a88b5ba8SSam Ravnborg 431a88b5ba8SSam Ravnborg2: ldx [%o1 + TSB_CONFIG_MAP_VADDR], %o4 432a88b5ba8SSam Ravnborg brz %o4, 9f 433a88b5ba8SSam Ravnborg ldx [%o1 + TSB_CONFIG_MAP_PTE], %o5 434a88b5ba8SSam Ravnborg 435a88b5ba8SSam Ravnborg sethi %hi(sparc64_highest_unlocked_tlb_ent), %g2 436a88b5ba8SSam Ravnborg mov TLB_TAG_ACCESS, %g3 437a88b5ba8SSam Ravnborg lduw [%g2 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 438a88b5ba8SSam Ravnborg stxa %o4, [%g3] ASI_DMMU 439a88b5ba8SSam Ravnborg membar #Sync 440a88b5ba8SSam Ravnborg sllx %g2, 3, %g2 441a88b5ba8SSam Ravnborg stxa %o5, [%g2] ASI_DTLB_DATA_ACCESS 442a88b5ba8SSam Ravnborg membar #Sync 443a88b5ba8SSam Ravnborg 444a88b5ba8SSam Ravnborg brz,pt %o2, 9f 445a88b5ba8SSam Ravnborg nop 446a88b5ba8SSam Ravnborg 447a88b5ba8SSam Ravnborg ldx [%o2 + TSB_CONFIG_MAP_VADDR], %o4 448a88b5ba8SSam Ravnborg ldx [%o2 + TSB_CONFIG_MAP_PTE], %o5 449a88b5ba8SSam Ravnborg mov TLB_TAG_ACCESS, %g3 450a88b5ba8SSam Ravnborg stxa %o4, [%g3] ASI_DMMU 451a88b5ba8SSam Ravnborg membar #Sync 452a88b5ba8SSam Ravnborg sub %g2, (1 << 3), %g2 453a88b5ba8SSam Ravnborg stxa %o5, [%g2] ASI_DTLB_DATA_ACCESS 454a88b5ba8SSam Ravnborg membar #Sync 455a88b5ba8SSam Ravnborg 456a88b5ba8SSam Ravnborg9: 457a88b5ba8SSam Ravnborg wrpr %g1, %pstate 458a88b5ba8SSam Ravnborg 459a88b5ba8SSam Ravnborg retl 460a88b5ba8SSam Ravnborg nop 461a88b5ba8SSam Ravnborg .size __tsb_context_switch, .-__tsb_context_switch 462a88b5ba8SSam Ravnborg 463a88b5ba8SSam Ravnborg#define TSB_PASS_BITS ((1 << TSB_TAG_LOCK_BIT) | \ 464a88b5ba8SSam Ravnborg (1 << TSB_TAG_INVALID_BIT)) 465a88b5ba8SSam Ravnborg 466a88b5ba8SSam Ravnborg .align 32 467a88b5ba8SSam Ravnborg .globl copy_tsb 468a88b5ba8SSam Ravnborg .type copy_tsb,#function 469a88b5ba8SSam Ravnborgcopy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size 470a88b5ba8SSam Ravnborg * %o2=new_tsb_base, %o3=new_tsb_size 471654f4807SMike Kravetz * %o4=page_size_shift 472a88b5ba8SSam Ravnborg */ 473a88b5ba8SSam Ravnborg sethi %uhi(TSB_PASS_BITS), %g7 474a88b5ba8SSam Ravnborg srlx %o3, 4, %o3 475654f4807SMike Kravetz add %o0, %o1, %o1 /* end of old tsb */ 476a88b5ba8SSam Ravnborg sllx %g7, 32, %g7 477a88b5ba8SSam Ravnborg sub %o3, 1, %o3 /* %o3 == new tsb hash mask */ 478a88b5ba8SSam Ravnborg 479654f4807SMike Kravetz mov %o4, %g1 /* page_size_shift */ 480654f4807SMike Kravetz 481a88b5ba8SSam Ravnborg661: prefetcha [%o0] ASI_N, #one_read 482a88b5ba8SSam Ravnborg .section .tsb_phys_patch, "ax" 483a88b5ba8SSam Ravnborg .word 661b 484a88b5ba8SSam Ravnborg prefetcha [%o0] ASI_PHYS_USE_EC, #one_read 485a88b5ba8SSam Ravnborg .previous 486a88b5ba8SSam Ravnborg 487a88b5ba8SSam Ravnborg90: andcc %o0, (64 - 1), %g0 488a88b5ba8SSam Ravnborg bne 1f 489a88b5ba8SSam Ravnborg add %o0, 64, %o5 490a88b5ba8SSam Ravnborg 491a88b5ba8SSam Ravnborg661: prefetcha [%o5] ASI_N, #one_read 492a88b5ba8SSam Ravnborg .section .tsb_phys_patch, "ax" 493a88b5ba8SSam Ravnborg .word 661b 494a88b5ba8SSam Ravnborg prefetcha [%o5] ASI_PHYS_USE_EC, #one_read 495a88b5ba8SSam Ravnborg .previous 496a88b5ba8SSam Ravnborg 497a88b5ba8SSam Ravnborg1: TSB_LOAD_QUAD(%o0, %g2) /* %g2/%g3 == TSB entry */ 498a88b5ba8SSam Ravnborg andcc %g2, %g7, %g0 /* LOCK or INVALID set? */ 499a88b5ba8SSam Ravnborg bne,pn %xcc, 80f /* Skip it */ 500a88b5ba8SSam Ravnborg sllx %g2, 22, %o4 /* TAG --> VADDR */ 501a88b5ba8SSam Ravnborg 502a88b5ba8SSam Ravnborg /* This can definitely be computed faster... */ 503a88b5ba8SSam Ravnborg srlx %o0, 4, %o5 /* Build index */ 504a88b5ba8SSam Ravnborg and %o5, 511, %o5 /* Mask index */ 505654f4807SMike Kravetz sllx %o5, %g1, %o5 /* Put into vaddr position */ 506a88b5ba8SSam Ravnborg or %o4, %o5, %o4 /* Full VADDR. */ 507654f4807SMike Kravetz srlx %o4, %g1, %o4 /* Shift down to create index */ 508a88b5ba8SSam Ravnborg and %o4, %o3, %o4 /* Mask with new_tsb_nents-1 */ 509a88b5ba8SSam Ravnborg sllx %o4, 4, %o4 /* Shift back up into tsb ent offset */ 510a88b5ba8SSam Ravnborg TSB_STORE(%o2 + %o4, %g2) /* Store TAG */ 511a88b5ba8SSam Ravnborg add %o4, 0x8, %o4 /* Advance to TTE */ 512a88b5ba8SSam Ravnborg TSB_STORE(%o2 + %o4, %g3) /* Store TTE */ 513a88b5ba8SSam Ravnborg 514a88b5ba8SSam Ravnborg80: add %o0, 16, %o0 515654f4807SMike Kravetz cmp %o0, %o1 516a88b5ba8SSam Ravnborg bne,pt %xcc, 90b 517a88b5ba8SSam Ravnborg nop 518a88b5ba8SSam Ravnborg 519a88b5ba8SSam Ravnborg retl 520a88b5ba8SSam Ravnborg nop 521a88b5ba8SSam Ravnborg .size copy_tsb, .-copy_tsb 522a88b5ba8SSam Ravnborg 523a88b5ba8SSam Ravnborg /* Set the invalid bit in all TSB entries. */ 524a88b5ba8SSam Ravnborg .align 32 525a88b5ba8SSam Ravnborg .globl tsb_init 526a88b5ba8SSam Ravnborg .type tsb_init,#function 527a88b5ba8SSam Ravnborgtsb_init: /* %o0 = TSB vaddr, %o1 = size in bytes */ 528a88b5ba8SSam Ravnborg prefetch [%o0 + 0x000], #n_writes 529a88b5ba8SSam Ravnborg mov 1, %g1 530a88b5ba8SSam Ravnborg prefetch [%o0 + 0x040], #n_writes 531a88b5ba8SSam Ravnborg sllx %g1, TSB_TAG_INVALID_BIT, %g1 532a88b5ba8SSam Ravnborg prefetch [%o0 + 0x080], #n_writes 533a88b5ba8SSam Ravnborg1: prefetch [%o0 + 0x0c0], #n_writes 534a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x00] 535a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x10] 536a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x20] 537a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x30] 538a88b5ba8SSam Ravnborg prefetch [%o0 + 0x100], #n_writes 539a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x40] 540a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x50] 541a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x60] 542a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x70] 543a88b5ba8SSam Ravnborg prefetch [%o0 + 0x140], #n_writes 544a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x80] 545a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0x90] 546a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0xa0] 547a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0xb0] 548a88b5ba8SSam Ravnborg prefetch [%o0 + 0x180], #n_writes 549a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0xc0] 550a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0xd0] 551a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0xe0] 552a88b5ba8SSam Ravnborg stx %g1, [%o0 + 0xf0] 553a88b5ba8SSam Ravnborg subcc %o1, 0x100, %o1 554a88b5ba8SSam Ravnborg bne,pt %xcc, 1b 555a88b5ba8SSam Ravnborg add %o0, 0x100, %o0 556a88b5ba8SSam Ravnborg retl 557a88b5ba8SSam Ravnborg nop 558a88b5ba8SSam Ravnborg nop 559a88b5ba8SSam Ravnborg nop 560a88b5ba8SSam Ravnborg .size tsb_init, .-tsb_init 561a88b5ba8SSam Ravnborg 562a88b5ba8SSam Ravnborg .globl NGtsb_init 563a88b5ba8SSam Ravnborg .type NGtsb_init,#function 564a88b5ba8SSam RavnborgNGtsb_init: 565a88b5ba8SSam Ravnborg rd %asi, %g2 566a88b5ba8SSam Ravnborg mov 1, %g1 567a88b5ba8SSam Ravnborg wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi 568a88b5ba8SSam Ravnborg sllx %g1, TSB_TAG_INVALID_BIT, %g1 569a88b5ba8SSam Ravnborg1: stxa %g1, [%o0 + 0x00] %asi 570a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x10] %asi 571a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x20] %asi 572a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x30] %asi 573a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x40] %asi 574a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x50] %asi 575a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x60] %asi 576a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x70] %asi 577a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x80] %asi 578a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0x90] %asi 579a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0xa0] %asi 580a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0xb0] %asi 581a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0xc0] %asi 582a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0xd0] %asi 583a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0xe0] %asi 584a88b5ba8SSam Ravnborg stxa %g1, [%o0 + 0xf0] %asi 585a88b5ba8SSam Ravnborg subcc %o1, 0x100, %o1 586a88b5ba8SSam Ravnborg bne,pt %xcc, 1b 587a88b5ba8SSam Ravnborg add %o0, 0x100, %o0 588a88b5ba8SSam Ravnborg membar #Sync 589a88b5ba8SSam Ravnborg retl 590a88b5ba8SSam Ravnborg wr %g2, 0x0, %asi 591a88b5ba8SSam Ravnborg .size NGtsb_init, .-NGtsb_init 592