Home | History | Annotate | Line # | Download | only in kern
      1  1.20        ad /*	$NetBSD: subr_kcpuset.c,v 1.20 2023/09/23 18:21:11 ad Exp $	*/
      2   1.1     rmind 
      3   1.1     rmind /*-
      4  1.20        ad  * Copyright (c) 2011, 2023 The NetBSD Foundation, Inc.
      5   1.1     rmind  * All rights reserved.
      6   1.1     rmind  *
      7   1.1     rmind  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1     rmind  * by Mindaugas Rasiukevicius.
      9   1.1     rmind  *
     10   1.1     rmind  * Redistribution and use in source and binary forms, with or without
     11   1.1     rmind  * modification, are permitted provided that the following conditions
     12   1.1     rmind  * are met:
     13   1.1     rmind  * 1. Redistributions of source code must retain the above copyright
     14   1.1     rmind  *    notice, this list of conditions and the following disclaimer.
     15   1.1     rmind  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1     rmind  *    notice, this list of conditions and the following disclaimer in the
     17   1.1     rmind  *    documentation and/or other materials provided with the distribution.
     18   1.1     rmind  *
     19   1.1     rmind  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1     rmind  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1     rmind  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1     rmind  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1     rmind  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1     rmind  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1     rmind  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1     rmind  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1     rmind  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1     rmind  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1     rmind  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1     rmind  */
     31   1.1     rmind 
     32   1.1     rmind /*
     33   1.1     rmind  * Kernel CPU set implementation.
     34   1.1     rmind  *
     35   1.1     rmind  * Interface can be used by kernel subsystems as a unified dynamic CPU
     36   1.1     rmind  * bitset implementation handling many CPUs.  Facility also supports early
     37   1.1     rmind  * use by MD code on boot, as it fixups bitsets on further boot.
     38   1.1     rmind  *
     39   1.1     rmind  * TODO:
     40   1.1     rmind  * - Handle "reverse" bitset on fixup/grow.
     41   1.1     rmind  */
     42   1.1     rmind 
     43   1.1     rmind #include <sys/cdefs.h>
     44  1.20        ad __KERNEL_RCSID(0, "$NetBSD: subr_kcpuset.c,v 1.20 2023/09/23 18:21:11 ad Exp $");
     45   1.1     rmind 
     46   1.1     rmind #include <sys/param.h>
     47   1.1     rmind #include <sys/types.h>
     48   1.1     rmind 
     49   1.1     rmind #include <sys/atomic.h>
     50  1.18    martin #include <sys/intr.h>
     51   1.1     rmind #include <sys/sched.h>
     52   1.1     rmind #include <sys/kcpuset.h>
     53  1.20        ad #include <sys/kmem.h>
     54   1.1     rmind 
     55   1.1     rmind /* Number of CPUs to support. */
     56   1.1     rmind #define	KC_MAXCPUS		roundup2(MAXCPUS, 32)
     57   1.1     rmind 
     58   1.1     rmind /*
     59   1.1     rmind  * Structure of dynamic CPU set in the kernel.
     60   1.1     rmind  */
     61   1.1     rmind struct kcpuset {
     62   1.1     rmind 	uint32_t		bits[0];
     63   1.1     rmind };
     64   1.1     rmind 
     65   1.1     rmind typedef struct kcpuset_impl {
     66   1.1     rmind 	/* Reference count. */
     67   1.1     rmind 	u_int			kc_refcnt;
     68  1.16     skrll 	/* Next to free, if non-NULL (used when multiple references). */
     69   1.1     rmind 	struct kcpuset *	kc_next;
     70   1.1     rmind 	/* Actual variable-sized field of bits. */
     71   1.1     rmind 	struct kcpuset		kc_field;
     72   1.1     rmind } kcpuset_impl_t;
     73   1.1     rmind 
     74   1.1     rmind #define	KC_BITS_OFF		(offsetof(struct kcpuset_impl, kc_field))
     75   1.1     rmind #define	KC_GETSTRUCT(b)		((kcpuset_impl_t *)((char *)(b) - KC_BITS_OFF))
     76   1.9      matt #define	KC_GETCSTRUCT(b)	((const kcpuset_impl_t *)((const char *)(b) - KC_BITS_OFF))
     77   1.1     rmind 
     78   1.1     rmind /* Sizes of a single bitset. */
     79   1.1     rmind #define	KC_SHIFT		5
     80   1.1     rmind #define	KC_MASK			31
     81   1.1     rmind 
     82   1.1     rmind /* An array of noted early kcpuset creations and data. */
     83   1.1     rmind #define	KC_SAVE_NITEMS		8
     84   1.1     rmind 
     85   1.1     rmind /* Structures for early boot mechanism (must be statically initialised). */
     86   1.1     rmind static kcpuset_t **		kc_noted_early[KC_SAVE_NITEMS];
     87   1.1     rmind static uint32_t			kc_bits_early[KC_SAVE_NITEMS];
     88   1.1     rmind static int			kc_last_idx = 0;
     89   1.1     rmind static bool			kc_initialised = false;
     90   1.1     rmind 
     91   1.1     rmind #define	KC_BITSIZE_EARLY	sizeof(kc_bits_early[0])
     92   1.4     rmind #define	KC_NFIELDS_EARLY	1
     93   1.1     rmind 
     94   1.1     rmind /*
     95   1.1     rmind  * The size of whole bitset fields and amount of fields.
     96   1.1     rmind  * The whole size must statically initialise for early case.
     97   1.1     rmind  */
     98   1.1     rmind static size_t			kc_bitsize __read_mostly = KC_BITSIZE_EARLY;
     99   1.1     rmind static size_t			kc_nfields __read_mostly = KC_NFIELDS_EARLY;
    100  1.20        ad static size_t			kc_memsize __read_mostly;
    101   1.1     rmind 
    102   1.3     rmind static kcpuset_t *		kcpuset_create_raw(bool);
    103   1.1     rmind 
    104   1.1     rmind /*
    105   1.1     rmind  * kcpuset_sysinit: initialize the subsystem, transfer early boot cases
    106   1.1     rmind  * to dynamically allocated sets.
    107   1.1     rmind  */
    108   1.1     rmind void
    109   1.1     rmind kcpuset_sysinit(void)
    110   1.1     rmind {
    111   1.1     rmind 	kcpuset_t *kc_dynamic[KC_SAVE_NITEMS], *kcp;
    112   1.1     rmind 	int i, s;
    113   1.1     rmind 
    114   1.1     rmind 	/* Set a kcpuset_t sizes. */
    115   1.1     rmind 	kc_nfields = (KC_MAXCPUS >> KC_SHIFT);
    116   1.1     rmind 	kc_bitsize = sizeof(uint32_t) * kc_nfields;
    117  1.20        ad 	kc_memsize = sizeof(kcpuset_impl_t) + kc_bitsize;
    118  1.15  riastrad 	KASSERT(kc_nfields != 0);
    119  1.15  riastrad 	KASSERT(kc_bitsize != 0);
    120   1.1     rmind 
    121   1.1     rmind 	/* First, pre-allocate kcpuset entries. */
    122   1.1     rmind 	for (i = 0; i < kc_last_idx; i++) {
    123   1.3     rmind 		kcp = kcpuset_create_raw(true);
    124   1.1     rmind 		kc_dynamic[i] = kcp;
    125   1.1     rmind 	}
    126   1.1     rmind 
    127   1.1     rmind 	/*
    128   1.1     rmind 	 * Prepare to convert all early noted kcpuset uses to dynamic sets.
    129   1.1     rmind 	 * All processors, except the one we are currently running (primary),
    130   1.1     rmind 	 * must not be spinned yet.  Since MD facilities can use kcpuset,
    131   1.1     rmind 	 * raise the IPL to high.
    132   1.1     rmind 	 */
    133   1.1     rmind 	KASSERT(mp_online == false);
    134   1.1     rmind 
    135   1.1     rmind 	s = splhigh();
    136   1.1     rmind 	for (i = 0; i < kc_last_idx; i++) {
    137   1.1     rmind 		/*
    138   1.1     rmind 		 * Transfer the bits from early static storage to the kcpuset.
    139   1.1     rmind 		 */
    140   1.1     rmind 		KASSERT(kc_bitsize >= KC_BITSIZE_EARLY);
    141   1.1     rmind 		memcpy(kc_dynamic[i], &kc_bits_early[i], KC_BITSIZE_EARLY);
    142   1.1     rmind 
    143   1.1     rmind 		/*
    144   1.1     rmind 		 * Store the new pointer, pointing to the allocated kcpuset.
    145   1.1     rmind 		 * Note: we are not in an interrupt context and it is the only
    146   1.1     rmind 		 * CPU running - thus store is safe (e.g. no need for pointer
    147   1.1     rmind 		 * variable to be volatile).
    148   1.1     rmind 		 */
    149   1.1     rmind 		*kc_noted_early[i] = kc_dynamic[i];
    150   1.1     rmind 	}
    151   1.1     rmind 	kc_initialised = true;
    152   1.1     rmind 	kc_last_idx = 0;
    153   1.1     rmind 	splx(s);
    154   1.1     rmind }
    155   1.1     rmind 
    156   1.1     rmind /*
    157   1.1     rmind  * kcpuset_early_ptr: note an early boot use by saving the pointer and
    158   1.1     rmind  * returning a pointer to a static, temporary bit field.
    159   1.1     rmind  */
    160   1.1     rmind static kcpuset_t *
    161   1.1     rmind kcpuset_early_ptr(kcpuset_t **kcptr)
    162   1.1     rmind {
    163   1.1     rmind 	kcpuset_t *kcp;
    164   1.1     rmind 	int s;
    165   1.1     rmind 
    166   1.1     rmind 	s = splhigh();
    167   1.1     rmind 	if (kc_last_idx < KC_SAVE_NITEMS) {
    168   1.1     rmind 		/*
    169   1.1     rmind 		 * Save the pointer, return pointer to static early field.
    170   1.1     rmind 		 * Need to zero it out.
    171   1.1     rmind 		 */
    172   1.5     rmind 		kc_noted_early[kc_last_idx] = kcptr;
    173   1.1     rmind 		kcp = (kcpuset_t *)&kc_bits_early[kc_last_idx];
    174   1.5     rmind 		kc_last_idx++;
    175   1.1     rmind 		memset(kcp, 0, KC_BITSIZE_EARLY);
    176   1.1     rmind 		KASSERT(kc_bitsize == KC_BITSIZE_EARLY);
    177   1.1     rmind 	} else {
    178   1.1     rmind 		panic("kcpuset(9): all early-use entries exhausted; "
    179   1.1     rmind 		    "increase KC_SAVE_NITEMS\n");
    180   1.1     rmind 	}
    181   1.1     rmind 	splx(s);
    182   1.1     rmind 
    183   1.1     rmind 	return kcp;
    184   1.1     rmind }
    185   1.1     rmind 
    186   1.1     rmind /*
    187   1.1     rmind  * Routines to create or destroy the CPU set.
    188   1.1     rmind  * Early boot case is handled.
    189   1.1     rmind  */
    190   1.1     rmind 
    191   1.1     rmind static kcpuset_t *
    192   1.3     rmind kcpuset_create_raw(bool zero)
    193   1.1     rmind {
    194   1.1     rmind 	kcpuset_impl_t *kc;
    195   1.1     rmind 
    196  1.20        ad 	kc = kmem_alloc(kc_memsize, KM_SLEEP);
    197   1.1     rmind 	kc->kc_refcnt = 1;
    198   1.1     rmind 	kc->kc_next = NULL;
    199   1.1     rmind 
    200   1.3     rmind 	if (zero) {
    201   1.3     rmind 		memset(&kc->kc_field, 0, kc_bitsize);
    202   1.3     rmind 	}
    203   1.3     rmind 
    204   1.1     rmind 	/* Note: return pointer to the actual field of bits. */
    205   1.1     rmind 	KASSERT((uint8_t *)kc + KC_BITS_OFF == (uint8_t *)&kc->kc_field);
    206   1.1     rmind 	return &kc->kc_field;
    207   1.1     rmind }
    208   1.1     rmind 
    209   1.1     rmind void
    210   1.3     rmind kcpuset_create(kcpuset_t **retkcp, bool zero)
    211   1.1     rmind {
    212   1.1     rmind 	if (__predict_false(!kc_initialised)) {
    213   1.1     rmind 		/* Early boot use - special case. */
    214   1.1     rmind 		*retkcp = kcpuset_early_ptr(retkcp);
    215   1.1     rmind 		return;
    216   1.1     rmind 	}
    217   1.3     rmind 	*retkcp = kcpuset_create_raw(zero);
    218   1.1     rmind }
    219   1.1     rmind 
    220   1.1     rmind void
    221   1.9      matt kcpuset_clone(kcpuset_t **retkcp, const kcpuset_t *kcp)
    222   1.9      matt {
    223   1.9      matt 	kcpuset_create(retkcp, false);
    224   1.9      matt 	memcpy(*retkcp, kcp, kc_bitsize);
    225   1.9      matt }
    226   1.9      matt 
    227   1.9      matt void
    228   1.1     rmind kcpuset_destroy(kcpuset_t *kcp)
    229   1.1     rmind {
    230  1.20        ad 	const size_t size = kc_memsize;
    231   1.2     rmind 	kcpuset_impl_t *kc;
    232   1.1     rmind 
    233   1.1     rmind 	KASSERT(kc_initialised);
    234   1.1     rmind 	KASSERT(kcp != NULL);
    235   1.1     rmind 
    236   1.1     rmind 	do {
    237   1.2     rmind 		kc = KC_GETSTRUCT(kcp);
    238   1.2     rmind 		kcp = kc->kc_next;
    239  1.20        ad 		kmem_free(kc, size);
    240   1.2     rmind 	} while (kcp);
    241   1.1     rmind }
    242   1.1     rmind 
    243   1.1     rmind /*
    244   1.4     rmind  * Routines to reference/unreference the CPU set.
    245   1.1     rmind  * Note: early boot case is not supported by these routines.
    246   1.1     rmind  */
    247   1.1     rmind 
    248   1.1     rmind void
    249   1.1     rmind kcpuset_use(kcpuset_t *kcp)
    250   1.1     rmind {
    251   1.1     rmind 	kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
    252   1.1     rmind 
    253   1.1     rmind 	KASSERT(kc_initialised);
    254   1.1     rmind 	atomic_inc_uint(&kc->kc_refcnt);
    255   1.1     rmind }
    256   1.1     rmind 
    257   1.1     rmind void
    258   1.1     rmind kcpuset_unuse(kcpuset_t *kcp, kcpuset_t **lst)
    259   1.1     rmind {
    260   1.1     rmind 	kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
    261   1.1     rmind 
    262   1.1     rmind 	KASSERT(kc_initialised);
    263   1.1     rmind 	KASSERT(kc->kc_refcnt > 0);
    264   1.1     rmind 
    265  1.14  riastrad 	membar_release();
    266   1.1     rmind 	if (atomic_dec_uint_nv(&kc->kc_refcnt) != 0) {
    267   1.1     rmind 		return;
    268   1.1     rmind 	}
    269  1.14  riastrad 	membar_acquire();
    270   1.1     rmind 	KASSERT(kc->kc_next == NULL);
    271   1.1     rmind 	if (lst == NULL) {
    272   1.1     rmind 		kcpuset_destroy(kcp);
    273   1.1     rmind 		return;
    274   1.1     rmind 	}
    275   1.1     rmind 	kc->kc_next = *lst;
    276   1.1     rmind 	*lst = kcp;
    277   1.1     rmind }
    278   1.1     rmind 
    279   1.1     rmind /*
    280   1.1     rmind  * Routines to transfer the CPU set from / to userspace.
    281   1.1     rmind  * Note: early boot case is not supported by these routines.
    282   1.1     rmind  */
    283   1.1     rmind 
    284   1.1     rmind int
    285   1.1     rmind kcpuset_copyin(const cpuset_t *ucp, kcpuset_t *kcp, size_t len)
    286   1.1     rmind {
    287  1.10    martin 	kcpuset_impl_t *kc __diagused = KC_GETSTRUCT(kcp);
    288   1.1     rmind 
    289   1.1     rmind 	KASSERT(kc_initialised);
    290   1.1     rmind 	KASSERT(kc->kc_refcnt > 0);
    291   1.1     rmind 	KASSERT(kc->kc_next == NULL);
    292   1.1     rmind 
    293   1.5     rmind 	if (len > kc_bitsize) { /* XXX */
    294   1.1     rmind 		return EINVAL;
    295   1.1     rmind 	}
    296   1.5     rmind 	return copyin(ucp, kcp, len);
    297   1.1     rmind }
    298   1.1     rmind 
    299   1.1     rmind int
    300   1.1     rmind kcpuset_copyout(kcpuset_t *kcp, cpuset_t *ucp, size_t len)
    301   1.1     rmind {
    302  1.10    martin 	kcpuset_impl_t *kc __diagused = KC_GETSTRUCT(kcp);
    303   1.1     rmind 
    304   1.1     rmind 	KASSERT(kc_initialised);
    305   1.1     rmind 	KASSERT(kc->kc_refcnt > 0);
    306   1.1     rmind 	KASSERT(kc->kc_next == NULL);
    307   1.1     rmind 
    308   1.5     rmind 	if (len > kc_bitsize) { /* XXX */
    309   1.1     rmind 		return EINVAL;
    310   1.1     rmind 	}
    311   1.5     rmind 	return copyout(kcp, ucp, len);
    312   1.1     rmind }
    313   1.1     rmind 
    314   1.6     rmind void
    315   1.8     rmind kcpuset_export_u32(const kcpuset_t *kcp, uint32_t *bitfield, size_t len)
    316   1.6     rmind {
    317   1.6     rmind 	size_t rlen = MIN(kc_bitsize, len);
    318   1.6     rmind 
    319   1.6     rmind 	KASSERT(kcp != NULL);
    320   1.6     rmind 	memcpy(bitfield, kcp->bits, rlen);
    321   1.6     rmind }
    322   1.6     rmind 
    323   1.1     rmind /*
    324   1.4     rmind  * Routines to change bit field - zero, fill, copy, set, unset, etc.
    325   1.1     rmind  */
    326   1.4     rmind 
    327   1.1     rmind void
    328   1.1     rmind kcpuset_zero(kcpuset_t *kcp)
    329   1.1     rmind {
    330   1.1     rmind 
    331   1.1     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
    332   1.1     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
    333   1.1     rmind 	memset(kcp, 0, kc_bitsize);
    334   1.1     rmind }
    335   1.1     rmind 
    336   1.1     rmind void
    337   1.1     rmind kcpuset_fill(kcpuset_t *kcp)
    338   1.1     rmind {
    339   1.1     rmind 
    340   1.1     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
    341   1.1     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
    342   1.1     rmind 	memset(kcp, ~0, kc_bitsize);
    343   1.1     rmind }
    344   1.1     rmind 
    345   1.1     rmind void
    346   1.9      matt kcpuset_copy(kcpuset_t *dkcp, const kcpuset_t *skcp)
    347   1.4     rmind {
    348   1.4     rmind 
    349   1.4     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(dkcp)->kc_refcnt > 0);
    350   1.4     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(dkcp)->kc_next == NULL);
    351   1.4     rmind 	memcpy(dkcp, skcp, kc_bitsize);
    352   1.4     rmind }
    353   1.4     rmind 
    354   1.4     rmind void
    355   1.1     rmind kcpuset_set(kcpuset_t *kcp, cpuid_t i)
    356   1.1     rmind {
    357   1.1     rmind 	const size_t j = i >> KC_SHIFT;
    358   1.1     rmind 
    359   1.1     rmind 	KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
    360   1.1     rmind 	KASSERT(j < kc_nfields);
    361   1.1     rmind 
    362  1.12   msaitoh 	kcp->bits[j] |= __BIT(i & KC_MASK);
    363   1.1     rmind }
    364   1.1     rmind 
    365   1.1     rmind void
    366   1.1     rmind kcpuset_clear(kcpuset_t *kcp, cpuid_t i)
    367   1.1     rmind {
    368   1.1     rmind 	const size_t j = i >> KC_SHIFT;
    369   1.1     rmind 
    370   1.9      matt 	KASSERT(!kc_initialised || KC_GETCSTRUCT(kcp)->kc_next == NULL);
    371   1.1     rmind 	KASSERT(j < kc_nfields);
    372   1.1     rmind 
    373  1.12   msaitoh 	kcp->bits[j] &= ~(__BIT(i & KC_MASK));
    374   1.1     rmind }
    375   1.1     rmind 
    376   1.4     rmind bool
    377   1.9      matt kcpuset_isset(const kcpuset_t *kcp, cpuid_t i)
    378   1.1     rmind {
    379   1.1     rmind 	const size_t j = i >> KC_SHIFT;
    380   1.1     rmind 
    381   1.1     rmind 	KASSERT(kcp != NULL);
    382   1.9      matt 	KASSERT(!kc_initialised || KC_GETCSTRUCT(kcp)->kc_refcnt > 0);
    383   1.9      matt 	KASSERT(!kc_initialised || KC_GETCSTRUCT(kcp)->kc_next == NULL);
    384   1.1     rmind 	KASSERT(j < kc_nfields);
    385   1.1     rmind 
    386  1.12   msaitoh 	return ((__BIT(i & KC_MASK)) & kcp->bits[j]) != 0;
    387   1.1     rmind }
    388   1.1     rmind 
    389   1.1     rmind bool
    390   1.9      matt kcpuset_isotherset(const kcpuset_t *kcp, cpuid_t i)
    391   1.4     rmind {
    392   1.4     rmind 	const size_t j2 = i >> KC_SHIFT;
    393  1.12   msaitoh 	const uint32_t mask = ~(__BIT(i & KC_MASK));
    394   1.4     rmind 
    395   1.4     rmind 	for (size_t j = 0; j < kc_nfields; j++) {
    396   1.4     rmind 		const uint32_t bits = kcp->bits[j];
    397   1.4     rmind 		if (bits && (j != j2 || (bits & mask) != 0)) {
    398   1.4     rmind 			return true;
    399   1.4     rmind 		}
    400   1.4     rmind 	}
    401   1.4     rmind 	return false;
    402   1.4     rmind }
    403   1.4     rmind 
    404   1.4     rmind bool
    405   1.9      matt kcpuset_iszero(const kcpuset_t *kcp)
    406   1.1     rmind {
    407   1.1     rmind 
    408   1.1     rmind 	for (size_t j = 0; j < kc_nfields; j++) {
    409   1.1     rmind 		if (kcp->bits[j] != 0) {
    410   1.1     rmind 			return false;
    411   1.1     rmind 		}
    412   1.1     rmind 	}
    413   1.1     rmind 	return true;
    414   1.1     rmind }
    415   1.1     rmind 
    416   1.1     rmind bool
    417   1.1     rmind kcpuset_match(const kcpuset_t *kcp1, const kcpuset_t *kcp2)
    418   1.1     rmind {
    419   1.1     rmind 
    420   1.1     rmind 	return memcmp(kcp1, kcp2, kc_bitsize) == 0;
    421   1.1     rmind }
    422   1.3     rmind 
    423   1.9      matt bool
    424   1.9      matt kcpuset_intersecting_p(const kcpuset_t *kcp1, const kcpuset_t *kcp2)
    425   1.9      matt {
    426   1.9      matt 
    427   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    428   1.9      matt 		if (kcp1->bits[j] & kcp2->bits[j])
    429   1.9      matt 			return true;
    430   1.9      matt 	}
    431   1.9      matt 	return false;
    432   1.9      matt }
    433   1.9      matt 
    434   1.9      matt cpuid_t
    435   1.9      matt kcpuset_ffs(const kcpuset_t *kcp)
    436   1.9      matt {
    437   1.9      matt 
    438   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    439   1.9      matt 		if (kcp->bits[j])
    440   1.9      matt 			return 32 * j + ffs(kcp->bits[j]);
    441   1.9      matt 	}
    442   1.9      matt 	return 0;
    443   1.9      matt }
    444   1.9      matt 
    445   1.9      matt cpuid_t
    446   1.9      matt kcpuset_ffs_intersecting(const kcpuset_t *kcp1, const kcpuset_t *kcp2)
    447   1.9      matt {
    448   1.9      matt 
    449   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    450   1.9      matt 		uint32_t bits = kcp1->bits[j] & kcp2->bits[j];
    451   1.9      matt 		if (bits)
    452   1.9      matt 			return 32 * j + ffs(bits);
    453   1.9      matt 	}
    454   1.9      matt 	return 0;
    455   1.9      matt }
    456   1.9      matt 
    457   1.3     rmind void
    458   1.9      matt kcpuset_merge(kcpuset_t *kcp1, const kcpuset_t *kcp2)
    459   1.3     rmind {
    460   1.3     rmind 
    461   1.3     rmind 	for (size_t j = 0; j < kc_nfields; j++) {
    462   1.3     rmind 		kcp1->bits[j] |= kcp2->bits[j];
    463   1.3     rmind 	}
    464   1.3     rmind }
    465   1.3     rmind 
    466   1.5     rmind void
    467   1.9      matt kcpuset_intersect(kcpuset_t *kcp1, const kcpuset_t *kcp2)
    468   1.5     rmind {
    469   1.5     rmind 
    470   1.5     rmind 	for (size_t j = 0; j < kc_nfields; j++) {
    471   1.5     rmind 		kcp1->bits[j] &= kcp2->bits[j];
    472   1.5     rmind 	}
    473   1.5     rmind }
    474   1.5     rmind 
    475   1.9      matt void
    476   1.9      matt kcpuset_remove(kcpuset_t *kcp1, const kcpuset_t *kcp2)
    477   1.9      matt {
    478   1.9      matt 
    479   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    480   1.9      matt 		kcp1->bits[j] &= ~kcp2->bits[j];
    481   1.9      matt 	}
    482   1.9      matt }
    483   1.9      matt 
    484   1.4     rmind int
    485  1.11     rmind kcpuset_countset(const kcpuset_t *kcp)
    486   1.4     rmind {
    487   1.4     rmind 	int count = 0;
    488   1.4     rmind 
    489   1.4     rmind 	for (size_t j = 0; j < kc_nfields; j++) {
    490   1.4     rmind 		count += popcount32(kcp->bits[j]);
    491   1.4     rmind 	}
    492   1.4     rmind 	return count;
    493   1.4     rmind }
    494   1.4     rmind 
    495   1.3     rmind /*
    496   1.3     rmind  * Routines to set/clear the flags atomically.
    497   1.3     rmind  */
    498   1.3     rmind 
    499   1.3     rmind void
    500   1.3     rmind kcpuset_atomic_set(kcpuset_t *kcp, cpuid_t i)
    501   1.3     rmind {
    502   1.3     rmind 	const size_t j = i >> KC_SHIFT;
    503   1.3     rmind 
    504   1.3     rmind 	KASSERT(j < kc_nfields);
    505  1.12   msaitoh 	atomic_or_32(&kcp->bits[j], __BIT(i & KC_MASK));
    506   1.3     rmind }
    507   1.3     rmind 
    508   1.3     rmind void
    509   1.3     rmind kcpuset_atomic_clear(kcpuset_t *kcp, cpuid_t i)
    510   1.3     rmind {
    511   1.3     rmind 	const size_t j = i >> KC_SHIFT;
    512   1.3     rmind 
    513   1.3     rmind 	KASSERT(j < kc_nfields);
    514  1.12   msaitoh 	atomic_and_32(&kcp->bits[j], ~(__BIT(i & KC_MASK)));
    515   1.3     rmind }
    516   1.9      matt 
    517   1.9      matt void
    518   1.9      matt kcpuset_atomicly_intersect(kcpuset_t *kcp1, const kcpuset_t *kcp2)
    519   1.9      matt {
    520   1.9      matt 
    521   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    522   1.9      matt 		if (kcp2->bits[j])
    523   1.9      matt 			atomic_and_32(&kcp1->bits[j], kcp2->bits[j]);
    524   1.9      matt 	}
    525   1.9      matt }
    526   1.9      matt 
    527   1.9      matt void
    528   1.9      matt kcpuset_atomicly_merge(kcpuset_t *kcp1, const kcpuset_t *kcp2)
    529   1.9      matt {
    530   1.9      matt 
    531   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    532   1.9      matt 		if (kcp2->bits[j])
    533   1.9      matt 			atomic_or_32(&kcp1->bits[j], kcp2->bits[j]);
    534   1.9      matt 	}
    535   1.9      matt }
    536   1.9      matt 
    537   1.9      matt void
    538   1.9      matt kcpuset_atomicly_remove(kcpuset_t *kcp1, const kcpuset_t *kcp2)
    539   1.9      matt {
    540   1.9      matt 
    541   1.9      matt 	for (size_t j = 0; j < kc_nfields; j++) {
    542   1.9      matt 		if (kcp2->bits[j])
    543   1.9      matt 			atomic_and_32(&kcp1->bits[j], ~kcp2->bits[j]);
    544   1.9      matt 	}
    545   1.9      matt }
    546