26
26
#include <linux/seq_file.h>
27
27
#include <linux/sched.h>
28
28
#include <linux/slab.h>
29
+ #include <linux/cpu.h>
29
30
30
31
#include <uapi/linux/magic.h>
31
32
32
33
#include <asm/intel_rdt.h>
34
+ #include <asm/intel_rdt_common.h>
33
35
34
36
DEFINE_STATIC_KEY_FALSE (rdt_enable_key );
35
37
struct kernfs_root * rdt_root ;
@@ -39,6 +41,55 @@ LIST_HEAD(rdt_all_groups);
39
41
/* Kernel fs node for "info" directory under root */
40
42
static struct kernfs_node * kn_info ;
41
43
44
+ /*
45
+ * Trivial allocator for CLOSIDs. Since h/w only supports a small number,
46
+ * we can keep a bitmap of free CLOSIDs in a single integer.
47
+ *
48
+ * Using a global CLOSID across all resources has some advantages and
49
+ * some drawbacks:
50
+ * + We can simply set "current->closid" to assign a task to a resource
51
+ * group.
52
+ * + Context switch code can avoid extra memory references deciding which
53
+ * CLOSID to load into the PQR_ASSOC MSR
54
+ * - We give up some options in configuring resource groups across multi-socket
55
+ * systems.
56
+ * - Our choices on how to configure each resource become progressively more
57
+ * limited as the number of resources grows.
58
+ */
59
+ static int closid_free_map ;
60
+
61
+ static void closid_init (void )
62
+ {
63
+ struct rdt_resource * r ;
64
+ int rdt_min_closid = 32 ;
65
+
66
+ /* Compute rdt_min_closid across all resources */
67
+ for_each_enabled_rdt_resource (r )
68
+ rdt_min_closid = min (rdt_min_closid , r -> num_closid );
69
+
70
+ closid_free_map = BIT_MASK (rdt_min_closid ) - 1 ;
71
+
72
+ /* CLOSID 0 is always reserved for the default group */
73
+ closid_free_map &= ~1 ;
74
+ }
75
+
76
+ int closid_alloc (void )
77
+ {
78
+ int closid = ffs (closid_free_map );
79
+
80
+ if (closid == 0 )
81
+ return - ENOSPC ;
82
+ closid -- ;
83
+ closid_free_map &= ~(1 << closid );
84
+
85
+ return closid ;
86
+ }
87
+
88
+ static void closid_free (int closid )
89
+ {
90
+ closid_free_map |= 1 << closid ;
91
+ }
92
+
42
93
/* set uid and gid of rdtgroup dirs and files to that of the creator */
43
94
static int rdtgroup_kn_set_ugid (struct kernfs_node * kn )
44
95
{
@@ -287,6 +338,54 @@ static int parse_rdtgroupfs_options(char *data)
287
338
return ret ;
288
339
}
289
340
341
+ /*
342
+ * We don't allow rdtgroup directories to be created anywhere
343
+ * except the root directory. Thus when looking for the rdtgroup
344
+ * structure for a kernfs node we are either looking at a directory,
345
+ * in which case the rdtgroup structure is pointed at by the "priv"
346
+ * field, otherwise we have a file, and need only look to the parent
347
+ * to find the rdtgroup.
348
+ */
349
+ static struct rdtgroup * kernfs_to_rdtgroup (struct kernfs_node * kn )
350
+ {
351
+ if (kernfs_type (kn ) == KERNFS_DIR )
352
+ return kn -> priv ;
353
+ else
354
+ return kn -> parent -> priv ;
355
+ }
356
+
357
+ struct rdtgroup * rdtgroup_kn_lock_live (struct kernfs_node * kn )
358
+ {
359
+ struct rdtgroup * rdtgrp = kernfs_to_rdtgroup (kn );
360
+
361
+ atomic_inc (& rdtgrp -> waitcount );
362
+ kernfs_break_active_protection (kn );
363
+
364
+ mutex_lock (& rdtgroup_mutex );
365
+
366
+ /* Was this group deleted while we waited? */
367
+ if (rdtgrp -> flags & RDT_DELETED )
368
+ return NULL ;
369
+
370
+ return rdtgrp ;
371
+ }
372
+
373
+ void rdtgroup_kn_unlock (struct kernfs_node * kn )
374
+ {
375
+ struct rdtgroup * rdtgrp = kernfs_to_rdtgroup (kn );
376
+
377
+ mutex_unlock (& rdtgroup_mutex );
378
+
379
+ if (atomic_dec_and_test (& rdtgrp -> waitcount ) &&
380
+ (rdtgrp -> flags & RDT_DELETED )) {
381
+ kernfs_unbreak_active_protection (kn );
382
+ kernfs_put (kn );
383
+ kfree (rdtgrp );
384
+ } else {
385
+ kernfs_unbreak_active_protection (kn );
386
+ }
387
+ }
388
+
290
389
static struct dentry * rdt_mount (struct file_system_type * fs_type ,
291
390
int flags , const char * unused_dev_name ,
292
391
void * data )
@@ -309,6 +408,8 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
309
408
goto out_cdp ;
310
409
}
311
410
411
+ closid_init ();
412
+
312
413
ret = rdtgroup_create_info_dir (rdtgroup_default .kn );
313
414
if (ret )
314
415
goto out_cdp ;
@@ -367,11 +468,40 @@ static int reset_all_cbms(struct rdt_resource *r)
367
468
return 0 ;
368
469
}
369
470
471
+ /*
472
+ * MSR_IA32_PQR_ASSOC is scoped per logical CPU, so all updates
473
+ * are always in thread context.
474
+ */
475
+ static void rdt_reset_pqr_assoc_closid (void * v )
476
+ {
477
+ struct intel_pqr_state * state = this_cpu_ptr (& pqr_state );
478
+
479
+ state -> closid = 0 ;
480
+ wrmsr (MSR_IA32_PQR_ASSOC , state -> rmid , 0 );
481
+ }
482
+
370
483
/*
371
484
* Forcibly remove all of subdirectories under root.
372
485
*/
373
486
static void rmdir_all_sub (void )
374
487
{
488
+ struct rdtgroup * rdtgrp , * tmp ;
489
+
490
+ get_cpu ();
491
+ /* Reset PQR_ASSOC MSR on this cpu. */
492
+ rdt_reset_pqr_assoc_closid (NULL );
493
+ /* Reset PQR_ASSOC MSR on the rest of cpus. */
494
+ smp_call_function_many (cpu_online_mask , rdt_reset_pqr_assoc_closid ,
495
+ NULL , 1 );
496
+ put_cpu ();
497
+ list_for_each_entry_safe (rdtgrp , tmp , & rdt_all_groups , rdtgroup_list ) {
498
+ /* Remove each rdtgroup other than root */
499
+ if (rdtgrp == & rdtgroup_default )
500
+ continue ;
501
+ kernfs_remove (rdtgrp -> kn );
502
+ list_del (& rdtgrp -> rdtgroup_list );
503
+ kfree (rdtgrp );
504
+ }
375
505
kernfs_remove (kn_info );
376
506
}
377
507
@@ -397,7 +527,108 @@ static struct file_system_type rdt_fs_type = {
397
527
.kill_sb = rdt_kill_sb ,
398
528
};
399
529
530
+ static int rdtgroup_mkdir (struct kernfs_node * parent_kn , const char * name ,
531
+ umode_t mode )
532
+ {
533
+ struct rdtgroup * parent , * rdtgrp ;
534
+ struct kernfs_node * kn ;
535
+ int ret , closid ;
536
+
537
+ /* Only allow mkdir in the root directory */
538
+ if (parent_kn != rdtgroup_default .kn )
539
+ return - EPERM ;
540
+
541
+ /* Do not accept '\n' to avoid unparsable situation. */
542
+ if (strchr (name , '\n' ))
543
+ return - EINVAL ;
544
+
545
+ parent = rdtgroup_kn_lock_live (parent_kn );
546
+ if (!parent ) {
547
+ ret = - ENODEV ;
548
+ goto out_unlock ;
549
+ }
550
+
551
+ ret = closid_alloc ();
552
+ if (ret < 0 )
553
+ goto out_unlock ;
554
+ closid = ret ;
555
+
556
+ /* allocate the rdtgroup. */
557
+ rdtgrp = kzalloc (sizeof (* rdtgrp ), GFP_KERNEL );
558
+ if (!rdtgrp ) {
559
+ ret = - ENOSPC ;
560
+ goto out_closid_free ;
561
+ }
562
+ rdtgrp -> closid = closid ;
563
+ list_add (& rdtgrp -> rdtgroup_list , & rdt_all_groups );
564
+
565
+ /* kernfs creates the directory for rdtgrp */
566
+ kn = kernfs_create_dir (parent -> kn , name , mode , rdtgrp );
567
+ if (IS_ERR (kn )) {
568
+ ret = PTR_ERR (kn );
569
+ goto out_cancel_ref ;
570
+ }
571
+ rdtgrp -> kn = kn ;
572
+
573
+ /*
574
+ * kernfs_remove() will drop the reference count on "kn" which
575
+ * will free it. But we still need it to stick around for the
576
+ * rdtgroup_kn_unlock(kn} call below. Take one extra reference
577
+ * here, which will be dropped inside rdtgroup_kn_unlock().
578
+ */
579
+ kernfs_get (kn );
580
+
581
+ ret = rdtgroup_kn_set_ugid (kn );
582
+ if (ret )
583
+ goto out_destroy ;
584
+
585
+ kernfs_activate (kn );
586
+
587
+ ret = 0 ;
588
+ goto out_unlock ;
589
+
590
+ out_destroy :
591
+ kernfs_remove (rdtgrp -> kn );
592
+ out_cancel_ref :
593
+ list_del (& rdtgrp -> rdtgroup_list );
594
+ kfree (rdtgrp );
595
+ out_closid_free :
596
+ closid_free (closid );
597
+ out_unlock :
598
+ rdtgroup_kn_unlock (parent_kn );
599
+ return ret ;
600
+ }
601
+
602
+ static int rdtgroup_rmdir (struct kernfs_node * kn )
603
+ {
604
+ struct rdtgroup * rdtgrp ;
605
+ int ret = 0 ;
606
+
607
+ rdtgrp = rdtgroup_kn_lock_live (kn );
608
+ if (!rdtgrp ) {
609
+ rdtgroup_kn_unlock (kn );
610
+ return - ENOENT ;
611
+ }
612
+
613
+ rdtgrp -> flags = RDT_DELETED ;
614
+ closid_free (rdtgrp -> closid );
615
+ list_del (& rdtgrp -> rdtgroup_list );
616
+
617
+ /*
618
+ * one extra hold on this, will drop when we kfree(rdtgrp)
619
+ * in rdtgroup_kn_unlock()
620
+ */
621
+ kernfs_get (kn );
622
+ kernfs_remove (rdtgrp -> kn );
623
+
624
+ rdtgroup_kn_unlock (kn );
625
+
626
+ return ret ;
627
+ }
628
+
400
629
static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {
630
+ .mkdir = rdtgroup_mkdir ,
631
+ .rmdir = rdtgroup_rmdir ,
401
632
};
402
633
403
634
static int __init rdtgroup_setup_root (void )
0 commit comments