1.
Void sched_init (void)
{...
00392
Set_tss_desc (gdt + first_tss_entry, & (init_task.task.tss ));
00393
Set_ldt_desc (gdt + first_ldt_entry, & (init_task.task.ldt ));
...}
Gdt: Global Descriptor. A total of 256 descriptors are defined. gdt itself is not a segment but a linear space.
. The base address and length of gdt must be loaded into the GDTR register. Gdt Base
The address must be aligned with 8 bytes for optimal running efficiency. Because gdt descriptive symbols are in 8 bytes
.
2. Structure Description
Typedef struct desc_struct {
Unsigned long A, B;
} Desc_table;
Here we use two standard four-byte long to store gdt and LDT.
First, the program runs on the virtual address (the actual program is in protection mode). The virtual address is
It consists of two parts: Segment selection symbol (16) + beam offset (32-bit valid address); Segment selection symbol
Access the corresponding segment description symbol. The segment base address, length limit, attribute, and virtual location provided by the segment descriptor
To construct a linear address.
A. segment selection character: the virtual address component is described above. The first 16 digits are the only identifier of the segment.
And provides the offset of a field in the segment descriptor table gdt. The specific composition is shown in the following table.
Description:
| 15-3 descriptor index | 2 is Ti | 1-0 is RPL |
Index: the index value is used to find specific segments in the corresponding Descriptor Table.
Ti: indicates whether it is gdt or LDT.
RPL: something similar to permission
Remark: a total of six segment delimiters are provided. The cs ds ss es FS Gs, in fact, the segment descriptor information is being accessed.
When asked, the CPU automatically loads a so-called shadow sending by decoding the 16-bit segment selector.
In the memory, the speed will be very fast. It can be used directly. Of course, it may not be visible to our users.
The existence and operation of this register.
B. segment descriptor table, which is also a type of segment descriptor table on gdt, used to provide segment Selector
To obtain the information of the bucket.
C: The final linear address is determined by the segment base address + virtual address segment offset provided in the segment descriptor.
Then obtain the final physical address based on the paging method.
3. description format
// The two lower-layer calls and the last implementation macro are used to call and set the TSS. The LDT segment describes the incubated content.
.
// N: the descriptor address, which is followed by a complete 8 word written from N to N + 7.
Segment descriptor.
// Add: The base address, that is, the base address of the segment saved in the segment information
// 0x8x indicates the type of TSS or LDT or the other.
# Define set_tss_desc (n, ADDR) _ set_tssldt_desc (char *)
(N), (INT) (ADDR), "0x89 ")
# Define set_ldt_desc (n, ADDR) _ set_tssldt_desc (char *)
(N), (INT) (ADDR), "0x82 ")
Segment descriptor format
32-bit high
| 31-24: Base Address
31 .. 24 | 23: G | 22: D/B | 21:0 | 20: AVL | 19-16: limit19.16 | 15: p | 14-13: DPL | 1
2: S | 11-8: type | 7-0: base address 23 .. 16 |
Low 32-bit
| 31-16: base address 15 .. 0 | 15-0: Segment limit |
4.
// See the specific process of loading segment Descriptors
# DEFINE _ set_tssldt_desc (n, ADDR, type)
// 104 indicates the segment length. The TSS can contain a maximum of 104 bytes, And the TSS can contain a maximum of 2 bytes. The value ranges from 15 to 0: Segment limit.
_ ASM _ ("movw $104, % 1/N/t "/
// Put the base address of the ax segment in the lower 16 bits 31-16: base address 15 .. 0
"Movw % ax, % 2/n/t "/
// Shifts the 16-bit value to the 16-bit address in height.
"Rorl $16, % eax/n/t "/
// Put the 8-bit low in the 16-bit high address into the 7-0: base address 23 .. 16
"Movb % Al, % 3/n/t "/
// Put the type in | 15: p | 14-13: DPL | 12: S | 11-8: Type
"Movb $" type ", % 4/n/t "/
// | 23: G | 22: D/B | 21:0 | 20: AVL | 19-16: limit19.. 16 | set all to zero
"Movb $0x00, % 5/n/t "/
// Put the 8-bit base address into the highest bit
"Movb % ah, % 6/n/t "/
"Rorl $16, % eax "/
// Enter rule % 0 specify the base address of the ADDR segment for eax storage, % 1 ~ % 6 are both specified M memory addresses respectively
Is n, n + 2, N + 4... address content
: "A" (ADDR), "M" (* (N), "M" (* (N + 2 )), "M" (* (N + 4 )),/
"M" (* (N + 5), "M" (* (N + 6), "M" (* (N + 7 ))/
)
5. Load Task TSS, LDT, and other segment Selection Characters and segment descriptors to the task register.
N: Segment offset of task N or local table
// The LTR or lldt command loads the % ax segment selector. You can see that this segment is
Macro _ tss and _ LDT.
# Define LTR (n) _ ASM _ ("LTR % ax": "A" (_ TSS (N )))
# Define lldt (n) _ ASM _ ("lldt % ax": "A" (_ LDT (N )))
// _ TSS _ LDT returns the information of the current task or the offset of the corresponding part of the local descriptor is relative
Here, we use a simple formula n * (8 + 8) + the number of start offsets * 8,
Here we should look at the location of these tss and LDT in gdt.
# DEFINE _ TSS (N) (unsigned long) n) <4) + (first_tss_entry <3 ))
# DEFINE _ LDT (N) (unsigned long) n) <4) + (first_ldt_entry <3 ))
6. Specific gdt Distribution
0 | null | unavailable gdt (0)
1 | system code segment CS | used by the operating system
2 | System Data Segment DS | Operating System Data Segment
3 | System Call | some call information characters
4 | tss0 | it is easy to see first_tss_entry = 4
5 | ldt0 | it is easy to see first_ldt_entry = 5
....
Each domain is 8 bytes so the nth TSS address = the base address of tss0 + (n * LSSi-LSSi-1)
= First_tss_entry * 8 + N * (8 + 8)
= First_tss_entry <3 + n <4
Similarly, you can push and export the LDT address for loading.
At this point, we have clearly understood the relationship between the segment selection operator segments and how to set them.
# Define STR (N)
_ ASM _ ("str % ax/n/t "/
"Subl % 2, % eax/n/t "/
"Shrl $4, % eax "/
: "= A" (N )/
: "A" (0), "I" (first_tss_entry <3 ))