Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add LM32 MMU documentation

  • Loading branch information...
commit 4c0f6c51253b4482fe7685e77d4d5549207a098c 1 parent cf2281b
Yann Sionneau authored sbourdeauducq committed

Showing 2 changed files with 481 additions and 0 deletions. Show diff stats Hide diff stats

  1. 17  doc/Makefile
  2. 464  doc/mmu.tex
17  doc/Makefile
... ...
@@ -0,0 +1,17 @@
  1
+TEX=mmu.tex
  2
+
  3
+RM ?= rm -f
  4
+
  5
+PDF=$(TEX:.tex=.pdf)
  6
+AUX=$(TEX:.tex=.aux)
  7
+LOG=$(TEX:.tex=.log)
  8
+
  9
+all: $(PDF)
  10
+
  11
+%.pdf: %.tex
  12
+	texi2pdf $<
  13
+
  14
+clean:
  15
+	$(RM) $(PDF) $(LOG) $(AUX)
  16
+
  17
+.PHONY: clean
464  doc/mmu.tex
... ...
@@ -0,0 +1,464 @@
  1
+\documentclass[a4paper,11pt]{article}
  2
+\usepackage{fullpage}
  3
+\usepackage[latin1]{inputenc}
  4
+\usepackage[T1]{fontenc}
  5
+\usepackage[normalem]{ulem}
  6
+\usepackage[english]{babel}
  7
+\usepackage{listings,babel}
  8
+\lstset{breaklines=true,basicstyle=\ttfamily}
  9
+\usepackage{graphicx}
  10
+\usepackage{moreverb}
  11
+\usepackage{url}
  12
+\usepackage{tabularx}
  13
+
  14
+\title{LatticeMico32 Memory Management Unit Documentation}
  15
+\author{Yann Sionneau}
  16
+\date{version 1.0 June 2013}
  17
+\begin{document}
  18
+\setlength{\parindent}{0pt}
  19
+\setlength{\parskip}{5pt}
  20
+\maketitle{}
  21
+
  22
+\tableofcontents
  23
+
  24
+\section{Overview}
  25
+
  26
+This document describes the LatticeMico32 MMU (Memory Management Unit) features and how it can be configured.
  27
+
  28
+This MMU is not part of the original LatticeMico32 CPU, it has been added by Yann Sionneau with the help of the Milkymist community in general and Michael Walle in particular.
  29
+
  30
+The LM32 MMU has been designed with "simplicity" in head, KISS (Keep It Simple Stupid) is the motto.
  31
+
  32
+Only the minimum has been implemented to have the minimalistic features which would allow a modern Operating System like Linux or *BSD to run, providing virtual memory and memory protection.
  33
+
  34
+The TLBs (Translation Lookaside Buffers) are designed to be VIPT (Virtually Indexed Physically Tagged) to allow the TLB lookup to take place in parallel of the cache lookup so that we don't need to stale the pipeline.
  35
+
  36
+\section{Features}
  37
+
  38
+\begin{itemize}
  39
+	\item 1024 entries ITLB (Instruction Translation Lookaside Buffer)
  40
+	\item 1024 entries DTLB (Data Translation Lookaside Buffer)
  41
+	\item CPU exceptions generated upon
  42
+	\begin{itemize}
  43
+			\item ITLB miss
  44
+			\item DTLB miss
  45
+			\item DTLB page fault (writing to a read-only page)
  46
+	\end{itemize}
  47
+	\item I/D TLB lookup in parallel of the I/D Cache lookup to avoid lookup penalties
  48
+	\item 4 kB pages
  49
+\end{itemize}
  50
+
  51
+As you can see, it is quite minimalistic, here is a list of what's not featured by this MMU:
  52
+
  53
+\begin{itemize}
  54
+	\item No hardware page tree walker
  55
+	\item No dirty or present bit
  56
+	\item No ASID (Address Space Identifier)
  57
+	\item No lockable TLB entries
  58
+	\item Only 1 page size supported: 4 kB
  59
+\end{itemize}
  60
+
  61
+\section{TLB Layout}
  62
+
  63
+Let's name our 32 bits virtual address "vaddr".
  64
