Multitasking/Context Switching: Exec outside RAM/ROM

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.
Post Reply
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Multitasking/Context Switching: Exec outside RAM/ROM

Post by zhiayang »

Help! I've been following this tutorial here, it was recommended by someone over here: http://hosted.cjmovie.net/TutMultitask.htm. I've basically finished reading the tutorial; I have finished writing the code, however:

The tutorial says to install the switching code directly into the irq0 asm stub, bypassing the irq_common_stub. As such, the moment I enable interrupts, that code is executed. Which leads to this:

Code: Select all

qemu: fatal: Trying to execute code outside RAM or ROM at 0xecfeb2ef

EAX=6c78c000 EBX=0010a000 ECX=00000001 EDX=00000001
ESI=00035a7e EDI=00035a83 EBP=00067ec4 ESP=ffffff88
EIP=ecfeb2ef EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00111040 00000017
IDT=     001110a0 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=0000000c CCD=ffffff84 CCO=ADDL    
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000

The first thing i see is that EIP matches the address of the faulty code. What can I do?


Such is my code:

start.s

Code: Select all

extern HandleTimer

irq0:
    ; cli
    ; push byte 0
    ; push byte 32
    ; jmp irq_common_stub
	
	pusha					;; Push standard regs
	push ds					;; Push segment d
	push es					;; Segment e
	push fs					;; Segment f
	push gs					;; Segment g
	
	mov eax, 0x10			;; Kernel data segment
	mov ds, eax				;; Place it in data segment regs
	mov es, eax
	mov fs, eax
	mov gs, eax
	
	push esp				;; Push pointer to things already on stack
	call HandleTimer		;; Hardcoded timer interrupt, timer.c
	
	mov esp, eax			;; Replace stack with what HandleTimer returns
	
	mov al, 0x20			;; ACK Interrupt
	out 0x20, al
	
	pop esp                            ;; Was not in tutorial originally
	
	pop gs					;; Put data segments back
	pop fs
	pop es
	pop ds
	
	popa					;; Put standard regs back
	
	iret					;; Interrupt return

timer.c

Code: Select all

unsigned int HandleTimer(unsigned int OldEsp)//struct regs *r)
{
	clear_screen();
	kprintf("TEST");
        timer_ticks++;	
	if(timer_ticks % 1000 == 0)
	{
		time_increment_seconds();
	}	
	if(wait != 0)
	{
		wait--;
	}
        kprintf("AAA");
	return Schedule(OldEsp);
}
Note: I see "TESTAAA" almost immediately after booting the kernel, as expected. What happens next is not. The return statement works fine, however when I return from the "call HandleTimer", qemu crashes with the above report.


Note the line that was "not in the tutorial originally". I examined the code and noticed that esp was never actually popped after it was pushed on the stack, so I added that line. When I do, the kernel hangs instead of crashing.

Help?


EDIT: If I actually initialise the tasks before calling sti(), the reverse of what occurs above happens:
When I include "pop esp", it crashes. When I remove it, it hangs. (In retrospect, the line was probably not meant to be included and was just my itchy fingers).
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by JAAman »

well, i don't have a lot of time to look at it carefully, but i can confirm that you definitely should not POP ESP

ESP is pushed onto the stack as a parameter to the C function that is called immediately after, and when the function returns, it removes the value from the stack for you, so you shouldn't -- and your trashing the new ESP value you got from the function

so obviously, if you POP ESP, then, since the PUSHed value has already been removed, you are instead POPing the GS value... then GS is getting the FS value, FS is getting ES value, ES is getting DS value, DS is getting part of the ALL_REGISTERS, and POPA is POPing part of the return value, and your IRET is getting trash... IRET will reload CS:eIP -- so obviously CS:IP is getting the wrong value, pointing into random memory (very likely memory that doesn't exist) and while this may result in very strange results (probably looks like "hanging") on real hardware, QEMU is kind enough to stop and let you know that something is obviously wrong
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by xenos »

requimrar wrote:

Code: Select all

	pop esp                            ;; Was not in tutorial originally
...and you shouldn't have put it in there. HandleTimer already gives you the new stack pointer value, so there is no need to "pop esp".

What do you mean by "it hangs"? Where does it hang?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by zhiayang »

It hangs somewhere after the call to HandleTimer(), somewhere when the stuff is getting pop'ed.
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by xenos »

It would be very helpful to see where exactly it hangs. Have you tried to debug this issue using either GDB with QEMU or Bochs?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by zhiayang »

Nevermind. Some random experimenting fixed the problem. I think what was going on was that I was clearing the screen and couldn't see the output.

Also, if I create 2 tasks that point to the same function, I get a #GP. It's a race condition, right?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by Combuster »

requimrar wrote:Also, if I create 2 tasks that point to the same function, I get a #GP. It's a race condition, right?
Other OSes can run multiple instances of an application binary, so that description alone is not sufficient.

Trying to run both instances with the same .data section, heap, and/or stack is the better way to get into trouble.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: Multitasking/Context Switching: Exec outside RAM/ROM

Post by zhiayang »

Given that they both point to the same function in my kernel, they probably point to the same address and share the same stack/heap space. Thanks for all your help, guys.
Post Reply