1285387Sadrian/*-
2285387Sadrian * Copyright (c) 2015, Adrian Chadd <adrian@FreeBSD.org>
3285387Sadrian * All rights reserved.
4285387Sadrian *
5285387Sadrian * Redistribution and use in source and binary forms, with or without
6285387Sadrian * modification, are permitted provided that the following conditions
7285387Sadrian * are met:
8285387Sadrian * 1. Redistributions of source code must retain the above copyright
9285387Sadrian *    notice unmodified, this list of conditions, and the following
10285387Sadrian *    disclaimer.
11285387Sadrian * 2. Redistributions in binary form must reproduce the above copyright
12285387Sadrian *    notice, this list of conditions and the following disclaimer in the
13285387Sadrian *    documentation and/or other materials provided with the distribution.
14285387Sadrian *
15285387Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16285387Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17285387Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18285387Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19285387Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20285387Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21285387Sadrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22285387Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23285387Sadrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24285387Sadrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25285387Sadrian *
26285387Sadrian */
27285387Sadrian
28285387Sadrian#include <sys/cdefs.h>
29285387Sadrian__FBSDID("$FreeBSD$");
30285387Sadrian
31285387Sadrian#include <sys/param.h>
32285387Sadrian#include <sys/systm.h>
33285387Sadrian#include <sys/sysproto.h>
34285387Sadrian#include <sys/jail.h>
35285387Sadrian#include <sys/kernel.h>
36285387Sadrian#include <sys/lock.h>
37285387Sadrian#include <sys/malloc.h>
38285387Sadrian#include <sys/mutex.h>
39285387Sadrian#include <sys/priv.h>
40285387Sadrian#include <sys/proc.h>
41285387Sadrian#include <sys/refcount.h>
42285387Sadrian#include <sys/sched.h>
43285387Sadrian#include <sys/smp.h>
44285387Sadrian#include <sys/syscallsubr.h>
45285387Sadrian#include <sys/cpuset.h>
46285387Sadrian#include <sys/sx.h>
47285387Sadrian#include <sys/queue.h>
48285387Sadrian#include <sys/libkern.h>
49285387Sadrian#include <sys/limits.h>
50285387Sadrian#include <sys/bus.h>
51285387Sadrian#include <sys/interrupt.h>
52285387Sadrian
53285387Sadrian#include <vm/uma.h>
54285387Sadrian#include <vm/vm.h>
55285387Sadrian#include <vm/vm_page.h>
56285387Sadrian#include <vm/vm_param.h>
57285387Sadrian#include <vm/vm_phys.h>
58285387Sadrian#include <vm/vm_domain.h>
59285387Sadrian
60285387Sadrianint
61285387Sadriansys_numa_setaffinity(struct thread *td, struct numa_setaffinity_args *uap)
62285387Sadrian{
63285387Sadrian	int error;
64285387Sadrian	struct vm_domain_policy vp;
65285387Sadrian	struct thread *ttd;
66285387Sadrian	struct proc *p;
67285387Sadrian	struct cpuset *set;
68285387Sadrian
69285387Sadrian	set = NULL;
70285387Sadrian	p = NULL;
71285387Sadrian
72285387Sadrian	/*
73285387Sadrian	 * Copy in just the policy information into the policy
74285387Sadrian	 * struct.  Userland only supplies vm_domain_policy_entry.
75285387Sadrian	 */
76285387Sadrian	error = copyin(uap->policy, &vp.p, sizeof(vp.p));
77285387Sadrian	if (error)
78285387Sadrian		goto out;
79285387Sadrian
80285387Sadrian	/*
81285387Sadrian	 * Ensure the seq number is zero - otherwise seq.h
82285387Sadrian	 * may get very confused.
83285387Sadrian	 */
84285387Sadrian	vp.seq = 0;
85285387Sadrian
86285387Sadrian	/*
87285387Sadrian	 * Validate policy.
88285387Sadrian	 */
89285387Sadrian	if (vm_domain_policy_validate(&vp) != 0) {
90285387Sadrian		error = EINVAL;
91285387Sadrian		goto out;
92285387Sadrian	}
93285387Sadrian
94285387Sadrian	/*
95285387Sadrian	 * Go find the desired proc/tid for this operation.
96285387Sadrian	 */
97285387Sadrian	error = cpuset_which(uap->which, uap->id, &p,
98285387Sadrian	    &ttd, &set);
99285387Sadrian	if (error)
100285387Sadrian		goto out;
101285387Sadrian
102285387Sadrian	/* Only handle CPU_WHICH_TID and CPU_WHICH_PID */
103285387Sadrian	/*
104285387Sadrian	 * XXX if cpuset_which is called with WHICH_CPUSET and NULL cpuset,
105285387Sadrian	 * it'll return ESRCH.  We should just return EINVAL.
106285387Sadrian	 */
107285387Sadrian	switch (uap->which) {
108285387Sadrian	case CPU_WHICH_TID:
109285387Sadrian		vm_domain_policy_copy(&ttd->td_vm_dom_policy, &vp);
110285387Sadrian		break;
111285387Sadrian	case CPU_WHICH_PID:
112285387Sadrian		vm_domain_policy_copy(&p->p_vm_dom_policy, &vp);
113285387Sadrian		break;
114285387Sadrian	default:
115285387Sadrian		error = EINVAL;
116285387Sadrian		break;
117285387Sadrian	}
118285387Sadrian
119285387Sadrian	PROC_UNLOCK(p);
120285387Sadrianout:
121285387Sadrian	if (set)
122285387Sadrian		cpuset_rel(set);
123285387Sadrian	return (error);
124285387Sadrian}
125285387Sadrian
126285387Sadrianint
127285387Sadriansys_numa_getaffinity(struct thread *td, struct numa_getaffinity_args *uap)
128285387Sadrian{
129285387Sadrian	int error;
130285387Sadrian	struct vm_domain_policy vp;
131285387Sadrian	struct thread *ttd;
132285387Sadrian	struct proc *p;
133285387Sadrian	struct cpuset *set;
134285387Sadrian
135285387Sadrian	set = NULL;
136285387Sadrian	p = NULL;
137285387Sadrian
138285387Sadrian	error = cpuset_which(uap->which, uap->id, &p,
139285387Sadrian	    &ttd, &set);
140285387Sadrian	if (error)
141285387Sadrian		goto out;
142285387Sadrian
143285387Sadrian	/* Only handle CPU_WHICH_TID and CPU_WHICH_PID */
144285387Sadrian	/*
145285387Sadrian	 * XXX if cpuset_which is called with WHICH_CPUSET and NULL cpuset,
146285387Sadrian	 * it'll return ESRCH.  We should just return EINVAL.
147285387Sadrian	 */
148285387Sadrian	switch (uap->which) {
149285387Sadrian	case CPU_WHICH_TID:
150285387Sadrian		vm_domain_policy_localcopy(&vp, &ttd->td_vm_dom_policy);
151285387Sadrian		break;
152285387Sadrian	case CPU_WHICH_PID:
153285387Sadrian		vm_domain_policy_localcopy(&vp, &p->p_vm_dom_policy);
154285387Sadrian		break;
155285387Sadrian	default:
156285387Sadrian		error = EINVAL;
157285387Sadrian		break;
158285387Sadrian	}
159285387Sadrian	if (p)
160285387Sadrian		PROC_UNLOCK(p);
161285387Sadrian	/*
162285387Sadrian	 * Copy out only the vm_domain_policy_entry part.
163285387Sadrian	 */
164285387Sadrian	if (error == 0)
165285387Sadrian		error = copyout(&vp.p, uap->policy, sizeof(vp.p));
166285387Sadrianout:
167285387Sadrian	if (set)
168285387Sadrian		cpuset_rel(set);
169285387Sadrian	return (error);
170285387Sadrian}
171