+
  65
+Let's name our 32 bits physical address "paddr".
  66
+
  67
+Let's say vaddr[0] is the Lowest Significant Bit and vaddr[31] the Most Significant Bit.
  68
+
  69
+Let's say vaddr[11:0] is the part of vaddr represented by its 12 Lowest Significant Bits.
  70
+\newline
  71
+
  72
+Deep inside, the TLB is a \textbf{Direct-mapped}, \textbf{VIPT} (Virtually Indexed Physically Tagged) Cache.
  73
+\newline
  74
+
  75
+When the LM32 core is synthetized with MMU support, the CPU pipeline Data and Instruction Caches turn into \textbf{VIPT} Caches as well.
  76
+\newline
  77
+
  78
+The TLB is indexed by vaddr[21:12]: The bottom 10 LSB of the virtual PFN (Page Frame Number).
  79
+\newline
  80
+
  81
+A TLB entry holds: Physical PFN, Physical Tag, Cache inhibit flag (for DTLB), Read-only flag (for DTLB), Valid entry tag
  82
+\newline
  83
+
  84
+More precisely:
  85
+
  86
+\begin{itemize}
  87
+	\item A valid DTLB entry: paddr[31:12], vaddr[31:22], paddr[2], paddr[1], 1
  88
+	\item An invalid DTLB entry: paddr[31:12], vaddr[21:22], paddr[2], paddr[1], 0
  89
+	\item A valid ITLB entry: paddr[31:12], vaddr[31:22], 1
  90
+	\item An invalid ITLB entry: paddr[31:12], vaddr[31:22], 0
  91
+\end{itemize}
  92
+
  93
+The meaning of paddr[2] and paddr[1] will be explained later on in the section which explains how to program the MMU using LM32 assembly instructions.
  94
+
  95
+\section{Interact with the TLB}
  96
+
  97
+In order to interact with the TLB, three CSR (Control and Status Registers) have been added to the LM32 CPU:
  98
+
  99
+\begin{tabular}{l p{0.5\textwidth} l}
  100
+\bf{CSR} & \bf{Description} & \bf{R/W} \\
  101
+\hline
  102
+TLBVADDR & You can write the virtual pfn of the entry you want to update or invalidate or cause a TLB flush.
  103
+\newline
  104
+	   You can read the virtual pfn causing a TLB miss or fault.
  105
+& Read-Write \\
  106
+TLBPADDR & You can write the physical pfn of the entry you want to update. & Write-only \\
  107
+TLBBADVADDR & You can read the virtual address which caused the TLB exception. & Read-only \\
  108
+\hline
  109
+\end{tabular}
  110
+
  111
+\begin{itemize}
  112
+	\item TLBVADDR: holds a virtual address
  113
+	\item TLBPADDR: holds a physical address
  114
+\end{itemize}
  115
+
  116
+A CSR register can be written to like this:
  117
+
  118
+The following code writes the content of the R1 register to TLBVADDR CSR:
  119
+\begin{lstlisting}
  120
+wcsr TLBVADDR, r1
  121
+\end{lstlisting}
  122
+
  123
+A CSR register can be read from like this:
  124
+
  125
+The following code writes the content of TLBPADDR CSR to the R1 register:
  126
+\begin{lstlisting}
  127
+rcsr r1, TLBPADDR
  128
+\end{lstlisting}
  129
+
  130
+\subsection{Add or Update a TLB entry}
  131
+
  132
