I have recently started to work on MIT's Jos. After some time, I plan to summarize it. As the basis of several subsequent experiments, there may be many errors. Please give me more advice.
1. Lab1-Booting a PC
Lab1 is about the PC startup process. PC boot follows BIOS loading (real mode)-> BIOS jump to boot loader (the address in Jos is 0x7c00)-> Boot Loader imports OS kernel. In the first step, you can use GDB to view each BIOS Assembly command that is executed from 0xfe05b after the PC is powered on. Basically, this is about some hardware Io settings, for more information about these BIOS commands, see here.
Next, jump to the boot loader and first execute the Assembly in Boot. S.CodeIn this example, convert the real mode to the protection mode. First, several constant values are set, such as prot_mode_cseg = 0x8, which indicates that the segment offset of the new segment is 0x8; next, let's look at the definition of gdt (in the boot. the last few lines of S), which defines the gdt used to jump to the 32-bit protection mode. Note that the gdt defined by the kernel will be re-used after the kernel is loaded, the two are different. Here, three gdt segments are defined: NULL segments (seg_null), code segments (Code SEG), and data segments (Data SEG). Take the code segment definition as an example: seg (sta_x | sta_r, 0x0, 0 xffffffff (For details, refer to INC/MMU. for the macro definition of SEG in row H 145th, SEG accepts three parameters to define the segment type, base address, and segment limitation respectively. This sentence defines the type, base address, and boundary of the segment, the base address is 0x0, indicating that the virtual address is physical address, which is equivalent to disabling field ing. Next we can see the code for switching to the 32-bit protection mode in the real mode:
1. Close the CLI and ensure that boot. S is the only command executed at this time.Program;
2. Enable A20 bits. If you are interested in this step, Google it o (Alipay _ Alipay) O ~ It has little to do with understanding jump
3. lgdt gdtdesc//Load definedGdt,GdtdescIs followedGdtDefinedGdtAddress
Movl % Cr0, % eax//Modify the following three statements:Cr0RegisterPEBit, enable32Bit protection mode
Orl $ cr0_pe_on, % eax
Movl % eax, % Cr0
4. Long jump command ljmp $ prot_mode_cseg, $ protcseg jumps to the next code to skip the remaining 16-bit commands. Here we can see that the new gdt has played a role, SEG = prot_mode_cseg, offset = protcseg, because the base address of cseg is 0, the program jumps to the protcseg offset of the code segment
5. Where is protcseg? Very conspicuous! It is in the following, where the commands re-write the DS, es and other segment register values, the last sentence jump to the bootmain function, start to read the kernel, OK, the real mode jump to the protection mode is complete! The bootmain function is located in Boot/main. in C, the kernel is read from the hard disk sector. It is troublesome to run various ide I/O commands. Be patient with your own shoes ~
All the commands described above can be seen in the compiled OBJ/boot. ASM file. We recommend that you read this file to have a clear understanding of the entire process.
After redirecting to the Jos kernel, the first file to be executed is Kern/entry. S. The main function and layout of this file are similar to those of the above boot. S. It is the process of creating a new gdt. Why do we need a new gdt? The reason is that the link address and load address of the kernel are different. To address the correct physical address, we must subtract the virtual address from the kernbase to obtain the correct physical address, this is the new gdt (defined in entry. in the last few lines of S, mygdt), the base addresses of codeseg and dataseg are defined as-kernbase ~
But there are several differences between the two files. One is entry. s defines a reloc (x) Macro, reloc (x) = (x)-kernbase), which is used to load the new gdt address in the lgdt command, because the new gdt has not yet taken effect, the old gdt is still executed, that is, the segment base address = 0; the second is to define the base address of the function call stack movl $0x0, % EBP, this sentence is also the end condition of the exercise 10 loop jump. Then the kernel calls the i386_init () function, which is the key to subsequent experiments ~
As for the number of exercise, I personally feel that it is not very difficult. After all, there are also correspondingSource code, Khan... I have an additional exercise in this Tsinghua version -- detecting processor features, which reads information about the CPU from the eflags register, and implements the functions for reading and writing registers, check the call. To flip the 21st-bit value of this Register, the corresponding main code is pasted below in an exclusive or 1 manner:
Bool
Is_cpuid_supported ()
{
Uint32_t eflags = read_eflags ();
Write_eflags (eflags ^ 0x00200000 );
If (read_eflags () = eflags) return 0;
Return 1;
}
By Feitian