[POWERPC] Celleb: New HTAB Guest OS Interface on Beat
authorIshizaki Kou <kou.ishizaki@toshiba.co.jp>
Tue, 2 Oct 2007 08:23:46 +0000 (18:23 +1000)
committerPaul Mackerras <paulus@samba.org>
Wed, 3 Oct 2007 03:25:28 +0000 (13:25 +1000)
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>
arch/powerpc/platforms/celleb/beat_syscall.h
arch/powerpc/platforms/celleb/beat_wrapper.h
arch/powerpc/platforms/celleb/htab.c
arch/powerpc/platforms/celleb/setup.c
include/asm-powerpc/mmu-hash64.h

index 14e16974773faf026df3688a30e5261f1052b9ef..8580dc7e1798dc6a0dd8c14124bf7159167d6057 100644 (file)
 #define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1)
 #define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1)
 #define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1)
+#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1)
+#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1)
+#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1)
+#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1)
 #endif
index 76ea0a6a90118802785e10b9b571e3f30f9b47f9..cbc1487df7def6cbb44d62d29462757eae35163f 100644 (file)
@@ -98,6 +98,37 @@ static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot,
        return ret;
 }
 
+static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group,
+       u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot)
+{
+       u64 dummy[1];
+       s64 ret;
+
+       ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group,
+               hpte_v, hpte_r, mask_v, value_v);
+       *slot = dummy[0];
+       return ret;
+}
+
+static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group,
+       u64 va, u64 pss)
+{
+       return beat_hcall_norets(HV_invalidate_htab_entry3,
+               htab_id, group, va, pss);
+}
+
+static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group,
+       u64 va, u64 pss, u64 ptel_mask, u64 ptel_value)
+{
+       return beat_hcall_norets(HV_update_htab_permission3,
+               htab_id, group, va, pss, ptel_mask, ptel_value);
+}
+
+static inline s64 beat_clear_htab3(u64 htab_id)
+{
+       return beat_hcall_norets(HV_clear_htab3, htab_id);
+}
+
 static inline void beat_shutdown_logical_partition(u64 code)
 {
        (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,
                ioid, flags);
 }
 
+static inline s64 beat_construct_event_receive_port(u64 *port)
+{
+       u64 dummy[1];
+       s64 ret;
+
+       ret = beat_hcall1(HV_construct_event_receive_port, dummy);
+       *port = dummy[0];
+       return ret;
+}
+
+static inline s64 beat_destruct_event_receive_port(u64 port)
+{
+       s64 ret;
+
+       ret = beat_hcall_norets(HV_destruct_event_receive_port, port);
+       return ret;
+}
+
+static inline s64 beat_create_repository_node(u64 path[4], u64 data[2])
+{
+       s64 ret;
+
+       ret = beat_hcall_norets(HV_create_repository_node2,
+               path[0], path[1], path[2], path[3], data[0], data[1]);
+       return ret;
+}
+
+static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4],
+       u64 data[2])
+{
+       s64 ret;
+
+       ret = beat_hcall2(HV_get_repository_node_value2, data,
+               lpid, path[0], path[1], path[2], path[3]);
+       return ret;
+}
+
 #endif
index 279d7339e1701a1678babb99801373485c299fbb..5e75c77ea8f375df1cd8a59f986676629e47b988 100644 (file)
@@ -306,3 +306,133 @@ void __init hpte_init_beat(void)
        ppc_md.hpte_remove      = beat_lpar_hpte_remove;
        ppc_md.hpte_clear_all   = beat_lpar_hptab_clear;
 }
