Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150170604
D14891.1791827577.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D14891.1791827577.diff
View Options
Index: compat/freebsd32/syscalls.master
===================================================================
--- compat/freebsd32/syscalls.master
+++ compat/freebsd32/syscalls.master
@@ -1118,5 +1118,9 @@
int policy); }
563 AUE_NULL NOPROTO { int getrandom(void *buf, size_t buflen, \
unsigned int flags); }
+564 AUE_NULL NOPROTO { int msetdomain(void *addr, \
+ size_t size, size_t domainsetsize, \
+ domainset_t *mask, int policy, \
+ int flags); }
; vim: syntax=off
Index: kern/kern_cpuset.c
===================================================================
--- kern/kern_cpuset.c
+++ kern/kern_cpuset.c
@@ -64,6 +64,9 @@
#include <vm/uma.h>
#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
@@ -2022,6 +2025,59 @@
return (error);
}
+static int
+domainset_copyin(struct domainset *domain, size_t domainsetsize,
+ const domainset_t *maskp, int policy)
+{
+ domainset_t *mask;
+ int error;
+
+ if (domainsetsize < sizeof(domainset_t) ||
+ domainsetsize > DOMAINSET_MAXSIZE / NBBY)
+ return (ERANGE);
+
+ if (policy <= DOMAINSET_POLICY_INVALID ||
+ policy > DOMAINSET_POLICY_MAX)
+ return (EINVAL);
+
+ memset(domain, 0, sizeof(*domain));
+ mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
+ error = copyin(maskp, mask, domainsetsize);
+ if (error)
+ goto out;
+ /*
+ * Verify that no high bits are set.
+ */
+ if (domainsetsize > sizeof(domainset_t)) {
+ char *end;
+ char *cp;
+
+ end = cp = (char *)&mask->__bits;
+ end += domainsetsize;
+ cp += sizeof(domainset_t);
+ while (cp != end)
+ if (*cp++ != 0) {
+ error = EINVAL;
+ goto out;
+ }
+
+ }
+ DOMAINSET_COPY(mask, &domain->ds_mask);
+ domain->ds_policy = policy;
+ /* Translate preferred policy into a mask and fallback. */
+ if (policy == DOMAINSET_POLICY_PREFER) {
+ /* Only support a single preferred domain. */
+ if (DOMAINSET_COUNT(&domain->ds_mask) != 1) {
+ error = EINVAL;
+ goto out;
+ }
+ domain->ds_prefer = DOMAINSET_FFS(&domain->ds_mask) - 1;
+ }
+out:
+ free(mask, M_TEMP);
+ return (error);
+}
+
#ifndef _SYS_SYSPROTO_H_
struct cpuset_setdomain_args {
cpulevel_t level;
@@ -2032,6 +2088,7 @@
int policy;
};
#endif
+
int
sys_cpuset_setdomain(struct thread *td, struct cpuset_setdomain_args *uap)
{
@@ -2049,12 +2106,8 @@
struct thread *ttd;
struct proc *p;
struct domainset domain;
- domainset_t *mask;
int error;
- if (domainsetsize < sizeof(domainset_t) ||
- domainsetsize > DOMAINSET_MAXSIZE / NBBY)
- return (ERANGE);
/* In Capability mode, you can only set your own CPU set. */
if (IN_CAPABILITY_MODE(td)) {
if (level != CPU_LEVEL_WHICH)
@@ -2064,43 +2117,13 @@
if (id != -1)
return (ECAPMODE);
}
- memset(&domain, 0, sizeof(domain));
- mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
- error = copyin(maskp, mask, domainsetsize);
+
+ error = domainset_copyin(&domain, domainsetsize, maskp, policy);
if (error)
- goto out;
- /*
- * Verify that no high bits are set.
- */
- if (domainsetsize > sizeof(domainset_t)) {
- char *end;
- char *cp;
-
- end = cp = (char *)&mask->__bits;
- end += domainsetsize;
- cp += sizeof(domainset_t);
- while (cp != end)
- if (*cp++ != 0) {
- error = EINVAL;
- goto out;
- }
-
- }
- DOMAINSET_COPY(mask, &domain.ds_mask);
- domain.ds_policy = policy;
- if (policy <= DOMAINSET_POLICY_INVALID ||
- policy > DOMAINSET_POLICY_MAX)
- return (EINVAL);
-
- /* Translate preferred policy into a mask and fallback. */
- if (policy == DOMAINSET_POLICY_PREFER) {
- /* Only support a single preferred domain. */
- if (DOMAINSET_COUNT(&domain.ds_mask) != 1)
- return (EINVAL);
- domain.ds_prefer = DOMAINSET_FFS(&domain.ds_mask) - 1;
- /* This will be constrained by domainset_shadow(). */
+ return (error);
+ /* This will be constrained by cpuset_shadow(). */
+ if (policy == DOMAINSET_POLICY_PREFER)
DOMAINSET_FILL(&domain.ds_mask);
- }
switch (level) {
case CPU_LEVEL_ROOT:
@@ -2163,10 +2186,91 @@
break;
}
out:
- free(mask, M_TEMP);
return (error);
}
+#ifndef _SYS_SYSPROTO_H_
+struct msetdomain_args {
+ void *addr;
+ size_t size;
+ size_t domainsetsize;
+ domainset_t *mask;
+ int policy;
+ int flags;
+};
+#endif
+
+int
+sys_msetdomain(struct thread *td, struct msetdomain_args *uap)
+{
+ return (kern_msetdomain(td, (uintptr_t)uap->addr, uap->size,
+ uap->domainsetsize, uap->mask, uap->policy, uap->flags));
+}
+
+int
+kern_msetdomain(struct thread *td, uintptr_t addr0, size_t size,
+ size_t domainsetsize, const domainset_t *mask, int policy, int flags)
+{
+ struct domainset domain, *set, *nset;
+ struct thread *ttd;
+ struct proc *p;
+ vm_offset_t addr;
+ vm_size_t pageoff;
+ int error;
+
+ /* Normalize the addresses. */
+ addr = addr0;
+ pageoff = (addr & PAGE_MASK);
+ addr -= pageoff;
+ size += pageoff;
+ size = (vm_size_t) round_page(size);
+ if (addr + size < addr)
+ return (EINVAL);
+
+ /*
+ * Copy in and initialize the domainset from the user arguments.
+ */
+ error = domainset_copyin(&domain, domainsetsize, mask, policy);
+ if (error)
+ return (error);
+
+ /*
+ * Grab the list of allowed domains from the numbered cpuset this
+ * process is a member of.
+ */
+ error = cpuset_which(CPU_WHICH_PID, -1, &p, &ttd, NULL);
+ if (error)
+ return (error);
+ thread_lock(ttd);
+ set = cpuset_getbase(ttd->td_cpuset)->cs_domain;
+ thread_unlock(ttd);
+ PROC_UNLOCK(p);
+
+ /*
+ * Validate the new policy against the allowed set.
+ */
+ if (policy == DOMAINSET_POLICY_PREFER)
+ DOMAINSET_COPY(&set->ds_mask, &domain.ds_mask);
+ if (!domainset_valid(set, &domain))
+ return (EINVAL);
+
+ /*
+ * Attempt to create a new set based on this key.
+ */
+ nset = domainset_create(&domain);
+ if (nset == NULL)
+ return (EINVAL);
+
+ /*
+ * Attempt to apply the new set to the memory range.
+ */
+ if (vm_map_setdomain(&td->td_proc->p_vmspace->vm_map, addr,
+ addr + size, nset, flags) != KERN_SUCCESS)
+ return (EINVAL);
+
+ return (0);
+}
+
static void
ddb_display_bitset(const struct bitset *set, int size)
{
Index: kern/syscalls.master
===================================================================
--- kern/syscalls.master
+++ kern/syscalls.master
@@ -1023,6 +1023,9 @@
int policy); }
563 AUE_NULL STD { int getrandom(void *buf, size_t buflen, \
unsigned int flags); }
+564 AUE_NULL STD { int msetdomain(void *addr, size_t size, \
+ size_t domainsetsize, domainset_t *mask, \
+ int policy, int flags); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/syscallsubr.h
===================================================================
--- sys/syscallsubr.h
+++ sys/syscallsubr.h
@@ -174,6 +174,9 @@
int kern_mmap(struct thread *td, uintptr_t addr, size_t size, int prot,
int flags, int fd, off_t pos);
int kern_mprotect(struct thread *td, uintptr_t addr, size_t size, int prot);
+int kern_msetdomain(struct thread *td, uintptr_t addr,
+ size_t size, size_t domainsetsize, const domainset_t *maskp,
+ int policy, int flags);
int kern_msgctl(struct thread *, int, int, struct msqid_ds *);
int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *);
int kern_msgsnd(struct thread *, int, const void *, size_t, int, long);
Index: vm/vm_fault.c
===================================================================
--- vm/vm_fault.c
+++ vm/vm_fault.c
@@ -1598,7 +1598,6 @@
KASSERT(upgrade || dst_entry->object.vm_object == NULL,
("vm_fault_copy_entry: vm_object not NULL"));
if (src_object != dst_object) {
- dst_object->domain = src_object->domain;
dst_entry->object.vm_object = dst_object;
dst_entry->offset = 0;
dst_object->charge = dst_entry->end - dst_entry->start;
Index: vm/vm_map.h
===================================================================
--- vm/vm_map.h
+++ vm/vm_map.h
@@ -403,5 +403,8 @@
int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
int flags);
long vmspace_swap_count(struct vmspace *vmspace);
+struct domainset;
+int vm_map_setdomain(vm_map_t, vm_offset_t, vm_offset_t,
+ struct domainset *, int);
#endif /* _KERNEL */
#endif /* _VM_MAP_ */
Index: vm/vm_map.c
===================================================================
--- vm/vm_map.c
+++ vm/vm_map.c
@@ -69,6 +69,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/domainset.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/lock.h>
@@ -848,6 +849,34 @@
}
/*
+ * vm_map_entry_object_allocate: [ internal use only ]
+ *
+ * Returns the object associated with a map entry, allocating
+ * a default object if non presently exists.
+ */
+static vm_object_t
+vm_map_entry_object_allocate(vm_map_t map, vm_map_entry_t entry)
+{
+ vm_object_t object;
+
+ VM_MAP_ASSERT_LOCKED(map);
+ if (entry->object.vm_object != NULL)
+ return (entry->object.vm_object);
+
+ object = vm_object_allocate(OBJT_DEFAULT,
+ atop(entry->end - entry->start));
+ entry->object.vm_object = object;
+ entry->offset = 0;
+ if (entry->cred != NULL) {
+ object->cred = entry->cred;
+ object->charge = entry->end - entry->start;
+ entry->cred = NULL;
+ }
+
+ return (object);
+}
+
+/*
* vm_map_entry_set_behavior:
*
* Set the expected access behavior, either normal, random, or
@@ -1773,16 +1802,7 @@
*/
if (entry->object.vm_object == NULL && !map->system_map &&
(entry->eflags & MAP_ENTRY_GUARD) == 0) {
- vm_object_t object;
- object = vm_object_allocate(OBJT_DEFAULT,
- atop(entry->end - entry->start));
- entry->object.vm_object = object;
- entry->offset = 0;
- if (entry->cred != NULL) {
- object->cred = entry->cred;
- object->charge = entry->end - entry->start;
- entry->cred = NULL;
- }
+ vm_map_entry_object_allocate(map, entry);
} else if (entry->object.vm_object != NULL &&
((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) &&
entry->cred != NULL) {
@@ -1853,16 +1873,7 @@
*/
if (entry->object.vm_object == NULL && !map->system_map &&
(entry->eflags & MAP_ENTRY_GUARD) == 0) {
- vm_object_t object;
- object = vm_object_allocate(OBJT_DEFAULT,
- atop(entry->end - entry->start));
- entry->object.vm_object = object;
- entry->offset = 0;
- if (entry->cred != NULL) {
- object->cred = entry->cred;
- object->charge = entry->end - entry->start;
- entry->cred = NULL;
- }
+ vm_map_entry_object_allocate(map, entry);
} else if (entry->object.vm_object != NULL &&
((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) &&
entry->cred != NULL) {
@@ -3449,21 +3460,11 @@
case VM_INHERIT_SHARE:
/*
- * Clone the entry, creating the shared object if necessary.
+ * Clone the entry, creating the shared object if
+ * necessary.
*/
- object = old_entry->object.vm_object;
- if (object == NULL) {
- object = vm_object_allocate(OBJT_DEFAULT,
- atop(old_entry->end - old_entry->start));
- old_entry->object.vm_object = object;
- old_entry->offset = 0;
- if (old_entry->cred != NULL) {
- object->cred = old_entry->cred;
- object->charge = old_entry->end -
- old_entry->start;
- old_entry->cred = NULL;
- }
- }
+ object = vm_map_entry_object_allocate(old_map,
+ old_entry);
/*
* Add the reference before calling vm_object_shadow
@@ -4195,16 +4196,7 @@
!map->system_map) {
if (vm_map_lock_upgrade(map))
goto RetryLookup;
- entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT,
- atop(size));
- entry->offset = 0;
- if (entry->cred != NULL) {
- VM_OBJECT_WLOCK(entry->object.vm_object);
- entry->object.vm_object->cred = entry->cred;
- entry->object.vm_object->charge = size;
- VM_OBJECT_WUNLOCK(entry->object.vm_object);
- entry->cred = NULL;
- }
+ vm_map_entry_object_allocate(map, entry);
vm_map_lock_downgrade(map);
}
@@ -4315,6 +4307,98 @@
vm_map_unlock_read(map);
}
+/*
+ * vm_map_setdomain:
+ *
+ * Sets the NUMA policy contained 'domain' to all objects
+ * overlapping the requested address range.
+ */
+int
+vm_map_setdomain(vm_map_t map, vm_offset_t start, vm_offset_t end,
+ struct domainset *domain, int flags)
+{
+ vm_map_entry_t current, entry;
+ vm_object_t object;
+ int error;
+
+ error = KERN_SUCCESS;
+ if (start == end || map->system_map)
+ return (error);
+
+ vm_map_lock(map);
+ /*
+ * Locate starting entry and clip if necessary.
+ */
+ VM_MAP_RANGE_CHECK(map, start, end);
+
+ if (vm_map_lookup_entry(map, start, &entry)) {
+ vm_map_clip_start(map, entry, start);
+ } else {
+ /*
+ * XXX Some calls silently succeed. That won't work
+ * here. Should evaluate what linux does for error
+ * compatibility.
+ */
+ error = KERN_INVALID_ADDRESS;
+ goto out;
+ }
+
+ /*
+ * Walk each overlapping map entry and update the backing
+ * object's memory policy.
+ */
+ for (current = entry;
+ (current != &map->header) && (current->start < end);
+ current = current->next
+ ) {
+ /* Skip incompatible entries. */
+ if ((current->eflags &
+ (MAP_ENTRY_GUARD | MAP_ENTRY_IS_SUB_MAP)) != 0)
+ continue;
+
+ /*
+ * Clip the end and allocate the object so that we are
+ * only modifying the requested range.
+ */
+ vm_map_clip_end(map, current, end);
+ object = vm_map_entry_object_allocate(map, current);
+ if (object == NULL) {
+ vm_map_simplify_entry(map, current);
+ continue;
+ }
+
+ /*
+ * If the object is anonymous memory we need to split it
+ * so that we can apply the unique alloction property to
+ * this range.
+ */
+ VM_OBJECT_WLOCK(object);
+ if ((object->type == OBJT_DEFAULT ||
+ object->type == OBJT_SWAP)) {
+ vm_object_collapse(object);
+ if ((object->flags & OBJ_NOSPLIT) == 0) {
+ vm_object_split(current);
+ object = current->object.vm_object;
+ }
+ }
+ object->domain.dr_policy = domain;
+ VM_OBJECT_WUNLOCK(object);
+ /*
+ * XXX Some security check for vnodes?
+ */
+
+ /*
+ * XXX This simplify is probably not fruitful should I elide
+ * it?
+ */
+ vm_map_simplify_entry(map, current);
+ }
+ vm_map_unlock(map);
+
+out:
+ return (error);
+}
+
#include "opt_ddb.h"
#ifdef DDB
#include <sys/kernel.h>
Index: vm/vm_object.c
===================================================================
--- vm/vm_object.c
+++ vm/vm_object.c
@@ -1328,7 +1328,6 @@
result->backing_object_offset = *offset;
if (source != NULL) {
VM_OBJECT_WLOCK(source);
- result->domain = source->domain;
LIST_INSERT_HEAD(&source->shadow_head, result, shadow_list);
source->shadow_count++;
#if VM_NRESERVLEVEL > 0
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Oct 12, 5:52 PM (8 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30344366
Default Alt Text
D14891.1791827577.diff (14 KB)
Attached To
Mode
D14891: msetdomain prototype (similar to mbind())
Attached
Detach File
Event Timeline
Log In to Comment