diff --git a/01_Build_Process/03_Gnu_Makefiles.md b/01_Build_Process/03_Gnu_Makefiles.md index 2f8ba885..74088f77 100644 --- a/01_Build_Process/03_Gnu_Makefiles.md +++ b/01_Build_Process/03_Gnu_Makefiles.md @@ -6,7 +6,7 @@ There's a million and one excellent resources on makefiles out there, so this ch There's multiple different make-like programs out there, a lot of them share a common base, usually the one specified in posix. GNU make also has a bunch of custom extensions it adds, which can be quite useful. These will render our Makefiles only usable for gnu make, which is the most common version. So this is fine, but if we care about being fully portable between make versions, we'll have to avoid these. -If we want to use gnu make extensions, we now have a makefile that wont run under every version of make. Fortunately the folks at gnu allow us to name our makefile `GNUMakefile` instead, and this will run as normal. However other versions of make won't see this file, meaning they wont try to run it. +If we want to use gnu make extensions, we now have a makefile that wont run under every version of make. Fortunately the folks at gnu allow us to name our makefile `GNUmakefile` instead, and this will run as normal. However other versions of make won't see this file, meaning they wont try to run it. ## Simple Makefile Example diff --git a/02_Architecture/06_ACPITables.md b/02_Architecture/06_ACPITables.md index 77b4afe0..1aa5dfae 100644 --- a/02_Architecture/06_ACPITables.md +++ b/02_Architecture/06_ACPITables.md @@ -20,8 +20,8 @@ The newer version is backward compatible with the older. Accessing the RSDP register depends on the boot system used, if we are using grub, we get a copy of the RSDT/XSDT in one of the multiboot2 header tags. The specs contains two possible tags for the RSDP value, which one is used depend on the version: -* For the version 1 the MULTIBOOT_TAG_TYPE_ACPI_OLD is used (type 14) -* For the version 2 the MULTIBOOT_TAG_TYPE_ACPI_NEW is used (type 15) +* For the version 1 the `MULTIBOOT_TAG_TYPE_ACPI_OLD` is used (type 14) +* For the version 2 the `MULTIBOOT_TAG_TYPE_ACPI_NEW` is used (type 15) Both headers are identical, with the only difference being in the type value, they are composed of just two fields: @@ -113,6 +113,8 @@ struct ACPISDTHeader { ``` * The second part is the table itself, every SDT has its own table +It's important to note that hte `Length` field contains the size of the table, header included. + #### RSDT vs XSDT These 2 tables have the same purpose and are mutually exclusive. If the latter exists, the former is to be ignored, otherwise use the former. @@ -142,8 +144,8 @@ ACPISDTHeader* header = (ACPISDTHeader*)(use_xsdt ? xsdt->sdtAddresses[n] : (uin ### Some useful infos -* Be aware that the Signature in the RSD* structure is not null terminated. This means that if we try to print it, you will most likely end up in printing garbage in the best case scenario. -* The RSDT Data is an array of uint32_t addresses while the XSDT data is an array of uint64_t addresses. The number of items in the RSDT and XSDT can be computed in the following way: +* Be aware that the `Signature` the signature in any of the ACPI tables are not null-terminated. This means that if we try to print it, you will most likely end up in printing garbage in the best case scenario. +* The RSDT Data is an array of `uint32_t` addresses while the XSDT data is an array of `uint64_t` addresses. The number of items in the RSDT and XSDT can be computed in the following way: ```c //for the RSDT diff --git a/04_Memory_Management/01_Overview.md b/04_Memory_Management/01_Overview.md index 534648f3..bbd6052d 100644 --- a/04_Memory_Management/01_Overview.md +++ b/04_Memory_Management/01_Overview.md @@ -28,7 +28,7 @@ Each of the layers has a dedicated chapter, however we'll start with a high leve ## A Word of Wisdom -As said at the beginning of this chapter Memory management is one of the most important parts of a kernel, as every other part of the kernel will interact with it in some way. It's worth taking the extra time to consider what features we want our PMM and VMM to have, and the ramifications. A little planning now can save us a lot of heacaches and rewriting code later! +As said at the beginning of this chapter Memory management is one of the most important parts of a kernel, as every other part of the kernel will interact with it in some way. It's worth taking the extra time to consider what features we want our PMM and VMM to have, and the ramifications. A little planning now can save us a lot of headaches and rewriting code later! ## PMM - Physical Memory Manager diff --git a/04_Memory_Management/03_Paging.md b/04_Memory_Management/03_Paging.md index 51a3be5e..6190d8b2 100644 --- a/04_Memory_Management/03_Paging.md +++ b/04_Memory_Management/03_Paging.md @@ -213,11 +213,11 @@ Note about PWT and PCD, the definiton of those bits depends on whether PAT (page If we are using 2MB pages this is how the address will be handled by the paging mechanism: -| | | | | | -|------------|-----------|---------------|------------|-----------| -| 63 .... 48 | 47 ... 39 | 38 ... 30 | 29 .. 21 | 20 ... 0 | -| 1 ... 1 | 1 ... 1 | 1 ... 0 | 0 ... 0 | 0 ... 0 | -| Sgn. ext | PML4 | PDPR | Page dir | Offset | +| | | | | | +|--------------|-----------|---------------|--------------|------------| +| 63 .... 48 | 47 ... 39 | 38 ... 30 | 29 .. 21 | 20 ... 0 | +| 1 ... 1 | 1 ... 1 | 1 ... 0 | 0 ... 0 | 0 ... 0 | +| **Sgn. ext** | **PML4** | **PDPR** | **Page dir** | **Offset** | * Bits 63 to 48, not used in address translation. * Bits 47 ... 39 are the PML4 entry. @@ -231,11 +231,11 @@ Every table has 512 elements, so we have an address space of $2^{512}*2^{512}*2^ If we are using 4kB pages this is how the address will be handled by the paging mechanism: -| | | | | | | -|-----------|-----------|-----------|-----------|-------------|-----------| -| 63 ... 48 | 47 ... 39 | 38 ... 30 | 29 ... 21 | 20 ... 12 | 11 ... 0 | -| 1 ... 1 | 1 ... 1 | 1 ... 0 | 0 ... 0 | 0 ... 0 | 0 ... 0 | -| Sgn. ext | PML4 | PDPR | Page dir | Page Table | Offset | +| | | | | | | +|--------------|-----------|-----------|--------------|----------------|-------------| +| 63 ... 48 | 47 ... 39 | 38 ... 30 | 29 ... 21 | 20 ... 12 | 11 ... 0 | +| 1 ... 1 | 1 ... 1 | 1 ... 0 | 0 ... 0 | 0 ... 0 | 0 ... 0 | +| **Sgn. ext** | **PML4** | **PDPR** | **Page dir** | **Page Table** | **Offset** | * Bits 63 to 48, not used in address translation. * Bits 47 ... 39 are the PML4 entry. @@ -257,10 +257,10 @@ The idea of the page fault handler is to look at the error code and faulting add The error code has the following structure: -| | | | | | | -|-----------|-------|--------|------|-------|-----| -| 31 .... 4 | 4 | 3 | 2 | 1 | 0 | -| Reserved | I/D | RSVD | U/S | W/R | P | +| | | | | | | +|------------|---------|----------|---------|---------|-------| +| 31 .... 4 | 4 | 3 | 2 | 1 | 0 | +| _Reserved_ | **I/D** | **RSVD** | **U/S** | **W/R** | **P** | The meanings of these bits are expanded below: diff --git a/04_Memory_Management/05_Heap_Allocation.md b/04_Memory_Management/05_Heap_Allocation.md index 580fe96c..2b909029 100644 --- a/04_Memory_Management/05_Heap_Allocation.md +++ b/04_Memory_Management/05_Heap_Allocation.md @@ -55,7 +55,7 @@ Well the answer is, as we already know: it allocates memory, specifically in byt If we are writing an OS, we already know that RAM can be viewed as a very long array, where the index into this array is the memory address. The allocator is returning these indices. So we can already see the first detail we'll need to keep track of: next available address. -Let's start with a simple example, assume that we have an address space of 100 bytes, nothing has allocated yet, and the program makes the following consecutive `alloc()` calls: +Let's start with a simple example, assume that we have an address space of 100 bytes, nothing has been allocated yet, and the program makes the following consecutive `alloc()` calls: ```c alloc(10); @@ -94,7 +94,7 @@ uint8_t *cur_heap_position = 0; //Just an example, in the real world you would u //a virtual address allocated from the VMM. void *first_alloc(size_t size) { uint8_t *addr_to_return = cur_heap_position; - cur_heap_position= cur_heap_position + size; + cur_heap_position = cur_heap_position + size; return (void*) addr_to_return; } ``` @@ -111,7 +111,7 @@ void first_free(void *ptr) { Yeah... that's right, it's not an error. A bump allocator does not have `free()`. -Why? Because we are not keeping track of the allocated memory, so we can't just update the `cur_heap_position` variable with the address of ptr, because we don't know who is using the memory after ptr. So we are forced just to do nothing. +Why? Because we are not keeping track of the allocated memory, so we can't just update the `cur_heap_position` variable with the address of ptr, since we don't know who is using the memory after ptr. So we are forced just to do nothing. Even if probably useless let's see what are the pros and cons of this approach: @@ -128,9 +128,9 @@ Of course the cons are probably pretty clear and make this algorithm pretty usel * There is no way to traverse the heap, because we don't keep track of the allocations. * We will eventually run out of memory (OOM - out of memory). -### Part 2: Adding Free() +### Part 2: Adding free() -The main problem with this algorithm is that we don't keep track of what we have allocated in the past, so we are not able to free that memory in the future, when it's no longer used. +The main problem with the algorithm outlined above is that we don't keep track of what we have allocated in the past, so we are not able to free that memory in the future, when it's no longer used. Now we're going to build a new allocator based on the one we just implemented. The first thing to do is try to figure out what are the information we need to keep track of from the previous allocations: diff --git a/99_Appendices/F_Debugging.md b/99_Appendices/F_Debugging.md index a756df60..d32836a0 100644 --- a/99_Appendices/F_Debugging.md +++ b/99_Appendices/F_Debugging.md @@ -24,10 +24,10 @@ symbol-file path/to/kernel.bin Below a list of some useful gdb commands -* Show register content: *info register reg* where reg is the register we need -* Set breakpoint to specific address: *break 0xaddress* -* Show memory address content: *x/nfu addr* wher: n is the number of iterations f the format (x = hex) and the addr we want to show -* We can show also the content of pointer stored into a register: *x/h ($rax)* shows the content of memory address pointed by rax +* Show register content: `info register reg` where reg is the register we need +* Set breakpoint to specific address: `break 0xaddress` +* Show memory address content: `x/nfu addr` where: *n* is the number of iterations *f* the format (*x* = hex) and the *addr* we want to show +* We can show also the content of pointer stored into a register: `x/h ($rax)` shows the content of memory address pointed by rax ### Navigation @@ -223,10 +223,10 @@ QEMU 6.1.0 monitor - type 'help' for more information From here is possible to send commands directly to the emulator, below a list of useful commands: -* **help** Well this is the first command to get some help on how to use the monitor. -* **info xxxx** It will print several information, depending on xxxx for example: *info lapic* will show the current status of the local apic, *info mem* will print current virtual memory mappings, *info registers* will print the registers content. -* **x/cf address** where c is the number of items we want to display in decimal, f is the format (`x` for hex, `c` for char, etc) display the content of c virtual memory locations starting from address. -* **xp/cf address** same as above, but for physical memory. +* `help` Well this is the first command to get some help on how to use the monitor. +* `info xxxx` It will print several information, depending on xxxx for example: `info lapic` will show the current status of the local apic, `info mem` will print current virtual memory mappings, `info registers` will print the registers content. +* `x /cf address` where c is the number of items we want to display in decimal, f is the format (`x` for hex, `c` for char, etc) display the content of c virtual memory locations starting from address. +* `xp /cf address` same as above, but for physical memory. #### Info mem & Info tlb diff --git a/99_Appendices/J_Updates.md b/99_Appendices/J_Updates.md index 0bd5a1e5..91d0bfd2 100644 --- a/99_Appendices/J_Updates.md +++ b/99_Appendices/J_Updates.md @@ -40,7 +40,7 @@ Third Book release ### Revision 3 -Release date: April 2024 +Release date: April 2024. Fourth book release * Typo fixes