From owner-svn-src-projects@FreeBSD.ORG Thu May 24 12:02:11 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6C400106567B; Thu, 24 May 2012 12:02:11 +0000 (UTC) (envelope-from cherry@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 54AC88FC23; Thu, 24 May 2012 12:02:11 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4OC2BIm036892; Thu, 24 May 2012 12:02:11 GMT (envelope-from cherry@svn.freebsd.org) Received: (from cherry@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4OC2BFp036889; Thu, 24 May 2012 12:02:11 GMT (envelope-from cherry@svn.freebsd.org) Message-Id: <201205241202.q4OC2BFp036889@svn.freebsd.org> From: "Cherry G. Mathew" Date: Thu, 24 May 2012 12:02:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235904 - in projects/amd64_xen_pv/sys: amd64/xen conf X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 May 2012 12:02:11 -0000 Author: cherry Date: Thu May 24 12:02:10 2012 New Revision: 235904 URL: http://svn.freebsd.org/changeset/base/235904 Log: This API is an attempt to abstract the MMU state in an MI fashion. It is heavily wip and may or may not go away, from amd64/ depending on how things go with the direct mapped implementation Added: projects/amd64_xen_pv/sys/amd64/xen/mmu_map.c projects/amd64_xen_pv/sys/amd64/xen/mmu_map.h Modified: projects/amd64_xen_pv/sys/conf/files.amd64 Added: projects/amd64_xen_pv/sys/amd64/xen/mmu_map.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/amd64_xen_pv/sys/amd64/xen/mmu_map.c Thu May 24 12:02:10 2012 (r235904) @@ -0,0 +1,389 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2011-2012 Spectra Logic Corporation + * All rights reserved. + * + * This software was developed by Cherry G. Mathew + * under sponsorship from Spectra Logic Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +/* + * This file implements the API that manages the page table + * hierarchy for the amd64 Xen pmap. + */ +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" +#include "opt_pmap.h" +#include "opt_smp.h" + + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +static int +pml4t_index(vm_offset_t va) +{ + /* amd64 sign extends 48th bit and upwards */ + const uint64_t SIGNMASK = (1UL << 48) - 1; + va &= SIGNMASK; /* Remove sign extension */ + + return (va >> PML4SHIFT); +} + +static int +pdpt_index(vm_offset_t va) +{ + /* amd64 sign extends 48th bit and upwards */ + const uint64_t SIGNMASK = (1UL << 48) - 1; + va &= SIGNMASK; /* Remove sign extension */ + + return ((va & PML4MASK) >> PDPSHIFT); +} + +static int +pdt_index(vm_offset_t va) +{ + /* amd64 sign extends 48th bit and upwards */ + const uint64_t SIGNMASK = (1UL << 48) - 1; + va &= SIGNMASK; /* Remove sign extension */ + + return ((va & PDPMASK) >> PDRSHIFT); +} + +/* + * The table get functions below assume that a table cannot exist at + * address 0 + */ +static pml4_entry_t * +pmap_get_pml4t(struct pmap *pm) +{ + KASSERT(pm != NULL, + ("NULL pmap passed in!\n")); + + pml4_entry_t *pm_pml4 = pm->pm_pml4; + + KASSERT(pm_pml4 != NULL, + ("pmap has NULL pml4!\n")); + + return pm->pm_pml4; +} + +/* Returns physical address */ +static vm_paddr_t +pmap_get_pdpt(vm_offset_t va, pml4_entry_t *pml4t) +{ + pml4_entry_t pml4e; + + KASSERT(va <= VM_MAX_KERNEL_ADDRESS, + ("invalid address requested")); + KASSERT(pml4t != 0, ("pml4t cannot be zero")); + + pml4e = pml4t[pml4t_index(va)]; + + if (!(pml4e & PG_V)) { + return 0; + } + + return xpmap_mtop(pml4e & PG_FRAME); +} + +/* Returns physical address */ +static vm_paddr_t +pmap_get_pdt(vm_offset_t va, pdp_entry_t *pdpt) +{ + pdp_entry_t pdpe; + + KASSERT(va <= VM_MAX_KERNEL_ADDRESS, + ("invalid address requested")); + KASSERT(pdpt != 0, ("pdpt cannot be zero")); + + pdpe = pdpt[pdpt_index(va)]; + + if (!(pdpe & PG_V)) { + return 0; + } + + return xpmap_mtop(pdpe & PG_FRAME); +} + +/* Returns physical address */ +static vm_paddr_t +pmap_get_pt(vm_offset_t va, pd_entry_t *pdt) +{ + pd_entry_t pdte; + + KASSERT(va <= VM_MAX_KERNEL_ADDRESS, + ("invalid address requested")); + + KASSERT(pdt != 0, ("pdt cannot be zero")); + + pdte = pdt[pdt_index(va)]; + + if (!(pdte & PG_V)) { + return 0; + } + + return xpmap_mtop(pdte & PG_FRAME); +} + +/* + * This structure defines the 4 indices that a given virtual + * address lookup would traverse. + * + * Note: this structure is opaque to API customers. Callers give us an + * untyped array which is marshalled/unmarshalled inside of the + * stateful api. + */ + +static const uint64_t SANE = 0xcafebabe; + +struct mmu_map_index { + pml4_entry_t *pml4t; /* Page Map Level 4 Table */ + pdp_entry_t *pdpt; /* Page Directory Pointer Table */ + pd_entry_t *pdt; /* Page Directory Table */ + pt_entry_t *pt; /* Page Table */ + + struct mmu_map_mbackend ptmb; /* Backend info */ + + uint32_t sanity; /* 32 bit (for alignment) magic XXX: + * Make optional on DEBUG */ +}; + +size_t +mmu_map_t_size(void) +{ + return sizeof (struct mmu_map_index); +} + +void +mmu_map_t_init(void *addr, struct mmu_map_mbackend *mb) +{ + KASSERT((addr != NULL) && (mb != NULL), ("NULL args given!")); + struct mmu_map_index *pti = addr; + KASSERT(pti->sanity != SANE, ("index initialised twice!")); + KASSERT(mb->alloc != NULL && + mb->ptov != NULL && + mb->vtop != NULL, + ("initialising with pre-registered alloc routine active")); + + pti->ptmb = *mb; + + /* Backend page allocation should provide default VA mapping */ + pti->sanity = SANE; +} + +void mmu_map_t_fini(void *addr) +{ + KASSERT(addr != NULL, ("NULL args given!")); + + struct mmu_map_index *pti = addr; + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + struct mmu_map_mbackend *mb = &pti->ptmb; + + pti->sanity = 0; + + if (mb->free != NULL) { + /* XXX: go through PT hierarchy and free + unmap + * unused tables */ + } +} + +pd_entry_t * +mmu_map_pml4t(void *addr) +{ + KASSERT(addr != NULL, ("NULL args given!")); + struct mmu_map_index *pti = addr; + + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + return pti->pml4t; +} + +pd_entry_t * +mmu_map_pdpt(void *addr) +{ + KASSERT(addr != NULL, ("NULL args given!")); + struct mmu_map_index *pti = addr; + + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + return pti->pdpt; +} + +pd_entry_t * +mmu_map_pdt(void *addr) +{ + KASSERT(addr != NULL, ("NULL args given!")); + struct mmu_map_index *pti = addr; + + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + return pti->pdt; +} + +pd_entry_t * +mmu_map_pt(void *addr) +{ + KASSERT(addr != NULL, ("NULL args given!")); + struct mmu_map_index *pti = addr; + + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + return pti->pt; +} + +bool +mmu_map_inspect_va(struct pmap *pm, void *addr, vm_offset_t va) +{ + KASSERT(addr != NULL && pm != NULL, ("NULL arg(s) given")); + + struct mmu_map_index *pti = addr; + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + vm_paddr_t pt; + + pti->pml4t = pmap_get_pml4t(pm); + + pt = pmap_get_pdpt(va, pti->pml4t); + + if (pt == 0) { + return false; + } else { + pti->pdpt = (pdp_entry_t *) pti->ptmb.ptov(pt); + } + + pt = pmap_get_pdt(va, pti->pdpt); + + if (pt == 0) { + return false; + } else { + pti->pdt = (pd_entry_t *) pti->ptmb.ptov(pt); + } + + pt = pmap_get_pt(va, pti->pdt); + + if (pt == 0) { + return false; + } else { + pti->pt = (pt_entry_t *)pti->ptmb.ptov(pt); + } + + return true; +} +extern uint64_t xenstack; /* The stack Xen gives us at boot */ +void +mmu_map_hold_va(struct pmap *pm, void *addr, vm_offset_t va) +{ + KASSERT(addr != NULL && pm != NULL, ("NULL arg(s) given")); + + struct mmu_map_index *pti = addr; + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + vm_paddr_t pt; + + pti->pml4t = pmap_get_pml4t(pm); + + pt = pmap_get_pdpt(va, pti->pml4t); + + if (pt == 0) { + pml4_entry_t *pml4tep; + vm_paddr_t pml4tep_ma; + pml4_entry_t pml4te; + + pti->pdpt = (pdp_entry_t *)pti->ptmb.alloc(PAGE_SIZE); + + pml4tep = &pti->pml4t[pml4t_index(va)]; + pml4tep_ma = xpmap_ptom(pti->ptmb.vtop((vm_offset_t)pml4tep)); + pml4te = xpmap_ptom(pti->ptmb.vtop((vm_offset_t)pti->pdpt)) | PG_RW | PG_V | PG_U; /* XXX: revisit flags */ + xen_queue_pt_update(pml4tep_ma, pml4te); + + } else { + pti->pdpt = (pdp_entry_t *) pti->ptmb.ptov(pt); + } + + pt = pmap_get_pdt(va, pti->pdpt); + + if (pt == 0) { + pdp_entry_t *pdptep; + vm_paddr_t pdptep_ma; + pdp_entry_t pdpte; + + pti->pdt = (pd_entry_t *)pti->ptmb.alloc(PAGE_SIZE); + + pdptep = &pti->pdpt[pdpt_index(va)]; + pdptep_ma = xpmap_ptom(pti->ptmb.vtop((vm_offset_t)pdptep)); + pdpte = xpmap_ptom(pti->ptmb.vtop((vm_offset_t)pti->pdt)) | PG_RW | PG_V | PG_U; /* XXX: revisit flags */ + xen_queue_pt_update(pdptep_ma, pdpte); + + } else { + pti->pdt = (pd_entry_t *) pti->ptmb.ptov(pt); + } + + pt = pmap_get_pt(va, pti->pdt); + + if (pt == 0) { + pd_entry_t *pdtep; + vm_paddr_t pdtep_ma; + pd_entry_t pdte; + + pti->pt = (pt_entry_t *) pti->ptmb.alloc(PAGE_SIZE); + + pdtep = &pti->pdt[pdt_index(va)]; + pdtep_ma = xpmap_ptom(pti->ptmb.vtop((vm_offset_t)pdtep)); + pdte = xpmap_ptom(pti->ptmb.vtop((vm_offset_t)pti->pt)) | PG_RW | PG_V | PG_U; /* XXX: revisit flags */ + xen_queue_pt_update(pdtep_ma, pdte); + + } else { + pti->pt = (pt_entry_t *) pti->ptmb.ptov(pt); + } +} + +void +mmu_map_release_va(struct pmap *pm, void *addr, vm_offset_t va) +{ + + KASSERT(addr != NULL && pm != NULL, ("NULL arg(s) given")); + + struct mmu_map_index *pti = addr; + KASSERT(pti->sanity == SANE, ("Uninitialised index cookie used")); + + /* XXX: */ +} Added: projects/amd64_xen_pv/sys/amd64/xen/mmu_map.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/amd64_xen_pv/sys/amd64/xen/mmu_map.h Thu May 24 12:02:10 2012 (r235904) @@ -0,0 +1,152 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2011-2012 Spectra Logic Corporation + * All rights reserved. + * + * This software was developed by Cherry G. Mathew + * under sponsorship from Spectra Logic Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _XEN_MMU_MAP_H_ +#define _XEN_MMU_MAP_H_ + +#include + +#include + +/* + * + * This API abstracts, in an MI fashion, the paging mechanism of an + * arbitrary CPU architecture as an opaque FSM, which may then be + * subject to inspection in MD ways. + * + * Use of this API can have the following effects on the VM system and + * the kernel address space: + * + * - physical memory pages may be allocated. + * - physical memory pages may be de-allocated. + * - kernel virtual address space may be allocated. + * - kernel virtual address space may be de-allocated. + * - The page table hierarchy may be modified. + * - TLB entries may be invalidated. + * + * The API is stateful, and designed around the following principles: + * - Simplicity + * - Object orientation + * - Code reuse. + */ + +/* + * We hide the page table structure behind an opaque "index" cookie + * which acts as the "key" to a given va->pa mapping being inspected. + */ +typedef void * mmu_map_t; + +/* + * Memory backend types: + * + * We provide a means to allocate ad-hoc memory/physical page + * requirements to the paging mechanism by means of a "backend" + * alloc function + * + * The memory backend is required to provide physical pages that are + * at least temporarily mapped into the kernel VA space and whose + * contents are thus accessible by a simple pointer indirection from + * within the kernel. This requirement may be revoked after conclusion + * of an instance of stateful usage of the API ( See: + * mmu_map_t_fini() below ), at which point the backend + * implementation is free to unmap any temporary mappings if so + * desired. (XXX: review this for non-x86) + * + * Note: Only the mappings may be revoked - any physical pages + * themselves allocated by the backend are considered allocated and + * part of the paging mechanism. + */ + +struct mmu_map_mbackend { /* Callbacks */ + + vm_offset_t (*alloc)(size_t); + void (*free)(vm_offset_t); /* May be NULL */ + + /* + * vtop()/ptov() conversion functions: + * These callbacks typically provide conversions for mapped + * pages allocated via the alloc()/free() callbacks (above). + * The API implementation is free to cache the mappings across + * multiple instances of use; ie; mappings may persist across + * one pair of mmu_map_t_init()/.._finit() calls. + */ + vm_offset_t (*ptov)(vm_paddr_t); + vm_paddr_t (*vtop)(vm_offset_t); +}; + +/* + * Return sizeof (mmu_map_t) as implemented within the api + * This may then be used to allocate untyped memory for the cookie + * which can then be operated on opaquely behind the API in a machine + * specific manner. + */ +size_t mmu_map_t_size(void); + +/* + * Initialise the API state to use a specified memory backend + */ +void mmu_map_t_init(mmu_map_t, struct mmu_map_mbackend *); + +/* Conclude this instance of use of the API */ +void mmu_map_t_fini(mmu_map_t); + +/* Set "index" cookie state based on va lookup. This state may then be + * inspected in MD ways ( See below ). Note that every call to the + * following functions can change the state of the backing paging + * mechanism FSM. + */ +bool mmu_map_inspect_va(struct pmap *, mmu_map_t, vm_offset_t); +/* + * Unconditionally allocate resources to setup and "inspect" (as + * above) a given va->pa mapping + */ +void mmu_map_hold_va(struct pmap *, mmu_map_t, vm_offset_t); + +/* Optionally release resources after tear down of a va->pa mapping */ +void mmu_map_release_va(struct pmap *, mmu_map_t, vm_offset_t); + +/* + * Machine dependant "view" into the page table hierarchy FSM. + * On amd64, there are four tables that are consulted for a va->pa + * translation. This information may be extracted by the MD functions + * below and is only considered valid between a successful call to + * mmu_map_inspect_va() or mmu_map_hold_va() and a subsequent + * call to mmu_map_release_va() + */ +pd_entry_t * mmu_map_pml4t(mmu_map_t); /* Page Map Level 4 Table */ +pd_entry_t * mmu_map_pdpt(mmu_map_t); /* Page Directory Pointer Table */ +pd_entry_t * mmu_map_pdt(mmu_map_t); /* Page Directory Table */ +pd_entry_t * mmu_map_pt(mmu_map_t); /* Page Table */ + +#endif /* !_XEN_MMU_MAP_H_ */ Modified: projects/amd64_xen_pv/sys/conf/files.amd64 ============================================================================== --- projects/amd64_xen_pv/sys/conf/files.amd64 Thu May 24 11:52:57 2012 (r235903) +++ projects/amd64_xen_pv/sys/conf/files.amd64 Thu May 24 12:02:10 2012 (r235904) @@ -128,6 +128,7 @@ amd64/amd64/mpboot.S optional native sm amd64/xen/mpboot.c optional xen smp amd64/amd64/pmap.c optional native amd64/xen/pmap.c optional xen +amd64/xen/mmu_map.c optional xen amd64/amd64/prof_machdep.c optional profiling-routine amd64/amd64/ptrace_machdep.c standard amd64/amd64/sigtramp.S standard