1 /* $NetBSD: kvm_i386pae.c,v 1.1 2010/10/05 23:48:16 jym 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.1 2010/10/05 23:48:16 jym 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/user.h> 40 #include <sys/stat.h> 41 #include <sys/kcore.h> 42 #include <sys/types.h> 43 44 #include <stdlib.h> 45 #include <unistd.h> 46 #include <nlist.h> 47 #include <kvm.h> 48 49 #include <uvm/uvm_extern.h> 50 51 #include <limits.h> 52 #include <db.h> 53 54 #include "kvm_private.h" 55 56 #include <i386/kcore.h> 57 #include <i386/pmap.h> 58 #include <i386/pte.h> 59 #include <i386/vmparam.h> 60 61 int _kvm_kvatop_i386pae(kvm_t *, vaddr_t, paddr_t *); 62 63 /* 64 * Used to translate a virtual address to a physical address for systems 65 * running under PAE mode. Three levels of virtual memory pages are handled 66 * here: the per-CPU L3 page, the 4 L2 PDs and the PTs. 67 */ 68 int 69 _kvm_kvatop_i386pae(kvm_t *kd, vaddr_t va, paddr_t *pa) 70 { 71 cpu_kcore_hdr_t *cpu_kh; 72 u_long page_off; 73 pd_entry_t pde; 74 pt_entry_t pte; 75 paddr_t pde_pa, pte_pa; 76 77 cpu_kh = kd->cpu_data; 78 page_off = va & PGOFSET; 79 80 /* 81 * Find and read the PDE. Ignore the L3, as it is only a per-CPU 82 * page, not needed for kernel VA => PA translations. 83 * Remember that the 4 L2 pages are contiguous, so it is safe 84 * to increment pdppaddr to compute the address of the PDE. 85 * pdppaddr being PAGE_SIZE aligned, we mask the option bits. 86 */ 87 pde_pa = (cpu_kh->pdppaddr & PG_FRAME) + (pl2_pi(va) * sizeof(pde)); 88 if (_kvm_pread(kd, kd->pmfd, (void *)&pde, sizeof(pde), 89 _kvm_pa2off(kd, pde_pa)) != sizeof(pde)) { 90 _kvm_syserr(kd, 0, "could not read PDE"); 91 goto lose; 92 } 93 94 /* 95 * Find and read the page table entry. 96 */ 97 if ((pde & PG_V) == 0) { 98 _kvm_err(kd, 0, "invalid translation (invalid PDE)"); 99 goto lose; 100 } 101 if ((pde & PG_PS) != 0) { 102 /* 103 * This is a 2MB page. 104 */ 105 page_off = va & ((vaddr_t)~PG_LGFRAME); 106 *pa = (pde & PG_LGFRAME) + page_off; 107 return (int)(NBPD_L2 - page_off); 108 } 109 110 pte_pa = (pde & PG_FRAME) + (pl1_pi(va) * sizeof(pt_entry_t)); 111 if (_kvm_pread(kd, kd->pmfd, (void *) &pte, sizeof(pte), 112 _kvm_pa2off(kd, pte_pa)) != sizeof(pte)) { 113 _kvm_syserr(kd, 0, "could not read PTE"); 114 goto lose; 115 } 116 117 /* 118 * Validate the PTE and return the physical address. 119 */ 120 if ((pte & PG_V) == 0) { 121 _kvm_err(kd, 0, "invalid translation (invalid PTE)"); 122 goto lose; 123 } 124 *pa = (pte & PG_FRAME) + page_off; 125 return (int)(NBPG - page_off); 126 127 lose: 128 *pa = (paddr_t)~0L; 129 return 0; 130 131 } 132