Skip to content

Commit

Permalink
Debugging minor changes (#88)
Browse files Browse the repository at this point in the history
* Minor fixes in the appendices section

* minor syntax fix to acpi chapter

* clarify length field in acpisdt header

* Fix file name (issue #86)

* minor changes to memory management section

* Minor changes to heap chapter

* Requested changes
  • Loading branch information
dreamos82 authored May 14, 2024
1 parent cd440f3 commit 1a02d1e
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 34 deletions.
2 changes: 1 addition & 1 deletion 01_Build_Process/03_Gnu_Makefiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 6 additions & 4 deletions 02_Architecture/06_ACPITables.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion 04_Memory_Management/01_Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
28 changes: 14 additions & 14 deletions 04_Memory_Management/03_Paging.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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:
Expand Down
10 changes: 5 additions & 5 deletions 04_Memory_Management/05_Heap_Allocation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
```
Expand All @@ -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:
Expand All @@ -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:
Expand Down
16 changes: 8 additions & 8 deletions 99_Appendices/F_Debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion 99_Appendices/J_Updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Third Book release

### Revision 3

Release date: April 2024
Release date: April 2024.
Fourth book release

* Typo fixes
Expand Down

0 comments on commit 1a02d1e

Please sign in to comment.