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 38f95a0250SRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 39c4a7cdb3SPeter Wemm #if 0 40f95a0250SRodney W. Grimes static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 41c4a7cdb3SPeter Wemm #else 42c4a7cdb3SPeter Wemm static const char rcsid[] = 43c4a7cdb3SPeter Wemm "$FreeBSD$"; 44c4a7cdb3SPeter Wemm #endif 45f95a0250SRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 46f95a0250SRodney W. Grimes 47f95a0250SRodney W. Grimes /* 4821d54b07SRodney W. Grimes * i386 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> 5382633431SMark Murray #include <sys/lock.h> 5482633431SMark Murray #include <sys/mutex.h> 55f95a0250SRodney W. Grimes #include <sys/user.h> 56f95a0250SRodney W. Grimes #include <sys/proc.h> 57f95a0250SRodney W. Grimes #include <sys/stat.h> 5851295a4dSJordan K. Hubbard #include <stdlib.h> 59f95a0250SRodney W. Grimes #include <unistd.h> 60f95a0250SRodney W. Grimes #include <nlist.h> 61f95a0250SRodney W. Grimes #include <kvm.h> 62f95a0250SRodney W. Grimes 63f95a0250SRodney W. Grimes #include <vm/vm.h> 64f95a0250SRodney W. Grimes #include <vm/vm_param.h> 65f95a0250SRodney W. Grimes 66f95a0250SRodney W. Grimes #include <limits.h> 67f95a0250SRodney W. Grimes 68f95a0250SRodney W. Grimes #include "kvm_private.h" 69f95a0250SRodney W. Grimes 70f95a0250SRodney W. Grimes #ifndef btop 7121d54b07SRodney W. Grimes #define btop(x) (i386_btop(x)) 7221d54b07SRodney W. Grimes #define ptob(x) (i386_ptob(x)) 73f95a0250SRodney W. Grimes #endif 74f95a0250SRodney W. Grimes 75f95a0250SRodney W. Grimes struct vmstate { 762f85bf6eSPeter Wemm pd_entry_t *PTD; 77f95a0250SRodney W. Grimes }; 78f95a0250SRodney W. Grimes 79f95a0250SRodney W. Grimes void 802f85bf6eSPeter Wemm _kvm_freevtop(kvm_t *kd) 812f85bf6eSPeter Wemm { 822f85bf6eSPeter Wemm if (kd->vmst != 0) { 8321d54b07SRodney W. Grimes if (kd->vmst->PTD) { 8421d54b07SRodney W. Grimes free(kd->vmst->PTD); 8521d54b07SRodney W. Grimes } 86f95a0250SRodney W. Grimes free(kd->vmst); 87f95a0250SRodney W. Grimes } 8821d54b07SRodney W. Grimes } 89f95a0250SRodney W. Grimes 90f95a0250SRodney W. Grimes int 912f85bf6eSPeter Wemm _kvm_initvtop(kvm_t *kd) 922f85bf6eSPeter Wemm { 93f95a0250SRodney W. Grimes struct vmstate *vm; 9421d54b07SRodney W. Grimes struct nlist nlist[2]; 952f85bf6eSPeter Wemm u_long pa; 96f85f3040SPeter Wemm u_long kernbase; 972f85bf6eSPeter Wemm pd_entry_t *PTD; 98f95a0250SRodney W. Grimes 99f95a0250SRodney W. Grimes vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 10021d54b07SRodney W. Grimes if (vm == 0) { 10121d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot allocate vm"); 102f95a0250SRodney W. Grimes return (-1); 10321d54b07SRodney W. Grimes } 104f95a0250SRodney W. Grimes kd->vmst = vm; 1052f85bf6eSPeter Wemm vm->PTD = 0; 106f95a0250SRodney W. Grimes 107f85f3040SPeter Wemm nlist[0].n_name = "kernbase"; 108f85f3040SPeter Wemm nlist[1].n_name = 0; 109f85f3040SPeter Wemm 110f85f3040SPeter Wemm if (kvm_nlist(kd, nlist) != 0) 111f85f3040SPeter Wemm kernbase = KERNBASE; /* for old kernels */ 112f85f3040SPeter Wemm else 113f85f3040SPeter Wemm kernbase = nlist[0].n_value; 114f85f3040SPeter Wemm 115f85f3040SPeter Wemm nlist[0].n_name = "IdlePTD"; 11621d54b07SRodney W. Grimes nlist[1].n_name = 0; 117f95a0250SRodney W. Grimes 118f95a0250SRodney W. Grimes if (kvm_nlist(kd, nlist) != 0) { 119f95a0250SRodney W. Grimes _kvm_err(kd, kd->program, "bad namelist"); 120f95a0250SRodney W. Grimes return (-1); 121f95a0250SRodney W. Grimes } 122f85f3040SPeter Wemm if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, sizeof(pa)) != 123f85f3040SPeter Wemm sizeof(pa)) { 12421d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read IdlePTD"); 125f95a0250SRodney W. Grimes return (-1); 126f95a0250SRodney W. Grimes } 1272f85bf6eSPeter Wemm PTD = _kvm_malloc(kd, PAGE_SIZE); 1282f85bf6eSPeter Wemm if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) { 12921d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read PTD"); 130f95a0250SRodney W. Grimes return (-1); 131f95a0250SRodney W. Grimes } 1322f85bf6eSPeter Wemm vm->PTD = PTD; 133f95a0250SRodney W. Grimes return (0); 134f95a0250SRodney W. Grimes } 135f95a0250SRodney W. Grimes 136f95a0250SRodney W. Grimes static int 1372f85bf6eSPeter Wemm _kvm_vatop(kvm_t *kd, u_long va, u_long *pa) 1382f85bf6eSPeter Wemm { 1392f85bf6eSPeter Wemm struct vmstate *vm; 1402f85bf6eSPeter Wemm u_long offset; 1412f85bf6eSPeter Wemm u_long pte_pa; 1422f85bf6eSPeter Wemm pd_entry_t pde; 1432f85bf6eSPeter Wemm pt_entry_t pte; 1442f85bf6eSPeter Wemm u_long pdeindex; 1452f85bf6eSPeter Wemm u_long pteindex; 1462f85bf6eSPeter Wemm int i; 147f95a0250SRodney W. Grimes 148f95a0250SRodney W. Grimes if (ISALIVE(kd)) { 149f95a0250SRodney W. Grimes _kvm_err(kd, 0, "vatop called in live kernel!"); 150f95a0250SRodney W. Grimes return((off_t)0); 151f95a0250SRodney W. Grimes } 1522f85bf6eSPeter Wemm 1532f85bf6eSPeter Wemm vm = kd->vmst; 1542f85bf6eSPeter Wemm offset = va & (PAGE_SIZE - 1); 1552f85bf6eSPeter Wemm 1562f85bf6eSPeter Wemm /* 1572f85bf6eSPeter Wemm * If we are initializing (kernel page table descriptor pointer 1582f85bf6eSPeter Wemm * not yet set) then return pa == va to avoid infinite recursion. 1592f85bf6eSPeter Wemm */ 1602f85bf6eSPeter Wemm if (vm->PTD == 0) { 1612f85bf6eSPeter Wemm *pa = va; 1622f85bf6eSPeter Wemm return (PAGE_SIZE - offset); 1632f85bf6eSPeter Wemm } 1642f85bf6eSPeter Wemm 1652f85bf6eSPeter Wemm pdeindex = va >> PDRSHIFT; 1662f85bf6eSPeter Wemm pde = vm->PTD[pdeindex]; 1672f85bf6eSPeter Wemm if (((u_long)pde & PG_V) == 0) 1682f85bf6eSPeter Wemm goto invalid; 1692f85bf6eSPeter Wemm 1704afb0d5aSTor Egge if ((u_long)pde & PG_PS) { 1714afb0d5aSTor Egge /* 1724afb0d5aSTor Egge * No second-level page table; ptd describes one 4MB page. 1734afb0d5aSTor Egge * (We assume that the kernel wouldn't set PG_PS without enabling 1744afb0d5aSTor Egge * it cr0, and that the kernel doesn't support 36-bit physical 1754afb0d5aSTor Egge * addresses). 1764afb0d5aSTor Egge */ 1774afb0d5aSTor Egge #define PAGE4M_MASK (NBPDR - 1) 1784afb0d5aSTor Egge #define PG_FRAME4M (~PAGE4M_MASK) 1794afb0d5aSTor Egge *pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); 1804afb0d5aSTor Egge return (NBPDR - (va & PAGE4M_MASK)); 1814afb0d5aSTor Egge } 1824afb0d5aSTor Egge 1832f85bf6eSPeter Wemm pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); 1842f85bf6eSPeter Wemm pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t)); 1852f85bf6eSPeter Wemm 1862f85bf6eSPeter Wemm /* XXX This has to be a physical address read, kvm_read is virtual */ 1872f85bf6eSPeter Wemm if (lseek(kd->pmfd, pte_pa, 0) == -1) { 1882f85bf6eSPeter Wemm _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); 1892f85bf6eSPeter Wemm goto invalid; 1902f85bf6eSPeter Wemm } 1912f85bf6eSPeter Wemm if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { 1922f85bf6eSPeter Wemm _kvm_syserr(kd, kd->program, "_kvm_vatop: read"); 1932f85bf6eSPeter Wemm goto invalid; 1942f85bf6eSPeter Wemm } 1952f85bf6eSPeter Wemm if (((u_long)pte & PG_V) == 0) 1962f85bf6eSPeter Wemm goto invalid; 1972f85bf6eSPeter Wemm 1982f85bf6eSPeter Wemm *pa = ((u_long)pte & PG_FRAME) + offset; 1992f85bf6eSPeter Wemm return (PAGE_SIZE - offset); 2002f85bf6eSPeter Wemm 2012f85bf6eSPeter Wemm invalid: 202f95a0250SRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", va); 2032f85bf6eSPeter Wemm return (0); 204f95a0250SRodney W. Grimes } 205f95a0250SRodney W. Grimes 206f95a0250SRodney W. Grimes int 2072f85bf6eSPeter Wemm _kvm_kvatop(kvm_t *kd, u_long va, u_long *pa) 2082f85bf6eSPeter Wemm { 20921d54b07SRodney W. Grimes return (_kvm_vatop(kd, va, pa)); 210f95a0250SRodney W. Grimes } 211