1 1.5 andvar /* $NetBSD: subr_interrupt.c,v 1.5 2021/12/10 20:36:04 andvar Exp $ */ 2 1.1 knakahar 3 1.1 knakahar /* 4 1.1 knakahar * Copyright (c) 2015 Internet Initiative Japan Inc. 5 1.1 knakahar * All rights reserved. 6 1.1 knakahar * 7 1.1 knakahar * Redistribution and use in source and binary forms, with or without 8 1.1 knakahar * modification, are permitted provided that the following conditions 9 1.1 knakahar * are met: 10 1.1 knakahar * 1. Redistributions of source code must retain the above copyright 11 1.1 knakahar * notice, this list of conditions and the following disclaimer. 12 1.1 knakahar * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 knakahar * notice, this list of conditions and the following disclaimer in the 14 1.1 knakahar * documentation and/or other materials provided with the distribution. 15 1.1 knakahar * 16 1.1 knakahar * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 knakahar * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 knakahar * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 knakahar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 knakahar * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 knakahar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 knakahar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 knakahar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 knakahar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 knakahar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 knakahar * POSSIBILITY OF SUCH DAMAGE. 27 1.1 knakahar */ 28 1.1 knakahar 29 1.1 knakahar #include <sys/cdefs.h> 30 1.5 andvar __KERNEL_RCSID(0, "$NetBSD: subr_interrupt.c,v 1.5 2021/12/10 20:36:04 andvar Exp $"); 31 1.1 knakahar 32 1.1 knakahar #include <sys/param.h> 33 1.1 knakahar #include <sys/systm.h> 34 1.1 knakahar #include <sys/kernel.h> 35 1.1 knakahar #include <sys/errno.h> 36 1.1 knakahar #include <sys/cpu.h> 37 1.1 knakahar #include <sys/interrupt.h> 38 1.1 knakahar #include <sys/intr.h> 39 1.1 knakahar #include <sys/kcpuset.h> 40 1.1 knakahar #include <sys/kmem.h> 41 1.1 knakahar #include <sys/proc.h> 42 1.1 knakahar #include <sys/xcall.h> 43 1.1 knakahar #include <sys/sysctl.h> 44 1.1 knakahar 45 1.1 knakahar #include <sys/conf.h> 46 1.1 knakahar #include <sys/intrio.h> 47 1.1 knakahar #include <sys/kauth.h> 48 1.1 knakahar 49 1.1 knakahar #include <machine/limits.h> 50 1.1 knakahar 51 1.1 knakahar #ifdef INTR_DEBUG 52 1.1 knakahar #define DPRINTF(msg) printf msg 53 1.1 knakahar #else 54 1.1 knakahar #define DPRINTF(msg) 55 1.1 knakahar #endif 56 1.1 knakahar 57 1.1 knakahar static struct intrio_set kintrio_set = { "\0", NULL, 0 }; 58 1.1 knakahar 59 1.1 knakahar #define UNSET_NOINTR_SHIELD 0 60 1.1 knakahar #define SET_NOINTR_SHIELD 1 61 1.1 knakahar 62 1.1 knakahar static void 63 1.1 knakahar interrupt_shield_xcall(void *arg1, void *arg2) 64 1.1 knakahar { 65 1.1 knakahar struct cpu_info *ci; 66 1.1 knakahar struct schedstate_percpu *spc; 67 1.1 knakahar int s, shield; 68 1.1 knakahar 69 1.1 knakahar ci = arg1; 70 1.1 knakahar shield = (int)(intptr_t)arg2; 71 1.1 knakahar spc = &ci->ci_schedstate; 72 1.1 knakahar 73 1.1 knakahar s = splsched(); 74 1.1 knakahar if (shield == UNSET_NOINTR_SHIELD) 75 1.1 knakahar spc->spc_flags &= ~SPCF_NOINTR; 76 1.1 knakahar else if (shield == SET_NOINTR_SHIELD) 77 1.1 knakahar spc->spc_flags |= SPCF_NOINTR; 78 1.1 knakahar splx(s); 79 1.1 knakahar } 80 1.1 knakahar 81 1.1 knakahar /* 82 1.1 knakahar * Change SPCF_NOINTR flag of schedstate_percpu->spc_flags. 83 1.1 knakahar */ 84 1.1 knakahar static int 85 1.1 knakahar interrupt_shield(u_int cpu_idx, int shield) 86 1.1 knakahar { 87 1.1 knakahar struct cpu_info *ci; 88 1.1 knakahar struct schedstate_percpu *spc; 89 1.1 knakahar 90 1.1 knakahar KASSERT(mutex_owned(&cpu_lock)); 91 1.1 knakahar 92 1.1 knakahar ci = cpu_lookup(cpu_idx); 93 1.1 knakahar if (ci == NULL) 94 1.1 knakahar return EINVAL; 95 1.1 knakahar 96 1.1 knakahar spc = &ci->ci_schedstate; 97 1.1 knakahar if (shield == UNSET_NOINTR_SHIELD) { 98 1.1 knakahar if ((spc->spc_flags & SPCF_NOINTR) == 0) 99 1.1 knakahar return 0; 100 1.1 knakahar } else if (shield == SET_NOINTR_SHIELD) { 101 1.1 knakahar if ((spc->spc_flags & SPCF_NOINTR) != 0) 102 1.1 knakahar return 0; 103 1.1 knakahar } 104 1.1 knakahar 105 1.1 knakahar if (ci == curcpu() || !mp_online) { 106 1.1 knakahar interrupt_shield_xcall(ci, (void *)(intptr_t)shield); 107 1.1 knakahar } else { 108 1.1 knakahar uint64_t where; 109 1.1 knakahar where = xc_unicast(0, interrupt_shield_xcall, ci, 110 1.1 knakahar (void *)(intptr_t)shield, ci); 111 1.1 knakahar xc_wait(where); 112 1.1 knakahar } 113 1.1 knakahar 114 1.1 knakahar spc->spc_lastmod = time_second; 115 1.1 knakahar return 0; 116 1.1 knakahar } 117 1.1 knakahar 118 1.1 knakahar /* 119 1.1 knakahar * Move all assigned interrupts from "cpu_idx" to the other cpu as possible. 120 1.1 knakahar * The destination cpu is the lowest cpuid of available cpus. 121 1.1 knakahar * If there are no available cpus, give up to move interrupts. 122 1.1 knakahar */ 123 1.1 knakahar static int 124 1.1 knakahar interrupt_avert_intr(u_int cpu_idx) 125 1.1 knakahar { 126 1.1 knakahar kcpuset_t *cpuset; 127 1.1 knakahar struct intrids_handler *ii_handler; 128 1.1 knakahar intrid_t *ids; 129 1.3 reinoud int error = 0, i, nids; 130 1.1 knakahar 131 1.1 knakahar kcpuset_create(&cpuset, true); 132 1.1 knakahar kcpuset_set(cpuset, cpu_idx); 133 1.1 knakahar 134 1.1 knakahar ii_handler = interrupt_construct_intrids(cpuset); 135 1.1 knakahar if (ii_handler == NULL) { 136 1.4 christos error = EINVAL; 137 1.1 knakahar goto out; 138 1.1 knakahar } 139 1.1 knakahar nids = ii_handler->iih_nids; 140 1.1 knakahar if (nids == 0) { 141 1.1 knakahar error = 0; 142 1.1 knakahar goto destruct_out; 143 1.1 knakahar } 144 1.1 knakahar 145 1.1 knakahar interrupt_get_available(cpuset); 146 1.1 knakahar kcpuset_clear(cpuset, cpu_idx); 147 1.1 knakahar if (kcpuset_iszero(cpuset)) { 148 1.1 knakahar DPRINTF(("%s: no available cpu\n", __func__)); 149 1.1 knakahar error = ENOENT; 150 1.1 knakahar goto destruct_out; 151 1.1 knakahar } 152 1.1 knakahar 153 1.1 knakahar ids = ii_handler->iih_intrids; 154 1.1 knakahar for (i = 0; i < nids; i++) { 155 1.1 knakahar error = interrupt_distribute_handler(ids[i], cpuset, NULL); 156 1.1 knakahar if (error) 157 1.1 knakahar break; 158 1.1 knakahar } 159 1.1 knakahar 160 1.1 knakahar destruct_out: 161 1.1 knakahar interrupt_destruct_intrids(ii_handler); 162 1.1 knakahar out: 163 1.1 knakahar kcpuset_destroy(cpuset); 164 1.1 knakahar return error; 165 1.1 knakahar } 166 1.1 knakahar 167 1.1 knakahar /* 168 1.1 knakahar * Return actual intrio_list_line size. 169 1.1 knakahar * intrio_list_line size is variable by ncpu. 170 1.1 knakahar */ 171 1.1 knakahar static size_t 172 1.1 knakahar interrupt_intrio_list_line_size(void) 173 1.1 knakahar { 174 1.1 knakahar 175 1.1 knakahar return sizeof(struct intrio_list_line) + 176 1.1 knakahar sizeof(struct intrio_list_line_cpu) * (ncpu - 1); 177 1.1 knakahar } 178 1.1 knakahar 179 1.1 knakahar /* 180 1.1 knakahar * Return the size of interrupts list data on success. 181 1.1 knakahar * Reterun 0 on failed. 182 1.1 knakahar */ 183 1.4 christos static int 184 1.4 christos interrupt_intrio_list_size(size_t *ilsize) 185 1.1 knakahar { 186 1.1 knakahar struct intrids_handler *ii_handler; 187 1.1 knakahar 188 1.4 christos *ilsize = 0; 189 1.1 knakahar 190 1.1 knakahar /* buffer header */ 191 1.4 christos *ilsize += sizeof(struct intrio_list); 192 1.1 knakahar 193 1.1 knakahar /* il_line body */ 194 1.1 knakahar ii_handler = interrupt_construct_intrids(kcpuset_running); 195 1.1 knakahar if (ii_handler == NULL) 196 1.4 christos return EOPNOTSUPP; 197 1.4 christos *ilsize += interrupt_intrio_list_line_size() * ii_handler->iih_nids; 198 1.1 knakahar 199 1.1 knakahar interrupt_destruct_intrids(ii_handler); 200 1.4 christos return 0; 201 1.1 knakahar } 202 1.1 knakahar 203 1.1 knakahar /* 204 1.1 knakahar * Set intrctl list data to "il", and return list structure bytes. 205 1.5 andvar * If error occurred, return <0. 206 1.1 knakahar * If "data" == NULL, simply return list structure bytes. 207 1.1 knakahar */ 208 1.1 knakahar static int 209 1.4 christos interrupt_intrio_list(struct intrio_list *il, size_t ilsize) 210 1.1 knakahar { 211 1.1 knakahar struct intrio_list_line *illine; 212 1.1 knakahar kcpuset_t *assigned, *avail; 213 1.1 knakahar struct intrids_handler *ii_handler; 214 1.1 knakahar intrid_t *ids; 215 1.1 knakahar u_int cpu_idx; 216 1.4 christos int nids, intr_idx, error, line_size; 217 1.1 knakahar 218 1.1 knakahar illine = (struct intrio_list_line *) 219 1.4 christos ((char *)il + sizeof(struct intrio_list)); 220 1.1 knakahar il->il_lineoffset = (off_t)((uintptr_t)illine - (uintptr_t)il); 221 1.1 knakahar 222 1.1 knakahar kcpuset_create(&avail, true); 223 1.1 knakahar interrupt_get_available(avail); 224 1.1 knakahar kcpuset_create(&assigned, true); 225 1.1 knakahar 226 1.1 knakahar ii_handler = interrupt_construct_intrids(kcpuset_running); 227 1.1 knakahar if (ii_handler == NULL) { 228 1.1 knakahar DPRINTF(("%s: interrupt_construct_intrids() failed\n", 229 1.4 christos __func__)); 230 1.4 christos error = EOPNOTSUPP; 231 1.1 knakahar goto out; 232 1.1 knakahar } 233 1.1 knakahar 234 1.1 knakahar line_size = interrupt_intrio_list_line_size(); 235 1.4 christos /* ensure interrupts are not added after interrupt_intrio_list_size() */ 236 1.1 knakahar nids = ii_handler->iih_nids; 237 1.1 knakahar ids = ii_handler->iih_intrids; 238 1.1 knakahar if (ilsize < sizeof(struct intrio_list) + line_size * nids) { 239 1.1 knakahar DPRINTF(("%s: interrupts are added during execution.\n", 240 1.4 christos __func__)); 241 1.4 christos error = EAGAIN; 242 1.1 knakahar goto destruct_out; 243 1.1 knakahar } 244 1.1 knakahar 245 1.1 knakahar for (intr_idx = 0; intr_idx < nids; intr_idx++) { 246 1.1 knakahar char devname[INTRDEVNAMEBUF]; 247 1.1 knakahar 248 1.1 knakahar strncpy(illine->ill_intrid, ids[intr_idx], INTRIDBUF); 249 1.1 knakahar interrupt_get_devname(ids[intr_idx], devname, sizeof(devname)); 250 1.1 knakahar strncpy(illine->ill_xname, devname, INTRDEVNAMEBUF); 251 1.1 knakahar 252 1.1 knakahar interrupt_get_assigned(ids[intr_idx], assigned); 253 1.1 knakahar for (cpu_idx = 0; cpu_idx < ncpu; cpu_idx++) { 254 1.1 knakahar struct intrio_list_line_cpu *illcpu = 255 1.4 christos &illine->ill_cpu[cpu_idx]; 256 1.1 knakahar 257 1.1 knakahar illcpu->illc_assigned = 258 1.4 christos kcpuset_isset(assigned, cpu_idx); 259 1.1 knakahar illcpu->illc_count = 260 1.4 christos interrupt_get_count(ids[intr_idx], cpu_idx); 261 1.1 knakahar } 262 1.1 knakahar 263 1.1 knakahar illine = (struct intrio_list_line *) 264 1.4 christos ((char *)illine + line_size); 265 1.1 knakahar } 266 1.1 knakahar 267 1.4 christos error = 0; 268 1.1 knakahar il->il_version = INTRIO_LIST_VERSION; 269 1.1 knakahar il->il_ncpus = ncpu; 270 1.1 knakahar il->il_nintrs = nids; 271 1.1 knakahar il->il_linesize = line_size; 272 1.1 knakahar il->il_bufsize = ilsize; 273 1.1 knakahar 274 1.1 knakahar destruct_out: 275 1.1 knakahar interrupt_destruct_intrids(ii_handler); 276 1.1 knakahar out: 277 1.1 knakahar kcpuset_destroy(assigned); 278 1.1 knakahar kcpuset_destroy(avail); 279 1.1 knakahar 280 1.4 christos return error; 281 1.1 knakahar } 282 1.1 knakahar 283 1.1 knakahar /* 284 1.1 knakahar * "intrctl list" entry 285 1.1 knakahar */ 286 1.1 knakahar static int 287 1.1 knakahar interrupt_intrio_list_sysctl(SYSCTLFN_ARGS) 288 1.1 knakahar { 289 1.4 christos int error; 290 1.1 knakahar void *buf; 291 1.4 christos size_t ilsize; 292 1.1 knakahar 293 1.1 knakahar if (oldlenp == NULL) 294 1.1 knakahar return EINVAL; 295 1.1 knakahar 296 1.4 christos if ((error = interrupt_intrio_list_size(&ilsize)) != 0) 297 1.4 christos return error; 298 1.4 christos 299 1.1 knakahar /* 300 1.1 knakahar * If oldp == NULL, the sysctl(8) caller process want to get the size of 301 1.1 knakahar * intrctl list data only. 302 1.1 knakahar */ 303 1.1 knakahar if (oldp == NULL) { 304 1.4 christos *oldlenp = ilsize; 305 1.1 knakahar return 0; 306 1.1 knakahar } 307 1.1 knakahar 308 1.1 knakahar /* 309 1.4 christos * If oldp != NULL, the sysctl(8) caller process want to get both the 310 1.4 christos * size and the contents of intrctl list data. 311 1.1 knakahar */ 312 1.4 christos if (*oldlenp < ilsize) 313 1.1 knakahar return ENOMEM; 314 1.1 knakahar 315 1.4 christos buf = kmem_zalloc(ilsize, KM_SLEEP); 316 1.4 christos if ((error = interrupt_intrio_list(buf, ilsize)) != 0) 317 1.1 knakahar goto out; 318 1.1 knakahar 319 1.4 christos error = copyout(buf, oldp, ilsize); 320 1.1 knakahar out: 321 1.4 christos kmem_free(buf, ilsize); 322 1.1 knakahar return error; 323 1.1 knakahar } 324 1.1 knakahar 325 1.1 knakahar /* 326 1.1 knakahar * "intrctl affinity" entry 327 1.1 knakahar */ 328 1.1 knakahar static int 329 1.1 knakahar interrupt_set_affinity_sysctl(SYSCTLFN_ARGS) 330 1.1 knakahar { 331 1.1 knakahar struct sysctlnode node; 332 1.1 knakahar struct intrio_set *iset; 333 1.1 knakahar cpuset_t *ucpuset; 334 1.1 knakahar kcpuset_t *kcpuset; 335 1.1 knakahar int error; 336 1.1 knakahar 337 1.1 knakahar error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_INTR, 338 1.1 knakahar KAUTH_REQ_SYSTEM_INTR_AFFINITY, NULL, NULL, NULL); 339 1.1 knakahar if (error) 340 1.1 knakahar return EPERM; 341 1.1 knakahar 342 1.1 knakahar node = *rnode; 343 1.1 knakahar iset = (struct intrio_set *)node.sysctl_data; 344 1.1 knakahar 345 1.1 knakahar error = sysctl_lookup(SYSCTLFN_CALL(&node)); 346 1.1 knakahar if (error != 0 || newp == NULL) 347 1.1 knakahar return error; 348 1.1 knakahar 349 1.1 knakahar ucpuset = iset->cpuset; 350 1.1 knakahar kcpuset_create(&kcpuset, true); 351 1.1 knakahar error = kcpuset_copyin(ucpuset, kcpuset, iset->cpuset_size); 352 1.1 knakahar if (error) 353 1.1 knakahar goto out; 354 1.1 knakahar if (kcpuset_iszero(kcpuset)) { 355 1.1 knakahar error = EINVAL; 356 1.1 knakahar goto out; 357 1.1 knakahar } 358 1.1 knakahar 359 1.1 knakahar error = interrupt_distribute_handler(iset->intrid, kcpuset, NULL); 360 1.1 knakahar 361 1.1 knakahar out: 362 1.1 knakahar kcpuset_destroy(kcpuset); 363 1.1 knakahar return error; 364 1.1 knakahar } 365 1.1 knakahar 366 1.1 knakahar /* 367 1.1 knakahar * "intrctl intr" entry 368 1.1 knakahar */ 369 1.1 knakahar static int 370 1.1 knakahar interrupt_intr_sysctl(SYSCTLFN_ARGS) 371 1.1 knakahar { 372 1.1 knakahar struct sysctlnode node; 373 1.1 knakahar struct intrio_set *iset; 374 1.1 knakahar cpuset_t *ucpuset; 375 1.1 knakahar kcpuset_t *kcpuset; 376 1.1 knakahar int error; 377 1.1 knakahar u_int cpu_idx; 378 1.1 knakahar 379 1.1 knakahar error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CPU, 380 1.1 knakahar KAUTH_REQ_SYSTEM_CPU_SETSTATE, NULL, NULL, NULL); 381 1.1 knakahar if (error) 382 1.1 knakahar return EPERM; 383 1.1 knakahar 384 1.1 knakahar node = *rnode; 385 1.1 knakahar iset = (struct intrio_set *)node.sysctl_data; 386 1.1 knakahar 387 1.1 knakahar error = sysctl_lookup(SYSCTLFN_CALL(&node)); 388 1.1 knakahar if (error != 0 || newp == NULL) 389 1.1 knakahar return error; 390 1.1 knakahar 391 1.1 knakahar ucpuset = iset->cpuset; 392 1.1 knakahar kcpuset_create(&kcpuset, true); 393 1.1 knakahar error = kcpuset_copyin(ucpuset, kcpuset, iset->cpuset_size); 394 1.1 knakahar if (error) 395 1.1 knakahar goto out; 396 1.1 knakahar if (kcpuset_iszero(kcpuset)) { 397 1.1 knakahar error = EINVAL; 398 1.1 knakahar goto out; 399 1.1 knakahar } 400 1.1 knakahar 401 1.1 knakahar cpu_idx = kcpuset_ffs(kcpuset) - 1; /* support one CPU only */ 402 1.1 knakahar 403 1.1 knakahar mutex_enter(&cpu_lock); 404 1.1 knakahar error = interrupt_shield(cpu_idx, UNSET_NOINTR_SHIELD); 405 1.1 knakahar mutex_exit(&cpu_lock); 406 1.1 knakahar 407 1.1 knakahar out: 408 1.1 knakahar kcpuset_destroy(kcpuset); 409 1.1 knakahar return error; 410 1.1 knakahar } 411 1.1 knakahar 412 1.1 knakahar /* 413 1.1 knakahar * "intrctl nointr" entry 414 1.1 knakahar */ 415 1.1 knakahar static int 416 1.1 knakahar interrupt_nointr_sysctl(SYSCTLFN_ARGS) 417 1.1 knakahar { 418 1.1 knakahar struct sysctlnode node; 419 1.1 knakahar struct intrio_set *iset; 420 1.1 knakahar cpuset_t *ucpuset; 421 1.1 knakahar kcpuset_t *kcpuset; 422 1.1 knakahar int error; 423 1.1 knakahar u_int cpu_idx; 424 1.1 knakahar 425 1.1 knakahar error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CPU, 426 1.1 knakahar KAUTH_REQ_SYSTEM_CPU_SETSTATE, NULL, NULL, NULL); 427 1.1 knakahar if (error) 428 1.1 knakahar return EPERM; 429 1.1 knakahar 430 1.1 knakahar node = *rnode; 431 1.1 knakahar iset = (struct intrio_set *)node.sysctl_data; 432 1.1 knakahar 433 1.1 knakahar error = sysctl_lookup(SYSCTLFN_CALL(&node)); 434 1.1 knakahar if (error != 0 || newp == NULL) 435 1.1 knakahar return error; 436 1.1 knakahar 437 1.1 knakahar ucpuset = iset->cpuset; 438 1.1 knakahar kcpuset_create(&kcpuset, true); 439 1.1 knakahar error = kcpuset_copyin(ucpuset, kcpuset, iset->cpuset_size); 440 1.1 knakahar if (error) 441 1.1 knakahar goto out; 442 1.1 knakahar if (kcpuset_iszero(kcpuset)) { 443 1.1 knakahar error = EINVAL; 444 1.1 knakahar goto out; 445 1.1 knakahar } 446 1.1 knakahar 447 1.1 knakahar cpu_idx = kcpuset_ffs(kcpuset) - 1; /* support one CPU only */ 448 1.1 knakahar 449 1.1 knakahar mutex_enter(&cpu_lock); 450 1.1 knakahar error = interrupt_shield(cpu_idx, SET_NOINTR_SHIELD); 451 1.1 knakahar mutex_exit(&cpu_lock); 452 1.1 knakahar if (error) 453 1.1 knakahar goto out; 454 1.1 knakahar 455 1.1 knakahar error = interrupt_avert_intr(cpu_idx); 456 1.1 knakahar 457 1.1 knakahar out: 458 1.1 knakahar kcpuset_destroy(kcpuset); 459 1.1 knakahar return error; 460 1.1 knakahar } 461 1.1 knakahar 462 1.1 knakahar SYSCTL_SETUP(sysctl_interrupt_setup, "sysctl interrupt setup") 463 1.1 knakahar { 464 1.1 knakahar const struct sysctlnode *node = NULL; 465 1.1 knakahar 466 1.1 knakahar sysctl_createv(clog, 0, NULL, &node, 467 1.1 knakahar CTLFLAG_PERMANENT, CTLTYPE_NODE, 468 1.1 knakahar "intr", SYSCTL_DESCR("Interrupt options"), 469 1.1 knakahar NULL, 0, NULL, 0, 470 1.1 knakahar CTL_KERN, CTL_CREATE, CTL_EOL); 471 1.1 knakahar 472 1.1 knakahar sysctl_createv(clog, 0, &node, NULL, 473 1.1 knakahar CTLFLAG_PERMANENT, CTLTYPE_STRUCT, 474 1.1 knakahar "list", SYSCTL_DESCR("intrctl list"), 475 1.1 knakahar interrupt_intrio_list_sysctl, 0, NULL, 476 1.1 knakahar 0, CTL_CREATE, CTL_EOL); 477 1.1 knakahar 478 1.1 knakahar sysctl_createv(clog, 0, &node, NULL, 479 1.1 knakahar CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRUCT, 480 1.1 knakahar "affinity", SYSCTL_DESCR("set affinity"), 481 1.1 knakahar interrupt_set_affinity_sysctl, 0, &kintrio_set, 482 1.1 knakahar sizeof(kintrio_set), CTL_CREATE, CTL_EOL); 483 1.1 knakahar 484 1.1 knakahar sysctl_createv(clog, 0, &node, NULL, 485 1.1 knakahar CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRUCT, 486 1.1 knakahar "intr", SYSCTL_DESCR("set intr"), 487 1.1 knakahar interrupt_intr_sysctl, 0, &kintrio_set, 488 1.1 knakahar sizeof(kintrio_set), CTL_CREATE, CTL_EOL); 489 1.1 knakahar 490 1.1 knakahar sysctl_createv(clog, 0, &node, NULL, 491 1.1 knakahar CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRUCT, 492 1.1 knakahar "nointr", SYSCTL_DESCR("set nointr"), 493 1.1 knakahar interrupt_nointr_sysctl, 0, &kintrio_set, 494 1.1 knakahar sizeof(kintrio_set), CTL_CREATE, CTL_EOL); 495 1.1 knakahar } 496