+First, make sure vaddr[2:0] == "000" (or 3'b0 in verilog) as those 3 bits will be used for other TLB operations.
  133
+
  134
+Then, write the virtual address to the TLBVADDR CSR.
  135
+
  136
+Then you need to do a logical "OR" operation on the physical address to set paddr[2:0] according to your needs:
  137
+
  138
+\begin{itemize}
  139
+	\item paddr[2] set to 1 means the page won't be cached by LM32 Data Cache (only for Data Cache / DTLB)
  140
+	\item paddr[1] set to 1 means the Page is Read-only (only valid for DTLB)
  141
+	\item paddr[0] set to 1 means you want to update DTLB, use 0 for ITLB
  142
+\end{itemize}
  143
+
  144
+Then, you need to write the OR'ed physical address to the TLBPADDR CSR.
  145
+
  146
+The TLB entry update will be triggered by the write to TLBPADDR CSR.
  147
+
  148
+Code samples:
  149
+
  150
+\begin{lstlisting}
  151
+
  152
+#define PAGE_SIZE (1 << 12)
  153
+#define PAGE_MASK (PAGE_SIZE - 1)
  154
+
  155
+void update_dtlb_entry(unsigned int vaddr, unsigned int paddr, bool read-only, bool not_cached)
  156
+{
  157
+	paddr &= ~PAGE_MASK; // Make sure page offset is zeroed
  158
+	vaddr &= ~PAGE_MASK; // Make sure page offset is zeroed
  159
+	paddr |= 1; // This means we are addressing DTLB
  160
+
  161
+	if (read-only)
  162
+		paddr |= 2;
  163
+
  164
+	if (not_cached)
  165
+		paddr |= 4;
  166
+
  167
+	asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : );
  168
+	asm volatile("wcsr TLBPADDR, %0" :: "r"(paddr) : );
  169
+}
  170
+
  171
+void update_itlb_entry(unsigned int vaddr, unsigned int paddr, bool not_cached)
  172
+{
  173
+	paddr &= ~PAGE_MASK; // Make sure page offset is zeroed
  174
+	vaddr &= ~PAGE_MASK; // Make sure page offset is zeroed
  175
+	// We don't set paddr[0] which means we are addressing ITLB
  176
+
  177
+	if (not_cached)
  178
+		paddr |= 4;
  179
+
  180
+	asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : );
  181
+	asm volatile("wcsr TLBPADDR, %0" :: "r"(paddr) : );
  182
+}
  183
+\end{lstlisting}
  184
+
  185
+\subsection{Invalidate a TLB entry or Flush the entire TLB}
  186
+
  187
+First, you need to do a logical "OR" operation on the virtual address to set vaddr[2:0] according to your needs:
  188
+
  189
+\begin{itemize}
  190
+	\item vaddr[2] set to 1 will trigger a flush of the entire selected TLB
  191
+	\item vaddr[1] set to 1 will trigger the invalidation of the entry indexed by vaddr[21:12] inside the selected TLB
  192
+	\item vaddr[0] set to 1 means you want to operate on DTLB, use 0 for ITLB
  193
+\end{itemize}
  194
+
  195
+The action is triggered upon the write of the OR'ed virtual address to the TLBVADDR CSR.
  196
+
  197
+Code samples:
  198
+
  199
+\begin{lstlisting}
  200
+
  201
+#define PAGE_SIZE (1 << 12)
  202
+#define PAGE_MASK (PAGE_SIZE - 1)
  203
+
  204
+void invalidate_dtlb_entry(unsigned int vaddr)
  205
+{
  206
+	vaddr &= ~PAGE_MASK; // Make sure page offset is zeroed
  207
+	/*
  208
+	 * 1 because we are addressing DTLB
  209
+         * 2 because we want to invalidate a specific line
  210
+	 */
  211
+	vaddr |= 1 | 2;
  212
+
  213
+	asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : );
  214
+}
  215
+
  216
+void invalidate_itlb_entry(unsigned int vaddr)
  217
+{
  218
+	vaddr &= ~PAGE_MASK; // Make sure page offset is zeroed
  219
+	vaddr |= 2; // 2 because we want to invalidate a specific line
  220
+
  221
+	asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : );
  222
+}
  223
+
  224
+void flush_dtlb(void)
  225
+{
  226
+	unsigned int cmd = 1 | 4;
  227
+	asm volatile("wcsr TLBVADDR, %0" :: "r"(cmd) : );
  228
+}
  229
+
  230
+void flush_itlb(void)
  231
+{
  232
+	unsigned int cmd = 4;
  233
+	asm volatile("wcsr TLBVADDR, %0" :: "r"(cmd) : );
  234
+}
  235
+
  236
+\end{lstlisting}
  237
+
  238
+\subsection{A sum up of TLB actions}
  239
+
  240
