1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #include <arch_features.h>
7 #include <assert.h>
8 #include <atomics.h>
9 #include <sizes.h>
10 #include <spinlock.h>
11 #include <vmid.h>
12 
13 #define VMID8_COUNT		(1U << 8)
14 #define VMID16_COUNT		(1U << 16)
15 #define MAX_VMID_COUNT		VMID16_COUNT
16 #define VMID_ARRAY_LONG_SIZE	(MAX_VMID_COUNT / BITS_PER_UL)
17 
18 /*
19  * The bitmap for the reserved/used VMID values.
20  */
21 static unsigned long vmids[VMID_ARRAY_LONG_SIZE];
22 
23 /*
24  * Marks the VMID value to be in use. It returns:
25  * - True, on success
26  * - False, if the vmid is out of range,
27  *   or if it was already reserved (in use).
28  */
vmid_reserve(unsigned int vmid)29 bool vmid_reserve(unsigned int vmid)
30 {
31 	unsigned int offset;
32 	unsigned int vmid_count;
33 
34 	/* Number of supported VMID values */
35 	vmid_count = is_feat_vmid16_present() ?	VMID16_COUNT : VMID8_COUNT;
36 	/*
37 	 * The input from NS as part of RMI_REALM_CREATE is 'short int' type,
38 	 * so this check will not fail on systems with FEAT_VMID16 implemented.
39 	 */
40 	if (vmid >= vmid_count) {
41 		return false;
42 	}
43 
44 	offset = vmid / BITS_PER_UL;
45 
46 	return !atomic_bit_set_acquire_release_64(&vmids[offset], vmid);
47 }
48 
49 /*
50  * Marks the VMID value to be not in use.
51  */
vmid_free(unsigned int vmid)52 void vmid_free(unsigned int vmid)
53 {
54 	unsigned int offset;
55 	unsigned int __unused vmid_count;
56 
57 	/* Number of supported VMID values */
58 	vmid_count = is_feat_vmid16_present() ? VMID16_COUNT : VMID8_COUNT;
59 
60 	/* Check the number of supported VMID values */
61 	assert(vmid < vmid_count);
62 	offset = vmid / BITS_PER_UL;
63 
64 	atomic_bit_clear_release_64(&vmids[offset], vmid);
65 }
66