1/* tlb-flush.S: TLB flushing routines
2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/sys.h>
13#include <linux/linkage.h>
14#include <asm/page.h>
15#include <asm/ptrace.h>
16#include <asm/spr-regs.h>
17
18.macro DEBUG ch
19#	sethi.p		%hi(0xfeff9c00),gr4
20#	setlo		%lo(0xfeff9c00),gr4
21#	setlos		#\ch,gr5
22#	stbi		gr5,@(gr4,#0)
23#	membar
24.endm
25
26	.section	.rodata
27
28	# sizes corresponding to TPXR.LMAX
29	.balign		1
30__tlb_lmax_sizes:
31	.byte		0, 64, 0, 0
32	.byte		0, 0, 0, 0
33	.byte		0, 0, 0, 0
34	.byte		0, 0, 0, 0
35
36	.section	.text
37	.balign		4
38
39###############################################################################
40#
41# flush everything
42# - void __flush_tlb_all(void)
43#
44###############################################################################
45	.globl		__flush_tlb_all
46	.type		__flush_tlb_all,@function
47__flush_tlb_all:
48	DEBUG		'A'
49
50	# kill cached PGE value
51	setlos		#0xffffffff,gr4
52	movgs		gr4,scr0
53	movgs		gr4,scr1
54
55	# kill AMPR-cached TLB values
56	movgs		gr0,iamlr1
57	movgs		gr0,iampr1
58	movgs		gr0,damlr1
59	movgs		gr0,dampr1
60
61	# find out how many lines there are
62	movsg		tpxr,gr5
63	sethi.p		%hi(__tlb_lmax_sizes),gr4
64	srli		gr5,#TPXR_LMAX_SHIFT,gr5
65	setlo.p		%lo(__tlb_lmax_sizes),gr4
66	andi		gr5,#TPXR_LMAX_SMASK,gr5
67	ldub		@(gr4,gr5),gr4
68
69	# now, we assume that the TLB line step is page size in size
70	setlos.p	#PAGE_SIZE,gr5
71	setlos		#0,gr6
721:
73	tlbpr		gr6,gr0,#6,#0
74	subicc.p	gr4,#1,gr4,icc0
75	add		gr6,gr5,gr6
76	bne		icc0,#2,1b
77
78	DEBUG		'B'
79	bralr
80
81	.size		__flush_tlb_all, .-__flush_tlb_all
82
83###############################################################################
84#
85# flush everything to do with one context
86# - void __flush_tlb_mm(unsigned long contextid [GR8])
87#
88###############################################################################
89	.globl		__flush_tlb_mm
90	.type		__flush_tlb_mm,@function
91__flush_tlb_mm:
92	DEBUG		'M'
93
94	# kill cached PGE value
95	setlos		#0xffffffff,gr4
96	movgs		gr4,scr0
97	movgs		gr4,scr1
98
99	# specify the context we want to flush
100	movgs		gr8,tplr
101
102	# find out how many lines there are
103	movsg		tpxr,gr5
104	sethi.p		%hi(__tlb_lmax_sizes),gr4
105	srli		gr5,#TPXR_LMAX_SHIFT,gr5
106	setlo.p		%lo(__tlb_lmax_sizes),gr4
107	andi		gr5,#TPXR_LMAX_SMASK,gr5
108	ldub		@(gr4,gr5),gr4
109
110	# now, we assume that the TLB line step is page size in size
111	setlos.p	#PAGE_SIZE,gr5
112	setlos		#0,gr6
1130:
114	tlbpr		gr6,gr0,#5,#0
115	subicc.p	gr4,#1,gr4,icc0
116	add		gr6,gr5,gr6
117	bne		icc0,#2,0b
118
119	DEBUG		'N'
120	bralr
121
122	.size		__flush_tlb_mm, .-__flush_tlb_mm
123
124###############################################################################
125#
126# flush a range of addresses from the TLB
127# - void __flush_tlb_page(unsigned long contextid [GR8],
128#			  unsigned long start [GR9])
129#
130###############################################################################
131	.globl		__flush_tlb_page
132	.type		__flush_tlb_page,@function
133__flush_tlb_page:
134	# kill cached PGE value
135	setlos		#0xffffffff,gr4
136	movgs		gr4,scr0
137	movgs		gr4,scr1
138
139	# specify the context we want to flush
140	movgs		gr8,tplr
141
142	# zap the matching TLB line and AMR values
143	setlos		#~(PAGE_SIZE-1),gr5
144	and		gr9,gr5,gr9
145	tlbpr		gr9,gr0,#5,#0
146
147	bralr
148
149	.size		__flush_tlb_page, .-__flush_tlb_page
150
151###############################################################################
152#
153# flush a range of addresses from the TLB
154# - void __flush_tlb_range(unsigned long contextid [GR8],
155#			   unsigned long start [GR9],
156#			   unsigned long end [GR10])
157#
158###############################################################################
159	.globl		__flush_tlb_range
160	.type		__flush_tlb_range,@function
161__flush_tlb_range:
162	# kill cached PGE value
163	setlos		#0xffffffff,gr4
164	movgs		gr4,scr0
165	movgs		gr4,scr1
166
167	# specify the context we want to flush
168	movgs		gr8,tplr
169
170	# round the start down to beginning of TLB line and end up to beginning of next TLB line
171	setlos.p	#~(PAGE_SIZE-1),gr5
172	setlos		#PAGE_SIZE,gr6
173	subi.p		gr10,#1,gr10
174	and		gr9,gr5,gr9
175	and		gr10,gr5,gr10
1762:
177	tlbpr		gr9,gr0,#5,#0
178	subcc.p		gr9,gr10,gr0,icc0
179	add		gr9,gr6,gr9
180	bne		icc0,#0,2b		; most likely a 1-page flush
181
182	bralr
183
184	.size		__flush_tlb_range, .-__flush_tlb_range
185