Index: share/man/man4/mem.4 =================================================================== --- share/man/man4/mem.4 +++ share/man/man4/mem.4 @@ -28,7 +28,7 @@ .\" @(#)mem.4 5.3 (Berkeley) 5/2/91 .\" $FreeBSD$ .\" -.Dd October 3, 2004 +.Dd August 25, 2020 .Dt MEM 4 .Os .Sh NAME @@ -54,11 +54,7 @@ .Pa /dev/mem . Only kernel virtual addresses that are currently mapped to memory are allowed. .Pp -On -.Tn ISA -the -.Tn I/O -memory space begins at physical address 0x000a0000 +On ISA the I/O memory space begins at physical address 0x000a0000 and runs to 0x00100000. The per-process data @@ -69,6 +65,19 @@ long, and ends at virtual address 0xf0000000. .Sh IOCTL INTERFACE +The +.Dv MEM_EXTRACT +ioctl can be used to look up the physical address and NUMA domain of a given +virtual address. +The request is described by +.Bd -literal +struct mem_extract { + uint64_t me_vaddr; + uint64_t me_paddr; + int me_domain; +}; +.Ed +.Pp Several architectures allow attributes to be associated with ranges of physical memory. These attributes can be manipulated via @@ -95,12 +104,13 @@ .El .Pp Memory ranges are described by -.Vt struct mem_range_desc : -.Bd -literal -offset indent -uint64_t mr_base; /\(** physical base address \(**/ -uint64_t mr_len; /\(** physical length of region \(**/ -int mr_flags; /\(** attributes of region \(**/ -char mr_owner[8]; +.Bd -literal +struct mem_range_desc { + uint64_t mr_base; /* physical base address */ + uint64_t mr_len; /* physical length of region */ + int mr_flags; /* attributes of region */ + char mr_owner[8]; +}; .Ed .Pp In addition to the region attributes listed above, the following flags @@ -165,7 +175,7 @@ .It Bq Er EOPNOTSUPP Memory range operations are not supported on this architecture. .It Bq Er ENXIO -No memory range descriptors are available (e.g.\& firmware has not enabled +No memory range descriptors are available (e.g., firmware has not enabled any). .It Bq Er EINVAL The memory range supplied as an argument is invalid or overlaps another @@ -174,7 +184,7 @@ An attempt to remove or update a range failed because the range is busy. .It Bq Er ENOSPC An attempt to create a new range failed due to a shortage of hardware -resources (e.g.\& descriptor slots). +resources (e.g., descriptor slots). .It Bq Er ENOENT An attempt to remove a range failed because no range matches the descriptor base/length supplied. Index: sys/amd64/amd64/mem.c =================================================================== --- sys/amd64/amd64/mem.c +++ sys/amd64/amd64/mem.c @@ -185,9 +185,8 @@ * This is basically just an ioctl shim for mem_range_attr_get * and mem_range_attr_set. */ -/* ARGSUSED */ int -memioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, +memioctl_md(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, struct thread *td) { int nd, error = 0; Index: sys/amd64/include/memdev.h =================================================================== --- sys/amd64/include/memdev.h +++ sys/amd64/include/memdev.h @@ -36,7 +36,7 @@ d_open_t memopen; d_read_t memrw; -d_ioctl_t memioctl; +d_ioctl_t memioctl_md; d_mmap_t memmmap; #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/arm/arm/mem.c =================================================================== --- sys/arm/arm/mem.c +++ sys/arm/arm/mem.c @@ -172,3 +172,10 @@ } return (-1); } + +int +memioctl_md(struct cdev *dev __unused, u_long cmd __unused, + caddr_t data __unused, int flags __unused, struct thread *td __unused) +{ + return (ENOTTY); +} Index: sys/arm/include/memdev.h =================================================================== --- sys/arm/include/memdev.h +++ sys/arm/include/memdev.h @@ -37,6 +37,6 @@ d_open_t memopen; d_read_t memrw; d_mmap_t memmmap; -#define memioctl (d_ioctl_t *)NULL +d_ioctl_t memioctl_md; #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/arm64/arm64/mem.c =================================================================== --- sys/arm64/arm64/mem.c +++ sys/arm64/arm64/mem.c @@ -129,3 +129,10 @@ } return (-1); } + +int +memioctl_md(struct cdev *dev __unused, u_long cmd __unused, + caddr_t data __unused, int flags __unused, struct thread *td __unused) +{ + return (ENOTTY); +} Index: sys/arm64/include/memdev.h =================================================================== --- sys/arm64/include/memdev.h +++ sys/arm64/include/memdev.h @@ -34,7 +34,7 @@ d_open_t memopen; d_read_t memrw; -#define memioctl (d_ioctl_t *)NULL +d_ioctl_t memioctl_md; d_mmap_t memmmap; #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/dev/mem/memdev.c =================================================================== --- sys/dev/mem/memdev.c +++ sys/dev/mem/memdev.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -46,12 +47,19 @@ #include #include +#include #include +#include +#include +#include +#include #include static struct cdev *memdev, *kmemdev; +static d_ioctl_t memioctl; + static struct cdevsw mem_cdevsw = { .d_version = D_VERSION, .d_flags = D_MEM, @@ -82,6 +90,29 @@ return (error); } +static int +memioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, + struct thread *td) +{ + struct mem_extract *me; + int error; + + error = 0; + switch (cmd) { + case MEM_EXTRACT: + me = (struct mem_extract *)data; + + me->me_paddr = pmap_extract(&td->td_proc->p_vmspace->vm_pmap, + me->me_vaddr); + me->me_domain = _vm_phys_domain(me->me_paddr); + break; + default: + error = memioctl_md(dev, cmd, data, flags, td); + break; + } + return (error); +} + /* ARGSUSED */ static int mem_modevent(module_t mod __unused, int type, void *data __unused) Index: sys/i386/i386/mem.c =================================================================== --- sys/i386/i386/mem.c +++ sys/i386/i386/mem.c @@ -177,9 +177,8 @@ * This is basically just an ioctl shim for mem_range_attr_get * and mem_range_attr_set. */ -/* ARGSUSED */ int -memioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, +memioctl_md(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, struct thread *td) { int nd, error = 0; Index: sys/i386/include/memdev.h =================================================================== --- sys/i386/include/memdev.h +++ sys/i386/include/memdev.h @@ -36,7 +36,7 @@ d_open_t memopen; d_read_t memrw; -d_ioctl_t memioctl; +d_ioctl_t memioctl_md; d_mmap_t memmmap; #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/mips/include/memdev.h =================================================================== --- sys/mips/include/memdev.h +++ sys/mips/include/memdev.h @@ -37,7 +37,7 @@ d_open_t memopen; d_read_t memrw; -#define memioctl (d_ioctl_t *)NULL +d_ioctl_t memioctl_md d_mmap_t memmmap; #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/powerpc/include/memdev.h =================================================================== --- sys/powerpc/include/memdev.h +++ sys/powerpc/include/memdev.h @@ -36,7 +36,7 @@ d_open_t memopen; d_read_t memrw; -d_ioctl_t memioctl; +d_ioctl_t memioctl_md; d_mmap_t memmmap; #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/powerpc/powerpc/mem.c =================================================================== --- sys/powerpc/powerpc/mem.c +++ sys/powerpc/powerpc/mem.c @@ -278,9 +278,8 @@ * This is basically just an ioctl shim for mem_range_attr_get * and mem_range_attr_set. */ -/* ARGSUSED */ int -memioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, +memioctl_md(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, struct thread *td) { int nd, error = 0; Index: sys/riscv/include/memdev.h =================================================================== --- sys/riscv/include/memdev.h +++ sys/riscv/include/memdev.h @@ -34,7 +34,7 @@ d_open_t memopen; d_read_t memrw; -#define memioctl (d_ioctl_t *)NULL +d_ioctl_t memioctl_md; #define memmmap (d_mmap_t *)NULL #endif /* _MACHINE_MEMDEV_H_ */ Index: sys/riscv/riscv/mem.c =================================================================== --- sys/riscv/riscv/mem.c +++ sys/riscv/riscv/mem.c @@ -122,3 +122,9 @@ return (error); } +int +memioctl_md(struct cdev *dev __unused, u_long cmd __unused, + caddr_t data __unused, int flags __unused, struct thread *td __unused) +{ + return (ENOTTY); +} Index: sys/sys/memrange.h =================================================================== --- sys/sys/memrange.h +++ sys/sys/memrange.h @@ -45,6 +45,16 @@ #define MEMRANGE_GET _IOWR('m', 50, struct mem_range_op) #define MEMRANGE_SET _IOW('m', 51, struct mem_range_op) +struct mem_extract { + uint64_t me_vaddr; + uint64_t me_paddr; + int me_domain; + uint32_t pad0; + uint64_t pad1[5]; +}; + +#define MEM_EXTRACT _IOWR('m', 52, struct mem_extract) + #ifdef _KERNEL MALLOC_DECLARE(M_MEMDESC);