1#include <drivers/iommu/vt_d.h>
2#include <global.h>
3#include <math/div.h>
4
5static inline int bit_is_used(const uint8_t *bitmap, size_t bit_index) {
6 return (bitmap[bit_index / 8] >> (bit_index % 8)) & 1u;
7}
8
9static inline void bit_set_used(uint8_t *bitmap, size_t bit_index) {
10 bitmap[bit_index / 8] |= (uint8_t) (1u << (bit_index % 8));
11}
12
13static inline void bit_clear_used(uint8_t *bitmap, size_t bit_index) {
14 bitmap[bit_index / 8] &= (uint8_t) ~(1u << (bit_index % 8));
15}
16
17ssize_t bitmap_alloc_first_free(uint8_t *bitmap, size_t total_bits) {
18 if (!bitmap)
19 return -1;
20
21 for (size_t i = 0; i < total_bits; ++i) {
22 if (!bit_is_used(bitmap, bit_index: i)) {
23 bit_set_used(bitmap, bit_index: i);
24 return (ssize_t) i;
25 }
26 }
27
28 return -1;
29}
30
31/* TODO: Move this out */
32ssize_t bitmap_free(uint8_t *bitmap, size_t total_bits, size_t bit_index) {
33 if (!bitmap)
34 return -1;
35
36 if (bit_index >= total_bits)
37 return -1;
38
39 bit_clear_used(bitmap, bit_index);
40 return 0;
41}
42
43ssize_t vtd_domain_alloc(struct vtd_unit *unit) {
44 enum irql irql = spin_lock(lock: &unit->domain_bitmap_lock);
45
46 size_t ret =
47 bitmap_alloc_first_free(bitmap: unit->domain_bitmap, total_bits: unit->domain_count);
48
49 spin_unlock(lock: &unit->domain_bitmap_lock, old: irql);
50
51 return ret;
52}
53
54ssize_t vtd_domain_free(struct vtd_unit *unit, size_t domain) {
55 enum irql irql = spin_lock(lock: &unit->domain_bitmap_lock);
56
57 size_t ret = bitmap_free(bitmap: unit->domain_bitmap, total_bits: unit->domain_count, bit_index: domain);
58
59 spin_unlock(lock: &unit->domain_bitmap_lock, old: irql);
60
61 return ret;
62}
63
64bool vtd_domain_init(struct vtd_unit *unit) {
65 spinlock_init(lock: &unit->domain_bitmap_lock);
66 return (unit->domain_bitmap =
67 kmalloc(DIV_ROUND_UP(unit->domain_count, 8), ALLOC_FLAGS_ZERO));
68}
69