Hooks to get the other CPUs into long mode
This commit is contained in:
		
							parent
							
								
									08900d56c8
								
							
						
					
					
						commit
						a8948fb246
					
				
					 2 changed files with 182 additions and 108 deletions
				
			
		| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
//! # ACPI
 | 
					//! # ACPI
 | 
				
			||||||
//! Code to parse the ACPI tables
 | 
					//! Code to parse the ACPI tables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use core::intrinsics::{atomic_load, atomic_store};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use memory::{Frame, FrameAllocator};
 | 
					use memory::{Frame, FrameAllocator};
 | 
				
			||||||
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
 | 
					use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +18,9 @@ pub mod rsdt;
 | 
				
			||||||
pub mod sdt;
 | 
					pub mod sdt;
 | 
				
			||||||
pub mod xsdt;
 | 
					pub mod xsdt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TRAMPOLINE: usize = 0x7E00;
 | 
				
			||||||
 | 
					const AP_STARTUP: usize = 0x8000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn init_sdt(sdt: &'static Sdt) {
 | 
					pub fn init_sdt(sdt: &'static Sdt) {
 | 
				
			||||||
    print!("  ");
 | 
					    print!("  ");
 | 
				
			||||||
    for &c in sdt.signature.iter() {
 | 
					    for &c in sdt.signature.iter() {
 | 
				
			||||||
| 
						 | 
					@ -37,16 +42,33 @@ pub fn init_sdt(sdt: &'static Sdt) {
 | 
				
			||||||
                    println!("        This is my local APIC");
 | 
					                    println!("        This is my local APIC");
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    if asp_local_apic.flags & 1 == 1 {
 | 
					                    if asp_local_apic.flags & 1 == 1 {
 | 
				
			||||||
 | 
					                        let ap_ready = TRAMPOLINE as *mut u64;
 | 
				
			||||||
 | 
					                        let ap_stack = unsafe { ap_ready.offset(1) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Set the ap_ready to 0, volatile
 | 
				
			||||||
 | 
					                        unsafe { atomic_store(ap_ready, 0) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Send INIT IPI
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            let icr = 0x00004500 | (asp_local_apic.id as u64) << 32;
 | 
					                            let icr = 0x00004500 | (asp_local_apic.id as u64) << 32;
 | 
				
			||||||
                            println!("        Sending IPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr));
 | 
					                            println!("        Sending IPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr));
 | 
				
			||||||
                            local_apic.set_icr(icr);
 | 
					                            local_apic.set_icr(icr);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Send START IPI
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            let icr = 0x00004600 | (asp_local_apic.id as u64) << 32;
 | 
					                            let ap_segment = (AP_STARTUP >> 12) & 0xFF;
 | 
				
			||||||
 | 
					                            let icr = 0x00004600 | ((asp_local_apic.id as u64) << 32) | ap_segment as u64; //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
 | 
				
			||||||
                            println!("        Sending SIPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr));
 | 
					                            println!("        Sending SIPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr));
 | 
				
			||||||
                            local_apic.set_icr(icr);
 | 
					                            local_apic.set_icr(icr);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Wait for trampoline ready
 | 
				
			||||||
 | 
					                        println!("        Waiting for AP {}", asp_local_apic.id);
 | 
				
			||||||
 | 
					                        while unsafe { atomic_load(ap_ready) } == 0 {
 | 
				
			||||||
 | 
					                            unsafe { asm!("pause" : : : : "intel", "volatile") };
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        println!("        AP {} is ready!", asp_local_apic.id);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        println!("        CPU Disabled");
 | 
					                        println!("        CPU Disabled");
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -63,15 +85,6 @@ pub fn init_sdt(sdt: &'static Sdt) {
 | 
				
			||||||
pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) -> Option<Acpi>
 | 
					pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) -> Option<Acpi>
 | 
				
			||||||
    where A: FrameAllocator
 | 
					    where A: FrameAllocator
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Stupidity of enormous proportion. Write the halt opcode to the 0'th physical address
 | 
					 | 
				
			||||||
    // so that START IPI's can halt the processor
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if active_table.translate_page(Page::containing_address(VirtualAddress::new(0))).is_none() {
 | 
					 | 
				
			||||||
            active_table.identity_map(Frame::containing_address(PhysicalAddress::new(0)), entry::PRESENT | entry::WRITABLE, allocator);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        unsafe { *(0 as *mut u8) = 0xF4 };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let start_addr = 0xE0000;
 | 
					    let start_addr = 0xE0000;
 | 
				
			||||||
    let end_addr = 0xFFFFF;
 | 
					    let end_addr = 0xFFFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,6 +99,13 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Map trampoline
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if active_table.translate_page(Page::containing_address(VirtualAddress::new(TRAMPOLINE))).is_none() {
 | 
				
			||||||
 | 
					            active_table.identity_map(Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)), entry::PRESENT | entry::WRITABLE, allocator);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Search for RSDP
 | 
					    // Search for RSDP
 | 
				
			||||||
    if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
 | 
					    if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
 | 
				
			||||||
        println!("{:?}", rsdp);
 | 
					        println!("{:?}", rsdp);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,45 @@
 | 
				
			||||||
 | 
					trampoline:
 | 
				
			||||||
 | 
					    .ready: dq 0
 | 
				
			||||||
 | 
					    .stack: dq 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    times 512 - ($ - trampoline) db 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					startup_ap:
 | 
				
			||||||
 | 
					    cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    xor ax, ax
 | 
				
			||||||
 | 
					    mov ds, ax
 | 
				
			||||||
 | 
					    mov es, ax
 | 
				
			||||||
 | 
					    mov ss, ax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ; initialize stack
 | 
				
			||||||
 | 
					    mov sp, 0x7C00
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ;cr3 holds pointer to PML4
 | 
				
			||||||
 | 
					    mov edi, 0x70000
 | 
				
			||||||
 | 
					    mov cr3, edi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ;enable Page Address Extension and Page Size Extension
 | 
				
			||||||
 | 
					    mov eax, cr4
 | 
				
			||||||
 | 
					    or eax, 1 << 5 | 1 << 4
 | 
				
			||||||
 | 
					    mov cr4, eax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ; load protected mode GDT
 | 
				
			||||||
 | 
					    lgdt [gdtr]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mov ecx, 0xC0000080               ; Read from the EFER MSR.
 | 
				
			||||||
 | 
					    rdmsr
 | 
				
			||||||
 | 
					    or eax, 1 << 11 | 1 << 8          ; Set the Long-Mode-Enable and NXE bit.
 | 
				
			||||||
 | 
					    wrmsr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ;enabling paging and protection simultaneously
 | 
				
			||||||
 | 
					    mov ebx, cr0
 | 
				
			||||||
 | 
					    or ebx, 1 << 31 | 1 << 16 | 1                ;Bit 31: Paging, Bit 16: write protect kernel, Bit 0: Protected Mode
 | 
				
			||||||
 | 
					    mov cr0, ebx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ; far jump to enable Long Mode and load CS with 64 bit segment
 | 
				
			||||||
 | 
					    jmp gdt.kernel_code:long_mode_ap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%include "startup-common.asm"
 | 
					%include "startup-common.asm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
startup_arch:
 | 
					startup_arch:
 | 
				
			||||||
| 
						 | 
					@ -74,106 +116,118 @@ long_mode:
 | 
				
			||||||
    ;rust init
 | 
					    ;rust init
 | 
				
			||||||
    xor rax, rax
 | 
					    xor rax, rax
 | 
				
			||||||
    mov eax, [kernel_base + 0x18]
 | 
					    mov eax, [kernel_base + 0x18]
 | 
				
			||||||
    mov rbx, gdtr
 | 
					 | 
				
			||||||
    jmp rax
 | 
					    jmp rax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdtr:
 | 
					long_mode_ap:
 | 
				
			||||||
        dw gdt.end + 1  ; size
 | 
					    mov rax, gdt.kernel_data
 | 
				
			||||||
        dq gdt          ; offset
 | 
					    mov ds, rax
 | 
				
			||||||
 | 
					    mov es, rax
 | 
				
			||||||
 | 
					    mov fs, rax
 | 
				
			||||||
 | 
					    mov gs, rax
 | 
				
			||||||
 | 
					    mov ss, rax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdt:
 | 
					    mov qword [trampoline.ready], 1
 | 
				
			||||||
    .null equ $ - gdt
 | 
					.lp:
 | 
				
			||||||
        dq 0
 | 
					    hlt
 | 
				
			||||||
 | 
					    jmp .lp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .kernel_code equ $ - gdt
 | 
					gdtr:
 | 
				
			||||||
    istruc GDTEntry
 | 
					    dw gdt.end + 1  ; size
 | 
				
			||||||
        at GDTEntry.limitl, dw 0
 | 
					    dq gdt          ; offset
 | 
				
			||||||
        at GDTEntry.basel, dw 0
 | 
					
 | 
				
			||||||
        at GDTEntry.basem, db 0
 | 
					gdt:
 | 
				
			||||||
        at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code
 | 
					.null equ $ - gdt
 | 
				
			||||||
        at GDTEntry.flags__limith, db flags.long_mode
 | 
					    dq 0
 | 
				
			||||||
        at GDTEntry.baseh, db 0
 | 
					
 | 
				
			||||||
 | 
					.kernel_code equ $ - gdt
 | 
				
			||||||
 | 
					istruc GDTEntry
 | 
				
			||||||
 | 
					    at GDTEntry.limitl, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basel, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basem, db 0
 | 
				
			||||||
 | 
					    at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code
 | 
				
			||||||
 | 
					    at GDTEntry.flags__limith, db flags.long_mode
 | 
				
			||||||
 | 
					    at GDTEntry.baseh, db 0
 | 
				
			||||||
 | 
					iend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.kernel_data equ $ - gdt
 | 
				
			||||||
 | 
					istruc GDTEntry
 | 
				
			||||||
 | 
					    at GDTEntry.limitl, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basel, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basem, db 0
 | 
				
			||||||
 | 
					; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
 | 
				
			||||||
 | 
					    at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
 | 
				
			||||||
 | 
					    at GDTEntry.flags__limith, db 0
 | 
				
			||||||
 | 
					    at GDTEntry.baseh, db 0
 | 
				
			||||||
 | 
					iend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.user_code equ $ - gdt
 | 
				
			||||||
 | 
					istruc GDTEntry
 | 
				
			||||||
 | 
					    at GDTEntry.limitl, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basel, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basem, db 0
 | 
				
			||||||
 | 
					    at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.code
 | 
				
			||||||
 | 
					    at GDTEntry.flags__limith, db flags.long_mode
 | 
				
			||||||
 | 
					    at GDTEntry.baseh, db 0
 | 
				
			||||||
 | 
					iend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.user_data equ $ - gdt
 | 
				
			||||||
 | 
					istruc GDTEntry
 | 
				
			||||||
 | 
					    at GDTEntry.limitl, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basel, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basem, db 0
 | 
				
			||||||
 | 
					; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
 | 
				
			||||||
 | 
					    at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
 | 
				
			||||||
 | 
					    at GDTEntry.flags__limith, db 0
 | 
				
			||||||
 | 
					    at GDTEntry.baseh, db 0
 | 
				
			||||||
 | 
					iend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.user_tls equ $ - gdt
 | 
				
			||||||
 | 
					istruc GDTEntry
 | 
				
			||||||
 | 
					    at GDTEntry.limitl, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basel, dw 0
 | 
				
			||||||
 | 
					    at GDTEntry.basem, db 0
 | 
				
			||||||
 | 
					; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
 | 
				
			||||||
 | 
					    at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
 | 
				
			||||||
 | 
					    at GDTEntry.flags__limith, db 0
 | 
				
			||||||
 | 
					    at GDTEntry.baseh, db 0
 | 
				
			||||||
 | 
					iend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tss equ $ - gdt
 | 
				
			||||||
 | 
					istruc GDTEntry
 | 
				
			||||||
 | 
					    at GDTEntry.limitl, dw (tss.end - tss) & 0xFFFF
 | 
				
			||||||
 | 
					    at GDTEntry.basel, dw (tss-$$+0x7C00) & 0xFFFF
 | 
				
			||||||
 | 
					    at GDTEntry.basem, db ((tss-$$+0x7C00) >> 16) & 0xFF
 | 
				
			||||||
 | 
					    at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.tssAvailabe64
 | 
				
			||||||
 | 
					    at GDTEntry.flags__limith, db ((tss.end - tss) >> 16) & 0xF
 | 
				
			||||||
 | 
					    at GDTEntry.baseh, db ((tss-$$+0x7C00) >> 24) & 0xFF
 | 
				
			||||||
 | 
					iend
 | 
				
			||||||
 | 
					dq 0 ;tss descriptors are extended to 16 Bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.end equ $ - gdt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struc TSS
 | 
				
			||||||
 | 
					    .reserved1 resd 1    ;The previous TSS - if we used hardware task switching this would form a linked list.
 | 
				
			||||||
 | 
					    .rsp0 resq 1        ;The stack pointer to load when we change to kernel mode.
 | 
				
			||||||
 | 
					    .rsp1 resq 1        ;everything below here is unused now..
 | 
				
			||||||
 | 
					    .rsp2 resq 1
 | 
				
			||||||
 | 
					    .reserved2 resd 1
 | 
				
			||||||
 | 
					    .reserved3 resd 1
 | 
				
			||||||
 | 
					    .ist1 resq 1
 | 
				
			||||||
 | 
					    .ist2 resq 1
 | 
				
			||||||
 | 
					    .ist3 resq 1
 | 
				
			||||||
 | 
					    .ist4 resq 1
 | 
				
			||||||
 | 
					    .ist5 resq 1
 | 
				
			||||||
 | 
					    .ist6 resq 1
 | 
				
			||||||
 | 
					    .ist7 resq 1
 | 
				
			||||||
 | 
					    .reserved4 resd 1
 | 
				
			||||||
 | 
					    .reserved5 resd 1
 | 
				
			||||||
 | 
					    .reserved6 resw 1
 | 
				
			||||||
 | 
					    .iomap_base resw 1
 | 
				
			||||||
 | 
					endstruc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tss:
 | 
				
			||||||
 | 
					    istruc TSS
 | 
				
			||||||
 | 
					        at TSS.rsp0, dd 0x800000 - 128
 | 
				
			||||||
 | 
					        at TSS.iomap_base, dw 0xFFFF
 | 
				
			||||||
    iend
 | 
					    iend
 | 
				
			||||||
 | 
					.end:
 | 
				
			||||||
    .kernel_data equ $ - gdt
 | 
					 | 
				
			||||||
    istruc GDTEntry
 | 
					 | 
				
			||||||
        at GDTEntry.limitl, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basel, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basem, db 0
 | 
					 | 
				
			||||||
    ; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
 | 
					 | 
				
			||||||
        at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
 | 
					 | 
				
			||||||
        at GDTEntry.flags__limith, db 0
 | 
					 | 
				
			||||||
        at GDTEntry.baseh, db 0
 | 
					 | 
				
			||||||
    iend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    .user_code equ $ - gdt
 | 
					 | 
				
			||||||
    istruc GDTEntry
 | 
					 | 
				
			||||||
        at GDTEntry.limitl, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basel, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basem, db 0
 | 
					 | 
				
			||||||
        at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.code
 | 
					 | 
				
			||||||
        at GDTEntry.flags__limith, db flags.long_mode
 | 
					 | 
				
			||||||
        at GDTEntry.baseh, db 0
 | 
					 | 
				
			||||||
    iend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    .user_data equ $ - gdt
 | 
					 | 
				
			||||||
    istruc GDTEntry
 | 
					 | 
				
			||||||
        at GDTEntry.limitl, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basel, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basem, db 0
 | 
					 | 
				
			||||||
    ; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
 | 
					 | 
				
			||||||
        at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
 | 
					 | 
				
			||||||
        at GDTEntry.flags__limith, db 0
 | 
					 | 
				
			||||||
        at GDTEntry.baseh, db 0
 | 
					 | 
				
			||||||
    iend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    .user_tls equ $ - gdt
 | 
					 | 
				
			||||||
    istruc GDTEntry
 | 
					 | 
				
			||||||
        at GDTEntry.limitl, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basel, dw 0
 | 
					 | 
				
			||||||
        at GDTEntry.basem, db 0
 | 
					 | 
				
			||||||
    ; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
 | 
					 | 
				
			||||||
        at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
 | 
					 | 
				
			||||||
        at GDTEntry.flags__limith, db 0
 | 
					 | 
				
			||||||
        at GDTEntry.baseh, db 0
 | 
					 | 
				
			||||||
    iend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    .tss equ $ - gdt
 | 
					 | 
				
			||||||
    istruc GDTEntry
 | 
					 | 
				
			||||||
        at GDTEntry.limitl, dw (tss.end - tss) & 0xFFFF
 | 
					 | 
				
			||||||
        at GDTEntry.basel, dw (tss-$$+0x7C00) & 0xFFFF
 | 
					 | 
				
			||||||
        at GDTEntry.basem, db ((tss-$$+0x7C00) >> 16) & 0xFF
 | 
					 | 
				
			||||||
        at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.tssAvailabe64
 | 
					 | 
				
			||||||
        at GDTEntry.flags__limith, db ((tss.end - tss) >> 16) & 0xF
 | 
					 | 
				
			||||||
        at GDTEntry.baseh, db ((tss-$$+0x7C00) >> 24) & 0xFF
 | 
					 | 
				
			||||||
    iend
 | 
					 | 
				
			||||||
    dq 0 ;tss descriptors are extended to 16 Bytes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    .end equ $ - gdt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    struc TSS
 | 
					 | 
				
			||||||
        .reserved1 resd 1    ;The previous TSS - if we used hardware task switching this would form a linked list.
 | 
					 | 
				
			||||||
        .rsp0 resq 1        ;The stack pointer to load when we change to kernel mode.
 | 
					 | 
				
			||||||
        .rsp1 resq 1        ;everything below here is unused now..
 | 
					 | 
				
			||||||
        .rsp2 resq 1
 | 
					 | 
				
			||||||
        .reserved2 resd 1
 | 
					 | 
				
			||||||
        .reserved3 resd 1
 | 
					 | 
				
			||||||
        .ist1 resq 1
 | 
					 | 
				
			||||||
        .ist2 resq 1
 | 
					 | 
				
			||||||
        .ist3 resq 1
 | 
					 | 
				
			||||||
        .ist4 resq 1
 | 
					 | 
				
			||||||
        .ist5 resq 1
 | 
					 | 
				
			||||||
        .ist6 resq 1
 | 
					 | 
				
			||||||
        .ist7 resq 1
 | 
					 | 
				
			||||||
        .reserved4 resd 1
 | 
					 | 
				
			||||||
        .reserved5 resd 1
 | 
					 | 
				
			||||||
        .reserved6 resw 1
 | 
					 | 
				
			||||||
        .iomap_base resw 1
 | 
					 | 
				
			||||||
    endstruc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tss:
 | 
					 | 
				
			||||||
        istruc TSS
 | 
					 | 
				
			||||||
            at TSS.rsp0, dd 0x800000 - 128
 | 
					 | 
				
			||||||
            at TSS.iomap_base, dw 0xFFFF
 | 
					 | 
				
			||||||
        iend
 | 
					 | 
				
			||||||
    .end:
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue