Permalink
Browse files

Bioscall: adapt to GDT translation.

At early boot stage the kernel is in 3GB virtual memory and the
translation is done by special segments in the Global Descriptor Table.
As bioscall have to be done in real mode without virtual adress space,
the code have been adapted to enter into a proper context before, and
restore the virtual context after the BIOS call.
  • Loading branch information...
1 parent 95b7a60 commit cd060f6b4ceb4de9ac924aaaaf1c16946543b8b6 @ddejean ddejean committed Jun 16, 2012
Showing with 65 additions and 21 deletions.
  1. +59 −15 kernel/Arch/x86/bioscall.S
  2. +6 −6 kernel/Boot/crt0.S
@@ -35,14 +35,68 @@ bioscall:
cli
/* Save the kernel IDT and GDT and segment registers. */
- sgdt gdt_loc
- sidt idt_loc
+ sgdt gdt_backup
+ sidt idt_backup
pushw %ds
pushw %es
pushw %fs
pushw %gs
pushw %ss
- lcall $0x08,$0f
+
+ /* Setup new data segment registers */
+ movl $0x10, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* Segments and interrupts stuff are saved, adjust pointers. */
+ movl $0xC0000000, %eax
+ subl %eax, %esp
+ subl %eax, %ebp
+ subl %eax, %ecx
+
+ /* Call with right adressing mode */
+ jmp $0x08, $real_code - 0xC0000000
+
+
+/*
+ * There is no more address translation, all pointers have to be physically
+ * related to memory.
+ */
+real_code:
+ /* Call real realmode code */
+ pushl %edx
+ pushl %ecx
+ movl $0x2000,%eax
+ call %eax
+ addl $8, %esp
+
+ /* Restore the kernel IDT and GDT and segment registers. */
+ lidt idt_backup - 0xC0000000
+ lgdt gdt_backup - 0xC0000000
+ jmp $0x18, $virtual_code
+
+
+/*
+ * Adresse are virtual again.
+ */
+virtual_code:
+ /* Restore pointers */
+ movl $0xC0000000, %eax
+ addl %eax, %esp
+ addl %eax, %ebp
+
+ /* Return to translated memory to 3GB */
+ movl $0x20, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* Restore execution context */
popw %ss
popw %gs
popw %fs
@@ -51,28 +105,18 @@ bioscall:
popfl
ret
-0: /* Segments and interrupts stuff are saved. */
- pushl %edx
- pushl %ecx
- call (0x2000 + 0xC0000000)
- addl $8,%esp
-
- /* Restore the kernel IDT and GDT and segment registers. */
- lidt idt_loc
- lgdt gdt_loc
- lret
/**
* Some space to save current GDT and IDT descriptors.
*/
.data
.align 2
-idt_loc:
+idt_backup:
.word 0
.long 0
.align 2
-gdt_loc:
+gdt_backup:
.word 0
.long 0
View
@@ -50,13 +50,13 @@ entry:
/* Load the tricky GDT */
lgdtl gdt_desc - 0xC0000000
- movw $0x10, %ax
+ movw $0x20, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
- jmp $0x08, $virtual_kernel
+ jmp $0x18, $virtual_kernel
/*
* Virtual kernel entry point.
@@ -101,14 +101,14 @@ virtual_gdt_desc:
bootstrap_gdt:
.long 0x0 /* Null gate */
.long 0x0
- .long 0x0000FFFF /* Code selector with offset 0x40000000 */
- .long 0x40CF9A00
- .long 0x0000FFFF /* Data selector with offset 0x40000000 */
- .long 0x40CF9200
.long 0x0000FFFF /* Code selector without offset */
.long 0x00CF9A00
.long 0x0000FFFF /* Data selector without offset */
.long 0x00CF9200
+ .long 0x0000FFFF /* Code selector with offset 0x40000000 */
+ .long 0x40CF9A00
+ .long 0x0000FFFF /* Data selector with offset 0x40000000 */
+ .long 0x40CF9200
bootstrap_gdt_end:
.align 4

0 comments on commit cd060f6

Please sign in to comment.