[bootlin/training-materials updates] master: slides/kernel-driver-development-io-memory: rework section on accessors (92438b53)

Thomas Petazzoni thomas.petazzoni at bootlin.com
Sun Apr 16 22:14:00 CEST 2023


Repository : https://github.com/bootlin/training-materials
On branch  : master
Link       : https://github.com/bootlin/training-materials/commit/92438b5341bbd11f2600dc673a092d77d8c35a30

>---------------------------------------------------------------

commit 92438b5341bbd11f2600dc673a092d77d8c35a30
Author: Thomas Petazzoni <thomas.petazzoni at bootlin.com>
Date:   Sun Apr 16 22:14:00 2023 +0200

    slides/kernel-driver-development-io-memory: rework section on accessors
    
    Signed-off-by: Thomas Petazzoni <thomas.petazzoni at bootlin.com>


>---------------------------------------------------------------

92438b5341bbd11f2600dc673a092d77d8c35a30
 .../endianness-conversion.dia                      | Bin 1875 -> 0 bytes
 .../kernel-driver-development-io-memory.tex        | 102 ++++++++++-----------
 2 files changed, 49 insertions(+), 53 deletions(-)

diff --git a/slides/kernel-driver-development-io-memory/endianness-conversion.dia b/slides/kernel-driver-development-io-memory/endianness-conversion.dia
deleted file mode 100644
index e155aff3..00000000
Binary files a/slides/kernel-driver-development-io-memory/endianness-conversion.dia and /dev/null differ
diff --git a/slides/kernel-driver-development-io-memory/kernel-driver-development-io-memory.tex b/slides/kernel-driver-development-io-memory/kernel-driver-development-io-memory.tex
index 9395b93c..70e5dcbe 100644
--- a/slides/kernel-driver-development-io-memory/kernel-driver-development-io-memory.tex
+++ b/slides/kernel-driver-development-io-memory/kernel-driver-development-io-memory.tex
@@ -134,78 +134,74 @@ if (IS_ERR(base))
 \end{frame}
 
 \begin{frame}[fragile]
-  \frametitle{Accessing MMIO devices}
+  \frametitle{Accessing MMIO devices: using accessor functions}
   \begin{itemize}
   \item Directly reading from or writing to addresses returned by
     \kfunc{ioremap} (\emph{pointer dereferencing}) may not work on some
     architectures.
-  \item To do PCI-style, little-endian accesses (byte swapping being done
-    automatically assuming a little-endian device):
-\begin{minted}[fontsize=\small]{c}
-u8  readb(void __iomem *addr);
-u16 readw(void __iomem *addr);
-u32 readl(void __iomem *addr);
-u64 readq(void __iomem *addr);
-void writeb(u8  val, void __iomem *addr);
-void writew(u16 val, void __iomem *addr);
-void writel(u32 val, void __iomem *addr);
-void writeq(u64 val, void __iomem *addr);
-\end{minted}
-  \item These helpers are protected against ordering issues and will
-    generally do the right thing for your architecture
-  \item Caching and speculative execution are disabled on I/O memory
+  \item A family of architecture-independent accessor functions are
+    available covering most needs.
+  \item A few architecture-specific accessor functions also exists.
   \end{itemize}
 \end{frame}
 
-\begin{frame}[fragile]
-  \frametitle{Byte endianness}
+\begin{frame}{MMIO access functions}
   \begin{itemize}
-  \item Not all devices are little-endian
-  \item Most networking protocols are big-endian
-  \item Manual handling of the endianness may sometimes be required
+  \item \code{read[b/w/l/q]} and \code{write[b/w/l/q]} for access to
+    little-endian devices, includes memory barriers
+  \item \code{ioread[8/16/32/64]} and \code{iowrite[8/16/32/64]} are
+    very similar to read/write but also work with port I/O (not
+    covered in the course), includes memory barriers
+  \item \code{ioread[8/16/32/64]be} and \code{iowrite[8/16/32/64]be]}
+    for access to big-endian devices, includes memory barriers
+  \item \code{__raw_read[b/w/l/q]} and \code{__raw_write[b/w/l/q]} for
+    raw access: no endianness conversion, no memory barriers
+  \item \code{read[b/w/l/q]_relaxed} and \code{write[b/q/l/w]_relaxed}
+    for access to little-endian devices, without memory barriers
+  \item All functions work on a \code{void __iomem *}
   \end{itemize}
-  \begin{columns}
-    \column{0.4\textwidth}
-    For portability purposes, drivers should handle all possibilities:
-    \begin{itemize}
-    \item \kfunc{cpu_to_be32}
-    \item \kfunc{cpu_to_le32}
-    \item \kfunc{be32_to_cpu}
-    \item \kfunc{le32_to_cpu}
-    \end{itemize}
-    \column{0.6\textwidth}
-    \begin{center}
-      \includegraphics[width=0.8\textwidth]{slides/kernel-driver-development-io-memory/endianness-conversion.pdf}
-    \end{center}
-  \end{columns}
+\end{frame}
+
+\begin{frame}{MMIO access functions summary}
+  \begin{center}
+    \begin{tabular}{|l|c|c|}
+      \hline
+      Name & Device endianness & Memory barriers \\
+      \hline
+      \code{read/write} & little & yes \\
+      \hline
+      \code{ioread/iowrite} & little & yes \\
+      \hline
+      \code{ioreadbe/iowritebe} & big & yes \\
+      \hline
+      \code{__raw_read/__raw_write} & native & no \\
+      \hline
+      \code{read_relaxed/write_relaxed} & little & no \\
+      \hline
+    \end{tabular}
+  \end{center}
+  More details at \url{https://docs.kernel.org/driver-api/device-io.html}
 \end{frame}
 
 \begin{frame}[fragile]
   \frametitle{Ordering}
   \begin{itemize}
-  \item The compiler and/or CPU can reorder memory accesses, which
-    might cause trouble for your devices is they expect one register
-    to be read/written before another one.
+  \item Reads/writes to MMIO-mapped registers of given device are done
+    in program order
+  \item However reads/writes to RAM can be re-ordered between
+    themselves, and between MMIO-mapped read/writes
+  \item Some of the accessor functions include memory barriers to help
+    with this:
     \begin{itemize}
-    \item Memory barriers are available to prevent this reordering
-    \item \code{write[bwlq]} starts with a write memory barrier which
-      prior writes cannot cross
-    \item \code{read[bwlq]} ends with a read memory barrier which
+    \item Write operation starts with a write memory barrier which prior
+      writes cannot cross
+    \item Read operation ends with a read memory barrier which
       guarantees the ordering with regard to the subsequent reads
     \end{itemize}
   \item Sometimes compiler/CPU reordering is not an issue, in this case
     the code may be optimized by dropping the memory barriers, using the
-    relaxed helpers:
-\begin{minted}{c}
-unsigned read[bwlq]_relaxed(void *addr);
-void write[bwlq]_relaxed(unsigned val, void *addr);
-\end{minted}
-  \item To do pure raw accesses, without barriers nor endianness
-    conversion:
-\begin{minted}{c}
-unsigned __raw_read[bwlq](void *addr);
-void __raw_write[bwlq](unsigned val, void *addr);
-\end{minted}
+    raw or relaxed helpers
+  \item See \kfile{Documentation/memory-barriers.txt}
   \end{itemize}
 \end{frame}
 




More information about the training-materials-updates mailing list