File size: 13,639 Bytes
96dc096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/**

 * ring_buffer.c

 * ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช ุงู„ุญู„ู‚ูŠ - ู†ู‚ู„ ุตูุฑ ู†ุณุฎุฉ

 * Ring Buffer - Zero-Copy Intent Transport

 *

 * Lock-free SPSC (Single Producer Single Consumer) ring buffer

 * for passing intent payloads between user space and kernel.

 *

 * Author: Ahmad Ali Parr

 * License: Sovereign Source

 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <asm/barrier.h>

#include "intent_schema.h"
#include "ring_buffer.h"

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Ring Buffer State | ุญุงู„ุฉ ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

struct IntentRing {
    struct RingBufferEntry *entries;  /* Ring buffer entries */
    size_t capacity;                  /* Total slots (power of 2) */
    atomic_t head;                    /* Producer write position */
    atomic_t tail;                    /* Consumer read position */
    atomic_t active_count;            /* Number of in-flight intents */
    void *mmap_base;                  /* mmap'd region for userspace */
    size_t mmap_size;                 /* Size of mapped region */
};

/* Default ring capacity (must be power of 2) */
#define DEFAULT_RING_CAPACITY   256

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Ring Buffer Lifecycle | ุฏูˆุฑุฉ ุญูŠุงุฉ ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

/**

 * ring_buffer_create - Allocate and initialize a new intent ring

 * @capacity: Number of ring slots (must be power of 2)

 *

 * Returns: Pointer to IntentRing on success, NULL on failure

 */
struct IntentRing *ring_buffer_create(size_t capacity)
{
    struct IntentRing *ring;
    size_t alloc_size;

    /* Validate capacity is power of 2 */
    if (capacity == 0 || (capacity & (capacity - 1)) != 0) {
        pr_err("ASOS Ring: capacity must be power of 2, got %zu\n", capacity);
        return NULL;
    }

    /* Allocate ring structure */
    ring = kzalloc(sizeof(*ring), GFP_KERNEL);
    if (!ring) {
        pr_err("ASOS Ring: failed to allocate ring structure\n");
        return NULL;
    }

    /* Allocate ring buffer entries */
    alloc_size = capacity * sizeof(struct RingBufferEntry);
    ring->entries = vmalloc_user(alloc_size);
    if (!ring->entries) {
        pr_err("ASOS Ring: failed to allocate %zu bytes for entries\n", alloc_size);
        kfree(ring);
        return NULL;
    }

    /* Initialize all entries to empty state */
    memset(ring->entries, 0, alloc_size);

    ring->capacity = capacity;
    atomic_set(&ring->head, 0);
    atomic_set(&ring->tail, 0);
    atomic_set(&ring->active_count, 0);
    ring->mmap_base = ring->entries;
    ring->mmap_size = alloc_size;

    pr_info("ASOS Ring: created ring buffer with %zu slots (%zu KB)\n",
            capacity, alloc_size / 1024);

    return ring;
}

/**

 * ring_buffer_destroy - Free ring buffer resources

 * @ring: Ring to destroy

 */
void ring_buffer_destroy(struct IntentRing *ring)
{
    if (!ring)
        return;

    if (ring->entries)
        vfree(ring->entries);

    kfree(ring);
    pr_info("ASOS Ring: destroyed ring buffer\n");
}

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Producer Operations (User Space) | ุนู…ู„ูŠุงุช ุงู„ู…ู†ุชุฌ

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

/**

 * ring_buffer_submit - Submit intent from user space

 * @ring: Target ring

 * @user_intent: User-space pointer to intent

 *

 * Returns: 0 on success, negative error code on failure

 *

 * This is called from user space via syscall. The intent is copied

 * safely from user memory into the ring buffer.

 */
int ring_buffer_submit(struct IntentRing *ring,

                       const struct SystemIntent __user *user_intent)
{
    struct RingBufferEntry *entry;
    struct SystemIntent intent;
    unsigned int head, next_head;
    unsigned int tail;

    if (!ring || !user_intent)
        return -EINVAL;

    /* Copy intent from user space */
    if (copy_from_user(&intent, user_intent, sizeof(intent)))
        return -EFAULT;

    /* Validate intent structure */
    if (intent.payload_len > MAX_INTENT_PAYLOAD) {
        pr_warn("ASOS Ring: payload too large (%u > %u)\n",
                intent.payload_len, MAX_INTENT_PAYLOAD);
        return EINVALID_INTENT;
    }

    /* Load current head and tail (with acquire semantics) */
    head = atomic_read(&ring->head);
    tail = atomic_read(&ring->tail);

    /* Calculate next head position (wrap using mask) */
    next_head = (head + 1) & (ring->capacity - 1);

    /* Check if ring is full */
    if (next_head == tail) {
        pr_warn("ASOS Ring: buffer full (head=%u, tail=%u)\n", head, tail);
        return -EAGAIN;
    }

    /* Get entry at head position */
    entry = &ring->entries[head];

    /* Ensure entry is empty (defensive check) */
    if (entry->state != RB_STATE_EMPTY) {
        pr_err("ASOS Ring: entry %u not empty (state=%u)\n", head, entry->state);
        return -EBUSY;
    }

    /* Fill entry (intent payload) */
    entry->sequence = head;
    memcpy(&entry->intent, &intent, sizeof(intent));

    /* Memory barrier: ensure intent is visible before state change */
    smp_wmb();

    /* Mark entry as submitted */
    entry->state = RB_STATE_SUBMITTED;

    /* Memory barrier: ensure state is visible before head update */
    smp_wmb();

    /* Advance head pointer */
    atomic_set(&ring->head, next_head);
    atomic_inc(&ring->active_count);

    pr_debug("ASOS Ring: submitted intent type=%u at slot %u\n",
             intent.intent_type, head);

    return 0;
}

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Consumer Operations (Kernel) | ุนู…ู„ูŠุงุช ุงู„ู…ุณุชู‡ู„ูƒ

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

