seg_mf.c revision 843e19887f64dde75055cf8842fc4db2171eff45
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Machine frame segment driver. This segment driver allows dom0 processes to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * map pages of other domains or Xen (e.g. during save/restore). ioctl()s on
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the privcmd driver provide the MFN values backing each mapping, and we map
843e19887f64dde75055cf8842fc4db2171eff45johnlev * them into the process's address space at this time. Demand-faulting is not
843e19887f64dde75055cf8842fc4db2171eff45johnlev * supported by this driver due to the requirements upon some of the ioctl()s.
843e19887f64dde75055cf8842fc4db2171eff45johnlev#pragma ident "%Z%%M% %I% %E% SMI"
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic struct segmf_data *
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct segmf_data *data = kmem_zalloc(sizeof (*data), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&data->lock, "segmf.lock", MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hat_map(as->a_hat, seg->s_base, seg->s_size, HAT_MAP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < npages; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev error = VOP_ADDMAP(VTOCVP(data->vp), 0, as, seg->s_base, seg->s_size,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Duplicate a seg and return new segment in newseg.
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (VOP_ADDMAP(VTOCVP(ndata->vp), 0, newseg->s_as,
843e19887f64dde75055cf8842fc4db2171eff45johnlev newseg->s_base, newseg->s_size, ndata->prot, ndata->maxprot,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We only support unmapping the whole segment, and we automatically unlock
843e19887f64dde75055cf8842fc4db2171eff45johnlev * what we previously soft-locked.
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_unmap(struct seg *seg, caddr_t addr, size_t len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (addr < seg->s_base || addr + len > seg->s_base + seg->s_size ||
843e19887f64dde75055cf8842fc4db2171eff45johnlev (len & PAGEOFFSET) || ((uintptr_t)addr & PAGEOFFSET))
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) VOP_DELMAP(VTOCVP(data->vp), off, seg->s_as, addr, len,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_faultpage(struct hat *hat, struct seg *seg, caddr_t addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev uprintf("segmf_faultpage: addr %p domid %x mfn %lx prot %x\n",
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Ask the HAT to load a throwaway mapping to page zero, then
843e19887f64dde75055cf8842fc4db2171eff45johnlev * overwrite it with our foreign domain mapping. It gets removed
843e19887f64dde75055cf8842fc4db2171eff45johnlev * later via hat_unload()
843e19887f64dde75055cf8842fc4db2171eff45johnlev pte = mmu_ptob((x86pte_t)mfn) | PT_VALID | PT_USER | PT_FOREIGN;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (HYPERVISOR_update_va_mapping_otherdomain((uintptr_t)addr, pte,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_softunlock(struct hat *hat, struct seg *seg, caddr_t addr, size_t len)
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_fault_range(struct hat *hat, struct seg *seg, caddr_t addr, size_t len,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* loop over the address range handling each fault */
843e19887f64dde75055cf8842fc4db2171eff45johnlev error = segmf_faultpage(hat, seg, a, type, data->prot);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Undo what's been done so far.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We never demand-fault for seg_mf.
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len,
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot)
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_kluster(struct seg *seg, caddr_t addr, ssize_t delta)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * XXPV Hmm. Should we say that mf mapping are "in core?"
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_incore(struct seg *seg, caddr_t addr, size_t len, char *vec)
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (v = 0, len = (len + PAGEOFFSET) & PAGEMASK; len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (v);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t len, int attr, int op, ulong_t *lockmap, size_t pos)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv)
843e19887f64dde75055cf8842fc4db2171eff45johnlev pgcnt_t pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pgno != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (pgno != 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED1*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_pagelock(struct seg *seg, caddr_t addr, size_t len,
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct page ***ppp, enum lock_type type, enum seg_rw rw)
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc)
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_getmemid(struct seg *seg, caddr_t addr, memid_t *memid)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_capable(struct seg *seg, segcapability_t capability)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Add a set of contiguous foreign MFNs to the segment. soft-locking them. The
843e19887f64dde75055cf8842fc4db2171eff45johnlev * pre-faulting is necessary due to live migration; in particular we must
843e19887f64dde75055cf8842fc4db2171eff45johnlev * return an error in response to IOCTL_PRIVCMD_MMAPBATCH rather than faulting
843e19887f64dde75055cf8842fc4db2171eff45johnlev * later on a bad MFN. Whilst this isn't necessary for the other MMAP
843e19887f64dde75055cf8842fc4db2171eff45johnlev * ioctl()s, we lock them too, as they should be transitory.
843e19887f64dde75055cf8842fc4db2171eff45johnlevsegmf_add_mfns(struct seg *seg, caddr_t addr, mfn_t mfn,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Don't mess with dom0.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Only allow the domid to be set once for the segment.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * After that attempts to add mappings to this segment for
843e19887f64dde75055cf8842fc4db2171eff45johnlev * other domains explicitly fails.
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < pgcnt; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (fc != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < pgcnt; i++)