+To summarize all possible TLB actions:
  241
+
  242
+\begin{itemize}
  243
+	\item Writing to TLBPADDR triggers the update of a TLB entry according to the content of TLBVADDR and TLBPADDR
  244
+	\item Writing to TLBVADDR either prepares for updating a TLB entry if it is followed by a write operation to TLBPADDR or immediately triggers an action determined by bits vaddr[2:0] written to TLBVADDR. In the latter case, the action is performed on the TLB entry indexed by vaddr[21:12].
  245
+\end{itemize}
  246
+
  247
+Possible actions triggered by writing to TLBVADDR:
  248
+
  249
+\begin{tabular}{|c|l|}
  250
+\hline
  251
+\bf{vaddr[2:0]} & \bf{action} \\
  252
+\hline
  253
+000 & No Operation, used for updating TLB entry by writting to TLBPADDR \\
  254
+\hline
  255
+011 & Invalidate DTLB entry indexed by vaddr[21:12] \\
  256
+\hline
  257
+010 & Invalidate ITLB entry indexed by vaddr[21:12] \\
  258
+\hline
  259
+101 & Flush DTLB \\
  260
+\hline
  261
+100 & Flush ITLB \\
  262
+\hline
  263
+11x & Not deterministic, do not use untill it's defined by a future MMU revision \\
  264
+\hline
  265
+\end{tabular}
  266
+
  267
+\section{Interact with the MMU}
  268
+
  269
+In order to interact with the MMU, a new CSR (Control and Status Register) has been added: PSW (Processor Status Word)
  270
+
  271
+\begin{tabular}{|c|l|}
  272
+\hline
  273
+\bf{Bits} & \bf{Meaning} \\
  274
+\hline
  275
+31:12 & unused \\
  276
+\hline
  277
+11 & BUSR: Breakpoint backup of USR\\
  278
+\hline
  279
+10 & EUSR: Exception backup of USR\\
  280
+\hline
  281
+9 & USR: User mode bit\\
  282
+\hline
  283
+8 & BDTLBE: Breakpoint backup of DTLBE \\
  284
+\hline
  285
+7 & EDTLBE: Exception backup of DTLBE \\
  286
+\hline
  287
+6 & DTLBE: DTLB enabled \\
  288
+\hline
  289
+5 & BITLBE: Breakpoint backup of ITLBE \\
  290
+\hline
  291
+4 & EITLBE: Exception backup of ITLBE \\
  292
+\hline
  293
+3 & ITLBE: ITLB enabled \\
  294
+\hline
  295
+2 & IE.BIE $^{*}$ \\
  296
+\hline
  297
+1 & IE.EIE $^{*}$ \\
  298
+\hline
  299
+0 & IE.IE $^{*}$ \\
  300
+\hline
  301
+\end{tabular}
  302
+
  303
+(*) PSW[2:0] is a real mirror of IE[2:0] as described in the LatticeMico32 Processor Reference Manuel p. 10 Table 5 "Fields of the IE CSR". In any condition: PSW[2:0] == IE[2:0]. IE CSR is mirrored in the lower bits of PSW CSR for compatibility reasons. Old programs (ignorant of the MMU) will keep using IE CSR, newer programs can use PSW to deal with MMU and interrupts.
  304
+
  305
+\subsection{Activate the MMU}
  306
+
  307
+Activating the MMU is done by activating each TLB by writing 1 into PSW[ITLBE] and PSW[DTLBE].
  308
+
  309
+\begin{lstlisting}
  310
+void enable_mmu(void)
  311
+{
  312
+	asm volatile("rcsr r1, PSW\n\t"
  313
+		     "ori r1, r1, 72\n\t"
  314
+		     "wcsr PSW, r1" ::: "r1");
  315
+}
  316
+\end{lstlisting}
  317
+
  318
+\subsection{Deactivate the MMU}
  319
+
  320
+Disactivating the MMU is done by deactivating each TLB by writing 0 into PSW[ITLBE] and PSW[DTLBE].
  321
+
  322
+\begin{lstlisting}
  323
+void disable_mmu(void)
  324
