From cd8fe59acca8d65e01f8a8a47504eecab3342c4d Mon Sep 17 00:00:00 2001 From: CleverMouse Date: Fri, 15 Aug 2014 11:18:27 +0000 Subject: [PATCH] don't rely on BIOS for returning to real mode git-svn-id: svn://kolibrios.org@5032 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/boot/shutdown.inc | 18 ++++++++++- kernel/trunk/core/memory.inc | 28 ++++++++++++++++ kernel/trunk/kernel.asm | 59 ++++++++++++++++------------------ 3 files changed, 72 insertions(+), 33 deletions(-) diff --git a/kernel/trunk/boot/shutdown.inc b/kernel/trunk/boot/shutdown.inc index 3214bda107..7b2977fc8f 100644 --- a/kernel/trunk/boot/shutdown.inc +++ b/kernel/trunk/boot/shutdown.inc @@ -13,8 +13,24 @@ $Revision$ +use32 +become_real: + cli + lgdt [realmode_gdt-OS_BASE] + jmp 8:@f +use16 +@@: + mov ax, 10h + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov eax, cr0 + and eax, not 80000001h + mov cr0, eax + jmp 0x1000:pr_mode_exit -align 4 pr_mode_exit: ; setup stack diff --git a/kernel/trunk/core/memory.inc b/kernel/trunk/core/memory.inc index f69f600556..a2416bd954 100644 --- a/kernel/trunk/core/memory.inc +++ b/kernel/trunk/core/memory.inc @@ -350,6 +350,34 @@ proc map_page_table stdcall, lin_addr:dword, phis_addr:dword ret endp +; Allocates a physical page for master page table +; that duplicates first Mb of OS_BASE at address 0; +; used for starting APs and for shutting down, +; where it is important to execute code in trivial-mapped pages. +; Returns eax = allocated physical page. +proc create_trampoline_pgmap +; The only non-trivial moment: +; we need a linear address to fill information, +; but we don't need it outside of this function, +; so we're returning physical address. +; Therefore, allocate memory with kernel_alloc, +; this will allocate physical page and a linear address somewhere, +; and deallocate only linear address with free_kernel_space. + stdcall kernel_alloc, 0x1000 + mov edi, eax + mov esi, master_tab + mov ecx, 1024 + rep movsd + mov ecx, [master_tab+(OS_BASE shr 20)] + mov [eax], ecx + mov edi, eax + call get_pg_addr + push eax + stdcall free_kernel_space, edi + pop eax + ret +endp + align 4 proc init_LFB locals diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index cd32e38fe6..8c375abda6 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -5452,22 +5452,6 @@ end if call IRQ_mask_all -if 0 - mov word [OS_BASE+0x467+0], pr_mode_exit - mov word [OS_BASE+0x467+2], 0x1000 - - mov al, 0x0F - out 0x70, al - mov al, 0x05 - out 0x71, al - - mov al, 0xFE - out 0x64, al - - hlt - jmp $-1 - -else cmp byte [OS_BASE + 0x9030], 2 jnz no_acpi_power_off @@ -5613,21 +5597,6 @@ do_acpi_power_off: jmp $ -no_acpi_power_off: - mov word [OS_BASE+0x467+0], pr_mode_exit - mov word [OS_BASE+0x467+2], 0x1000 - - mov al, 0x0F - out 0x70, al - mov al, 0x05 - out 0x71, al - - mov al, 0xFE - out 0x64, al - - hlt - jmp $-1 - scan_rsdp: add eax, OS_BASE .s: @@ -5650,7 +5619,33 @@ scan_rsdp: stc .ok: ret -end if + +no_acpi_power_off: + call create_trampoline_pgmap + mov cr3, eax + jmp become_real+0x10000 +iglobal +align 4 +realmode_gdt: +; selector 0 - not used + dw 23 + dd realmode_gdt-OS_BASE + dw 0 +; selector 8 - code from 1000:0000 to 1000:FFFF + dw 0FFFFh + dw 0 + db 1 + db 10011011b + db 00000000b + db 0 +; selector 10h - data from 1000:0000 to 1000:FFFF + dw 0FFFFh + dw 0 + db 1 + db 10010011b + db 00000000b + db 0 +endg if ~ lang eq sp diff16 "end of .text segment",0,$