Merge pull request #693 from darkstar/fix_images

Fix (almost) all images by storing them locally
pull/694/head
0xAX 5 years ago committed by GitHub
commit 7730b08da7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -138,7 +138,7 @@ This will instruct [QEMU](https://www.qemu.org/) to use the `boot` binary that w
You will see:
![Simple bootloader which prints only `!`](http://oi60.tinypic.com/2qbwup0.jpg)
![Simple bootloader which prints only `!`](images/simple_bootloader.png)
In this example, we can see that the code will be executed in `16-bit` real mode and will start at `0x7c00` in memory. After starting, it calls the [0x10](http://www.ctyme.com/intr/rb-0106.htm) interrupt, which just prints the `!` symbol. It fills the remaining `510` bytes with zeros and finishes with the two magic bytes `0xaa` and `0x55`.
@ -250,7 +250,7 @@ X + sizeof(KernelBootSector) + 1
where `X` is the address of the kernel boot sector being loaded. In my case, `X` is `0x10000`, as we can see in a memory dump:
![kernel first address](http://oi57.tinypic.com/16bkco2.jpg)
![kernel first address](images/kernel_first_address.png)
The bootloader has now loaded the Linux kernel into memory, filled the header fields, and then jumped to the corresponding memory address. We now move directly to the kernel setup code.
@ -267,7 +267,7 @@ qemu-system-x86_64 vmlinuz-3.18-generic
then you will see:
![Try vmlinuz in qemu](http://oi60.tinypic.com/r02xkz.jpg)
![Try vmlinuz in qemu](images/try_vmlinuz_in_qemu.png)
Actually, the file `header.S` starts with the magic number [MZ](https://en.wikipedia.org/wiki/DOS_MZ_executable) (see image above), the error message that displays and, following that, the [PE](https://en.wikipedia.org/wiki/Portable_Executable) header:
@ -407,7 +407,7 @@ Let's look at all three of these scenarios in turn:
Here we set the alignment of `dx` (which contains the value of `sp` as given by the bootloader) to `4` bytes and check if it is zero. If it is, we set `dx` to `0xfffc` (The last 4-byte aligned address in a 64KB segment). If it is not zero, we continue to use the value of `sp` given by the bootloader (`0xf7f4` in my case). Afterwards, we put the value of `ax` (`0x1000`) into `ss`. We now have a correct stack:
![stack](http://oi58.tinypic.com/16iwcis.jpg)
![stack](images/stack1.png)
* The second scenario, (`ss` != `ds`). First, we put the value of [_end](https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld) (the address of the end of the setup code) into `dx` and check the `loadflags` header field using the `testb` instruction to see whether we can use the heap. [loadflags](https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L320) is a bitmask header defined as:
@ -433,11 +433,11 @@ Field name: loadflags
If the `CAN_USE_HEAP` bit is set, we put `heap_end_ptr` into `dx` (which points to `_end`) and add `STACK_SIZE` (the minimum stack size, `1024` bytes) to it. After this, if `dx` is not carried (it will not be carried, `dx = _end + 1024`), jump to label `2` (as in the previous case) and make a correct stack.
![stack](http://oi62.tinypic.com/dr7b5w.jpg)
![stack](images/stack2.png)
* When `CAN_USE_HEAP` is not set, we just use a minimal stack from `_end` to `_end + STACK_SIZE`:
![minimal stack](http://oi60.tinypic.com/28w051y.jpg)
![minimal stack](images/minimal_stack.png)
BSS Setup
--------------------------------------------------------------------------------
@ -466,7 +466,7 @@ The BSS section is used to store statically allocated, uninitialized data. Linux
First, the [__bss_start](https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld) address is moved into `di`. Next, the `_end + 3` address (+3 - aligns to 4 bytes) is moved into `cx`. The `eax` register is cleared (using the `xor` instruction), and the bss section size (`cx - di`) is calculated and put into `cx`. Then, `cx` is divided by four (the size of a 'word'), and the `stosl` instruction is used repeatedly, storing the value of `eax` (zero) into the address pointed to by `di`, automatically increasing `di` by four, repeating until `cx` reaches zero. The net effect of this code is that zeros are written through all words in memory from `__bss_start` to `_end`:
![bss](http://oi59.tinypic.com/29m2eyr.jpg)
![bss](images/bss.png)
Jump to main
--------------------------------------------------------------------------------

@ -166,7 +166,7 @@ The following steps are needed to get a physical address in protected mode:
Schematically it will look like this:
![linear address](http://oi62.tinypic.com/2yo369v.jpg)
![linear address](images/linear_address.png)
The algorithm for the transition from real mode into protected mode is:

@ -42,7 +42,7 @@ vga=<mode>
So we can add the `vga` option to the grub (or another bootloader's) configuration file and it will pass this option to the kernel command line. This option can have different values as mentioned in the description. For example, it can be an integer number `0xFFFD` or `ask`. If you pass `ask` to `vga`, you will see a menu like this:
![video mode setup menu](http://oi59.tinypic.com/ejcz81.jpg)
![video mode setup menu](images/video_mode_setup_menu.png)
which will ask to select a video mode. We will look at its implementation, but before diving into the implementation we have to look at some other things.

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

@ -25,7 +25,7 @@ One `control group subsystem` represents one kind of resources like a processor
Each of these control group subsystems depends on related configuration option. For example the `cpuset` subsystem should be enabled via `CONFIG_CPUSETS` kernel configuration option, the `io` subsystem via `CONFIG_BLK_CGROUP` kernel configuration option and etc. All of these kernel configuration options may be found in the `General setup → Control Group support` menu:
![menuconfig](http://oi66.tinypic.com/2rc2a9e.jpg)
![menuconfig](images/menuconfig.png)
You may see enabled control groups on your computer via [proc](https://en.wikipedia.org/wiki/Procfs) filesystem:

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -89,7 +89,7 @@ noexec [X86]
We can see it in the booting time:
![NX](http://oi62.tinypic.com/swwxhy.jpg)
![NX](images/NX.png)
After this we can see call of the:
@ -465,7 +465,7 @@ First of all it get the size of the page table buffer, it will be `INIT_PGT_BUF_
Or we can find it with `readelf` util:
![brk area](http://oi61.tinypic.com/71lkeu.jpg)
![brk area](images/brk_area.png)
After that we got physical address of the new `brk` with the `__pa` macro, we calculate the base address and the end of the page table buffer. In the next step as we got page table buffer, we reserve memory block for the brk area with the `reserve_brk` function:

@ -390,7 +390,7 @@ void __init setup_nr_cpu_ids(void)
Here `nr_cpu_ids` represents number of CPUs, `NR_CPUS` represents the maximum number of CPUs which we can set in configuration time:
![CONFIG_NR_CPUS](http://oi59.tinypic.com/28mh45h.jpg)
![CONFIG_NR_CPUS](images/CONFIG_NR_CPUS.png)
Actually we need to call this function, because `NR_CPUS` can be greater than actual amount of the CPUs in the your computer. Here we can see that we call `find_last_bit` function and pass two parameters to it:

@ -203,7 +203,7 @@ It setups setup the `startup` and `teardown` callbacks (second and third paramet
After this function we can see the kernel command line in the initialization output:
![kernel command line](http://oi58.tinypic.com/2m7vz10.jpg)
![kernel command line](images/kernel_command_line.png)
And a couple of functions such as `parse_early_param` and `parse_args` which handles linux kernel command line. You may remember that we already saw the call of the `parse_early_param` function in the sixth [part](https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-6.html) of the kernel initialization chapter, so why we call it again? Answer is simple: we call this function in the architecture-specific code (`x86_64` in our case), but not all architecture calls this function. And we need to call the second function `parse_args` to parse and handle non-early command line arguments.

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

@ -159,7 +159,7 @@ In other way, when the `CONFIG_X86_IO_APIC` kernel configuration option is set,
We remember from the previous parts, that the amount of processors we can set during Linux kernel configuration process with the `CONFIG_NR_CPUS` configuration option:
![kernel](http://oi60.tinypic.com/1zdm1dt.jpg)
![kernel](images/kernel.png)
In the first case (`CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT`), the `NR_IRQS` will be `4352`, in the second case (`CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT`), the `NR_IRQS` will be `768`. In my case the `NR_CPUS` is `8` as you can see in the my configuration, the `CPU_VECTOR_LIMIT` is `512` and the `IO_APIC_VECTOR_LIMIT` is `4096`. So `NR_IRQS` for my configuration is `4352`:

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

@ -397,7 +397,7 @@ memblock_dbg("memblock_reserve: [%#016llx-%#016llx] flags %#02lx %pF\n",
And you will see something like this:
![Memblock](http://oi57.tinypic.com/1zoj589.jpg)
![Memblock](images/memblock.png)
Memblock also has support in [debugfs](http://en.wikipedia.org/wiki/Debugfs). If you run the kernel on another architecture than `X86` you can access:

@ -125,7 +125,7 @@ Kernel hacking
menu of the Linux kernel configuration:
![kernel configuration menu](http://oi63.tinypic.com/2pzbog7.jpg)
![kernel configuration menu](images/kernel_configuration_menu1.png)
We may not only enable support of the `kmemcheck` mechanism in the Linux kernel, but it also provides some configuration options for us. We will see all of these options in the next paragraph of this part. Last note before we will consider how does the `kmemcheck` check memory. Now this mechanism is implemented only for the [x86_64](https://en.wikipedia.org/wiki/X86-64) architecture. You can be sure if you will look in the [arch/x86/Kconfig](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/Kconfig) `x86` related kernel configuration file, you will see following lines:
@ -165,7 +165,7 @@ Let's start from the initialization of this mechanism. We already know that to e
to the Linux kernel command line. The first two are clear, but the last needs a little explanation. This option switches the `kmemcheck` in a special mode when it will be turned off after detecting the first use of uninitialized memory. Actually this mode is enabled by default in the Linux kernel:
![kernel configuration menu](http://oi66.tinypic.com/y2eeh.jpg)
![kernel configuration menu](images/kernel_configuration_menu2.png)
We know from the seventh [part](https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-7.html) of the chapter which describes initialization of the Linux kernel that the kernel command line is parsed during initialization of the Linux kernel in `do_initcall_level`, `do_early_param` functions. Actually the `kmemcheck` subsystem consists from two stages. The first stage is early. If we will look at the [mm/kmemcheck.c](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/mm/kmemcheck.c) source code file, we will see the `param_kmemcheck` function which is will be called during early command line parsing:

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

@ -10,11 +10,11 @@ After writing some assembler code I began to understand how my program looks aft
I'm writing this part nine and a half months after I've started to learn from the source code of the Linux kernel and published the first [part](https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html) of this book. Now it contains forty parts and it is not the end. I decided to write this series about the Linux kernel mostly for myself. As you know the Linux kernel is very huge piece of code and it is easy to forget what does this or that part of the Linux kernel mean and how does it implement something. But soon the [linux-insides](https://github.com/0xAX/linux-insides) repo became popular and after nine months it has `9096` stars:
![github](http://i63.tinypic.com/2lbgc9f.png)
![github](images/github.png)
It seems that people are interested in the insides of the Linux kernel. Besides this, in all the time that I have been writing `linux-insides`, I have received many questions from different people about how to begin contributing to the Linux kernel. Generally people are interested in contributing to open source projects and the Linux kernel is not an exception:
![google-linux](http://i64.tinypic.com/2j4ot5e.png)
![google-linux](images/google_linux.png)
So, it seems that people are interested in the Linux kernel development process. I thought it would be strange if a book about the Linux kernel would not contain a part describing how to take a part in the Linux kernel development and that's why I decided to write it. You will not find information about why you should be interested in contributing to the Linux kernel in this part. But if you are interested how to start with Linux kernel development, this part is for you.
@ -102,7 +102,7 @@ $ cat /proc/config.gz | gunzip > ~/dev/linux/.config
If you are not satisfied with the standard kernel configuration that is provided by the maintainers of your distro, you can configure the Linux kernel manually. There are a couple of ways to do it. The Linux kernel root [Makefile](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/Makefile) provides a set of targets that allows you to configure it. For example `menuconfig` provides a menu-driven interface for the kernel configuration:
![menuconfig](http://i64.tinypic.com/zn5zbq.png)
![menuconfig](images/menuconfig.png)
The `defconfig` argument generates the default kernel configuration file for the current architecture, for example [x86_64 defconfig](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/configs/x86_64_defconfig). You can pass the `ARCH` command line argument to `make` to build `defconfig` for the given architecture:
@ -112,7 +112,7 @@ $ make ARCH=arm64 defconfig
The `allnoconfig`, `allyesconfig` and `allmodconfig` arguments allow you to generate a new configuration file where all options will be disabled, enabled, and enabled as modules respectively. The `nconfig` command line arguments that provides `ncurses` based program with menu to configure Linux kernel:
![nconfig](http://i68.tinypic.com/jjmlfn.png)
![nconfig](images/nconfig.png)
And even `randconfig` to generate random Linux kernel configuration file. I will not write about how to configure the Linux kernel or which options to enable because it makes no sense to do so for two reasons: First of all I do not know your hardware and second, if you know your hardware, the only remaining task is to find out how to use programs for kernel configuration, and all of them are pretty simple to use.
@ -273,7 +273,7 @@ We can now run our kernel in the virtual machine. As I already wrote I prefer [q
$ qemu-system-x86_64 -snapshot -m 8GB -serial stdio -kernel ~/dev/linux/arch/x86_64/boot/bzImage -initrd ~/dev/initrd_x86_64.gz -append "root=/dev/sda1 ignore_loglevel"
```
![qemu](http://i67.tinypic.com/15i6law.png)
![qemu](images/qemu.png)
From now we can run the Linux kernel in the virtual machine and this means that we can begin to change and test the kernel.
@ -330,7 +330,7 @@ Device Drivers
----> Digi EPCA PCI products
```
![dgap menu](http://i65.tinypic.com/v8o5rs.png)
![dgap menu](images/dgap_menu.png)
Now is time to make commit. I'm using following combination for this:
@ -424,7 +424,7 @@ CHECK: spaces preferred around that '|' (ctx:VxV)
Also you can see problematic places with the help of the `git diff`:
![git diff](http://oi60.tinypic.com/2u91rgn.jpg)
![git diff](images/git_diff.png)
* [Linus doesn't accept github pull requests](https://github.com/torvalds/linux/pull/17#issuecomment-5654674)

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

@ -20,7 +20,7 @@ There are many different ways to launch an application from a user perspective.
In this part we will consider the way when we just launch an application from the shell. As you know, the standard way to launch an application from shell is the following: We just launch a [terminal emulator](https://en.wikipedia.org/wiki/Terminal_emulator) application and just write the name of the program and pass or not arguments to our program, for example:
![ls shell](http://i66.tinypic.com/214w6so.jpg)
![ls shell](images/ls_shell.png)
Let's consider what does occur when we launch an application from the shell, what does shell do when we write program name, what does Linux kernel do etc. But before we will start to consider these interesting things, I want to warn that this book is about the Linux kernel. That's why we will see Linux kernel insides related stuff mostly in this part. We will not consider in details what does shell do, we will not consider complex cases, for example subshells etc.

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -93,7 +93,7 @@ The linear address translation is following:
schematically, we can imagine it like this:
![4-level paging](http://oi58.tinypic.com/207mb0x.jpg)
![4-level paging](images/4_level_paging.png)
Every access to a linear address is either a supervisor-mode access or a user-mode access. This access is determined by the `CPL` (current privilege level). If `CPL < 3` it is a supervisor mode access level, otherwise it is a user mode access level. For example, the top level page table entry contains access bits and has the following structure (See [arch/x86/include/asm/pgtable_types.h](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/include/asm/pgtable_types.h) for the bit offset definitions):

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 KiB

@ -259,7 +259,7 @@ The `jiffies` clock source uses the `NSEC_PER_JIFFY` multiplier conversion to sp
Where `CONFIG_HZ` can be one of the following values:
![HZ](http://i63.tinypic.com/v8d6ph.png)
![HZ](images/HZ.png)
This means that in our case the timer interrupt frequency is `250 HZ` or occurs `250` times per second or one timer interrupt each `4ms`.

@ -117,7 +117,7 @@ struct tvec_root {
type. Note that the value of the `TVR_SIZE` depends on the `CONFIG_BASE_SMALL` kernel configuration option:
![base small](http://i68.tinypic.com/aylkt2.png)
![base small](images/base_small.png)
that reduces size of the kernel data structures if disabled. The `v1` is array that may contain `64` or `256` elements where an each element represents a dynamic timer that will decay within the next `255` system timer interrupts. Next three fields: `tv2`, `tv3` and `tv4` are lists with dynamic timers too, but they store dynamic timers which will decay the next `2^14 - 1`, `2^20 - 1` and `2^26` respectively. The last `tv5` field represents list which stores dynamic timers with a large expiring period.

Loading…
Cancel
Save