+{
  325
+	unsigned int mask = ~(72);
  326
+	asm volatile("rcsr r1, PSW\n\t"
  327
+		     "and r1, r1, %0\n\t"
  328
+		     "wcsr PSW, r1" :: "r"(mask) : "r1");
  329
+}
  330
+\end{lstlisting}
  331
+
  332
+\section{TLB lookups}
  333
+
  334
+This section explains in details how the TLB lookup takes place: what happens in which condition.
  335
+
  336
+If the TLBs are disabled, nothing special happens, LM32 will behave as if it has been synthetized without MMU support (except for the presence of PSW, TLBVADDR and TLBPADDR).
  337
+
  338
+If DTLB is enabled:
  339
+
  340
+In parallel of the Data Cache lookup, the DTLB lookup happens.
  341
+
  342
+If the DTLB contains an invalid TLB entry, then the DTLB generates a DTLB miss exception.
  343
+
  344
+If the DTLB contains a valid TLB entry, the DTLB uses vaddr[21:11] as an index to the DTLB and compares vaddr[31:22] with the DTLB entry tag, if this comparison fails: the DTLB generates a DTLB miss exception as well.
  345
+
  346
+If the DTLB contains a valid TLB entry and the vaddr[21:11] used to index the DTLB matches the DTLB entry tag:
  347
+
  348
+\begin{itemize}
  349
+	\item Then if the memory access was a READ (lb, lbu, lh, lhu, lw)
  350
+	\begin{itemize}
  351
+		\item the Data Cache compares the tag of its selected line with the paddr[31:11] extracted from the DTLB to check if we Hit or Miss the Data Cache
  352
+		\item Then the usual Cache refill happens (using the physical address) in case of a cache miss
  353
+	\end{itemize}
  354
+	\item Then if the memory access was a WRITE (sb, sh, sw)
  355
+	\begin{itemize}
  356
+		\item The read-only bit flag contained in the DTLB entry is checked
  357
+		\begin{itemize}
  358
+			\item If it is set: it triggers a DTLB fault CPU exception
  359
+			\item If it's not set: The Data Cache does the same tag comparison as with the READ operation to check for Cache Hit/Miss
  360
+		\end{itemize}
  361
+	\end{itemize}
  362
+\end{itemize}
  363
+
  364
+All these behaviours are summed up in the following table:
  365
+\newline
  366
+
  367
+\begin{tabular}{|l l p{0.5\textwidth}|}
  368
+\hline
  369
+\bf{Exception} & \bf{EID} & \bf{Condition} \\
  370
+\hline
  371
+ITLB miss & 8 &
  372
+\parbox{0.5\textwidth}{
  373
+\begin{itemize}
  374
+	\item ITLB entry is invalid
  375
+	\item ITLB entry tag does not match vaddr[21:12]
  376
+\end{itemize} }
  377
+\\
  378
+\hline
  379
+DTLB miss & 9 &
  380
+\parbox{0.5\textwidth}{
  381
+\begin{itemize}
  382
+	\item DTLB entry is invalid
  383
+	\item DTLB entry tag does not match vaddr[21:12]
  384
+\end{itemize} }
  385
+\\
  386
+\hline
  387
+DTLB fault & 10 &
  388
+DTLB entry is valid \newline\textbf{AND} the entry tag matches vaddr[21:12] \newline\textbf{AND} the read-only bit is set \newline\textbf{AND} the cpu is doing a memory store
  389
+\\
  390
+\hline
  391
+Privilege exception & 11 &
  392
+\parbox{0.5\textwidth}{
  393
+PSW[USR] == 1 and one of the following instruction is executed:\newline
  394
+\begin{itemize}
  395
+	\item iret
  396
+	\item bret
  397
+	\item wcsr
  398
+\end{itemize}
  399
+}
  400
+\\
  401
+\hline
  402
+\end{tabular}
  403
+
  404
+The "\textbf{Condition}" column's content is a logical \textbf{OR} between each bullet point except for the DTLB fault where the logical \textbf{AND} is explicitly specified.
  405
+
  406
+\section{CSR registers special behaviours}
  407
+
  408
+Upon any exception, PSW CSR is modified automatically by the CPU pipeline itself:
  409
