~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/RCU/NMI-RCU.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /Documentation/RCU/NMI-RCU.rst (Version linux-6.12-rc7) and /Documentation/RCU/NMI-RCU.rst (Version linux-4.9.337)


  1 .. _NMI_rcu_doc:                                  
  2                                                   
  3 Using RCU to Protect Dynamic NMI Handlers         
  4 =========================================         
  5                                                   
  6                                                   
  7 Although RCU is usually used to protect read-m    
  8 it is possible to use RCU to provide dynamic n    
  9 handlers, as well as dynamic irq handlers.  Th    
 10 how to do this, drawing loosely from Zwane Mwa    
 11 work in an old version of "arch/x86/kernel/tra    
 12                                                   
 13 The relevant pieces of code are listed below,     
 14 brief explanation::                               
 15                                                   
 16         static int dummy_nmi_callback(struct p    
 17         {                                         
 18                 return 0;                         
 19         }                                         
 20                                                   
 21 The dummy_nmi_callback() function is a "dummy"    
 22 nothing, but returns zero, thus saying that it    
 23 the NMI handler to take the default machine-sp    
 24                                                   
 25         static nmi_callback_t nmi_callback = d    
 26                                                   
 27 This nmi_callback variable is a global functio    
 28 NMI handler::                                     
 29                                                   
 30         void do_nmi(struct pt_regs * regs, lon    
 31         {                                         
 32                 int cpu;                          
 33                                                   
 34                 nmi_enter();                      
 35                                                   
 36                 cpu = smp_processor_id();         
 37                 ++nmi_count(cpu);                 
 38                                                   
 39                 if (!rcu_dereference_sched(nmi    
 40                         default_do_nmi(regs);     
 41                                                   
 42                 nmi_exit();                       
 43         }                                         
 44                                                   
 45 The do_nmi() function processes each NMI.  It     
 46 in the same way that a hardware irq would, the    
 47 count of NMIs.  It then invokes the NMI handle    
 48 function pointer.  If this handler returns zer    
 49 default_do_nmi() function to handle a machine-    
 50 preemption is restored.                           
 51                                                   
 52 In theory, rcu_dereference_sched() is not need    
 53 only on i386, which in theory does not need rc    
 54 anyway.  However, in practice it is a good doc    
 55 for anyone attempting to do something similar     
 56 with aggressive optimizing compilers.             
 57                                                   
 58 Quick Quiz:                                       
 59                 Why might the rcu_dereference_    
 60                                                   
 61 :ref:`Answer to Quick Quiz <answer_quick_quiz_    
 62                                                   
 63 Back to the discussion of NMI and RCU::           
 64                                                   
 65         void set_nmi_callback(nmi_callback_t c    
 66         {                                         
 67                 rcu_assign_pointer(nmi_callbac    
 68         }                                         
 69                                                   
 70 The set_nmi_callback() function registers an N    
 71 data that is to be used by the callback must b    
 72 the call to set_nmi_callback().  On architectu    
 73 writes, the rcu_assign_pointer() ensures that     
 74 initialized values::                              
 75                                                   
 76         void unset_nmi_callback(void)             
 77         {                                         
 78                 rcu_assign_pointer(nmi_callbac    
 79         }                                         
 80                                                   
 81 This function unregisters an NMI handler, rest    
 82 dummy_nmi_handler().  However, there may well     
 83 currently executing on some other CPU.  We the    
 84 up any data structures used by the old NMI han    
 85 of it completes on all other CPUs.                
 86                                                   
 87 One way to accomplish this is via synchronize_    
 88 follows::                                         
 89                                                   
 90         unset_nmi_callback();                     
 91         synchronize_rcu();                        
 92         kfree(my_nmi_data);                       
 93                                                   
 94 This works because (as of v4.20) synchronize_r    
 95 CPUs complete any preemption-disabled segments    
 96 executing.                                        
 97 Since NMI handlers disable preemption, synchro    
 98 not to return until all ongoing NMI handlers e    
 99 to free up the handler's data as soon as synch    
100                                                   
101 Important note: for this to work, the architec    
102 invoke nmi_enter() and nmi_exit() on NMI entry    
103                                                   
104 .. _answer_quick_quiz_NMI:                        
105                                                   
106 Answer to Quick Quiz:                             
107         Why might the rcu_dereference_sched()     
108                                                   
109         The caller to set_nmi_callback() might    
110         initialized some data that is to be us    
111         handler.  In this case, the rcu_derefe    
112         be needed, because otherwise a CPU tha    
113         just after the new handler was set mig    
114         to the new NMI handler, but the old pr    
115         version of the handler's data.            
116                                                   
117         This same sad story can happen on othe    
118         a compiler with aggressive pointer-val    
119         optimizations.  (But please don't!)       
120                                                   
121         More important, the rcu_dereference_sc    
122         clear to someone reading the code that    
123         being protected by RCU-sched.             
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php