Skip to content

Commit

Permalink
Bioscall: adapt to GDT translation.
Browse files Browse the repository at this point in the history
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
ddejean committed Jun 16, 2012
1 parent 95b7a60 commit cd060f6
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 21 deletions.
74 changes: 59 additions & 15 deletions kernel/Arch/x86/bioscall.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

12 changes: 6 additions & 6 deletions kernel/Boot/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit cd060f6

Please sign in to comment.