1f95a0250SRodney W. Grimes /*- 2f95a0250SRodney W. Grimes * Copyright (c) 1989, 1992, 1993 3f95a0250SRodney W. Grimes * The Regents of the University of California. All rights reserved. 4f95a0250SRodney W. Grimes * 5f95a0250SRodney W. Grimes * This code is derived from software developed by the Computer Systems 6f95a0250SRodney W. Grimes * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7f95a0250SRodney W. Grimes * BG 91-66 and contributed to Berkeley. 8f95a0250SRodney W. Grimes * 9f95a0250SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 10f95a0250SRodney W. Grimes * modification, are permitted provided that the following conditions 11f95a0250SRodney W. Grimes * are met: 12f95a0250SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 13f95a0250SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 14f95a0250SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 15f95a0250SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 16f95a0250SRodney W. Grimes * documentation and/or other materials provided with the distribution. 17f95a0250SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 18f95a0250SRodney W. Grimes * must display the following acknowledgement: 19f95a0250SRodney W. Grimes * This product includes software developed by the University of 20f95a0250SRodney W. Grimes * California, Berkeley and its contributors. 21f95a0250SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 22f95a0250SRodney W. Grimes * may be used to endorse or promote products derived from this software 23f95a0250SRodney W. Grimes * without specific prior written permission. 24f95a0250SRodney W. Grimes * 25f95a0250SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26f95a0250SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27f95a0250SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28f95a0250SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29f95a0250SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30f95a0250SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31f95a0250SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32f95a0250SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33f95a0250SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34f95a0250SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35f95a0250SRodney W. Grimes * SUCH DAMAGE. 36f95a0250SRodney W. Grimes */ 37f95a0250SRodney W. Grimes 38e67f5b9fSMatthew Dillon #include <sys/cdefs.h> 39e67f5b9fSMatthew Dillon __FBSDID("$FreeBSD$"); 40e67f5b9fSMatthew Dillon 41f95a0250SRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 42c4a7cdb3SPeter Wemm #if 0 43f95a0250SRodney W. Grimes static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 44c4a7cdb3SPeter Wemm #endif 45f95a0250SRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 46f95a0250SRodney W. Grimes 47f95a0250SRodney W. Grimes /* 48a1de871dSPeter Wemm * AMD64 machine dependent routines for kvm. Hopefully, the forthcoming 49f95a0250SRodney W. Grimes * vm code will one day obsolete this module. 50f95a0250SRodney W. Grimes */ 51f95a0250SRodney W. Grimes 52f95a0250SRodney W. Grimes #include <sys/param.h> 53f95a0250SRodney W. Grimes #include <sys/user.h> 54f95a0250SRodney W. Grimes #include <sys/proc.h> 55f95a0250SRodney W. Grimes #include <sys/stat.h> 5651295a4dSJordan K. Hubbard #include <stdlib.h> 57f95a0250SRodney W. Grimes #include <unistd.h> 58f95a0250SRodney W. Grimes #include <nlist.h> 59f95a0250SRodney W. Grimes #include <kvm.h> 60f95a0250SRodney W. Grimes 61f95a0250SRodney W. Grimes #include <vm/vm.h> 62f95a0250SRodney W. Grimes #include <vm/vm_param.h> 63f95a0250SRodney W. Grimes 64f95a0250SRodney W. Grimes #include <limits.h> 65f95a0250SRodney W. Grimes 66f95a0250SRodney W. Grimes #include "kvm_private.h" 67f95a0250SRodney W. Grimes 68f95a0250SRodney W. Grimes #ifndef btop 69a1de871dSPeter Wemm #define btop(x) (amd64_btop(x)) 70a1de871dSPeter Wemm #define ptob(x) (amd64_ptob(x)) 71f95a0250SRodney W. Grimes #endif 72f95a0250SRodney W. Grimes 73f95a0250SRodney W. Grimes struct vmstate { 742f85bf6eSPeter Wemm pd_entry_t *PTD; 75f95a0250SRodney W. Grimes }; 76f95a0250SRodney W. Grimes 77f95a0250SRodney W. Grimes void 782f85bf6eSPeter Wemm _kvm_freevtop(kvm_t *kd) 792f85bf6eSPeter Wemm { 802f85bf6eSPeter Wemm if (kd->vmst != 0) { 8121d54b07SRodney W. Grimes if (kd->vmst->PTD) { 8221d54b07SRodney W. Grimes free(kd->vmst->PTD); 8321d54b07SRodney W. Grimes } 84f95a0250SRodney W. Grimes free(kd->vmst); 85f95a0250SRodney W. Grimes } 8621d54b07SRodney W. Grimes } 87f95a0250SRodney W. Grimes 88f95a0250SRodney W. Grimes int 892f85bf6eSPeter Wemm _kvm_initvtop(kvm_t *kd) 902f85bf6eSPeter Wemm { 91f95a0250SRodney W. Grimes struct vmstate *vm; 9221d54b07SRodney W. Grimes struct nlist nlist[2]; 932f85bf6eSPeter Wemm u_long pa; 94f85f3040SPeter Wemm u_long kernbase; 952f85bf6eSPeter Wemm pd_entry_t *PTD; 96f95a0250SRodney W. Grimes 97f95a0250SRodney W. Grimes vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 9821d54b07SRodney W. Grimes if (vm == 0) { 9921d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot allocate vm"); 100f95a0250SRodney W. Grimes return (-1); 10121d54b07SRodney W. Grimes } 102f95a0250SRodney W. Grimes kd->vmst = vm; 1032f85bf6eSPeter Wemm vm->PTD = 0; 104f95a0250SRodney W. Grimes 105f85f3040SPeter Wemm nlist[0].n_name = "kernbase"; 106f85f3040SPeter Wemm nlist[1].n_name = 0; 107f85f3040SPeter Wemm 108f85f3040SPeter Wemm if (kvm_nlist(kd, nlist) != 0) 109f85f3040SPeter Wemm kernbase = KERNBASE; /* for old kernels */ 110f85f3040SPeter Wemm else 111f85f3040SPeter Wemm kernbase = nlist[0].n_value; 112f85f3040SPeter Wemm 113f85f3040SPeter Wemm nlist[0].n_name = "IdlePTD"; 11421d54b07SRodney W. Grimes nlist[1].n_name = 0; 115f95a0250SRodney W. Grimes 116f95a0250SRodney W. Grimes if (kvm_nlist(kd, nlist) != 0) { 117f95a0250SRodney W. Grimes _kvm_err(kd, kd->program, "bad namelist"); 118f95a0250SRodney W. Grimes return (-1); 119f95a0250SRodney W. Grimes } 120f85f3040SPeter Wemm if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, sizeof(pa)) != 121f85f3040SPeter Wemm sizeof(pa)) { 12221d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read IdlePTD"); 123f95a0250SRodney W. Grimes return (-1); 124f95a0250SRodney W. Grimes } 1252f85bf6eSPeter Wemm PTD = _kvm_malloc(kd, PAGE_SIZE); 1262f85bf6eSPeter Wemm if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) { 12721d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read PTD"); 128f95a0250SRodney W. Grimes return (-1); 129f95a0250SRodney W. Grimes } 1302f85bf6eSPeter Wemm vm->PTD = PTD; 131f95a0250SRodney W. Grimes return (0); 132f95a0250SRodney W. Grimes } 133f95a0250SRodney W. Grimes 134f95a0250SRodney W. Grimes static int 1352f85bf6eSPeter Wemm _kvm_vatop(kvm_t *kd, u_long va, u_long *pa) 1362f85bf6eSPeter Wemm { 1372f85bf6eSPeter Wemm struct vmstate *vm; 1382f85bf6eSPeter Wemm u_long offset; 1392f85bf6eSPeter Wemm u_long pte_pa; 1402f85bf6eSPeter Wemm pd_entry_t pde; 1412f85bf6eSPeter Wemm pt_entry_t pte; 1422f85bf6eSPeter Wemm u_long pdeindex; 1432f85bf6eSPeter Wemm u_long pteindex; 1442f85bf6eSPeter Wemm int i; 145f95a0250SRodney W. Grimes 146f95a0250SRodney W. Grimes if (ISALIVE(kd)) { 147f95a0250SRodney W. Grimes _kvm_err(kd, 0, "vatop called in live kernel!"); 148f95a0250SRodney W. Grimes return((off_t)0); 149f95a0250SRodney W. Grimes } 1502f85bf6eSPeter Wemm 1512f85bf6eSPeter Wemm vm = kd->vmst; 1522f85bf6eSPeter Wemm offset = va & (PAGE_SIZE - 1); 1532f85bf6eSPeter Wemm 1542f85bf6eSPeter Wemm /* 1552f85bf6eSPeter Wemm * If we are initializing (kernel page table descriptor pointer 1562f85bf6eSPeter Wemm * not yet set) then return pa == va to avoid infinite recursion. 1572f85bf6eSPeter Wemm */ 1582f85bf6eSPeter Wemm if (vm->PTD == 0) { 1592f85bf6eSPeter Wemm *pa = va; 1602f85bf6eSPeter Wemm return (PAGE_SIZE - offset); 1612f85bf6eSPeter Wemm } 1622f85bf6eSPeter Wemm 1632f85bf6eSPeter Wemm pdeindex = va >> PDRSHIFT; 1642f85bf6eSPeter Wemm pde = vm->PTD[pdeindex]; 1652f85bf6eSPeter Wemm if (((u_long)pde & PG_V) == 0) 1662f85bf6eSPeter Wemm goto invalid; 1672f85bf6eSPeter Wemm 1684afb0d5aSTor Egge if ((u_long)pde & PG_PS) { 1694afb0d5aSTor Egge /* 1704afb0d5aSTor Egge * No second-level page table; ptd describes one 4MB page. 1714afb0d5aSTor Egge * (We assume that the kernel wouldn't set PG_PS without enabling 1724afb0d5aSTor Egge * it cr0, and that the kernel doesn't support 36-bit physical 1734afb0d5aSTor Egge * addresses). 1744afb0d5aSTor Egge */ 1754afb0d5aSTor Egge #define PAGE4M_MASK (NBPDR - 1) 1764afb0d5aSTor Egge #define PG_FRAME4M (~PAGE4M_MASK) 1774afb0d5aSTor Egge *pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); 1784afb0d5aSTor Egge return (NBPDR - (va & PAGE4M_MASK)); 1794afb0d5aSTor Egge } 1804afb0d5aSTor Egge 1812f85bf6eSPeter Wemm pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); 1822f85bf6eSPeter Wemm pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t)); 1832f85bf6eSPeter Wemm 1842f85bf6eSPeter Wemm /* XXX This has to be a physical address read, kvm_read is virtual */ 1852f85bf6eSPeter Wemm if (lseek(kd->pmfd, pte_pa, 0) == -1) { 1862f85bf6eSPeter Wemm _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); 1872f85bf6eSPeter Wemm goto invalid; 1882f85bf6eSPeter Wemm } 1892f85bf6eSPeter Wemm if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { 1902f85bf6eSPeter Wemm _kvm_syserr(kd, kd->program, "_kvm_vatop: read"); 1912f85bf6eSPeter Wemm goto invalid; 1922f85bf6eSPeter Wemm } 1932f85bf6eSPeter Wemm if (((u_long)pte & PG_V) == 0) 1942f85bf6eSPeter Wemm goto invalid; 1952f85bf6eSPeter Wemm 1962f85bf6eSPeter Wemm *pa = ((u_long)pte & PG_FRAME) + offset; 1972f85bf6eSPeter Wemm return (PAGE_SIZE - offset); 1982f85bf6eSPeter Wemm 1992f85bf6eSPeter Wemm invalid: 200f95a0250SRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", va); 2012f85bf6eSPeter Wemm return (0); 202f95a0250SRodney W. Grimes } 203f95a0250SRodney W. Grimes 204f95a0250SRodney W. Grimes int 2052f85bf6eSPeter Wemm _kvm_kvatop(kvm_t *kd, u_long va, u_long *pa) 2062f85bf6eSPeter Wemm { 20721d54b07SRodney W. Grimes return (_kvm_vatop(kd, va, pa)); 208f95a0250SRodney W. Grimes } 209