Page MenuHomeFreeBSD

D49566.id178524.diff
No OneTemporary

D49566.id178524.diff

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

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)

Event Timeline