1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * HAT interfaces used by the kernel debugger to interact with the VM system.
  29  * These interfaces are invoked when the world is stopped.  As such, no blocking
  30  * operations may be performed.
  31  */
  32 
  33 #include <sys/cpuvar.h>
  34 #include <sys/kdi_impl.h>
  35 #include <sys/errno.h>
  36 #include <sys/systm.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/mman.h>
  39 #include <sys/bootconf.h>
  40 #include <sys/cmn_err.h>
  41 #include <vm/seg_kmem.h>
  42 #include <vm/hat_i86.h>
  43 #if defined(__xpv)
  44 #include <sys/hypervisor.h>
  45 #endif
  46 #include <sys/bootinfo.h>
  47 #include <vm/kboot_mmu.h>
  48 #include <sys/machsystm.h>
  49 
  50 /*
  51  * The debugger needs direct access to the PTE of one page table entry
  52  * in order to implement vtop and physical read/writes
  53  */
  54 static uintptr_t hat_kdi_page = 0;      /* vaddr for phsical page accesses */
  55 static uint_t use_kbm = 1;
  56 uint_t hat_kdi_use_pae;                 /* if 0, use x86pte32_t for pte type */
  57 
  58 #if !defined(__xpv)
  59 static x86pte_t *hat_kdi_pte = NULL;    /* vaddr of pte for hat_kdi_page */
  60 #endif
  61 
  62 /*
  63  * Get the address for remapping physical pages during boot
  64  */
  65 void
  66 hat_boot_kdi_init(void)
  67 {
  68         hat_kdi_page = (uintptr_t)kbm_push(0);  /* first call gets address... */
  69 }
  70 
  71 /*
  72  * Switch to using a page in the kernel's va range for physical memory access.
  73  * We need to allocate a virtual page, then permanently map in the page that
  74  * contains the PTE to it.
  75  */
  76 void
  77 hat_kdi_init(void)
  78 {
  79         /*LINTED:set but not used in function*/
  80         htable_t *ht __unused;
  81 
  82         /*
  83          * Get an kernel page VA to use for phys mem access. Then make sure
  84          * the VA has a page table.
  85          */
  86         hat_kdi_use_pae = mmu.pae_hat;
  87         hat_kdi_page = (uintptr_t)vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
  88         ht = htable_create(kas.a_hat, hat_kdi_page, 0, NULL);
  89         use_kbm = 0;
  90 
  91 #ifndef __xpv
  92         /*
  93          * Get an address at which to put the pagetable and devload it.
  94          */
  95         hat_kdi_pte = vmem_xalloc(heap_arena, MMU_PAGESIZE, MMU_PAGESIZE, 0,
  96             0, NULL, NULL, VM_SLEEP);
  97         hat_devload(kas.a_hat, (caddr_t)hat_kdi_pte, MMU_PAGESIZE, ht->ht_pfn,
  98             PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK,
  99             HAT_LOAD | HAT_LOAD_NOCONSIST);
 100         hat_kdi_pte =
 101             PT_INDEX_PTR(hat_kdi_pte, htable_va2entry(hat_kdi_page, ht));
 102 
 103         HTABLE_INC(ht->ht_valid_cnt);
 104         htable_release(ht);
 105 #endif
 106 }
 107 
 108 #ifdef __xpv
 109 
 110 /*
 111  * translate machine address to physical address
 112  */
 113 static uint64_t
 114 kdi_ptom(uint64_t pa)
 115 {
 116         extern pfn_t *mfn_list;
 117         ulong_t mfn = mfn_list[mmu_btop(pa)];
 118 
 119         return (pfn_to_pa(mfn) | (pa & MMU_PAGEOFFSET));
 120 }
 121 
 122 /*
 123  * This is like mfn_to_pfn(), but we can't use ontrap() from kmdb.
 124  * Instead we let the fault happen and kmdb deals with it.
 125  */
 126 static uint64_t
 127 kdi_mtop(uint64_t ma)
 128 {
 129         pfn_t pfn;
 130         mfn_t mfn = ma >> MMU_PAGESHIFT;
 131 
 132         if (HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL) < mfn)
 133                 return (ma | PFN_IS_FOREIGN_MFN);
 134 
 135         pfn = mfn_to_pfn_mapping[mfn];
 136         if (pfn >= mfn_count || pfn_to_mfn(pfn) != mfn)
 137                 return (ma | PFN_IS_FOREIGN_MFN);
 138         return (pfn_to_pa(pfn) | (ma & MMU_PAGEOFFSET));
 139 }
 140 
 141 #else
 142 #define kdi_mtop(m)     (m)
 143 #define kdi_ptom(p)     (p)
 144 #endif
 145 
 146 /*ARGSUSED*/
 147 int
 148 kdi_vtop(uintptr_t va, uint64_t *pap)
 149 {
 150         uintptr_t vaddr = va;
 151         size_t  len;
 152         pfn_t   pfn;
 153         uint_t  prot;
 154         int     level;
 155         x86pte_t pte;
 156         int     index;
 157 
 158         /*
 159          * if the mmu struct isn't relevant yet, we need to probe
 160          * the boot loader's pagetables.
 161          */
 162         if (!khat_running) {
 163                 if (kbm_probe(&vaddr, &len, &pfn, &prot) == 0)
 164                         return (ENOENT);
 165                 if (vaddr > va)
 166                         return (ENOENT);
 167                 if (vaddr < va)
 168                         pfn += mmu_btop(va - vaddr);
 169                 *pap = pfn_to_pa(pfn) + (vaddr & MMU_PAGEOFFSET);
 170                 return (0);
 171         }
 172 
 173         /*
 174          * We can't go through normal hat routines, so we'll use
 175          * kdi_pread() to walk the page tables
 176          */
 177 #if defined(__xpv)
 178         *pap = pfn_to_pa(CPU->cpu_current_hat->hat_htable->ht_pfn);
 179 #else
 180         *pap = getcr3() & MMU_PAGEMASK;
 181 #endif
 182         for (level = mmu.max_level; ; --level) {
 183                 index = (va >> LEVEL_SHIFT(level)) & (mmu.ptes_per_table - 1);
 184                 *pap += index << mmu.pte_size_shift;
 185                 pte = 0;
 186                 if (kdi_pread((caddr_t)&pte, mmu.pte_size, *pap, &len) != 0)
 187                         return (ENOENT);
 188                 if (pte == 0)
 189                         return (ENOENT);
 190                 if (level > 0 && level <= mmu.max_page_level &&
 191                     (pte & PT_PAGESIZE)) {
 192                         *pap = kdi_mtop(pte & PT_PADDR_LGPG);
 193                         break;
 194                 } else {
 195                         *pap = kdi_mtop(pte & PT_PADDR);
 196                         if (level == 0)
 197                                 break;
 198                 }
 199         }
 200         *pap += va & LEVEL_OFFSET(level);
 201         return (0);
 202 }
 203 
 204 static int
 205 kdi_prw(caddr_t buf, size_t nbytes, uint64_t pa, size_t *ncopiedp, int doread)
 206 {
 207         size_t  ncopied = 0;
 208         off_t   pgoff;
 209         size_t  sz;
 210         caddr_t va;
 211         caddr_t from;
 212         caddr_t to;
 213         x86pte_t pte;
 214 
 215         /*
 216          * if this is called before any initialization - fail
 217          */
 218         if (hat_kdi_page == 0)
 219                 return (EAGAIN);
 220 
 221         while (nbytes > 0) {
 222                 /*
 223                  * figure out the addresses and construct a minimal PTE
 224                  */
 225                 pgoff = pa & MMU_PAGEOFFSET;
 226                 sz = MIN(nbytes, MMU_PAGESIZE - pgoff);
 227                 va = (caddr_t)hat_kdi_page + pgoff;
 228                 pte = kdi_ptom(mmu_ptob(mmu_btop(pa))) | PT_VALID;
 229                 if (doread) {
 230                         from = va;
 231                         to = buf;
 232                 } else {
 233                         PTE_SET(pte, PT_WRITABLE);
 234                         from = buf;
 235                         to = va;
 236                 }
 237 
 238                 /*
 239                  * map the physical page
 240                  */
 241                 if (use_kbm)
 242                         (void) kbm_push(pa);
 243 #if defined(__xpv)
 244                 else
 245                         (void) HYPERVISOR_update_va_mapping(
 246                             (uintptr_t)va, pte, UVMF_INVLPG);
 247 #else
 248                 else if (hat_kdi_use_pae)
 249                         *hat_kdi_pte = pte;
 250                 else
 251                         *(x86pte32_t *)hat_kdi_pte = pte;
 252                 mmu_tlbflush_entry((caddr_t)hat_kdi_page);
 253 #endif
 254 
 255                 bcopy(from, to, sz);
 256 
 257                 /*
 258                  * erase the mapping
 259                  */
 260                 if (use_kbm)
 261                         kbm_pop();
 262 #if defined(__xpv)
 263                 else
 264                         (void) HYPERVISOR_update_va_mapping(
 265                             (uintptr_t)va, 0, UVMF_INVLPG);
 266 #else
 267                 else if (hat_kdi_use_pae)
 268                         *hat_kdi_pte = 0;
 269                 else
 270                         *(x86pte32_t *)hat_kdi_pte = 0;
 271                 mmu_tlbflush_entry((caddr_t)hat_kdi_page);
 272 #endif
 273 
 274                 buf += sz;
 275                 pa += sz;
 276                 nbytes -= sz;
 277                 ncopied += sz;
 278         }
 279 
 280         if (ncopied == 0)
 281                 return (ENOENT);
 282 
 283         *ncopiedp = ncopied;
 284         return (0);
 285 }
 286 
 287 int
 288 kdi_pread(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp)
 289 {
 290         return (kdi_prw(buf, nbytes, addr, ncopiedp, 1));
 291 }
 292 
 293 int
 294 kdi_pwrite(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp)
 295 {
 296         return (kdi_prw(buf, nbytes, addr, ncopiedp, 0));
 297 }
 298 
 299 
 300 /*
 301  * Return the number of bytes, relative to the beginning of a given range, that
 302  * are non-toxic (can be read from and written to with relative impunity).
 303  */
 304 /*ARGSUSED*/
 305 size_t
 306 kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write)
 307 {
 308 #if defined(__amd64)
 309         extern uintptr_t toxic_addr;
 310         extern size_t   toxic_size;
 311 
 312         /*
 313          * Check 64 bit toxic range.
 314          */
 315         if (toxic_addr != 0 &&
 316             va + sz >= toxic_addr &&
 317             va < toxic_addr + toxic_size)
 318                 return (va < toxic_addr ? toxic_addr - va : 0);
 319 
 320         /*
 321          * avoid any Virtual Address hole
 322          */
 323         if (va + sz >= hole_start && va < hole_end)
 324                 return (va < hole_start ? hole_start - va : 0);
 325 
 326         return (sz);
 327 
 328 #elif defined(__i386)
 329         extern void *device_arena_contains(void *, size_t, size_t *);
 330         uintptr_t v;
 331 
 332         v = (uintptr_t)device_arena_contains((void *)va, sz, NULL);
 333         if (v == 0)
 334                 return (sz);
 335         else if (v <= va)
 336                 return (0);
 337         else
 338                 return (v - va);
 339 
 340 #endif  /* __i386 */
 341 }