Module Name: src Committed By: bouyer Date: Wed Aug 31 12:51:56 UTC 2022
Modified Files: src/sys/arch/x86/x86: pmap.c src/sys/arch/xen/conf: files.xen src/sys/arch/xen/xen: privcmd.c Added Files: src/sys/arch/xen/include: xenmem.h src/sys/arch/xen/xen: xenmem.c Log Message: Work in progress on dom0 PVH support: ioctl support for tools. Basically, in PVH mode (where XENFEAT_auto_translated_physmap is enabled), the hypervisor will not map foreing ressources in our virtual address space for us. Instead, we have to pass it an address in our physical address space (but not mapped to some RAM) where the ressource will show up and then enter this PA in pour page table. For this, introduce xenmem_* which manage the PA space. In PVH mode this is just allocated from the iomem_ex extent. With this, I can start a PV domU, and the guest's kernel boots (and the console works). It hangs because the backend driver can't map the frontend ressources (yet). Note that, per https://xenbits.xen.org/docs/unstable/support-matrix.html, dom0 PVH support is still considered experimental by Xen. To generate a diff of this commit: cvs rdiff -u -r1.420 -r1.421 src/sys/arch/x86/x86/pmap.c cvs rdiff -u -r1.186 -r1.187 src/sys/arch/xen/conf/files.xen cvs rdiff -u -r0 -r1.1 src/sys/arch/xen/include/xenmem.h cvs rdiff -u -r1.61 -r1.62 src/sys/arch/xen/xen/privcmd.c cvs rdiff -u -r0 -r1.1 src/sys/arch/xen/xen/xenmem.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/x86/pmap.c diff -u src/sys/arch/x86/x86/pmap.c:1.420 src/sys/arch/x86/x86/pmap.c:1.421 --- src/sys/arch/x86/x86/pmap.c:1.420 Sat Aug 20 23:49:31 2022 +++ src/sys/arch/x86/x86/pmap.c Wed Aug 31 12:51:56 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.420 2022/08/20 23:49:31 riastradh Exp $ */ +/* $NetBSD: pmap.c,v 1.421 2022/08/31 12:51:56 bouyer Exp $ */ /* * Copyright (c) 2008, 2010, 2016, 2017, 2019, 2020 The NetBSD Foundation, Inc. @@ -130,7 +130,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.420 2022/08/20 23:49:31 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.421 2022/08/31 12:51:56 bouyer Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -5229,6 +5229,9 @@ pmap_enter_gnt(struct pmap *pmap, vaddr_ { struct pmap_data_gnt *pgnt; pt_entry_t *ptes, opte; +#ifndef XENPV + pt_entry_t npte; +#endif pt_entry_t *ptep; pd_entry_t * const *pdes; struct vm_page *ptp; @@ -5305,8 +5308,13 @@ pmap_enter_gnt(struct pmap *pmap, vaddr_ idx = (va - pgnt->pd_gnt_sva) / PAGE_SIZE; op = &pgnt->pd_gnt_ops[idx]; -#ifdef XENPV /* XXX */ +#ifdef XENPV + KASSERT(op->flags & GNTMAP_contains_pte); op->host_addr = xpmap_ptetomach(ptep); +#else + KASSERT((op->flags & GNTMAP_contains_pte) == 0); + KASSERT(op->flags != 0); + KASSERT(op->host_addr != 0); #endif op->dev_bus_addr = 0; op->status = GNTST_general_error; @@ -5328,10 +5336,18 @@ pmap_enter_gnt(struct pmap *pmap, vaddr_ if (__predict_false(op->status != GNTST_okay)) { printf("%s: GNTTABOP_map_grant_ref status: %d\n", __func__, op->status); - if (have_oldpa) { + if (have_oldpa) { /* XXX did the pte really change if XENPV ?*/ ptp->wire_count--; } } else { +#ifndef XENPV + npte = op->host_addr | pmap_pg_nx | PTE_U | PTE_P; + if ((op->flags & GNTMAP_readonly) == 0) + npte |= PTE_W; + do { + opte = *ptep; + } while (pmap_pte_cas(ptep, opte, npte) != opte); +#endif pgnt->pd_gnt_refs++; if (!have_oldpa) { ptp->wire_count++; @@ -5417,7 +5433,6 @@ pmap_remove_gnt(struct pmap *pmap, vaddr idx = (va - pgnt->pd_gnt_sva) / PAGE_SIZE; op = &pgnt->pd_gnt_ops[idx]; KASSERT(lvl == 1); - KASSERT(op->status == GNTST_okay); /* Get PTP if non-kernel mapping. */ ptp = pmap_find_ptp(pmap, va, 1); @@ -5426,11 +5441,14 @@ pmap_remove_gnt(struct pmap *pmap, vaddr if (op->status == GNTST_okay) { KASSERT(pmap_valid_entry(ptes[pl1_i(va)])); - unmap_op.handle = op->handle; - unmap_op.dev_bus_addr = 0; -#ifdef XENPV /* XXX */ +#ifdef XENPV unmap_op.host_addr = xpmap_ptetomach(&ptes[pl1_i(va)]); +#else + unmap_op.host_addr = op->host_addr; + pmap_pte_testset(&ptes[pl1_i(va)], 0); #endif + unmap_op.handle = op->handle; + unmap_op.dev_bus_addr = 0; ret = HYPERVISOR_grant_table_op( GNTTABOP_unmap_grant_ref, &unmap_op, 1); if (ret) { @@ -5440,9 +5458,9 @@ pmap_remove_gnt(struct pmap *pmap, vaddr ptp->wire_count--; pgnt->pd_gnt_refs--; - if (pgnt->pd_gnt_refs == 0) { - pmap_free_gnt(pmap, pgnt); - } + } + if (pgnt->pd_gnt_refs == 0) { + pmap_free_gnt(pmap, pgnt); } /* * if mapping removed and the PTP is no longer Index: src/sys/arch/xen/conf/files.xen diff -u src/sys/arch/xen/conf/files.xen:1.186 src/sys/arch/xen/conf/files.xen:1.187 --- src/sys/arch/xen/conf/files.xen:1.186 Tue May 26 10:37:24 2020 +++ src/sys/arch/xen/conf/files.xen Wed Aug 31 12:51:56 2022 @@ -1,4 +1,4 @@ -# $NetBSD: files.xen,v 1.186 2020/05/26 10:37:24 bouyer Exp $ +# $NetBSD: files.xen,v 1.187 2022/08/31 12:51:56 bouyer Exp $ defflag opt_xen.h XEN XENPVH XENPVHVM PAE DOM0OPS @@ -7,6 +7,7 @@ file arch/xen/x86/xen_intr.c xen file arch/xen/xen/xen_machdep.c xen file arch/xen/xen/evtchn.c xen file arch/xen/xen/xengnt.c xen +file arch/xen/xen/xenmem.c xen & !xenpv file arch/xen/x86/xen_mainbus.c xen file arch/xen/xen/xen_clock.c xen file arch/xen/x86/xen_bus_dma.c xen Index: src/sys/arch/xen/xen/privcmd.c diff -u src/sys/arch/xen/xen/privcmd.c:1.61 src/sys/arch/xen/xen/privcmd.c:1.62 --- src/sys/arch/xen/xen/privcmd.c:1.61 Fri Dec 10 20:36:03 2021 +++ src/sys/arch/xen/xen/privcmd.c Wed Aug 31 12:51:56 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: privcmd.c,v 1.61 2021/12/10 20:36:03 andvar Exp $ */ +/* $NetBSD: privcmd.c,v 1.62 2022/08/31 12:51:56 bouyer Exp $ */ /*- * Copyright (c) 2004 Christian Limpach. @@ -27,7 +27,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: privcmd.c,v 1.61 2021/12/10 20:36:03 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: privcmd.c,v 1.62 2022/08/31 12:51:56 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: privcmd.c,v #include <xen/hypervisor.h> #include <xen/xen.h> #include <xen/xenio.h> +#include <xen/xenmem.h> #include <xen/xenpmap.h> #include <xen/granttables.h> @@ -60,17 +61,20 @@ __KERNEL_RCSID(0, "$NetBSD: privcmd.c,v typedef enum _privcmd_type { PTYPE_PRIVCMD, + PTYPE_PRIVCMD_PHYSMAP, PTYPE_GNTDEV_REF, PTYPE_GNTDEV_ALLOC } privcmd_type; struct privcmd_object_privcmd { + paddr_t base_paddr; /* base address of physical space */ paddr_t *maddr; /* array of machine address to map */ int domid; bool no_translate; }; struct privcmd_object_gntref { + paddr_t base_paddr; /* base address of physical space */ struct ioctl_gntdev_grant_notify notify; struct gnttab_map_grant_ref ops[1]; /* variable length */ }; @@ -316,6 +320,10 @@ privcmd_get_map_prot(struct vm_map *map, static int privcmd_mmap(struct vop_ioctl_args *ap) { +#ifndef XENPV + printf("IOCTL_PRIVCMD_MMAP not supported\n"); + return EINVAL; +#else int i, j; privcmd_mmap_t *mcmd = ap->a_data; privcmd_mmap_entry_t mentry; @@ -357,11 +365,16 @@ privcmd_mmap(struct vop_ioctl_args *ap) return error; } return 0; +#endif } static int privcmd_mmapbatch(struct vop_ioctl_args *ap) { +#ifndef XENPV + printf("IOCTL_PRIVCMD_MMAPBATCH not supported\n"); + return EINVAL; +#else int i; privcmd_mmapbatch_t* pmb = ap->a_data; vaddr_t va0; @@ -432,6 +445,7 @@ privcmd_mmapbatch(struct vop_ioctl_args error = privcmd_map_obj(vmm, va0, obj, prot); return error; +#endif } static int @@ -446,6 +460,7 @@ privcmd_mmapbatch_v2(struct vop_ioctl_ar struct privcmd_object *obj; vm_prot_t prot; int error; + paddr_t base_paddr = 0; vmm = &curlwp->l_proc->p_vmspace->vm_map; va0 = pmb->addr & ~PAGE_MASK; @@ -461,10 +476,16 @@ privcmd_mmapbatch_v2(struct vop_ioctl_ar if (prot == UVM_PROT_NONE) return EINVAL; +#ifndef XENPV + KASSERT(xen_feature(XENFEAT_auto_translated_physmap)); + base_paddr = xenmem_alloc_pa(pmb->num * PAGE_SIZE, PAGE_SIZE, true); + KASSERT(base_paddr != 0); +#endif maddr = kmem_alloc(sizeof(paddr_t) * pmb->num, KM_SLEEP); obj = kmem_alloc(sizeof(*obj), KM_SLEEP); - obj->type = PTYPE_PRIVCMD; + obj->type = PTYPE_PRIVCMD_PHYSMAP; obj->u.pc.maddr = maddr; + obj->u.pc.base_paddr = base_paddr; obj->u.pc.no_translate = false; obj->npages = pmb->num; obj->u.pc.domid = pmb->dom; @@ -473,9 +494,18 @@ privcmd_mmapbatch_v2(struct vop_ioctl_ar error = copyin(&pmb->arr[i], &mfn, sizeof(mfn)); if (error != 0) { kmem_free(maddr, sizeof(paddr_t) * pmb->num); + kmem_free(obj, sizeof(*obj)); +#ifndef XENPV + xenmem_free_pa(base_paddr, pmb->num * PAGE_SIZE); +#endif return error; } +#ifdef XENPV maddr[i] = ((paddr_t)mfn) << PGSHIFT; +#else + maddr[i] = mfn; /* TMP argument for XENMEM_add_to_physmap */ +#endif + } error = privcmd_map_obj(vmm, va0, obj, prot); if (error) @@ -487,6 +517,7 @@ privcmd_mmapbatch_v2(struct vop_ioctl_ar */ for(i = 0; i < pmb->num; i++, va0 += PAGE_SIZE) { int err, cerr; +#ifdef XENPV for (int j = 0 ; j < 10; j++) { err = pmap_enter_ma(vmm->pmap, va0, maddr[i], 0, prot, PMAP_CANFAIL | prot, @@ -499,6 +530,37 @@ privcmd_mmapbatch_v2(struct vop_ioctl_ar if (err) { maddr[i] = INVALID_PAGE; } +#else /* XENPV */ + xen_add_to_physmap_batch_t add; + u_long idx; + xen_pfn_t gpfn; + int err2; + memset(&add, 0, sizeof(add)); + + add.domid = DOMID_SELF; + add.space = XENMAPSPACE_gmfn_foreign; + add.size = 1; + add.foreign_domid = pmb->dom; + idx = maddr[i]; + set_xen_guest_handle(add.idxs, &idx); + maddr[i] = INVALID_PAGE; + gpfn = (base_paddr >> PGSHIFT) + i; + set_xen_guest_handle(add.gpfns, &gpfn); + err2 = 0; + set_xen_guest_handle(add.errs, &err2); + err = HYPERVISOR_memory_op(XENMEM_add_to_physmap_batch, &add); + if (err < 0) { + printf("privcmd_mmapbatch_v2: XENMEM_add_to_physmap_batch failed %d\n", err); + privpgop_detach(&obj->uobj); + return privcmd_xen2bsd_errno(err); + } + err = err2; + if (err == 0) + maddr[i] = base_paddr + i * PAGE_SIZE; + else + printf("privcmd_mmapbatch_v2: XENMEM_add_to_physmap_batch failed %d for entry %d\n", err, i); +#endif /* XENPV */ + cerr = copyout(&err, &pmb->err[i], sizeof(pmb->err[i])); if (cerr) { privpgop_detach(&obj->uobj); @@ -521,8 +583,7 @@ privcmd_mmap_resource(struct vop_ioctl_a struct xen_mem_acquire_resource op; xen_pfn_t *pfns; paddr_t *maddr; - - KASSERT(!xen_feature(XENFEAT_auto_translated_physmap)); + paddr_t base_paddr = 0; vmm = &curlwp->l_proc->p_vmspace->vm_map; va0 = pmr->addr & ~PAGE_MASK; @@ -539,6 +600,17 @@ privcmd_mmap_resource(struct vop_ioctl_a return EINVAL; pfns = kmem_alloc(sizeof(xen_pfn_t) * pmr->num, KM_SLEEP); +#ifndef XENPV + KASSERT(xen_feature(XENFEAT_auto_translated_physmap)); + base_paddr = xenmem_alloc_pa(pmr->num * PAGE_SIZE, PAGE_SIZE, true); + KASSERT(base_paddr != 0); + for (i = 0; i < pmr->num; i++) { + pfns[i] = (base_paddr >> PGSHIFT) + i; + } +#else + KASSERT(!xen_feature(XENFEAT_auto_translated_physmap)); +#endif + memset(&op, 0, sizeof(op)); op.domid = pmr->dom; op.type = pmr->type; @@ -560,7 +632,8 @@ privcmd_mmap_resource(struct vop_ioctl_a kmem_free(pfns, sizeof(xen_pfn_t) * pmr->num); obj = kmem_alloc(sizeof(*obj), KM_SLEEP); - obj->type = PTYPE_PRIVCMD; + obj->type = PTYPE_PRIVCMD_PHYSMAP; + obj->u.pc.base_paddr = base_paddr; obj->u.pc.maddr = maddr; obj->u.pc.no_translate = true; obj->npages = pmr->num; @@ -600,6 +673,14 @@ privcmd_map_gref(struct vop_ioctl_args * obj->npages = mgr->count; memcpy(&obj->u.gr.notify, &mgr->notify, sizeof(obj->u.gr.notify)); +#ifndef XENPV + KASSERT(xen_feature(XENFEAT_auto_translated_physmap)); + obj->u.gr.base_paddr = xenmem_alloc_pa(obj->npages * PAGE_SIZE, + PAGE_SIZE, true); + KASSERT(obj->u.gr.base_paddr != 0); +#else + obj->u.gr.base_paddr = 0; +#endif /* !XENPV */ for (int i = 0; i < obj->npages; ++i) { struct ioctl_gntdev_grant_ref gref; @@ -607,20 +688,28 @@ privcmd_map_gref(struct vop_ioctl_args * if (error != 0) { goto err1; } +#ifdef XENPV obj->u.gr.ops[i].host_addr = 0; + obj->u.gr.ops[i].flags = GNTMAP_host_map | + GNTMAP_application_map | GNTMAP_contains_pte; +#else /* XENPV */ + obj->u.gr.ops[i].host_addr = + obj->u.gr.base_paddr + PAGE_SIZE * i; + obj->u.gr.ops[i].flags = GNTMAP_host_map; +#endif /* XENPV */ obj->u.gr.ops[i].dev_bus_addr = 0; obj->u.gr.ops[i].ref = gref.ref; obj->u.gr.ops[i].dom = gref.domid; obj->u.gr.ops[i].handle = -1; - obj->u.gr.ops[i].flags = GNTMAP_host_map | - GNTMAP_application_map | GNTMAP_contains_pte; if (prot == UVM_PROT_READ) obj->u.gr.ops[i].flags |= GNTMAP_readonly; } error = privcmd_map_obj(vmm, va0, obj, prot); return error; - err1: +#ifndef XENPV + xenmem_free_pa(obj->u.gr.base_paddr, obj->npages * PAGE_SIZE); +#endif kmem_free(obj, PGO_GNTREF_LEN(obj->npages)); return error; } @@ -879,6 +968,20 @@ privpgop_detach(struct uvm_object *uobj) } rw_exit(uobj->vmobjlock); switch (pobj->type) { + case PTYPE_PRIVCMD_PHYSMAP: +#ifndef XENPV + for (int i = 0; i < pobj->npages; i++) { + if (pobj->u.pc.maddr[i] != INVALID_PAGE) { + struct xen_remove_from_physmap rm; + rm.domid = DOMID_SELF; + rm.gpfn = pobj->u.pc.maddr[i] >> PGSHIFT; + HYPERVISOR_memory_op( + XENMEM_remove_from_physmap, &rm); + } + } + xenmem_free_pa(pobj->u.pc.base_paddr, pobj->npages * PAGE_SIZE); +#endif + /* FALLTHROUGH */ case PTYPE_PRIVCMD: kmem_free(pobj->u.pc.maddr, sizeof(paddr_t) * pobj->npages); uvm_obj_destroy(uobj, true); @@ -887,6 +990,16 @@ privpgop_detach(struct uvm_object *uobj) case PTYPE_GNTDEV_REF: { privcmd_notify(&pobj->u.gr.notify, 0, pobj->u.gr.ops); +#ifndef XENPV + KASSERT(pobj->u.gr.base_paddr != 0); + for (int i = 0; i < pobj->npages; i++) { + struct xen_remove_from_physmap rm; + rm.domid = DOMID_SELF; + rm.gpfn = (pobj->u.gr.base_paddr << PGSHIFT) + i; + HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &rm); + } + xenmem_free_pa(pobj->u.gr.base_paddr, pobj->npages * PAGE_SIZE); +#endif kmem_free(pobj, PGO_GNTREF_LEN(pobj->npages)); break; } @@ -923,6 +1036,7 @@ privpgop_fault(struct uvm_faultinfo *ufi continue; switch(pobj->type) { case PTYPE_PRIVCMD: + case PTYPE_PRIVCMD_PHYSMAP: { u_int pm_flags = PMAP_CANFAIL | ufi->entry->protection; #ifdef XENPV Added files: Index: src/sys/arch/xen/include/xenmem.h diff -u /dev/null src/sys/arch/xen/include/xenmem.h:1.1 --- /dev/null Wed Aug 31 12:51:56 2022 +++ src/sys/arch/xen/include/xenmem.h Wed Aug 31 12:51:56 2022 @@ -0,0 +1,42 @@ +/* $NetBSD: xenmem.h,v 1.1 2022/08/31 12:51:56 bouyer Exp $ */ +/* + * Copyright (c) 2022 Manuel Bouyer. + * + * 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, 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 DAMAGE. + * + */ + +/* Xen physical space management */ + +#ifndef _XEN_XENMEM_H_ +#define _XEN_XENMEM_H_ +#include "opt_xen.h" +#ifdef XENPV +extern paddr_t pmap_pa_start; /* PA of first physical page for this domain */ +extern paddr_t pmap_pa_end; /* PA of last physical page for this domain */ + +void xenmem_pa_register(paddr_t, paddr_t); +#endif /* XENPV */ + +paddr_t xenmem_alloc_pa(u_long, u_long, bool); +void xenmem_free_pa(paddr_t, u_long); + +#endif /* _XEN_XENMEM_H_ */ Index: src/sys/arch/xen/xen/xenmem.c diff -u /dev/null src/sys/arch/xen/xen/xenmem.c:1.1 --- /dev/null Wed Aug 31 12:51:56 2022 +++ src/sys/arch/xen/xen/xenmem.c Wed Aug 31 12:51:56 2022 @@ -0,0 +1,108 @@ +/* $NetBSD: xenmem.c,v 1.1 2022/08/31 12:51:56 bouyer Exp $ */ +/* + * Copyright (c) 2022 Manuel Bouyer. + * + * 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, 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 DAMAGE. + * + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: xenmem.c,v 1.1 2022/08/31 12:51:56 bouyer Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/extent.h> +#include <sys/kmem.h> +#include <uvm/uvm_physseg.h> + +#include <xen/xenmem.h> + +/* + * Xen physical space management + * The xenmem_ex extent manage the VM's pseudo-physical memory space. + * This contains the mémory allocated to the VM, and is also used to allocate + * extra physical space used for XENMEM_add_to_physmap (in come cases) + * In the !XENPV case, the physical space is managed by bus_space, so + * we reuse the iomem_ex + */ + +#if 0 /* def XENPV */ +extern paddr_t pmap_pa_start; /* PA of first physical page for this domain */ +extern paddr_t pmap_pa_end; /* PA of last physical page for this domain */ + +static long xenmem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(64) / sizeof(long)]; +struct extent *xenmem_ex; +#define XENMEM_EX xenmem_ex +#else /* !XENPV */ +extern struct extent *iomem_ex; +#define XENMEM_EX iomem_ex +#endif /* XENPV */ + +#ifdef XENPV +void +xenmem_pa_register(paddr_t pa_start, paddr_t pa_end) +{ + int error; + uvm_page_physload(atop(pa_start), atop(pa_end), + atop(pa_start), atop(pa_end), VM_FREELIST_DEFAULT); + xenmem_ex = extent_create("xenmem", 0x0, MAXIOMEM, + (void *)xenmem_ex_storage, sizeof(xenmem_ex_storage), + EX_NOCOALESCE|EX_NOWAIT); + + error = extent_alloc_region(xenmem_ex, 0, pa_end, EX_NOWAIT); + if (error) + panic("xenmem_ex: can't reserve allocated RAM"); + +} +#endif /* XENPV */ + +paddr_t +xenmem_alloc_pa(u_long size, u_long align, bool waitok) +{ + u_long result; + int error; + +#ifdef _LP64 + /* allocate above the 4Gb range to not collide wit devices */ + error = extent_alloc_subregion(XENMEM_EX, 0x100000000UL, MAXIOMEM, + size, align, 0, waitok ? (EX_WAITSPACE | EX_WAITOK) : EX_NOWAIT, + &result); +#else + error = extent_alloc(XENMEM_EX, size, align, 0, + waitok ? (EX_WAITSPACE | EX_WAITOK) : EX_NOWAIT, &result); +#endif + if (error) { + printf("xenmem_alloc_pa: failed %d\n", error); + return 0; + } + return result; +} + +void +xenmem_free_pa(paddr_t start, u_long size) +{ + int error; + error = extent_free(XENMEM_EX, start, size, EX_NOWAIT); + if (error) { + printf("WARNING: xenmem_alloc_pa failed: %d\n", error); + } +}