On 5/7/20 11:50 am, Damien Zammit wrote:
> One thing that is missing from this patch is the "vm_allocate_contiguous" RPC.
> It is required for DMA.  How should I proceed with it?  Do I make it an RPC 
> on the
> "mem" device only?

See attached for first attempt at reworking this RPC.

Thanks,
Damien
>From d487e6393191f29361f76fcb89ea02f561fea82a Mon Sep 17 00:00:00 2001
From: Damien Zammit <dam...@zamaudio.com>
Date: Sun, 5 Jul 2020 16:42:28 +1000
Subject: [PATCH] Add ds_device_vm_allocate_contiguous RPC

---
 device/ds_routines.c       | 17 +++++++++++++++++
 include/device/device.defs | 31 +++++++++++++++++++++++++++++++
 include/mach/mach.defs     | 33 +--------------------------------
 vm/vm_user.c               |  6 +-----
 vm/vm_user.h               |  2 ++
 5 files changed, 52 insertions(+), 37 deletions(-)

diff --git a/device/ds_routines.c b/device/ds_routines.c
index 69e963bd..28100da1 100644
--- a/device/ds_routines.c
+++ b/device/ds_routines.c
@@ -1848,6 +1848,23 @@ ds_device_intr_ack (device_t dev, ipc_port_t receive_port)
   return irq_acknowledge(receive_port);
 }
 
+kern_return_t
+ds_device_allocate_contiguous (device_t dev, vm_address_t *vaddr,
+			       vm_address_t *paddr, vm_size_t size)
+{
+  mach_device_t mdev = dev->emul_data;
+
+  /* Refuse if device is dead or not completely open.  */
+  if (dev == DEVICE_NULL)
+    return D_NO_SUCH_DEVICE;
+
+  /* Must be called on the mem device only */
+  if (! name_equal(mdev->dev_ops->d_name, 3, "mem"))
+    return D_INVALID_OPERATION;
+
+  return vm_allocate_contiguous (kernel_map, vaddr, paddr, size);
+}
+
 struct device_emulation_ops mach_device_emulation_ops =
 {
   (void*) mach_device_reference,
diff --git a/include/device/device.defs b/include/device/device.defs
index ec4b5bf8..bf81b9ae 100644
--- a/include/device/device.defs
+++ b/include/device/device.defs
@@ -160,3 +160,34 @@ routine device_intr_ack(
 		device		: device_t;
 	in	receive_port	: mach_port_send_t);
 
+/*
+ *	This routine is created for allocating DMA buffers.
+ *	We are going to get contiguous physical memory
+ *	and its physical address in addition to the virtual address.
+ *	It only works on the mem device.
+ */
+ /* XXX
+ This RPC lacks a few additional constraints like boundaries, alignment
+and maybe phase. We may not use them now, but they're important for
+portability (e.g. if GNU Mach supports PAE, drivers that can't use
+physical memory beyond the 4 GiB limit must be able to express it).
+
+> What do you mean by "phase"?
+
+Offset from the alignment. But I don't think it's useful at all in this
+case. Minimum and maximum addresses and alignment should do. Maybe
+boundary crossing but usually, specifying the right alignment and size
+is enough.
+
+For upstream
+inclusion, we need to do it properly: the RPC should return a special
+memory object (similar to device_map() ), which can then be mapped into
+the process address space with vm_map() like any other memory object.
+
+phys_address_t?
+ */
+routine device_allocate_contiguous(
+		device		: device_t;
+	out	vaddr		: vm_address_t;
+	out	paddr		: vm_address_t;
+		size		: vm_size_t);
diff --git a/include/mach/mach.defs b/include/mach/mach.defs
index 77cc7d49..20f425fa 100644
--- a/include/mach/mach.defs
+++ b/include/mach/mach.defs
@@ -719,38 +719,7 @@ skip;	/* old host_fpa_counters_reset */
 
 #endif	/* ! KERNEL_USER */
 
-/*
- *	This routine is created for allocating DMA buffers.
- *	We are going to get a contiguous physical memory
- *	and its physical address in addition to the virtual address.
- */
-
- /* XXX
- This RPC lacks a few additional constraints like boundaries, alignment
-and maybe phase. We may not use them now, but they're important for
-portability (e.g. if GNU Mach supports PAE, drivers that can't use
-physical memory beyond the 4 GiB limit must be able to express it).
-
-> What do you mean by "phase"?
-
-Offset from the alignment. But I don't think it's useful at all in this
-case. Minimum and maximum addresses and alignment should do. Maybe
-boundary crossing but usually, specifying the right alignment and size
-is enough.
-
-For upstream
-inclusion, we need to do it properly: the RPC should return a special
-memory object (similar to device_map() ), which can then be mapped into
-the process address space with vm_map() like any other memory object.
-
-phys_address_t?
- */
-routine vm_allocate_contiguous(
-		host_priv	: host_priv_t;
-		target_task	: vm_task_t;
-	out	vaddr		: vm_address_t;
-	out	paddr		: vm_address_t;
-		size		: vm_size_t);
+skip;	/* old vm_allocate_contiguous */
 
 /*
  *	There is no more room in this interface for additional calls.
diff --git a/vm/vm_user.c b/vm/vm_user.c
index 1789dbfa..44a3e578 100644
--- a/vm/vm_user.c
+++ b/vm/vm_user.c
@@ -532,8 +532,7 @@ kern_return_t vm_msync(
 	return vm_map_msync(map, (vm_offset_t) address, size, sync_flags);
 }
 
-kern_return_t vm_allocate_contiguous(host_priv, map, result_vaddr, result_paddr, size)
-	host_t			host_priv;
+kern_return_t vm_allocate_contiguous(map, result_vaddr, result_paddr, size)
 	vm_map_t		map;
 	vm_address_t		*result_vaddr;
 	vm_address_t		*result_paddr;
@@ -548,9 +547,6 @@ kern_return_t vm_allocate_contiguous(host_priv, map, result_vaddr, result_paddr,
 	kern_return_t		kr;
 	vm_address_t		vaddr;
 
-	if (host_priv == HOST_NULL)
-		return KERN_INVALID_HOST;
-
 	if (map == VM_MAP_NULL)
 		return KERN_INVALID_TASK;
 
diff --git a/vm/vm_user.h b/vm/vm_user.h
index c6f20a82..85918417 100644
--- a/vm/vm_user.h
+++ b/vm/vm_user.h
@@ -56,5 +56,7 @@ extern kern_return_t	vm_copy(vm_map_t, vm_address_t, vm_size_t,
 extern kern_return_t	vm_map(vm_map_t, vm_offset_t *, vm_size_t, vm_offset_t,
 			       boolean_t, ipc_port_t, vm_offset_t, boolean_t,
 			       vm_prot_t, vm_prot_t, vm_inherit_t);
+extern kern_return_t	vm_allocate_contiguous(vm_map_t, vm_address_t *,
+					       vm_address_t *, vm_size_t);
 
 #endif	/* _VM_VM_USER_H_ */
-- 
2.25.1

Reply via email to