Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F2889222
Masterwork From Distant Lands
No One
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
cem
Oct 10 2017, 9:47 PM
2017-10-10 21:47:46 (UTC+0)
Size
3 KB
Referenced Files
None
Subscribers
None
Masterwork From Distant Lands
View Options
commit d20373d3bfb8872cae43a8f2804e8a4d7aeb2e73
Author: Conrad Meyer <cem@FreeBSD.org>
Date: Tue Oct 10 13:43:50 2017 -0700
mem: Hack to allow libkvm to read device registers
diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c
index 067da04dfc4f..9fb90767688f 100644
--- a/sys/amd64/amd64/mem.c
+++ b/sys/amd64/amd64/mem.c
@@ -73,6 +73,94 @@ __FBSDID("$FreeBSD$");
*/
MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
+static bool
+is_word_aligned(u_int len, u_long addr)
+{
+ return ((len == 8 && (addr & 7) == 0) || (len == 4 && (addr & 3) == 0)
+ || (len == 2 && (addr & 1) == 0));
+}
+
+static int
+alignmove(void *cp, u_int len, struct uio *uio)
+{
+ struct iovec *iov;
+ size_t cnt;
+ union {
+ uint64_t u64;
+ uint32_t u32;
+ uint16_t u16;
+ } devmem;
+ void *memp;
+ int error;
+
+ switch (len) {
+ case 8:
+ memp = &devmem.u64;
+ break;
+ case 4:
+ memp = &devmem.u32;
+ break;
+ case 2:
+ memp = &devmem.u16;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ error = 0;
+ iov = uio->uio_iov;
+ cnt = iov->iov_len;
+ if (cnt > len)
+ cnt = len;
+
+ if (uio->uio_rw == UIO_WRITE) {
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ error = copyin(iov->iov_base, memp, cnt);
+ if (error != 0)
+ goto out;
+ } else if (uio->uio_segflg == UIO_SYSSPACE)
+ bcopy(iov->iov_base, memp, cnt);
+
+ switch (len) {
+ case 8:
+ *(volatile uint64_t *)cp = devmem.u64;
+ break;
+ case 4:
+ *(volatile uint32_t *)cp = devmem.u32;
+ break;
+ case 2:
+ *(volatile uint16_t *)cp = devmem.u16;
+ break;
+ }
+ } else {
+ switch (len) {
+ case 8:
+ devmem.u64 = *(volatile uint64_t *)cp;
+ break;
+ case 4:
+ devmem.u32 = *(volatile uint32_t *)cp;
+ break;
+ case 2:
+ devmem.u16 = *(volatile uint16_t *)cp;
+ break;
+ }
+
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ error = copyout(memp, iov->iov_base, cnt);
+ if (error != 0)
+ goto out;
+ } else if (uio->uio_segflg == UIO_SYSSPACE)
+ bcopy(memp, iov->iov_base, cnt);
+ }
+
+ iov->iov_base = (char *)iov->iov_base + cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_offset += cnt;
+out:
+ return (error);
+}
+
/* ARGSUSED */
int
memrw(struct cdev *dev, struct uio *uio, int flags)
@@ -107,7 +195,10 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
*/
if (v >= DMAP_MIN_ADDRESS &&
v < DMAP_MIN_ADDRESS + dmaplimit) {
- error = uiomove((void *)v, c, uio);
+ if (is_word_aligned(c, v))
+ error = alignmove((void *)v, c, uio);
+ else
+ error = uiomove((void *)v, c, uio);
break;
}
@@ -137,7 +228,10 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
case CDEV_MINOR_MEM:
if (v < dmaplimit) {
vd = PHYS_TO_DMAP(v);
- error = uiomove((void *)vd, c, uio);
+ if (is_word_aligned(c, vd))
+ error = alignmove((void *)vd, c, uio);
+ else
+ error = uiomove((void *)vd, c, uio);
break;
}
if (v > cpu_getmaxphyaddr()) {
@@ -145,7 +239,10 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
break;
}
p = pmap_mapdev(v, PAGE_SIZE);
- error = uiomove(p, c, uio);
+ if (is_word_aligned(c, (u_long)p))
+ error = alignmove(p, c, uio);
+ else
+ error = uiomove(p, c, uio);
pmap_unmapdev((vm_offset_t)p, PAGE_SIZE);
break;
}
File Metadata
Details
Attached
Mime Type
text/plain; charset=utf-8
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1147226
Default Alt Text
Masterwork From Distant Lands (3 KB)
Attached To
Mode
P146 Masterwork From Distant Lands
Attached
Detach File
Event Timeline
Log In to Comment