+
  410
+\begin{itemize}
  411
+	\item PSW[ITLBE] is saved in PSW[EITLBE] and the former is cleared
  412
+	\item PSW[DTLBE] is saved in PSW[EDTLBE] and the former is cleared
  413
+	\item PSW[USR] is saved in PSW[EUSR] and the former is cleared
  414
+	\item TLBVADDR is pre-charged with the virtual PFN (page frame number) which caused an exception (in case of TLB miss or fault only)
  415
+	\begin{itemize}
  416
+		\item TLBVADDR[0] is set to 1 when then exception is caused by DTLB, else it is clear
  417
+		\item In case of DTLB miss or fault, TLBVADDR[31:12] is pre-charged the virtual PFN whose load or store operation caused the exception
  418
+		\item In case of ITLB miss, TLBVADDR[31:12] is pre-charged with the virtual PFN of the instruction whose fetch caused the exception
  419
+		\item This mechanism allows for faster TLB miss handling because TLBVADDR is already pre-charged with the right value
  420
+		\item Since TLBVADDR is pre-charged with the virtual PFN: page offset bits (TLBVADDR[11:1]) are not set
  421
+	\end{itemize}
  422
+	\item TLBBADVADDR$^{**}$ is written with a virtual address when an exception is caused by a TLB miss
  423
+	\begin{itemize}
  424
+		\item In case of ITLB miss, TLBBADVADDR[31:1] contains the PC address whose fetch triggered the ITLB miss exception
  425
+		\item In case of DTLB miss or fault, TLBBADVADDR[31:1] contains the virtual address whose load or store operation caused the exception
  426
+		\item Unlike TLBVADDR, TLBBADVADDR page offset bits are set according to what caused the exception
  427
+	\end{itemize}
  428
+\end{itemize}
  429
+
  430
+$^{*}$ In LM32 pipeline, exception happens in the e\textbf{X}ecute stage, even though they may be triggered in the \textbf{F}etch or \textbf{M}emory stage for example. Load and Store instructions therefore stall the pipeline for 1 cycle during the e\textbf{X}ecute stage if the DTLB is activated.
  431
+
  432
+$^{**}$ TLBBADVADDR is the same CSR ID as TLBPADDR. The former is read-only and the latter is write-only.
  433
+
  434
+Upon any breakpoint hit, PSW CSR is also modified by the CPU pipeline:
  435
+
  436
+\begin{itemize}
  437
+	\item PSW[ITLBE] is saved in PSW[BITLBE] and the former is cleared
  438
+	\item PSW[DTLBE] is saved in PSW[BDTLBE] and the former is cleared
  439
+	\item PSW[USR] is saved in PSW[BUSR] and the former is cleared
  440
+\end{itemize}
  441
+
  442
+This means MMU is \textbf{turned off} upon CPU exception or breakpoint hit.
  443
+
  444
+Upon return from exception (\textbf{iret} instruction), PSW CSR is also modified by the CPU pipeline:
  445
+
  446
+\begin{itemize}
  447
+	\item PSW[ITLBE] is restored using the value from PSW[EITLBE]
  448
+	\item PSW[DTLBE] is restored using the value from PSW[EDTLBE]
  449
+	\item PSW[USR] is restored using the value from PSW[EUSR]
  450
+\end{itemize}
  451
+
  452
+Upon return from breakpoint (\textbf{bret} instruction), PSW CSR is also modified by the CPU pipeline:
  453
+
  454
+\begin{itemize}
  455
+	\item PSW[ITLBE] is restored using the value from PSW[BITLBE]
  456
+	\item PSW[DTLBE] is restored using the value from PSW[BDTLBE]
  457
+	\item PSW[USR] is restored using the value from PSW[BUSR]
  458
+\end{itemize}
  459
+
  460
+\section*{Copyright notice}
  461
+Copyright \copyright 2013 Yann Sionneau. \\
  462
+Permission is granted to copy, distribute and/or modify this document under the terms of the BSD License.
  463
+
  464
+\end{document}

0 notes on commit 4c0f6c5

Please sign in to comment.
Something went wrong with that request. Please try again.