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#include <linux/miscdevice.h>
41#include <linux/fs.h>
42#include <linux/slab.h>
43#include <linux/kref.h>
44#include <linux/mutex.h>
45#include <linux/kernel.h>
46#include <linux/uaccess.h>
47#include <linux/mm.h>
48#include <linux/ioport.h>
49#include <linux/io.h>
50#include <linux/rar_register.h>
51
52#include "memrar.h"
53#include "memrar_allocator.h"
54
55
56#define MEMRAR_VER "1.0"
57
58
59
60
61
62
63
64
65#define MRST_NUM_RAR 2
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83struct memrar_buffer_info {
84 struct list_head list;
85 struct RAR_buffer buffer;
86 struct kref refcount;
87 struct file *owner;
88};
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109struct memrar_rar_info {
110 dma_addr_t base;
111 unsigned long length;
112 void __iomem *iobase;
113 struct memrar_allocator *allocator;
114 struct memrar_buffer_info buffers;
115 struct mutex lock;
116 int allocated;
117};
118
119
120
121
122static struct memrar_rar_info memrars[MRST_NUM_RAR];
123
124
125
126
127static inline int memrar_is_valid_rar_type(u32 type)
128{
129 return type == RAR_TYPE_VIDEO || type == RAR_TYPE_AUDIO;
130}
131
132
133static inline int memrar_handle_in_range(struct memrar_rar_info *rar,
134 u32 vaddr)
135{
136 unsigned long const iobase = (unsigned long) (rar->iobase);
137 return (vaddr >= iobase && vaddr < iobase + rar->length);
138}
139
140
141static struct memrar_rar_info *memrar_get_rar_info(u32 vaddr)
142{
143 int i;
144 for (i = 0; i < MRST_NUM_RAR; ++i) {
145 struct memrar_rar_info * const rar = &memrars[i];
146 if (memrar_handle_in_range(rar, vaddr))
147 return rar;
148 }
149
150 return NULL;
151}
152
153
154
155
156
157
158
159
160
161static dma_addr_t memrar_get_bus_address(
162 struct memrar_rar_info *rar,
163 u32 vaddr)
164{
165 unsigned long const iobase = (unsigned long) (rar->iobase);
166
167 if (!memrar_handle_in_range(rar, vaddr))
168 return 0;
169
170
171
172
173
174
175
176
177
178 return rar->base + (vaddr - iobase);
179}
180
181
182
183
184
185
186
187
188
189static dma_addr_t memrar_get_physical_address(
190 struct memrar_rar_info *rar,
191 u32 vaddr)
192{
193
194
195
196
197
198
199 return memrar_get_bus_address(rar, vaddr);
200}
201
202
203
204
205
206
207
208
209
210
211
212static void memrar_release_block_i(struct kref *ref)
213{
214
215
216
217
218
219 struct memrar_buffer_info * const node =
220 container_of(ref, struct memrar_buffer_info, refcount);
221
222 struct RAR_block_info * const user_info =
223 &node->buffer.info;
224
225 struct memrar_allocator * const allocator =
226 memrars[user_info->type].allocator;
227
228 list_del(&node->list);
229
230 memrar_allocator_free(allocator, user_info->handle);
231
232 kfree(node);
233}
234
235
236
237
238
239
240
241
242
243static int memrar_init_rar_resources(int rarnum, char const *devname)
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 static size_t const RAR_BLOCK_SIZE = PAGE_SIZE;
273
274 dma_addr_t low, high;
275 struct memrar_rar_info * const rar = &memrars[rarnum];
276
277 BUG_ON(MRST_NUM_RAR != ARRAY_SIZE(memrars));
278 BUG_ON(!memrar_is_valid_rar_type(rarnum));
279 BUG_ON(rar->allocated);
280
281 if (rar_get_address(rarnum, &low, &high) != 0)
282
283 return -ENODEV;
284
285 if (low == 0 || high == 0) {
286 rar->base = 0;
287 rar->length = 0;
288 rar->iobase = NULL;
289 rar->allocator = NULL;
290 return -ENOSPC;
291 }
292
293
294
295
296
297
298
299 rar->length = high - low + 1;
300
301
302 if (request_mem_region(low, rar->length, devname) == NULL) {
303 rar->length = 0;
304 pr_err("%s: Unable to claim RAR[%d] memory.\n",
305 devname, rarnum);
306 pr_err("%s: RAR[%d] disabled.\n", devname, rarnum);
307 return -EBUSY;
308 }
309
310 rar->base = low;
311
312
313
314
315
316
317
318
319
320
321
322
323
324 rar->iobase = ioremap_nocache(rar->base, rar->length);
325 if (rar->iobase == NULL) {
326 pr_err("%s: Unable to map RAR memory.\n", devname);
327 release_mem_region(low, rar->length);
328 return -ENOMEM;
329 }
330
331
332 rar->allocator = memrar_create_allocator((unsigned long) rar->iobase,
333 rar->length, RAR_BLOCK_SIZE);
334 if (rar->allocator == NULL) {
335 iounmap(rar->iobase);
336 release_mem_region(low, rar->length);
337 return -ENOMEM;
338 }
339
340 pr_info("%s: BRAR[%d] bus address range = [0x%lx, 0x%lx]\n",
341 devname, rarnum, (unsigned long) low, (unsigned long) high);
342
343 pr_info("%s: BRAR[%d] size = %zu KiB\n",
344 devname, rarnum, rar->allocator->capacity / 1024);
345
346 rar->allocated = 1;
347 return 0;
348}
349
350
351
352
353
354
355
356static void memrar_fini_rar_resources(void)
357{
358 int z;
359 struct memrar_buffer_info *pos;
360 struct memrar_buffer_info *tmp;
361
362
363
364
365
366
367 for (z = MRST_NUM_RAR; z-- != 0; ) {
368 struct memrar_rar_info * const rar = &memrars[z];
369
370 if (!rar->allocated)
371 continue;
372
373
374
375 list_for_each_entry_safe(pos,
376 tmp,
377 &rar->buffers.list,
378 list) {
379 kref_put(&pos->refcount, memrar_release_block_i);
380 }
381
382 memrar_destroy_allocator(rar->allocator);
383 rar->allocator = NULL;
384
385 iounmap(rar->iobase);
386 release_mem_region(rar->base, rar->length);
387
388 rar->iobase = NULL;
389 rar->base = 0;
390 rar->length = 0;
391
392 unregister_rar(z);
393 }
394}
395
396
397
398
399
400
401
402
403
404
405static long memrar_reserve_block(struct RAR_buffer *request,
406 struct file *filp)
407{
408 struct RAR_block_info * const rinfo = &request->info;
409 struct RAR_buffer *buffer;
410 struct memrar_buffer_info *buffer_info;
411 u32 handle;
412 struct memrar_rar_info *rar = NULL;
413
414
415 if (!memrar_is_valid_rar_type(rinfo->type))
416 return -EINVAL;
417
418 rar = &memrars[rinfo->type];
419 if (!rar->allocated)
420 return -ENODEV;
421
422
423 handle = memrar_allocator_alloc(rar->allocator, rinfo->size);
424 if (handle == 0)
425 return -ENOMEM;
426
427 buffer_info = kmalloc(sizeof(*buffer_info), GFP_KERNEL);
428
429 if (buffer_info == NULL) {
430 memrar_allocator_free(rar->allocator, handle);
431 return -ENOMEM;
432 }
433
434 buffer = &buffer_info->buffer;
435 buffer->info.type = rinfo->type;
436 buffer->info.size = rinfo->size;
437
438
439 buffer->info.handle = handle;
440 buffer->bus_address = memrar_get_bus_address(rar, handle);
441
442
443
444
445
446 buffer_info->owner = filp;
447
448 kref_init(&buffer_info->refcount);
449
450 mutex_lock(&rar->lock);
451 list_add(&buffer_info->list, &rar->buffers.list);
452 mutex_unlock(&rar->lock);
453
454 rinfo->handle = buffer->info.handle;
455 request->bus_address = buffer->bus_address;
456
457 return 0;
458}
459
460
461
462
463
464
465
466
467
468static long memrar_release_block(u32 addr)
469{
470 struct memrar_buffer_info *pos;
471 struct memrar_buffer_info *tmp;
472 struct memrar_rar_info * const rar = memrar_get_rar_info(addr);
473 long result = -EINVAL;
474
475 if (rar == NULL)
476 return -ENOENT;
477
478 mutex_lock(&rar->lock);
479
480
481
482
483
484 list_for_each_entry_safe(pos,
485 tmp,
486 &rar->buffers.list,
487 list) {
488 struct RAR_block_info * const info =
489 &pos->buffer.info;
490
491
492
493
494
495
496
497
498
499
500 if (addr >= info->handle
501 && addr < (info->handle + info->size)
502 && memrar_is_valid_rar_type(info->type)) {
503 kref_put(&pos->refcount, memrar_release_block_i);
504 result = 0;
505 break;
506 }
507 }
508
509 mutex_unlock(&rar->lock);
510
511 return result;
512}
513
514
515
516
517
518
519
520
521static long memrar_get_stat(struct RAR_stat *r)
522{
523 struct memrar_allocator *allocator;
524
525 if (!memrar_is_valid_rar_type(r->type))
526 return -EINVAL;
527
528 if (!memrars[r->type].allocated)
529 return -ENODEV;
530
531 allocator = memrars[r->type].allocator;
532
533 BUG_ON(allocator == NULL);
534
535
536
537
538
539 r->capacity = allocator->capacity;
540
541 mutex_lock(&allocator->lock);
542 r->largest_block_size = allocator->largest_free_area;
543 mutex_unlock(&allocator->lock);
544 return 0;
545}
546
547
548
549
550
551
552
553
554
555
556static long memrar_ioctl(struct file *filp,
557 unsigned int cmd,
558 unsigned long arg)
559{
560 void __user *argp = (void __user *)arg;
561 long result = 0;
562
563 struct RAR_buffer buffer;
564 struct RAR_block_info * const request = &buffer.info;
565 struct RAR_stat rar_info;
566 u32 rar_handle;
567
568 switch (cmd) {
569 case RAR_HANDLER_RESERVE:
570 if (copy_from_user(request,
571 argp,
572 sizeof(*request)))
573 return -EFAULT;
574
575 result = memrar_reserve_block(&buffer, filp);
576 if (result != 0)
577 return result;
578
579 return copy_to_user(argp, request, sizeof(*request));
580
581 case RAR_HANDLER_RELEASE:
582 if (copy_from_user(&rar_handle,
583 argp,
584 sizeof(rar_handle)))
585 return -EFAULT;
586
587 return memrar_release_block(rar_handle);
588
589 case RAR_HANDLER_STAT:
590 if (copy_from_user(&rar_info,
591 argp,
592 sizeof(rar_info)))
593 return -EFAULT;
594
595
596
597
598
599 if (memrar_get_stat(&rar_info) != 0)
600 return -EINVAL;
601
602
603
604
605
606
607 return copy_to_user(argp,
608 &rar_info,
609 sizeof(rar_info)) ? -EFAULT : 0;
610
611 default:
612 return -ENOTTY;
613 }
614
615 return 0;
616}
617
618
619
620
621
622
623
624
625
626
627static int memrar_mmap(struct file *filp, struct vm_area_struct *vma)
628{
629
630
631
632
633
634
635
636
637
638
639
640
641 size_t const size = vma->vm_end - vma->vm_start;
642
643
644 unsigned long const handle = vma->vm_pgoff << PAGE_SHIFT;
645
646 struct memrar_rar_info * const rar = memrar_get_rar_info(handle);
647 unsigned long pfn;
648
649
650 if (!capable(CAP_SYS_RAWIO))
651 return -EPERM;
652
653
654 if (rar == NULL
655 || handle == 0
656 || size > (handle - (unsigned long) rar->iobase))
657 return -EINVAL;
658
659
660
661
662
663 pfn = memrar_get_physical_address(rar, handle) >> PAGE_SHIFT;
664
665
666 pr_debug("memrar: mapping RAR range [0x%lx, 0x%lx) into user space.\n",
667 handle,
668 handle + size);
669
670
671
672
673
674
675
676 if (remap_pfn_range(vma,
677 vma->vm_start,
678 pfn,
679 size,
680 vma->vm_page_prot))
681 return -EAGAIN;
682
683
684
685 return 0;
686}
687
688
689
690
691
692
693
694
695
696
697static int memrar_open(struct inode *inode, struct file *filp)
698{
699 nonseekable_open(inode, filp);
700 return 0;
701}
702
703
704
705
706
707
708
709
710
711
712
713
714static int memrar_release(struct inode *inode, struct file *filp)
715{
716
717
718 struct memrar_buffer_info *pos;
719 struct memrar_buffer_info *tmp;
720 int z;
721
722 for (z = 0; z != MRST_NUM_RAR; ++z) {
723 struct memrar_rar_info * const rar = &memrars[z];
724
725 mutex_lock(&rar->lock);
726
727 list_for_each_entry_safe(pos,
728 tmp,
729 &rar->buffers.list,
730 list) {
731 if (filp == pos->owner)
732 kref_put(&pos->refcount,
733 memrar_release_block_i);
734 }
735
736 mutex_unlock(&rar->lock);
737 }
738
739 return 0;
740}
741
742
743
744
745
746
747
748
749
750
751size_t rar_reserve(struct RAR_buffer *buffers, size_t count)
752{
753 struct RAR_buffer * const end =
754 (buffers == NULL ? buffers : buffers + count);
755 struct RAR_buffer *i;
756
757 size_t reserve_count = 0;
758
759 for (i = buffers; i != end; ++i) {
760 if (memrar_reserve_block(i, NULL) == 0)
761 ++reserve_count;
762 else
763 i->bus_address = 0;
764 }
765
766 return reserve_count;
767}
768EXPORT_SYMBOL(rar_reserve);
769
770
771
772
773
774
775
776
777
778size_t rar_release(struct RAR_buffer *buffers, size_t count)
779{
780 struct RAR_buffer * const end =
781 (buffers == NULL ? buffers : buffers + count);
782 struct RAR_buffer *i;
783
784 size_t release_count = 0;
785
786 for (i = buffers; i != end; ++i) {
787 u32 * const handle = &i->info.handle;
788 if (memrar_release_block(*handle) == 0) {
789
790
791
792
793
794
795
796
797 *handle = 0;
798 ++release_count;
799 }
800 }
801
802 return release_count;
803}
804EXPORT_SYMBOL(rar_release);
805
806
807
808
809
810
811
812
813
814
815
816size_t rar_handle_to_bus(struct RAR_buffer *buffers, size_t count)
817{
818 struct RAR_buffer * const end =
819 (buffers == NULL ? buffers : buffers + count);
820 struct RAR_buffer *i;
821 struct memrar_buffer_info *pos;
822
823 size_t conversion_count = 0;
824
825
826
827
828
829
830 for (i = buffers; i != end; ++i) {
831 struct memrar_rar_info * const rar =
832 memrar_get_rar_info(i->info.handle);
833
834
835
836
837
838 if (rar == NULL) {
839 i->bus_address = 0;
840 continue;
841 }
842
843 mutex_lock(&rar->lock);
844
845 list_for_each_entry(pos, &rar->buffers.list, list) {
846 struct RAR_block_info * const user_info =
847 &pos->buffer.info;
848
849
850
851
852
853
854
855
856
857
858 if (i->info.handle >= user_info->handle
859 && i->info.handle < (user_info->handle
860 + user_info->size)) {
861 u32 const offset =
862 i->info.handle - user_info->handle;
863
864 i->info.type = user_info->type;
865 i->info.size = user_info->size - offset;
866 i->bus_address =
867 pos->buffer.bus_address
868 + offset;
869
870
871 kref_get(&pos->refcount);
872
873 ++conversion_count;
874 break;
875 } else {
876 i->bus_address = 0;
877 }
878 }
879
880 mutex_unlock(&rar->lock);
881 }
882
883 return conversion_count;
884}
885EXPORT_SYMBOL(rar_handle_to_bus);
886
887static const struct file_operations memrar_fops = {
888 .owner = THIS_MODULE,
889 .unlocked_ioctl = memrar_ioctl,
890 .mmap = memrar_mmap,
891 .open = memrar_open,
892 .release = memrar_release,
893 .llseek = no_llseek,
894};
895
896static struct miscdevice memrar_miscdev = {
897 .minor = MISC_DYNAMIC_MINOR,
898 .name = "memrar",
899 .fops = &memrar_fops
900};
901
902static char const banner[] __initdata =
903 KERN_INFO
904 "Intel RAR Handler: " MEMRAR_VER " initialized.\n";
905
906
907
908
909
910
911
912
913
914static int memrar_registration_callback(unsigned long rar)
915{
916
917
918
919
920
921 return memrar_init_rar_resources(rar, memrar_miscdev.name);
922}
923
924
925
926
927
928
929
930
931
932static int __init memrar_init(void)
933{
934 int err;
935 int i;
936
937 printk(banner);
938
939
940
941
942
943
944
945
946
947
948
949
950
951 for (i = 0; i != ARRAY_SIZE(memrars); ++i) {
952 struct memrar_rar_info * const rar = &memrars[i];
953 mutex_init(&rar->lock);
954 INIT_LIST_HEAD(&rar->buffers.list);
955 }
956
957 err = misc_register(&memrar_miscdev);
958 if (err)
959 return err;
960
961
962 err = register_rar(0, memrar_registration_callback, 0);
963 if (err)
964 goto fail;
965
966 err = register_rar(1, memrar_registration_callback, 1);
967 if (err == 0)
968 return 0;
969
970
971
972 memrar_fini_rar_resources();
973fail:
974 misc_deregister(&memrar_miscdev);
975 return err;
976}
977
978
979
980
981
982
983
984
985static void __exit memrar_exit(void)
986{
987 misc_deregister(&memrar_miscdev);
988 memrar_fini_rar_resources();
989}
990
991
992module_init(memrar_init);
993module_exit(memrar_exit);
994
995
996MODULE_AUTHOR("Ossama Othman <ossama.othman@intel.com>");
997MODULE_DESCRIPTION("Intel Restricted Access Region Handler");
998MODULE_LICENSE("GPL");
999MODULE_VERSION(MEMRAR_VER);
1000
1001
1002
1003
1004
1005
1006
1007
1008