aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/celleb
diff options
context:
space:
mode:
authorIshizaki Kou <kou.ishizaki@toshiba.co.jp>2007-10-02 04:23:46 -0400
committerPaul Mackerras <paulus@samba.org>2007-10-02 23:25:28 -0400
commit7f2c85777db26c120821bc1c9b8273a30a705a09 (patch)
tree49f2f0ea2208e98b9a5998bccc34ec0d13b8e533 /arch/powerpc/platforms/celleb
parentb41848031ac16aee8d045e86f0b7ad3ba97e961e (diff)
[POWERPC] Celleb: New HTAB Guest OS Interface on Beat
This changes the Celleb code to work with new Guest OS Interface to tweak HTAB on Beat. It detects old and new Guest OS Interfaces automatically. Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp> Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/celleb')
-rw-r--r--arch/powerpc/platforms/celleb/beat_syscall.h4
-rw-r--r--arch/powerpc/platforms/celleb/beat_wrapper.h68
-rw-r--r--arch/powerpc/platforms/celleb/htab.c130
-rw-r--r--arch/powerpc/platforms/celleb/setup.c2
4 files changed, 203 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/celleb/beat_syscall.h b/arch/powerpc/platforms/celleb/beat_syscall.h
index 14e16974773..8580dc7e179 100644
--- a/arch/powerpc/platforms/celleb/beat_syscall.h
+++ b/arch/powerpc/platforms/celleb/beat_syscall.h
@@ -157,4 +157,8 @@
157#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1) 157#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1)
158#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1) 158#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1)
159#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1) 159#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1)
160#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1)
161#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1)
162#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1)
163#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1)
160#endif 164#endif
diff --git a/arch/powerpc/platforms/celleb/beat_wrapper.h b/arch/powerpc/platforms/celleb/beat_wrapper.h
index 76ea0a6a901..cbc1487df7d 100644
--- a/arch/powerpc/platforms/celleb/beat_wrapper.h
+++ b/arch/powerpc/platforms/celleb/beat_wrapper.h
@@ -98,6 +98,37 @@ static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot,
98 return ret; 98 return ret;
99} 99}
100 100
101static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group,
102 u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot)
103{
104 u64 dummy[1];
105 s64 ret;
106
107 ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group,
108 hpte_v, hpte_r, mask_v, value_v);
109 *slot = dummy[0];
110 return ret;
111}
112
113static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group,
114 u64 va, u64 pss)
115{
116 return beat_hcall_norets(HV_invalidate_htab_entry3,
117 htab_id, group, va, pss);
118}
119
120static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group,
121 u64 va, u64 pss, u64 ptel_mask, u64 ptel_value)
122{
123 return beat_hcall_norets(HV_update_htab_permission3,
124 htab_id, group, va, pss, ptel_mask, ptel_value);
125}
126
127static inline s64 beat_clear_htab3(u64 htab_id)
128{
129 return beat_hcall_norets(HV_clear_htab3, htab_id);
130}
131
101static inline void beat_shutdown_logical_partition(u64 code) 132static inline void beat_shutdown_logical_partition(u64 code)
102{ 133{
103 (void)beat_hcall_norets(HV_shutdown_logical_partition, code); 134 (void)beat_hcall_norets(HV_shutdown_logical_partition, code);
@@ -217,4 +248,41 @@ static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr,
217 ioid, flags); 248 ioid, flags);
218} 249}
219 250
251static inline s64 beat_construct_event_receive_port(u64 *port)
252{
253 u64 dummy[1];
254 s64 ret;
255
256 ret = beat_hcall1(HV_construct_event_receive_port, dummy);
257 *port = dummy[0];
258 return ret;
259}
260
261static inline s64 beat_destruct_event_receive_port(u64 port)
262{
263 s64 ret;
264
265 ret = beat_hcall_norets(HV_destruct_event_receive_port, port);
266 return ret;
267}
268
269static inline s64 beat_create_repository_node(u64 path[4], u64 data[2])
270{
271 s64 ret;
272
273 ret = beat_hcall_norets(HV_create_repository_node2,
274 path[0], path[1], path[2], path[3], data[0], data[1]);
275 return ret;
276}
277
278static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4],
279 u64 data[2])
280{
281 s64 ret;
282
283 ret = beat_hcall2(HV_get_repository_node_value2, data,
284 lpid, path[0], path[1], path[2], path[3]);
285 return ret;
286}
287
220#endif 288#endif
diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c
index 279d7339e17..5e75c77ea8f 100644
--- a/arch/powerpc/platforms/celleb/htab.c
+++ b/arch/powerpc/platforms/celleb/htab.c
@@ -306,3 +306,133 @@ void __init hpte_init_beat(void)
306 ppc_md.hpte_remove = beat_lpar_hpte_remove; 306 ppc_md.hpte_remove = beat_lpar_hpte_remove;
307 ppc_md.hpte_clear_all = beat_lpar_hptab_clear; 307 ppc_md.hpte_clear_all = beat_lpar_hptab_clear;
308} 308}
309
310static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
311 unsigned long va, unsigned long pa,
312 unsigned long rflags, unsigned long vflags,
313 int psize)
314{
315 unsigned long lpar_rc;
316 unsigned long slot;
317 unsigned long hpte_v, hpte_r;
318
319 /* same as iseries */
320 if (vflags & HPTE_V_SECONDARY)
321 return -1;
322
323 if (!(vflags & HPTE_V_BOLTED))
324 DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
325 "rflags=%lx, vflags=%lx, psize=%d)\n",
326 hpte_group, va, pa, rflags, vflags, psize);
327
328 hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
329 hpte_r = hpte_encode_r(pa, psize) | rflags;
330
331 if (!(vflags & HPTE_V_BOLTED))
332 DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
333
334 if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
335 hpte_r &= ~_PAGE_COHERENT;
336
337 /* insert into not-volted entry */
338 lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
339 HPTE_V_BOLTED, 0, &slot);
340 /*
341 * Since we try and ioremap PHBs we don't own, the pte insert
342 * will fail. However we must catch the failure in hash_page
343 * or we will loop forever, so return -2 in this case.
344 */
345 if (unlikely(lpar_rc != 0)) {
346 if (!(vflags & HPTE_V_BOLTED))
347 DBG_LOW(" lpar err %lx\n", lpar_rc);
348 return -2;
349 }
350 if (!(vflags & HPTE_V_BOLTED))
351 DBG_LOW(" -> slot: %lx\n", slot);
352
353 /* We have to pass down the secondary bucket bit here as well */
354 return (slot ^ hpte_group) & 15;
355}
356
357/*
358 * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
359 * the low 3 bits of flags happen to line up. So no transform is needed.
360 * We can probably optimize here and assume the high bits of newpp are
361 * already zero. For now I am paranoid.
362 */
363static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
364 unsigned long newpp,
365 unsigned long va,
366 int psize, int local)
367{
368 unsigned long lpar_rc;
369 unsigned long want_v;
370 unsigned long pss;
371
372 want_v = hpte_encode_v(va, psize);
373 pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
374
375 DBG_LOW(" update: "
376 "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
377 want_v & HPTE_V_AVPN, slot, psize, newpp);
378
379 lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp);
380
381 if (lpar_rc == 0xfffffff7) {
382 DBG_LOW("not found !\n");
383 return -1;
384 }
385
386 DBG_LOW("ok\n");
387
388 BUG_ON(lpar_rc != 0);
389
390 return 0;
391}
392
393static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
394 int psize, int local)
395{
396 unsigned long want_v;
397 unsigned long lpar_rc;
398 unsigned long pss;
399
400 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
401 slot, va, psize, local);
402 want_v = hpte_encode_v(va, psize);
403 pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
404
405 lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
406
407 /* E_busy can be valid output: page may be already replaced */
408 BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7);
409}
410
411static int64_t _beat_lpar_hptab_clear_v3(void)
412{
413 return beat_clear_htab3(0);
414}
415
416static void beat_lpar_hptab_clear_v3(void)
417{
418 _beat_lpar_hptab_clear_v3();
419}
420
421void __init hpte_init_beat_v3(void)
422{
423 if (_beat_lpar_hptab_clear_v3() == 0) {
424 ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate_v3;
425 ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp_v3;
426 ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
427 ppc_md.hpte_insert = beat_lpar_hpte_insert_v3;
428 ppc_md.hpte_remove = beat_lpar_hpte_remove;
429 ppc_md.hpte_clear_all = beat_lpar_hptab_clear_v3;
430 } else {
431 ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate;
432 ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp;
433 ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
434 ppc_md.hpte_insert = beat_lpar_hpte_insert;
435 ppc_md.hpte_remove = beat_lpar_hpte_remove;
436 ppc_md.hpte_clear_all = beat_lpar_hptab_clear;
437 }
438}
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index a2180aa509d..59731e836e2 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -119,7 +119,7 @@ static int __init celleb_probe(void)
119 return 0; 119 return 0;
120 120
121 powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; 121 powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
122 hpte_init_beat(); 122 hpte_init_beat_v3();
123 return 1; 123 return 1;
124} 124}
125 125