summaryrefslogtreecommitdiff
path: root/rt/+x86_64/realcall.S
diff options
context:
space:
mode:
authorAlejandro Sior <aho@sior.be>2022-05-20 10:33:27 +0200
committerAlejandro Sior <aho@sior.be>2022-05-20 10:33:27 +0200
commit74d0e8c1f9527054a012aa9937c590537f9d3d5b (patch)
treea83448feac9e803c3844ba8eb8137aef8c26239d /rt/+x86_64/realcall.S
parent776a3710652f78b44718450406d0683974aef72a (diff)
bios.call: clean and avoid hardcoding the gdt and idt when returning to long mode
Do not make assumptions on the previous gdt and idt, as well as the state of the flags when operating.
Diffstat (limited to 'rt/+x86_64/realcall.S')
-rw-r--r--rt/+x86_64/realcall.S81
1 files changed, 39 insertions, 42 deletions
diff --git a/rt/+x86_64/realcall.S b/rt/+x86_64/realcall.S
index 9e9afb4..ffbc0a9 100644
--- a/rt/+x86_64/realcall.S
+++ b/rt/+x86_64/realcall.S
@@ -14,18 +14,13 @@ redi:
.int 0x0
resi:
.int 0x0
-rds:
- .short 0x0
res:
.short 0x0
-rss:
- .short 0x0
-rgs:
- .short 0x0
-rfs:
- .short 0x0
-
+prev_idt:
+ .quad 0x0
+prev_gdt:
+ .quad 0x0
# :real_call
# This function is intended to be called from long mode
@@ -45,12 +40,25 @@ bios.call:
push %r13
push %r14
push %r15
+ pushf
+
+ # :Save code segment (and second push to prepare for far return)
+ mov %cs, %ax
+ push %ax
+ push %ax
+
+ # :Save data segment
+ mov %ds, %ax
+ push %ax
+ # :Save the interrupt number
push %di
cli
+ sidt (prev_idt)
+ sgdt (prev_gdt)
- lgdt gdtr32
+ lgdt (gdtr32)
pushq $(gdt32_code - gdt32)
pushq $real_call_to_pmode_down
retfq
@@ -92,15 +100,12 @@ real_call_to_16bits_rmode_down:
mov %ax, %fs
lidt bios_idtr
- sti
# :Self modifying code to call arbitrary interrupts
pop %ax
mov $real_call_int, %bx
mov %al, 1(%bx)
- push %ds
-
# :Load registers
mov (reax), %eax
mov (rebx), %ebx
@@ -108,29 +113,22 @@ real_call_to_16bits_rmode_down:
mov (redx), %edx
mov (redi), %edi
mov (resi), %esi
- mov %ds:(res), %es
- mov %ds:(rss), %ss
- mov %ds:(rgs), %gs
- mov %ds:(rfs), %fs
- mov %ds:(rds), %ds
- xchg %bx, %bx
+ mov (res), %es
+
+ sti
real_call_int:
int $0x0
-
- pop %ds
- mov %ds:(rfs), %fs
- mov %ds:(rgs), %gs
- mov %ds:(rss), %ss
- mov %ds:(res), %es
+
+ cli
+
+ mov %es, (res)
mov %eax, (reax)
mov %ebx, (rebx)
mov %ecx, (recx)
mov %edx, (redx)
mov %edi, (redi)
mov %esi, (resi)
-
- cli
# :Restore protected mode
mov %cr0, %eax
@@ -157,33 +155,32 @@ real_call_to_pmode_up:
or $1 << 31, %eax
mov %eax, %cr0
- lgdt gdtr64
- ljmp $(gdt64_code - gdt64), $real_call_to_longmode_up
+ lgdt (prev_gdt)
+
+ # :At this point %ds is latest in stack
+ pop %ax
+
+ # :At this point %cs is latest in stack
+ # Do a long jump
+ push $real_call_to_longmode_up
+ retf
.code64
real_call_to_longmode_up:
- mov $(gdt64_data - gdt64), %ax
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov %ax, %es
mov %ax, %ds
+ # :Avoid doing this until the bootloader loads a 64 bits IDT
+ # XXX
+ #idt (prev_idt)
+
real_call_end:
+ popf
pop %r15
pop %r14
pop %r13
pop %r12
pop %rbx
ret
-
-.globl testt
-testt:
- mov $1, %al
- mov $0x43, %bh
- mov $0x6, %ah
- mov $0, %ch
- mov $0, %cl
- mov $5, %dh
- mov $5, %dl
- int $0x10
- ret