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);
+	}
+}

Reply via email to