OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Sep 30, 2020 8:03 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Can you jmp to a memory operand instead of a register value?
PostPosted: Wed Sep 16, 2020 1:59 am 
Offline
Member
Member

Joined: Sat Aug 18, 2018 8:44 pm
Posts: 105
I finally got my syscall_fork to work...
also I got my scheduler to deviate from james molloy's.. it worked after a few trial and error...

here is my code for doing the actual switch...
Code:
asm volatile( "pushl %%edi;"
                "pushl %%esi;"
                "pushl %%ebx;"
                "movl %%esp, %0;"
                "movl $1f, %1;"
                "movl %%ebp, %2;"
                "movl  %6, %%eax;" // load new cr3
                "movl  %%eax, %%cr3;"
                "movl  %5, %%ebp;"
                "movl  %4, %%esp;" // load new esp
                "jmp  *%3;"
                "1: ;"
                "popl %%ebx;"
                "popl %%esi;"
                "popl %%edi;"
                :"=m"(prev->esp),"=m"(prev->eip), "=m"(prev->ebp)
                :"r"(current_task->eip), "m"(current_task->esp),"g"(current_task->ebp),"m"(current_task->page_dir->phy_addr)     
                :
   );


what I noticed that if I put current_task->eip into a memory operand (ie. "m"(current_task->eip)) it won't work... it will only work if I put it a register...

why is that the case? Can't I jump to a eip located in a memory location?


Last edited by ITchimp on Wed Sep 16, 2020 4:20 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Can you jmp to a memory operand instead of a register va
PostPosted: Wed Sep 16, 2020 2:58 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2330
Of course you can jump to a memory operand.

The problem is that you've written your inline assembly according to the System V ABI, but the System V ABI only applies to function calls. For inline assembly, all registers are owned by the "caller" and you cannot modify any of them without using them as outputs or putting them in the clobber list. Since you're switching tasks, that means all registers need to be preserved.

I suggest you put your task switch code in an external function instead of using inline assembly.


Top
 Profile  
 
 Post subject: Re: Can you jmp to a memory operand instead of a register va
PostPosted: Wed Sep 16, 2020 3:55 am 
Offline
Member
Member

Joined: Sat Aug 18, 2018 8:44 pm
Posts: 105
since eax, edx, and ecx are scratch register, there should not be a need to preserve those.. that was what system V abi says...

are you saying I have to do a pusha and popa to make the code work, and jmp *%3, will them work, be it register or memory?


Top
 Profile  
 
 Post subject: Re: Can you jmp to a memory operand instead of a register va
PostPosted: Wed Sep 16, 2020 7:29 am 
Offline
Member
Member

Joined: Tue Apr 03, 2018 2:44 am
Posts: 62
ITchimp wrote:
since eax, edx, and ecx are scratch register, there should not be a need to preserve those.. that was what system V abi says...

are you saying I have to do a pusha and popa to make the code work, and jmp *%3, will them work, be it register or memory?



The part of the ABI you're referring to covers register use across function calls.

You're not calling a function. Therefore, all the registers at the point you're doing the inline assembly, belong to the compiler to use at it sees fit.

If it helps, move away from inline assembly, and do context switching in a self contained assembly, in either a single context switch function (which can trash eax, edx, and ecx) or in a pair of save/restore context functions (which can do the same.)

setjmp/longjmp is an example of the latter, as is getcontext/setcontext (but these are for user context, mentioned here for reference.)

https://wiki.osdev.org/Kernel_Multitasking contains an example of the former.


Top
 Profile  
 
 Post subject: Re: Can you jmp to a memory operand instead of a register va
PostPosted: Wed Sep 16, 2020 11:32 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1642
Location: Athens, GA, USA
As an aside, please used [ CODE ] tags in the future, like so:

Code:
asm volatile( "pushl %%edi;"
                "pushl %%esi;"
                "pushl %%ebx;"
                "movl %%esp, %0;"
                "movl $1f, %1;"
                "movl %%ebp, %2;"
                "movl  %6, %%eax;" // load new cr3
                "movl  %%eax, %%cr3;"
                "movl  %5, %%ebp;"
                "movl  %4, %%esp;" // load new esp
                "jmp  *%3;"
                "1: ;"
                "popl %%ebx;"
                "popl %%esi;"
                "popl %%edi;"
                :"=m"(prev->esp),"=m"(prev->eip), "=m"(prev->ebp)
                :"r"(current_task->eip), "m"(current_task->esp),"g"(current_task->ebp),"m"(current_task->page_dir->phy_addr)     
                :
   );

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
μή εἶναι βασιλικήν ἀτραπόν ἐπί γεωμετρίαν
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: Can you jmp to a memory operand instead of a register va
PostPosted: Wed Sep 16, 2020 2:53 pm 
Offline
Member
Member

Joined: Wed Mar 09, 2011 3:55 am
Posts: 387
ITchimp wrote:
since eax, edx, and ecx are scratch register, there should not be a need to preserve those.. that was what system V abi says...

are you saying I have to do a pusha and popa to make the code work, and jmp *%3, will them work, be it register or memory?


The ABI talks about what happens when one bit of code gives control to another. It tells each bit of code what it can expect from the other bit of code. The designation of registers as scratch registers means that the code giving control must expect the code receiving control to use those registers.

During a task switch, the task being switched out is, in general, not giving control to the kernel. The kernel is *taking* control without asking. The task may not be ready to transfer control (it may currently be using a scratch register, for instance). Therefore, the kernel needs to save the complete state of the task it's taking control from, and restore that state when it next selects the task to run. If it does not do this, it will almost certainly cause the task to crash.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group