Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F158041496
D49566.id178524.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D49566.id178524.diff
View Options
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1853,6 +1853,22 @@
memset_early(gpf_descr, 0, sizeof(*gpf_descr));
}
+int
+safe_read(vm_offset_t addr, char *valp)
+{
+ struct uio uio;
+ struct iovec iov;
+
+ iov.iov_base = valp;
+ iov.iov_len = 1;
+ uio.uio_offset = addr;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_resid = 1;
+ /* uio_segflg, uio_rw, uio_td are ignored */
+ return (uiomove_mem(UIO_MEM_KMEM, &uio));
+}
+
#ifdef KDB
/*
diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c
--- a/sys/amd64/amd64/mem.c
+++ b/sys/amd64/amd64/mem.c
@@ -61,10 +61,6 @@
#include <machine/specialreg.h>
#include <machine/vmparam.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-
#include <machine/memdev.h>
/*
@@ -72,99 +68,22 @@
*/
MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
-/* ARGSUSED */
int
memrw(struct cdev *dev, struct uio *uio, int flags)
{
- struct iovec *iov;
- void *p, *vd;
- ssize_t orig_resid;
- vm_prot_t prot;
- u_long v;
- u_int c;
- int error;
+ enum uiomove_mem_req req;
- error = 0;
- orig_resid = uio->uio_resid;
- while (uio->uio_resid > 0 && error == 0) {
- iov = uio->uio_iov;
- if (iov->iov_len == 0) {
- uio->uio_iov++;
- uio->uio_iovcnt--;
- if (uio->uio_iovcnt < 0)
- panic("memrw");
- continue;
- }
- v = uio->uio_offset;
- c = ulmin(iov->iov_len, PAGE_SIZE - (u_int)(v & PAGE_MASK));
-
- switch (dev2unit(dev)) {
- case CDEV_MINOR_KMEM:
- /*
- * Since c is clamped to be less or equal than
- * PAGE_SIZE, the uiomove() call does not
- * access past the end of the direct map.
- */
- if (v >= kva_layout.dmap_low &&
- v < kva_layout.dmap_high) {
- error = uiomove((void *)v, c, uio);
- break;
- }
-
- switch (uio->uio_rw) {
- case UIO_READ:
- prot = VM_PROT_READ;
- break;
- case UIO_WRITE:
- prot = VM_PROT_WRITE;
- break;
- }
-
- if (!kernacc((void *)v, c, prot)) {
- error = EFAULT;
- break;
- }
-
- /*
- * If the extracted address is not accessible
- * through the direct map, then we make a
- * private (uncached) mapping because we can't
- * depend on the existing kernel mapping
- * remaining valid until the completion of
- * uiomove().
- *
- * XXX We cannot provide access to the
- * physical page 0 mapped into KVA.
- */
- v = pmap_extract(kernel_pmap, v);
- if (v == 0) {
- error = EFAULT;
- break;
- }
- /* FALLTHROUGH */
- case CDEV_MINOR_MEM:
- if (v < dmaplimit) {
- vd = PHYS_TO_DMAP(v);
- error = uiomove(vd, c, uio);
- break;
- }
- if (v > cpu_getmaxphyaddr()) {
- error = EFAULT;
- break;
- }
- p = pmap_mapdev(v, PAGE_SIZE);
- error = uiomove(p, c, uio);
- pmap_unmapdev(p, PAGE_SIZE);
- break;
- }
+ switch (dev2unit(dev)) {
+ case CDEV_MINOR_KMEM:
+ req = UIO_MEM_KMEM;
+ break;
+ case CDEV_MINOR_MEM:
+ req = UIO_MEM_MEM;
+ break;
+ default:
+ __unreachable();
}
- /*
- * Don't return error if any byte was written. Read and write
- * can return error only if no i/o was performed.
- */
- if (uio->uio_resid != orig_resid)
- error = 0;
- return (error);
+ return (uiomove_mem(req, uio));
}
/*
diff --git a/sys/amd64/amd64/uio_machdep.c b/sys/amd64/amd64/uio_machdep.c
--- a/sys/amd64/amd64/uio_machdep.c
+++ b/sys/amd64/amd64/uio_machdep.c
@@ -44,9 +44,11 @@
#include <sys/uio.h>
#include <vm/vm.h>
+#include <vm/vm_extern.h>
#include <vm/vm_page.h>
#include <machine/vmparam.h>
+#include <machine/md_var.h>
/*
* Implement uiomove(9) from physical memory using the direct map to
@@ -141,3 +143,97 @@
td->td_pflags &= ~TDP_DEADLKTREAT;
return (error);
}
+
+int
+uiomove_mem(enum uiomove_mem_req req, struct uio *uio)
+{
+ struct iovec *iov;
+ void *p, *vd;
+ ssize_t orig_resid;
+ vm_prot_t prot;
+ u_long v;
+ u_int c;
+ int error;
+
+ error = 0;
+ orig_resid = uio->uio_resid;
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("memrw");
+ continue;
+ }
+ v = uio->uio_offset;
+ c = ulmin(iov->iov_len, PAGE_SIZE - (u_int)(v & PAGE_MASK));
+
+ switch (req) {
+ case UIO_MEM_KMEM:
+ /*
+ * Since c is clamped to be less or equal than
+ * PAGE_SIZE, the uiomove() call does not
+ * access past the end of the direct map.
+ */
+ if (v >= kva_layout.dmap_low &&
+ v < kva_layout.dmap_high) {
+ error = uiomove((void *)v, c, uio);
+ break;
+ }
+
+ switch (uio->uio_rw) {
+ case UIO_READ:
+ prot = VM_PROT_READ;
+ break;
+ case UIO_WRITE:
+ prot = VM_PROT_WRITE;
+ break;
+ }
+
+ if (!kernacc((void *)v, c, prot)) {
+ error = EFAULT;
+ break;
+ }
+
+ /*
+ * If the extracted address is not accessible
+ * through the direct map, then we make a
+ * private (uncached) mapping because we can't
+ * depend on the existing kernel mapping
+ * remaining valid until the completion of
+ * uiomove().
+ *
+ * XXX We cannot provide access to the
+ * physical page 0 mapped into KVA.
+ */
+ v = pmap_extract(kernel_pmap, v);
+ if (v == 0) {
+ error = EFAULT;
+ break;
+ }
+ /* FALLTHROUGH */
+ case UIO_MEM_MEM:
+ if (v < dmaplimit) {
+ vd = PHYS_TO_DMAP(v);
+ error = uiomove(vd, c, uio);
+ break;
+ }
+ if (v > cpu_getmaxphyaddr()) {
+ error = EFAULT;
+ break;
+ }
+ p = pmap_mapdev(v, PAGE_SIZE);
+ error = uiomove(p, c, uio);
+ pmap_unmapdev(p, PAGE_SIZE);
+ break;
+ }
+ }
+ /*
+ * Don't return error if any byte was written. Read and write
+ * can return error only if no i/o was performed.
+ */
+ if (uio->uio_resid != orig_resid)
+ error = 0;
+ return (error);
+}
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -107,6 +107,12 @@
void wrmsr_early_safe_end(void);
int wrmsr_early_safe(u_int msr, uint64_t data);
+enum uiomove_mem_req {
+ UIO_MEM_KMEM = 101,
+ UIO_MEM_MEM,
+};
+int uiomove_mem(enum uiomove_mem_req req, struct uio *uio);
+
#endif /* !_MACHINE_MD_VAR_H_ */
#endif /* __i386__ */
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -553,6 +553,14 @@
void counted_warning(unsigned *counter, const char *msg);
+/*
+ * Safely read one byte of kernel memory at address addr, placing the
+ * value into *valp. Returns 0 on success, EFAULT if read was
+ * impossible, e.g. due to the address not being mapped or not having
+ * necessary permissions.
+ */
+int safe_read(vm_offset_t addr, char *valp);
+
/*
* APIs to manage deprecation and obsolescence.
*/
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, May 28, 8:30 PM (7 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33592025
Default Alt Text
D49566.id178524.diff (6 KB)
Attached To
Mode
D49566: sys: add safe_read(9)
Attached
Detach File
Event Timeline
Log In to Comment