diff --git a/notes/chapter3-page-tables b/notes/chapter3-page-tables
new file mode 100644
index 0000000..90b47bd
--- /dev/null
+++ b/notes/chapter3-page-tables
@@ -0,0 +1,37 @@
+Pages tables enables each process to have its own private memory space.
+It's slicing the memory into small pages (PGSIZE, 4KiB) so we can
+distribute it to many processes without much fragmentation, and enables
+xv6 a few tricks:
+
+- mapping the same memory (a trampoline page) in several address spaces
+- guarding kernel and user stacks with an unmapped page
+
+3.1 Paging hardware
+
+
+RISC-V instruction (both user and kernel) manipulate virtual addresses.
+Physical memory (RAM) = physical addresses (phy@ in the notes).
+Virtual memory = fake memory addresses (virt@ in the notes).
+RISC-V page table hardware maps virt@ and phy@.
+
+XV6 = Sv39 RISC-V = only bottom 39 bits for virt@ (top 25 bits are not used).
+2^39 @ = 2^27 page table entries (PTEs)
+a PTE = 44 bits of physical page number (PPN) + flags
+
+vocabulary, acronyms, et caetera:
+- physical/virtual addresses = phy@/virt@
+- Page Table Entry = PTE
+- Physical Page Number = PPN
+
+virt@ = [ 25-bit EXT ; 27-bit index ; 12-bit offset ]
+        ↑64          ↑39            ↑12             ↑0
+                              index = index to the PPN in the page table
+page table = 2^27 entries
+page table entry = [ 44-bit PPN ; 10-bit flags ]
+                   ↑54          ↑10            ↑0
+phy@ = [ 44-bit PPN (indexed by virt@ index) ; 12-bit virt@ offset ]
+       ↑56                                   ↑12                   ↑0
+
+virt@ = 39 (usable) bits, phy@ = 56 bits
+
+Paging hardware translates virt@ with its top 27 of the 39 bits to find a PTE