Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
[GLOBAL gdt_flush]
gdt_flush:
mov eax, [esp+4]
lgdt [eax]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:.flush ; this is line 28
.flush:
ret
I am using nasm, and running it with this flag: '-f elf64'. I do not have any BITS 64 flags at the top of my asm file. UEFI is landing me in 64-bit mode, I am trying to change the GDT.
Last edited by chris13524 on Thu Aug 25, 2016 7:36 am, edited 1 time in total.
ld: build/kernel/gdtasm.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
I'm assuming this is because I'm pushing a label, so that would be it's absolute address, rather than a relative one. I tried adding the 'DEFAULT REL' modifier (before and after 'BITS 64'), but it didn't help.
The question is, why are you wanting to do such a jump?
64-bit long mode uses a flat address space, so the only real point of changing the CS register is to change to privilege level. A far jump would not be the appropriate way to do this; normally you would do so via a syscall instruction or an interrupt. The sysret, or iret, instruction would then change the privilege level back again - manipulating these instructions can be done to put the processor into user mode initially; after that you shouldn't need to manipulate CS.
iansjack wrote:The question is, why are you wanting to do such a jump?
64-bit long mode uses a flat address space, so the only real point of changing the CS register is to change to privilege level. A far jump would not be the appropriate way to do this; normally you would do so via a syscall instruction or an interrupt. The sysret, or iret, instruction would then change the privilege level back again - manipulating these instructions can be done to put the processor into user mode initially; after that you shouldn't need to manipulate CS.
I'd say that the reason that you were given there "to make sure you actually have access to all of the memory space" is invalid (in 64-bit mode). It is certainly true that you will want to create a valid IDT (I've no idea what UEFI sets up) and you may need to modify the GDT that UEFI has provided. But IMO you shouldn't need to do the sort of far jump that you propose.
chris13524 wrote:I'm assuming this is because I'm pushing a label, so that would be it's absolute address, rather than a relative one. I tried adding the 'DEFAULT REL' modifier (before and after 'BITS 64'), but it didn't help.
That's because "push .flush" isn't calculating an effective address, it only pushes a fixed value. You need to use an instruction that calculates an effective address, for example:
iansjack wrote:It is certainly true that you will want to create a valid IDT (I've no idea what UEFI sets up) and you may need to modify the GDT that UEFI has provided. But IMO you shouldn't need to do the sort of far jump that you propose.
It's necessary to ensure that CS has a reasonable value so interrupts can return properly. Otherwise, the CS pushed to the stack when an interrupt occurs may not refer to a valid code selector.