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