+
+static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
+                                 unsigned long va, unsigned long pa,
+                                 unsigned long rflags, unsigned long vflags,
+                                 int psize)
+{
+       unsigned long lpar_rc;
+       unsigned long slot;
+       unsigned long hpte_v, hpte_r;
+
+       /* same as iseries */
+       if (vflags & HPTE_V_SECONDARY)
+               return -1;
+
+       if (!(vflags & HPTE_V_BOLTED))
+               DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+                       "rflags=%lx, vflags=%lx, psize=%d)\n",
+               hpte_group, va, pa, rflags, vflags, psize);
+
+       hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
+       hpte_r = hpte_encode_r(pa, psize) | rflags;
+
+       if (!(vflags & HPTE_V_BOLTED))
+               DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+
+       if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+               hpte_r &= ~_PAGE_COHERENT;
+
+       /* insert into not-volted entry */
+       lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
+               HPTE_V_BOLTED, 0, &slot);
+       /*
+        * Since we try and ioremap PHBs we don't own, the pte insert
+        * will fail. However we must catch the failure in hash_page
+        * or we will loop forever, so return -2 in this case.
+        */
+       if (unlikely(lpar_rc != 0)) {
+               if (!(vflags & HPTE_V_BOLTED))
+                       DBG_LOW(" lpar err %lx\n", lpar_rc);
+               return -2;
+       }
+       if (!(vflags & HPTE_V_BOLTED))
+               DBG_LOW(" -> slot: %lx\n", slot);
+
+       /* We have to pass down the secondary bucket bit here as well */
+       return (slot ^ hpte_group) & 15;
+}
+
+/*
+ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+ * the low 3 bits of flags happen to line up.  So no transform is needed.
+ * We can probably optimize here and assume the high bits of newpp are
+ * already zero.  For now I am paranoid.
+ */
+static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
+                                   unsigned long newpp,
+                                   unsigned long va,
+                                   int psize, int local)
+{
+       unsigned long lpar_rc;
+       unsigned long want_v;
+       unsigned long pss;
+
+       want_v = hpte_encode_v(va, psize);
+       pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
+
+       DBG_LOW("    update: "
+               "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
+               want_v & HPTE_V_AVPN, slot, psize, newpp);
+
+       lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp);
+
+       if (lpar_rc == 0xfffffff7) {
+               DBG_LOW("not found !\n");
+               return -1;
+       }
+
+       DBG_LOW("ok\n");
+
+       BUG_ON(lpar_rc != 0);
+
+       return 0;
+}
+
+static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+                                        int psize, int local)
+{
+       unsigned long want_v;
+       unsigned long lpar_rc;
+       unsigned long pss;
+
+       DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+               slot, va, psize, local);
+       want_v = hpte_encode_v(va, psize);
+       pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
+
+       lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
+
+       /* E_busy can be valid output: page may be already replaced */
+       BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7);
+}
+
+static int64_t _beat_lpar_hptab_clear_v3(void)
+{
+       return beat_clear_htab3(0);
+}
+
+static void beat_lpar_hptab_clear_v3(void)
+{
+       _beat_lpar_hptab_clear_v3();
+}
+
+void __init hpte_init_beat_v3(void)
+{
+       if (_beat_lpar_hptab_clear_v3() == 0) {
+               ppc_md.hpte_invalidate  = beat_lpar_hpte_invalidate_v3;
+               ppc_md.hpte_updatepp    = beat_lpar_hpte_updatepp_v3;
+               ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+               ppc_md.hpte_insert      = beat_lpar_hpte_insert_v3;
+               ppc_md.hpte_remove      = beat_lpar_hpte_remove;
+               ppc_md.hpte_clear_all   = beat_lpar_hptab_clear_v3;
+       } else {
+               ppc_md.hpte_invalidate  = beat_lpar_hpte_invalidate;
+               ppc_md.hpte_updatepp    = beat_lpar_hpte_updatepp;
+               ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+               ppc_md.hpte_insert      = beat_lpar_hpte_insert;
+               ppc_md.hpte_remove      = beat_lpar_hpte_remove;
+               ppc_md.hpte_clear_all   = beat_lpar_hptab_clear;
+       }
+}
index a2180aa509d99d254d99682295f84ba579a95630..59731e836e288b7e2812b99f1f0c5a19e8d152f8 100644 (file)
@@ -119,7 +119,7 @@ static int __init celleb_probe(void)
                return 0;
 
        powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
-       hpte_init_beat();
+       hpte_init_beat_v3();
        return 1;
 }
 
index 3112ad14ad9504b699f6c4e65cc41d4a76dc332d..b22b0d20e157a0f08938c5b415c10236a903a64e 100644 (file)
@@ -256,6 +256,7 @@ extern void hpte_init_native(void);
 extern void hpte_init_lpar(void);
 extern void hpte_init_iSeries(void);
 extern void hpte_init_beat(void);
+extern void hpte_init_beat_v3(void);
 
 extern void stabs_alloc(void);
 extern void slb_initialize(void);