root/arch/powerpc/platforms/ps3/htab.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ps3_hpte_insert
  2. ps3_hpte_remove
  3. ps3_hpte_updatepp
  4. ps3_hpte_updateboltedpp
  5. ps3_hpte_invalidate
  6. ps3_hpte_clear
  7. ps3_hpte_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  PS3 pagetable management routines.
   4  *
   5  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
   6  *  Copyright 2006, 2007 Sony Corporation
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/memblock.h>
  11 
  12 #include <asm/machdep.h>
  13 #include <asm/prom.h>
  14 #include <asm/udbg.h>
  15 #include <asm/lv1call.h>
  16 #include <asm/ps3fb.h>
  17 
  18 #define PS3_VERBOSE_RESULT
  19 #include "platform.h"
  20 
  21 /**
  22  * enum lpar_vas_id - id of LPAR virtual address space.
  23  * @lpar_vas_id_current: Current selected virtual address space
  24  *
  25  * Identify the target LPAR address space.
  26  */
  27 
  28 enum ps3_lpar_vas_id {
  29         PS3_LPAR_VAS_ID_CURRENT = 0,
  30 };
  31 
  32 
  33 static DEFINE_SPINLOCK(ps3_htab_lock);
  34 
  35 static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn,
  36         unsigned long pa, unsigned long rflags, unsigned long vflags,
  37         int psize, int apsize, int ssize)
  38 {
  39         int result;
  40         u64 hpte_v, hpte_r;
  41         u64 inserted_index;
  42         u64 evicted_v, evicted_r;
  43         u64 hpte_v_array[4], hpte_rs;
  44         unsigned long flags;
  45         long ret = -1;
  46 
  47         /*
  48          * lv1_insert_htab_entry() will search for victim
  49          * entry in both primary and secondary pte group
  50          */
  51         vflags &= ~HPTE_V_SECONDARY;
  52 
  53         hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
  54         hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize) | rflags;
  55 
  56         spin_lock_irqsave(&ps3_htab_lock, flags);
  57 
  58         /* talk hvc to replace entries BOLTED == 0 */
  59         result = lv1_insert_htab_entry(PS3_LPAR_VAS_ID_CURRENT, hpte_group,
  60                                        hpte_v, hpte_r,
  61                                        HPTE_V_BOLTED, 0,
  62                                        &inserted_index,
  63                                        &evicted_v, &evicted_r);
  64 
  65         if (result) {
  66                 /* all entries bolted !*/
  67                 pr_info("%s:result=%s vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
  68                         __func__, ps3_result(result), vpn, pa, hpte_group,
  69                         hpte_v, hpte_r);
  70                 BUG();
  71         }
  72 
  73         /*
  74          * see if the entry is inserted into secondary pteg
  75          */
  76         result = lv1_read_htab_entries(PS3_LPAR_VAS_ID_CURRENT,
  77                                        inserted_index & ~0x3UL,
  78                                        &hpte_v_array[0], &hpte_v_array[1],
  79                                        &hpte_v_array[2], &hpte_v_array[3],
  80                                        &hpte_rs);
  81         BUG_ON(result);
  82 
  83         if (hpte_v_array[inserted_index % 4] & HPTE_V_SECONDARY)
  84                 ret = (inserted_index & 7) | (1 << 3);
  85         else
  86                 ret = inserted_index & 7;
  87 
  88         spin_unlock_irqrestore(&ps3_htab_lock, flags);
  89 
  90         return ret;
  91 }
  92 
  93 static long ps3_hpte_remove(unsigned long hpte_group)
  94 {
  95         panic("ps3_hpte_remove() not implemented");
  96         return 0;
  97 }
  98 
  99 static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
 100                               unsigned long vpn, int psize, int apsize,
 101                               int ssize, unsigned long inv_flags)
 102 {
 103         int result;
 104         u64 hpte_v, want_v, hpte_rs;
 105         u64 hpte_v_array[4];
 106         unsigned long flags;
 107         long ret;
 108 
 109         want_v = hpte_encode_avpn(vpn, psize, ssize);
 110 
 111         spin_lock_irqsave(&ps3_htab_lock, flags);
 112 
 113         result = lv1_read_htab_entries(PS3_LPAR_VAS_ID_CURRENT, slot & ~0x3UL,
 114                                        &hpte_v_array[0], &hpte_v_array[1],
 115                                        &hpte_v_array[2], &hpte_v_array[3],
 116                                        &hpte_rs);
 117 
 118         if (result) {
 119                 pr_info("%s: result=%s read vpn=%lx slot=%lx psize=%d\n",
 120                         __func__, ps3_result(result), vpn, slot, psize);
 121                 BUG();
 122         }
 123 
 124         hpte_v = hpte_v_array[slot % 4];
 125 
 126         /*
 127          * As lv1_read_htab_entries() does not give us the RPN, we can
 128          * not synthesize the new hpte_r value here, and therefore can
 129          * not update the hpte with lv1_insert_htab_entry(), so we
 130          * instead invalidate it and ask the caller to update it via
 131          * ps3_hpte_insert() by returning a -1 value.
 132          */
 133         if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
 134                 /* not found */
 135                 ret = -1;
 136         } else {
 137                 /* entry found, just invalidate it */
 138                 result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT,
 139                                               slot, 0, 0);
 140                 ret = -1;
 141         }
 142 
 143         spin_unlock_irqrestore(&ps3_htab_lock, flags);
 144         return ret;
 145 }
 146 
 147 static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 148         int psize, int ssize)
 149 {
 150         panic("ps3_hpte_updateboltedpp() not implemented");
 151 }
 152 
 153 static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn,
 154                                 int psize, int apsize, int ssize, int local)
 155 {
 156         unsigned long flags;
 157         int result;
 158 
 159         spin_lock_irqsave(&ps3_htab_lock, flags);
 160 
 161         result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
 162 
 163         if (result) {
 164                 pr_info("%s: result=%s vpn=%lx slot=%lx psize=%d\n",
 165                         __func__, ps3_result(result), vpn, slot, psize);
 166                 BUG();
 167         }
 168 
 169         spin_unlock_irqrestore(&ps3_htab_lock, flags);
 170 }
 171 
 172 static void ps3_hpte_clear(void)
 173 {
 174         unsigned long hpte_count = (1UL << ppc64_pft_size) >> 4;
 175         u64 i;
 176 
 177         for (i = 0; i < hpte_count; i++)
 178                 lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, i, 0, 0);
 179 
 180         ps3_mm_shutdown();
 181         ps3_mm_vas_destroy();
 182 }
 183 
 184 void __init ps3_hpte_init(unsigned long htab_size)
 185 {
 186         mmu_hash_ops.hpte_invalidate = ps3_hpte_invalidate;
 187         mmu_hash_ops.hpte_updatepp = ps3_hpte_updatepp;
 188         mmu_hash_ops.hpte_updateboltedpp = ps3_hpte_updateboltedpp;
 189         mmu_hash_ops.hpte_insert = ps3_hpte_insert;
 190         mmu_hash_ops.hpte_remove = ps3_hpte_remove;
 191         mmu_hash_ops.hpte_clear_all = ps3_hpte_clear;
 192 
 193         ppc64_pft_size = __ilog2(htab_size);
 194 }
 195 

/* [<][>][^][v][top][bottom][index][help] */