/**

 * ring_buffer_consume - Consume next intent from ring

 * @ring: Source ring

 * @intent_out: Output buffer for intent (kernel memory)

 *

 * Returns: 0 on success, -EAGAIN if empty, negative on error

 *

 * Called by KAR dispatcher to fetch the next intent for processing.

 */
int ring_buffer_consume(struct IntentRing *ring, struct SystemIntent *intent_out)
{
    struct RingBufferEntry *entry;
    unsigned int tail;

    if (!ring || !intent_out)
        return -EINVAL;

    /* Load current tail */
    tail = atomic_read(&ring->tail);

    /* Get entry at tail position */
    entry = &ring->entries[tail];

    /* Memory barrier: ensure we see latest state */
    smp_rmb();

    /* Check if entry is ready for consumption */
    if (entry->state != RB_STATE_SUBMITTED) {
        /* Ring is empty or entry not yet submitted */
        return -EAGAIN;
    }

    /* Mark entry as processing */
    entry->state = RB_STATE_PROCESSING;

    /* Memory barrier: ensure state change is visible */
    smp_wmb();

    /* Copy intent to output buffer */
    memcpy(intent_out, &entry->intent, sizeof(*intent_out));

    pr_debug("ASOS Ring: consumed intent type=%u from slot %u\n",
             intent_out->intent_type, tail);

    return 0;
}

/**

 * ring_buffer_complete - Mark intent processing complete

 * @ring: Target ring

 * @result: Processing result to write back

 *

 * Returns: 0 on success, negative on error

 *

 * Called by KAR after intent processing completes. Writes result

 * back to ring buffer and advances tail pointer.

 */
int ring_buffer_complete(struct IntentRing *ring,

                         const struct IntentResult *result)
{
    struct RingBufferEntry *entry;
    unsigned int tail, next_tail;

    if (!ring || !result)
        return -EINVAL;

    /* Load current tail */
    tail = atomic_read(&ring->tail);

    /* Get entry at tail position */
    entry = &ring->entries[tail];

    /* Defensive check: entry should be in processing state */
    if (entry->state != RB_STATE_PROCESSING) {
        pr_err("ASOS Ring: entry %u not processing (state=%u)\n",
               tail, entry->state);
        return -EINVAL;
    }

    /* Write result back */
    memcpy(&entry->result, result, sizeof(entry->result));

    /* Memory barrier: ensure result is visible before state change */
    smp_wmb();

    /* Mark entry as done */
    entry->state = RB_STATE_DONE;

    /* Memory barrier: ensure state is visible */
    smp_wmb();

    /* Calculate next tail (wrap) */
    next_tail = (tail + 1) & (ring->capacity - 1);

    /* Advance tail pointer */
    atomic_set(&ring->tail, next_tail);
    atomic_dec(&ring->active_count);

    /* After user space reads result, it will reset state to RB_STATE_EMPTY */

    pr_debug("ASOS Ring: completed intent at slot %u, status=%d\n",
             tail, result->status);

    return 0;
}

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Ring Buffer Status | ุญุงู„ุฉ ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

/**

 * ring_buffer_stats - Get ring buffer statistics

 * @ring: Target ring

 * @head_out: Output for current head position

 * @tail_out: Output for current tail position

 * @active_out: Output for number of active intents

 *

 * Returns: 0 on success

 */
int ring_buffer_stats(struct IntentRing *ring,

                      unsigned int *head_out,

                      unsigned int *tail_out,

                      unsigned int *active_out)
{
    if (!ring)
        return -EINVAL;

    if (head_out)
        *head_out = atomic_read(&ring->head);
    if (tail_out)
        *tail_out = atomic_read(&ring->tail);
    if (active_out)
        *active_out = atomic_read(&ring->active_count);

    return 0;
}

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Memory Mapping (for zero-copy from user space) | ุชุนูŠูŠู† ุงู„ุฐุงูƒุฑุฉ

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

/**

 * ring_buffer_mmap - Map ring buffer into user space

 * @ring: Ring to map

 * @vma: Virtual memory area from mmap() syscall

 *

 * Returns: 0 on success, negative on error

 *

 * Allows user space to directly access ring buffer for zero-copy

 * operation (advanced usage โ€” default is copy-based submit).

 */
int ring_buffer_mmap(struct IntentRing *ring, struct vm_area_struct *vma)
{
    unsigned long size;
    unsigned long pfn;
    int ret;

    if (!ring || !vma)
        return -EINVAL;

    size = vma->vm_end - vma->vm_start;

    /* Validate requested size */
    if (size != ring->mmap_size) {
        pr_err("ASOS Ring: mmap size mismatch (req=%lu, actual=%zu)\n",
               size, ring->mmap_size);
        return -EINVAL;
    }

    /* Map pages to user space */
    pfn = vmalloc_to_pfn(ring->mmap_base);
    ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);

    if (ret) {
        pr_err("ASOS Ring: mmap failed, error=%d\n", ret);
        return ret;
    }

    pr_info("ASOS Ring: mapped %lu bytes to user space at 0x%lx\n",
            size, vma->vm_start);

    return 0;
}

/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

 * Module Metadata | ุจูŠุงู†ุงุช ูˆุญุฏุฉ ุงู„ู†ู…ุท

 * โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */

MODULE_LICENSE("Proprietary");
MODULE_AUTHOR("Ahmad Ali Parr <ahmedparr93@gmail.com>");
MODULE_DESCRIPTION("ASOS Ring Buffer - Zero-Copy Intent Transport");
MODULE_VERSION("1.0.0");