flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Stack Switching.

Author
Thread Post new topic Reply to topic
calpol2004



Joined: 16 Dec 2004
Posts: 110
calpol2004 25 Dec 2008, 00:08
EDIT: turns out that wouldnt work anyway, if it was a sysenter/exit then it wouldnt put cs on the stack, it would be in a MSR. NEVERMIND.

Okay, im currently working on a task scheduler which works but im just curious about how i should act during system routines.

Take for example Process A and Process B, if you have IF flag set during system routines then you could switch to from A to Process B during a system routine which uses the kernel stack, but process B could call a system routine (TSS would set stack pointer) and process B could overwrite the data on the kernel stack that process A left on there. It took me a while to realise this...way too long :p.

However by setting IF to 0 during system routines (with interrupts you can use an interrupt gate) you fix this problem (not very elegant IMO but im open to suggestions). However, onto my problem with the use of sysenter/exit instructions where you cant automaticall set IF to 0. So what if you get a interrupt just as you jump to the routine BUT before the cli? Youll overrwrite the eip/cs/flags which will stored on the kernel stack on the entry to the routine by process A IF process B also enters a system routine. This can be fixed by ONLY using sysenter/sysexit (they dont leave stuff on the stack) and no interrupts and by doing cli before you use the stack and sti when you done (or cli and sti around stuff that cant be interrupted, e.g. port I/O).

Another solution is maybe in the task scheduler check cs on the stack. 3 and if it was coming from a ring 0 routine id simply just jump back without a switch. Here lies my problem, i can't get it to work i get GPF when i switch back to process A. Take a look at my IRQ 0 handler:

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   IRQ 0 - Task Switcher   ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IRQ0:
push  eax              ;temporarily store eax as i use it for ptr to struct and checking if caller is ring 3 or 0
mov   eax,[esp+8]      ;check if previous process was in ring 0 or ring 3, if ring 0 then dont task switch
or    eax,3
jnz   SwitchTask
pop   eax
jmp   DontSwitchTask
SwitchTask:
      mov   eax,[ActiveProcess]
      mov   [eax],edi        ;save context to current process structure
      mov   [eax+4],esi
      mov   [eax+8],ebp
      mov   [eax+16],ebx
      mov   [eax+20],edx
      mov   [eax+24],ecx
      popd  [eax+28]
      popd  [eax+32]
      popd  [eax+36]
      popd  [eax+40]
      popd  [eax+44]
      popd  [eax+48]
      mov   eax,[eax+52]     ;get pointer to next process from link entry in current processes context structure
      mov   [ActiveProcess],eax  ;set it as current process structure
      mov   esp,eax          ;set esp to this structure and pop of values, okay to trash esp as it gets reset on each ring 3 -> 0 switch
      popa                   ;it doesnt actually load the ESP from the struct Smile
DontSwitchTask:
iret
ActiveProcess dd ProcessAContext
    


My processes are laid out like this. Its a round robin scheduler, each process has a context structure attributed with it, you set the last entry of this structure to a pointer to the next processes context structure (set a to b and b to a so they loop around). Really simple and somewhat elegant way of doing it i think. I plan to have 3 priorities levels and round robin each process in each priority level but its simple for now.

Code:
ProcessA:                        ;main process that initialize jumps to
mov   esi,AMsg                   ;before activating scheduler.
xor   eax,eax
int   0x30
jmp   ProcessA
AMsg  db 'A',0
ProcessAContext:
dd         0        ;edi
dd         0        ;esi
dd         0        ;ebp
dd         0x9FFFF  ;esp
dd         0        ;ebx
dd         0        ;edx
dd         0        ;ecx
dd         0        ;eax
dd         ProcessA ;eip
dd         0x1B     ;cs
dd         0x200    ;eflags
dd         0x80000  ;esp    (only used when switching back to ring 3)
dd         0x23     ;ss     (only used when switching back to ring 3)
dd         ProcessBContext  ;link the next process in chain
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;         Process B         ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ProcessB:                        ;simple process repeatedly prints "B"
mov   esi,BMsg
xor   eax,eax
int   0x30
jmp   ProcessB
BMsg  db 'B',0
ProcessBContext:
dd         0        ;edi
dd         0        ;esi
dd         0        ;ebp
dd         0x9FFFF  ;esp
dd         0        ;ebx
dd         0        ;edx
dd         0        ;ecx
dd         0        ;eax
dd         ProcessB ;eip
dd         0x1B     ;cs
dd         0x200    ;eflags
dd         0x70000  ;esp    (only used when switching back to ring 3)
dd         0x23     ;ss     (only used when switching back to ring 3)
dd         ProcessAContext  ;link the next process in chain   
    


I figured this would work, i took into account that eax would reduce esp by 4 and id have to add another 4 to get past EIP yet i still get GPF. If its a ring 0 routine that gets interrupted all that should happen is a push and pop for eax then a iret. why would a push and a pop of eax make any difference? is cs at [esp+8] at that point?

it works if i set the systemcall to be a interrupt gate so its definetly happening because its not switching back if its from ring 0, but not if i set it to be a trap gate. I *SHOULD* have it as a interrupt gate, i know, im just trying to simulate how im going to handle sysenter/exit as you cant automatically set them to clear IF on the entry to the routine.

Any advice appreciated.

Cal.
Post 25 Dec 2008, 00:08
View user's profile Send private message MSN Messenger Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 25 Dec 2008, 21:02
Try asking on alt.os.development (usenet/nntp)
Post 25 Dec 2008, 21:02
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
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 vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.