1 /* $NetBSD: kvm_i386pae.c,v 1.2 2014/02/19 20:21:22 dsl Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Jean-Yves Migeon. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __RCSID("$NetBSD: kvm_i386pae.c,v 1.2 2014/02/19 20:21:22 dsl Exp $"); 30 31 /* 32 * This will expose PAE functions, macros, definitions and constants. 33 * Note: this affects all virtual memory related functions. Only their 34 * PAE versions can be used below. 35 */ 36 #define PAE 37 38 #include <sys/param.h> 39 #include <sys/stat.h> 40 #include <sys/kcore.h> 41 #include <sys/types.h> 42 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include <nlist.h> 46 #include <kvm.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #include <limits.h> 51 #include <db.h> 52 53 #include "kvm_private.h" 54 55 #include <i386/kcore.h> 56 #include <i386/pmap.h> 57 #include <i386/pte.h> 58 #include <i386/vmparam.h> 59 60 int _kvm_kvatop_i386pae(kvm_t *, vaddr_t, paddr_t *); 61 62 /* 63 * Used to translate a virtual address to a physical address for systems 64 * running under PAE mode. Three levels of virtual memory pages are handled 65 * here: the per-CPU L3 page, the 4 L2 PDs and the PTs. 66 */ 67 int 68 _kvm_kvatop_i386pae(kvm_t *kd, vaddr_t va, paddr_t *pa) 69 { 70 cpu_kcore_hdr_t *cpu_kh; 71 u_long page_off; 72 pd_entry_t pde; 73 pt_entry_t pte; 74 paddr_t pde_pa, pte_pa; 75 76 cpu_kh = kd->cpu_data; 77 page_off = va & PGOFSET; 78 79 /* 80 * Find and read the PDE. Ignore the L3, as it is only a per-CPU 81 * page, not needed for kernel VA => PA translations. 82 * Remember that the 4 L2 pages are contiguous, so it is safe 83 * to increment pdppaddr to compute the address of the PDE. 84 * pdppaddr being PAGE_SIZE aligned, we mask the option bits. 85 */ 86 pde_pa = (cpu_kh->pdppaddr & PG_FRAME) + (pl2_pi(va) * sizeof(pde)); 87 if (_kvm_pread(kd, kd->pmfd, (void *)&pde, sizeof(pde), 88 _kvm_pa2off(kd, pde_pa)) != sizeof(pde)) { 89 _kvm_syserr(kd, 0, "could not read PDE"); 90 goto lose; 91 } 92 93 /* 94 * Find and read the page table entry. 95 */ 96 if ((pde & PG_V) == 0) { 97 _kvm_err(kd, 0, "invalid translation (invalid PDE)"); 98 goto lose; 99 } 100 if ((pde & PG_PS) != 0) { 101 /* 102 * This is a 2MB page. 103 */ 104 page_off = va & ((vaddr_t)~PG_LGFRAME); 105 *pa = (pde & PG_LGFRAME) + page_off; 106 return (int)(NBPD_L2 - page_off); 107 } 108 109 pte_pa = (pde & PG_FRAME) + (pl1_pi(va) * sizeof(pt_entry_t)); 110 if (_kvm_pread(kd, kd->pmfd, (void *) &pte, sizeof(pte), 111 _kvm_pa2off(kd, pte_pa)) != sizeof(pte)) { 112 _kvm_syserr(kd, 0, "could not read PTE"); 113 goto lose; 114 } 115 116 /* 117 * Validate the PTE and return the physical address. 118 */ 119 if ((pte & PG_V) == 0) { 120 _kvm_err(kd, 0, "invalid translation (invalid PTE)"); 121 goto lose; 122 } 123 *pa = (pte & PG_FRAME) + page_off; 124 return (int)(NBPG - page_off); 125 126 lose: 127 *pa = (paddr_t)~0L; 128 return 0; 129 130 } 131