1cf901fa9031d51a86c97ed33b6b70b9bae196b6
2 * PS3 pagetable management routines.
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006, 2007 Sony Corporation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/kernel.h>
22 #include <linux/lmb.h>
24 #include <asm/machdep.h>
27 #include <asm/lv1call.h>
28 #include <asm/ps3fb.h>
33 #define DBG udbg_printf
38 static struct hash_pte
*htab
;
39 static unsigned long htab_addr
;
40 static unsigned char *bolttab
;
41 static unsigned char *inusetab
;
43 static DEFINE_SPINLOCK(ps3_bolttab_lock
);
45 #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
46 _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
47 static void _debug_dump_hpte(unsigned long pa
, unsigned long va
,
48 unsigned long group
, unsigned long bitmap
, struct hash_pte lhpte
,
49 int psize
, unsigned long slot
, const char* func
, int line
)
51 DBG("%s:%d: pa = %lxh\n", func
, line
, pa
);
52 DBG("%s:%d: lpar = %lxh\n", func
, line
,
53 ps3_mm_phys_to_lpar(pa
));
54 DBG("%s:%d: va = %lxh\n", func
, line
, va
);
55 DBG("%s:%d: group = %lxh\n", func
, line
, group
);
56 DBG("%s:%d: bitmap = %lxh\n", func
, line
, bitmap
);
57 DBG("%s:%d: hpte.v = %lxh\n", func
, line
, lhpte
.v
);
58 DBG("%s:%d: hpte.r = %lxh\n", func
, line
, lhpte
.r
);
59 DBG("%s:%d: psize = %xh\n", func
, line
, psize
);
60 DBG("%s:%d: slot = %lxh\n", func
, line
, slot
);
63 static long ps3_hpte_insert(unsigned long hpte_group
, unsigned long va
,
64 unsigned long pa
, unsigned long rflags
, unsigned long vflags
,
68 struct hash_pte lhpte
;
73 unsigned long p_pteg
, s_pteg
, b_index
, b_mask
, cb
, ci
;
75 vflags
&= ~HPTE_V_SECONDARY
; /* this bit is ignored */
77 lhpte
.v
= hpte_encode_v(va
, psize
, MMU_SEGSIZE_256M
) |
78 vflags
| HPTE_V_VALID
;
79 lhpte
.r
= hpte_encode_r(ps3_mm_phys_to_lpar(pa
), psize
) | rflags
;
81 p_pteg
= hpte_group
/ HPTES_PER_GROUP
;
82 s_pteg
= ~p_pteg
& htab_hash_mask
;
84 spin_lock_irqsave(&ps3_bolttab_lock
, flags
);
86 BUG_ON(bolttab
[p_pteg
] == 0xff && bolttab
[s_pteg
] == 0xff);
88 bitmap
= (inusetab
[p_pteg
] << 8) | inusetab
[s_pteg
];
90 if (bitmap
== 0xffff) {
92 * PTEG is full. Search for victim.
94 bitmap
&= ~((bolttab
[p_pteg
] << 8) | bolttab
[s_pteg
]);
98 } while ((cb
& bitmap
) == 0);
101 * search free slot in hardware order
102 * [primary] 0, 2, 4, 6, 1, 3, 5, 7
103 * [secondary] 0, 2, 4, 6, 1, 3, 5, 7
105 for (ci
= 0; ci
< HPTES_PER_GROUP
; ci
+= 2) {
107 if ((cb
& bitmap
) == 0)
110 for (ci
= 1; ci
< HPTES_PER_GROUP
; ci
+= 2) {
112 if ((cb
& bitmap
) == 0)
115 for (ci
= HPTES_PER_GROUP
; ci
< HPTES_PER_GROUP
*2; ci
+= 2) {
117 if ((cb
& bitmap
) == 0)
120 for (ci
= HPTES_PER_GROUP
+1; ci
< HPTES_PER_GROUP
*2; ci
+= 2) {
122 if ((cb
& bitmap
) == 0)
128 if (ci
< HPTES_PER_GROUP
) {
129 slot
= p_pteg
* HPTES_PER_GROUP
+ ci
;
131 slot
= s_pteg
* HPTES_PER_GROUP
+ (ci
& 7);
132 /* lhpte.dw0.dw0.h = 1; */
133 vflags
|= HPTE_V_SECONDARY
;
134 lhpte
.v
|= HPTE_V_SECONDARY
;
137 result
= lv1_write_htab_entry(0, slot
, lhpte
.v
, lhpte
.r
);
140 debug_dump_hpte(pa
, va
, hpte_group
, bitmap
, lhpte
, psize
, slot
);
145 * If used slot is not in primary HPTE group,
146 * the slot should be in secondary HPTE group.
149 if ((hpte_group
^ slot
) & ~(HPTES_PER_GROUP
- 1)) {
157 b_mask
= (lhpte
.v
& HPTE_V_BOLTED
) ? 1 << 7 : 0 << 7;
158 bolttab
[b_index
] |= b_mask
>> (slot
& 7);
160 inusetab
[b_index
] |= b_mask
>> (slot
& 7);
161 spin_unlock_irqrestore(&ps3_bolttab_lock
, flags
);
163 return (slot
& 7) | (secondary
<< 3);
166 static long ps3_hpte_remove(unsigned long hpte_group
)
168 panic("ps3_hpte_remove() not implemented");
172 static long ps3_hpte_updatepp(unsigned long slot
, unsigned long newpp
,
173 unsigned long va
, int psize
, int ssize
, int local
)
176 unsigned long result
;
177 unsigned long pteg
, bit
;
178 unsigned long hpte_v
, want_v
;
180 want_v
= hpte_encode_v(va
, psize
, MMU_SEGSIZE_256M
);
182 spin_lock_irqsave(&ps3_bolttab_lock
, flags
);
184 hpte_v
= htab
[slot
].v
;
185 if (!HPTE_V_COMPARE(hpte_v
, want_v
) || !(hpte_v
& HPTE_V_VALID
)) {
186 spin_unlock_irqrestore(&ps3_bolttab_lock
, flags
);
188 /* ps3_hpte_insert() will be used to update PTE */
192 result
= lv1_write_htab_entry(0, slot
, 0, 0);
195 DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n",
196 __func__
, va
, slot
, psize
, result
, result
);
200 pteg
= slot
/ HPTES_PER_GROUP
;
201 bit
= slot
% HPTES_PER_GROUP
;
202 inusetab
[pteg
] &= ~(0x80 >> bit
);
204 spin_unlock_irqrestore(&ps3_bolttab_lock
, flags
);
206 /* ps3_hpte_insert() will be used to update PTE */
210 static void ps3_hpte_updateboltedpp(unsigned long newpp
, unsigned long ea
,
211 int psize
, int ssize
)
213 panic("ps3_hpte_updateboltedpp() not implemented");
216 static void ps3_hpte_invalidate(unsigned long slot
, unsigned long va
,
217 int psize
, int ssize
, int local
)
220 unsigned long result
;
221 unsigned long pteg
, bit
;
223 spin_lock_irqsave(&ps3_bolttab_lock
, flags
);
224 result
= lv1_write_htab_entry(0, slot
, 0, 0);
227 DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n",
228 __func__
, va
, slot
, psize
, result
, result
);
232 pteg
= slot
/ HPTES_PER_GROUP
;
233 bit
= slot
% HPTES_PER_GROUP
;
234 inusetab
[pteg
] &= ~(0x80 >> bit
);
235 spin_unlock_irqrestore(&ps3_bolttab_lock
, flags
);
238 static void ps3_hpte_clear(void)
242 DBG(" -> %s:%d\n", __func__
, __LINE__
);
244 result
= lv1_unmap_htab(htab_addr
);
248 ps3_mm_vas_destroy();
250 DBG(" <- %s:%d\n", __func__
, __LINE__
);
253 void __init
ps3_hpte_init(unsigned long htab_size
)
257 DBG(" -> %s:%d\n", __func__
, __LINE__
);
259 ppc_md
.hpte_invalidate
= ps3_hpte_invalidate
;
260 ppc_md
.hpte_updatepp
= ps3_hpte_updatepp
;
261 ppc_md
.hpte_updateboltedpp
= ps3_hpte_updateboltedpp
;
262 ppc_md
.hpte_insert
= ps3_hpte_insert
;
263 ppc_md
.hpte_remove
= ps3_hpte_remove
;
264 ppc_md
.hpte_clear_all
= ps3_hpte_clear
;
266 ppc64_pft_size
= __ilog2(htab_size
);
268 bitmap_size
= htab_size
/ sizeof(struct hash_pte
) / 8;
270 bolttab
= __va(lmb_alloc(bitmap_size
, 1));
271 inusetab
= __va(lmb_alloc(bitmap_size
, 1));
273 memset(bolttab
, 0, bitmap_size
);
274 memset(inusetab
, 0, bitmap_size
);
276 DBG(" <- %s:%d\n", __func__
, __LINE__
);
279 void __init
ps3_map_htab(void)
282 unsigned long htab_size
= (1UL << ppc64_pft_size
);
284 result
= lv1_map_htab(0, &htab_addr
);
286 htab
= (__force
struct hash_pte
*)ioremap_flags(htab_addr
, htab_size
,
287 pgprot_val(PAGE_READONLY_X
));
289 DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__
, __LINE__
,
290 htab_addr
, (unsigned long)htab
);
This page took 0.03551 seconds and 4 git commands to generate.