Commit 6705cae4 authored by Madhuparna Bhowmik's avatar Madhuparna Bhowmik Committed by Paul E. McKenney

doc: Converted NMI-RCU.txt to NMI-RCU.rst.

This patch converts NMI-RCU from txt to rst format.
Also adds NMI-RCU in the index.rst file.
Signed-off-by: default avatarMadhuparna Bhowmik <madhuparnabhowmik04@gmail.com>
[ paulmck: Apply feedback from Phong Tran. ]
Tested-by: default avatarPhong Tran <tranmanphong@gmail.com>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 9ffdd798
.. _NMI_rcu_doc:
Using RCU to Protect Dynamic NMI Handlers Using RCU to Protect Dynamic NMI Handlers
=========================================
Although RCU is usually used to protect read-mostly data structures, Although RCU is usually used to protect read-mostly data structures,
...@@ -9,7 +12,7 @@ work in "arch/x86/oprofile/nmi_timer_int.c" and in ...@@ -9,7 +12,7 @@ work in "arch/x86/oprofile/nmi_timer_int.c" and in
"arch/x86/kernel/traps.c". "arch/x86/kernel/traps.c".
The relevant pieces of code are listed below, each followed by a The relevant pieces of code are listed below, each followed by a
brief explanation. brief explanation::
static int dummy_nmi_callback(struct pt_regs *regs, int cpu) static int dummy_nmi_callback(struct pt_regs *regs, int cpu)
{ {
...@@ -18,12 +21,12 @@ brief explanation. ...@@ -18,12 +21,12 @@ brief explanation.
The dummy_nmi_callback() function is a "dummy" NMI handler that does The dummy_nmi_callback() function is a "dummy" NMI handler that does
nothing, but returns zero, thus saying that it did nothing, allowing nothing, but returns zero, thus saying that it did nothing, allowing
the NMI handler to take the default machine-specific action. the NMI handler to take the default machine-specific action::
static nmi_callback_t nmi_callback = dummy_nmi_callback; static nmi_callback_t nmi_callback = dummy_nmi_callback;
This nmi_callback variable is a global function pointer to the current This nmi_callback variable is a global function pointer to the current
NMI handler. NMI handler::
void do_nmi(struct pt_regs * regs, long error_code) void do_nmi(struct pt_regs * regs, long error_code)
{ {
...@@ -53,11 +56,12 @@ anyway. However, in practice it is a good documentation aid, particularly ...@@ -53,11 +56,12 @@ anyway. However, in practice it is a good documentation aid, particularly
for anyone attempting to do something similar on Alpha or on systems for anyone attempting to do something similar on Alpha or on systems
with aggressive optimizing compilers. with aggressive optimizing compilers.
Quick Quiz: Why might the rcu_dereference_sched() be necessary on Alpha, Quick Quiz:
given that the code referenced by the pointer is read-only? Why might the rcu_dereference_sched() be necessary on Alpha, given that the code referenced by the pointer is read-only?
:ref:`Answer to Quick Quiz <answer_quick_quiz_NMI>`
Back to the discussion of NMI and RCU... Back to the discussion of NMI and RCU::
void set_nmi_callback(nmi_callback_t callback) void set_nmi_callback(nmi_callback_t callback)
{ {
...@@ -68,7 +72,7 @@ The set_nmi_callback() function registers an NMI handler. Note that any ...@@ -68,7 +72,7 @@ The set_nmi_callback() function registers an NMI handler. Note that any
data that is to be used by the callback must be initialized up -before- data that is to be used by the callback must be initialized up -before-
the call to set_nmi_callback(). On architectures that do not order the call to set_nmi_callback(). On architectures that do not order
writes, the rcu_assign_pointer() ensures that the NMI handler sees the writes, the rcu_assign_pointer() ensures that the NMI handler sees the
initialized values. initialized values::
void unset_nmi_callback(void) void unset_nmi_callback(void)
{ {
...@@ -82,7 +86,7 @@ up any data structures used by the old NMI handler until execution ...@@ -82,7 +86,7 @@ up any data structures used by the old NMI handler until execution
of it completes on all other CPUs. of it completes on all other CPUs.
One way to accomplish this is via synchronize_rcu(), perhaps as One way to accomplish this is via synchronize_rcu(), perhaps as
follows: follows::
unset_nmi_callback(); unset_nmi_callback();
synchronize_rcu(); synchronize_rcu();
...@@ -98,13 +102,12 @@ to free up the handler's data as soon as synchronize_rcu() returns. ...@@ -98,13 +102,12 @@ to free up the handler's data as soon as synchronize_rcu() returns.
Important note: for this to work, the architecture in question must Important note: for this to work, the architecture in question must
invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively. invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively.
.. _answer_quick_quiz_NMI:
Answer to Quick Quiz Answer to Quick Quiz:
Why might the rcu_dereference_sched() be necessary on Alpha, given that the code referenced by the pointer is read-only?
Why might the rcu_dereference_sched() be necessary on Alpha, given
that the code referenced by the pointer is read-only?
Answer: The caller to set_nmi_callback() might well have The caller to set_nmi_callback() might well have
initialized some data that is to be used by the new NMI initialized some data that is to be used by the new NMI
handler. In this case, the rcu_dereference_sched() would handler. In this case, the rcu_dereference_sched() would
be needed, because otherwise a CPU that received an NMI be needed, because otherwise a CPU that received an NMI
......
...@@ -10,6 +10,7 @@ RCU concepts ...@@ -10,6 +10,7 @@ RCU concepts
arrayRCU arrayRCU
rcu rcu
listRCU listRCU
NMI-RCU
UP UP
Design/Memory-Ordering/Tree-RCU-Memory-Ordering Design/Memory-Ordering/Tree-RCU-Memory-Ordering
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment