kvm_i386.c revision 55127
112437Speter/*- 212437Speter * Copyright (c) 1989, 1992, 1993 312437Speter * The Regents of the University of California. All rights reserved. 412437Speter * 512437Speter * This code is derived from software developed by the Computer Systems 612437Speter * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 712437Speter * BG 91-66 and contributed to Berkeley. 812437Speter * 912437Speter * Redistribution and use in source and binary forms, with or without 1012437Speter * modification, are permitted provided that the following conditions 1112437Speter * are met: 1212437Speter * 1. Redistributions of source code must retain the above copyright 1312437Speter * notice, this list of conditions and the following disclaimer. 1412437Speter * 2. Redistributions in binary form must reproduce the above copyright 1512437Speter * notice, this list of conditions and the following disclaimer in the 1612437Speter * documentation and/or other materials provided with the distribution. 1712437Speter * 3. All advertising materials mentioning features or use of this software 1812437Speter * must display the following acknowledgement: 1912437Speter * This product includes software developed by the University of 2012437Speter * California, Berkeley and its contributors. 2112437Speter * 4. Neither the name of the University nor the names of its contributors 2212437Speter * may be used to endorse or promote products derived from this software 2312437Speter * without specific prior written permission. 2412437Speter * 2512437Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2612437Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2712437Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2812437Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2912437Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3012437Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3112437Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3214643Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3312437Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3412437Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3512437Speter * SUCH DAMAGE. 3612437Speter */ 3712437Speter 3812437Speter#if defined(LIBC_SCCS) && !defined(lint) 3912437Speter#if 0 4012437Speterstatic char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 4112437Speter#else 4212437Speterstatic const char rcsid[] = 4312437Speter "$FreeBSD: head/lib/libkvm/kvm_i386.c 55127 1999-12-27 07:14:58Z peter $"; 4412437Speter#endif 4512437Speter#endif /* LIBC_SCCS and not lint */ 4612437Speter 4712437Speter/* 4812437Speter * i386 machine dependent routines for kvm. Hopefully, the forthcoming 4912437Speter * vm code will one day obsolete this module. 5012437Speter */ 5112437Speter 5212437Speter#include <sys/param.h> 5312437Speter#include <sys/user.h> 5412437Speter#include <sys/proc.h> 5512437Speter#include <sys/stat.h> 5612437Speter#include <stdlib.h> 5712437Speter#include <unistd.h> 5812437Speter#include <nlist.h> 5912437Speter#include <kvm.h> 6012437Speter 6112437Speter#include <vm/vm.h> 6212437Speter#include <vm/vm_param.h> 6312437Speter 6412437Speter#include <limits.h> 6512437Speter 6612437Speter#include "kvm_private.h" 6712437Speter 6812437Speter#ifndef btop 6912437Speter#define btop(x) (i386_btop(x)) 7012437Speter#define ptob(x) (i386_ptob(x)) 7112437Speter#endif 7212437Speter 7312437Speterstruct vmstate { 7412437Speter pd_entry_t *PTD; 7512437Speter}; 7612437Speter 7712437Spetervoid 7812437Speter_kvm_freevtop(kvm_t *kd) 7912437Speter{ 8012437Speter if (kd->vmst != 0) { 8112437Speter if (kd->vmst->PTD) { 8212437Speter free(kd->vmst->PTD); 8312437Speter } 8412437Speter free(kd->vmst); 8512437Speter } 8612437Speter} 8712437Speter 8812437Speterint 8912437Speter_kvm_initvtop(kvm_t *kd) 9012437Speter{ 9112437Speter struct vmstate *vm; 9212437Speter struct nlist nlist[2]; 9312437Speter u_long pa; 9412437Speter pd_entry_t *PTD; 9512437Speter 9612437Speter vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 9712437Speter if (vm == 0) { 9812437Speter _kvm_err(kd, kd->program, "cannot allocate vm"); 9912437Speter return (-1); 10012437Speter } 10112437Speter kd->vmst = vm; 10212437Speter vm->PTD = 0; 10312437Speter 10412437Speter nlist[0].n_name = "_IdlePTD"; 10512437Speter nlist[1].n_name = 0; 10612437Speter 10712437Speter if (kvm_nlist(kd, nlist) != 0) { 10812437Speter _kvm_err(kd, kd->program, "bad namelist"); 10912437Speter return (-1); 11012437Speter } 11112437Speter if (kvm_read(kd, (nlist[0].n_value - KERNBASE), &pa, sizeof(pa)) != sizeof(pa)) { 11212437Speter _kvm_err(kd, kd->program, "cannot read IdlePTD"); 11312437Speter return (-1); 11412437Speter } 11512437Speter PTD = _kvm_malloc(kd, PAGE_SIZE); 11612437Speter if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) { 11712437Speter _kvm_err(kd, kd->program, "cannot read PTD"); 11812437Speter return (-1); 11912437Speter } 12012437Speter vm->PTD = PTD; 12112437Speter return (0); 12212437Speter} 12312437Speter 12412437Speterstatic int 12512437Speter_kvm_vatop(kvm_t *kd, u_long va, u_long *pa) 12612437Speter{ 12712437Speter struct vmstate *vm; 12812437Speter u_long offset; 12912437Speter u_long pte_pa; 13012437Speter pd_entry_t pde; 13112437Speter pt_entry_t pte; 13212437Speter u_long pdeindex; 13312437Speter u_long pteindex; 13412437Speter int i; 13512437Speter 13612437Speter if (ISALIVE(kd)) { 13712437Speter _kvm_err(kd, 0, "vatop called in live kernel!"); 13812437Speter return((off_t)0); 13912437Speter } 14012437Speter 14112437Speter vm = kd->vmst; 14212437Speter offset = va & (PAGE_SIZE - 1); 14312437Speter 14412437Speter /* 14512437Speter * If we are initializing (kernel page table descriptor pointer 14612437Speter * not yet set) then return pa == va to avoid infinite recursion. 14712437Speter */ 14812437Speter if (vm->PTD == 0) { 14912437Speter *pa = va; 15012437Speter return (PAGE_SIZE - offset); 15112437Speter } 15212437Speter 15312437Speter pdeindex = va >> PDRSHIFT; 15412437Speter pde = vm->PTD[pdeindex]; 15512437Speter if (((u_long)pde & PG_V) == 0) 15612437Speter goto invalid; 15712437Speter 15812437Speter if ((u_long)pde & PG_PS) { 15912437Speter /* 16012437Speter * No second-level page table; ptd describes one 4MB page. 16112437Speter * (We assume that the kernel wouldn't set PG_PS without enabling 16212437Speter * it cr0, and that the kernel doesn't support 36-bit physical 16312437Speter * addresses). 16412437Speter */ 16512437Speter#define PAGE4M_MASK (NBPDR - 1) 16612437Speter#define PG_FRAME4M (~PAGE4M_MASK) 16712437Speter *pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); 16812437Speter return (NBPDR - (va & PAGE4M_MASK)); 16912437Speter } 17012437Speter 17112437Speter pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); 17212437Speter pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t)); 17312437Speter 17412437Speter /* XXX This has to be a physical address read, kvm_read is virtual */ 17512437Speter if (lseek(kd->pmfd, pte_pa, 0) == -1) { 17612437Speter _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); 17712437Speter goto invalid; 17812437Speter } 17912437Speter if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { 18012437Speter _kvm_syserr(kd, kd->program, "_kvm_vatop: read"); 18112437Speter goto invalid; 18212437Speter } 18312437Speter if (((u_long)pte & PG_V) == 0) 18412437Speter goto invalid; 18512437Speter 18612437Speter *pa = ((u_long)pte & PG_FRAME) + offset; 18712437Speter return (PAGE_SIZE - offset); 18812437Speter 18912437Speterinvalid: 19012437Speter _kvm_err(kd, 0, "invalid address (%x)", va); 19112437Speter return (0); 19212437Speter} 19312437Speter 19412437Speterint 19512437Speter_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa) 19612437Speter{ 19712437Speter return (_kvm_vatop(kd, va, pa)); 19812437Speter} 19912437Speter