multitasking and ring0/ring3

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
sigler
Posts: 15
Joined: Wed Oct 31, 2007 11:37 am

multitasking and ring0/ring3

Post by sigler »

Hello,

I've got my kernel with software multitasking, up to now all the tasks are running in ring0. So I tried to setup a task to run in ring3. I made two new entries in the gdt, one for code and one for data in ring3.
my gdt now looks like this

code ring0 // 8
data ring0 // 16
code ring3 // 24
data ring3 // 32
tss

Then I setup the task like this (the only difference I've done from ring0 tasks is change the cs and ds)

Code: Select all


        // ring0
         //       int cs = 8;
         //       int ds = 16;

           // ring3
                int cs = 24;
                int ds = 32;

	// iret pops these
	*(--esp) = EFLAGS | EFLAGS_IF;	// eflags
	*(--esp) = cs;	// cs
	*(--esp) = (dword)entrypoint; // eip

               // the timer interrupt pops/pushes these
	*(--esp) = 0;		// ebp
	*(--esp) = 0;		// esp
	*(--esp) = 0;		// edi
	*(--esp) = 0;		// esi
	*(--esp) = 0;		// edx
	*(--esp) = 0;		// ecx
	*(--esp) = 0;		// ebx
	*(--esp) = 0;		// eax
	*(--esp) = ds;		// ds
	*(--esp) = ds;		// es
	*(--esp) = ds;		// fs
	*(--esp) = ds;		// gs
If I correctly understand what's happening, I get a general protection fault when this task is selected in the timer interrupt and iret is performed.
(again the only change I've made to what's working, is change the cs/ds in the tasks stack)

What am I missing?

Must I introduce ldt ? (I haven't yet understood what ldt is for)

thanks,

--
Sigurd Lerstad
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

I remember I had a lot of difficulty when I was implementing software context switching in my kernel. Some of the most important ones were (Perhaps you can use them as a simple checklist):

1) I wasn't using the TSS correctly (with the SS:ESP of the kernel in TSS)
2) I was not setting EFLAGS correctly for the new task (Interrupt Flag and etc were not correctly set).
3) I was not setting the GS/DS/FS/ES of the kernel upon each Timer Interrupt. So when I was addressing a memory location with DS, I could be using an arbitrary memory address.

These were just a few. I think it would help if you gave us Bochs' debug output.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: multitasking and ring0/ring3

Post by egos »

sigler wrote:What am I missing?
In user mode (ring3) the values of segment registers must include in self RPL=3, e.g. cs=24+3=27.
Must I introduce ldt?
No, but it is possible.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

Something else to check:

If you are using paging, ensure that all code and data for your ring 3 task has the u/s bit of the PDE and PTE *set*. If not, you will get a GPF. This includes the stack, all variables, bss and all code.

Cheers,
Adam
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:

Post by Combuster »

since you IRET to a lower privilege, you must add an additional SS and ESP to the stack frame to give it all the data it needs
"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 ]
sigler
Posts: 15
Joined: Wed Oct 31, 2007 11:37 am

Post by sigler »

Combuster wrote:since you IRET to a lower privilege, you must add an additional SS and ESP to the stack frame to give it all the data it needs
Okay, I now setup task like this:

Code: Select all

	unsigned int cs = 24+3;
	unsigned int ds = 32+3;

	// iret pops these

	*(--esp) = ds;	// ss
	*(--esp) = ustacktop;	// esp

	*(--esp) = EFLAGS | EFLAGS_IF;	// eflags
	*(--esp) = cs;	// cs
	*(--esp) = (dword)entrypoint; // eip
The bochs error message is:

00003694910p[CPU0 ] >>PANIC<< get_SS_ESP_from_TSS: TR.cache invalid

So is there something wrong in my tss? not setup correctly etc.

I have added a tss to the gdt. Do I have to do more to make it visible? (I think there's a task register in hardware multitasking, but in software multitasking ?)

Before calling the iret that crashes, I set the global tss.esp0 to the task's esp, and tss.ss0 to 32+3 (the task's stack segment), all other fields in tss are zero.

I'm not setting the NT flag in EFLAGS ever, should I ?

Anything else?

thanks,

--
Sigurd Lerstad
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

When you do a privilege level switch from a lesser privilege to a higher one, the CPU reads SS0:ESP0 from the TSS and sets that as the ring0 ss:esp pair. You'll need to make sure that the TSS is loaded into the TR (even for software multitasking) and that a valid SS0:ESP0 pair is stored in it.
sigler
Posts: 15
Joined: Wed Oct 31, 2007 11:37 am

Post by sigler »

Thanks everyone,

It works now.

One more question:

When an interrupt occurs, to know the ring that the current task was running in, is the correct way to store a ring field in the task structure?

*edit*

I just thought of:
I could look at the lower two bits of cs segment that is on the stack?

--
Sigurd Lerstad
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Yes - that's how to do it :)

I originally had a flags field in my task structure and stored it there - the only problem with this was that if you preempted a task when it had called a system service, you are in ring 0 even though it is a ring 3 task. As you say - look at the lower bits of CS.

Cheers,
Adam
Post Reply