OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Oct 17, 2017 7:29 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: (Solved) v8086 task switching problems
PostPosted: Thu Mar 02, 2017 2:28 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
Hello, I have a simple software multitasking implementation.

As ESP only gets popped off by iret if privilege level changes, I used the easy way, I just forgot about Ring0 tasks, just used Ring3 tasks. And I want to improve it, by adding support to switching reliably between Ring3 and Ring0 tasks. Then my drivers can run in Ring0 tasks, while Virtual 8086 mode and user tasks can run in Ring3 tasks.

The problem is the ESP. I think I need to handle the case the current task and the next task is a Ring0 task.

How can I switch reliably between Ring3 and Ring0 tasks?

I got really confused and I can't think anymore. Maybe I should have a rest a bit.

Thanks in advance.

Edit:
That was a question about switching between ring0 and ring3, now it is for v8086 tasks, because I didn't want to open a new thread for it. Because the thread was short, and opening a new thread wouldn't be a good idea as it blocks another questions.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Last edited by Agola on Tue Mar 07, 2017 9:43 am, edited 3 times in total.

Top
 Profile  
 
 Post subject: Re: Switching between Ring3 and Ring0 tasks
PostPosted: Thu Mar 02, 2017 3:21 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8109
Location: At his keyboard!
Hi,

Agola wrote:
Hello, I have a simple software multitasking implementation.

As ESP only gets popped off by iret if privilege level changes, I used the easy way, I just forgot about Ring0 tasks, just used Ring3 tasks. And I want to improve it, by adding support to switching reliably between Ring3 and Ring0 tasks. Then my drivers can run in Ring0 tasks, while Virtual 8086 mode and user tasks can run in Ring3 tasks.

The problem is the ESP. I think I need to handle the case the current task and the next task is a Ring0 task.

How can I switch reliably between Ring3 and Ring0 tasks?

I got really confused and I can't think anymore. Maybe I should have a rest a bit.

Thanks in advance.


Assume a task switches back and forth between CPL=3 and CPL=0 for various reasons. None of that has anything to do with task switching whatsoever.

Assume that while a task is running at CPL=0 (for whatever reason) and only while a task is running at CPL=0, the kernel can switch from that task to another task. The other task must have been running at CPL=0 when it stopped running last time, so task switches can only possibly occur between tasks at CPL=0, and therefore task switches have nothing (directly) to do with CPL=3 or interrupts.

Some "very simplified" task switch code might look like this:
Code:
doSwitch:
    pushad
    mov ebx,[currentTaskReference]
    mov [ebx+something],esp
    mov [currentTaskReference],eax
    mov esp,[eax+something]
    popad
    ret


Because it only ever switches between tasks that are running CPL=0 code and tasks that were running CPL=0 code; there isn't any reason to bother saving/loading CS, DS, ES, SS. Also; typically your kernel's functions would be using some sort of ABI that says some registers are "preserved by caller" (including arithmetic flags) so there's no reason to bother saving/restoring any of those either.

There are some things (not shown in the "very simplified" example) that you would have to care about, like FPU/MMX/SSE/AVX state and CR3; but none of that changes the "task switching has nothing to do with CPL=3 at all" point that I'm making here.


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Switching between Ring3 and Ring0 tasks
PostPosted: Thu Mar 02, 2017 9:38 pm 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 958
Location: Athens, GA, USA
As a slight redirect on Brendan's point, are you asking about switching from CPL=3 to CPL=0 and vice versa, or how to manage IPC between CPL=3 and CPL=0 tasks?

As Brendan said, if you are using both CPL=0 and CPL=3 (and not trying to force the OS, including the kernel, to always run in one or the other - in anything other than real-mode, where there are no privilege controls - a common 'clever idea' that comes up from time to time), then it stands to reason that the process-level Context Switching is going to done inside the kernel (whether threads - sub-tasks running within a process and having no memory protection from other threads in the same process - are kernel switched or run entirely in user mode is another matter, but one thing at a time).

Why? Simple: because if you have configured you memory protection correctly, a process can only access those pages (or segments, to forestall rdos' next comment) which it has access to, and in most cases, that won't include either the scheduler queues (owned by the kernel) or the other process' own data (owned by that process). Even if they share code pages, they shouldn't be sharing writable data pages unless they are treating them as a shared resource (which means they need to synchronize their access to it, a can of worms you don't want to open just yet, or better still, ever - efficiency reasons dictate that you probably will want eventually, but you want to have a solid hold of the task switching itself first).

This means that a) each task has to have a way to call to the kernel, whether through an interrupt, a call gate, the SYSENTER/SYSCALL instructions, or something similar, and b) only the kernel can perform a process context switch. Now, for a number of reasons, many operating systems (especially monolithic and hybrid ones) use a model called a Higher Half Kernel, in which the kernel pages are mapped into a large block of memory at the top of the address range (usually 1/4 to 1/2 of the total address space to make it easier) of ever single process, but set that memory to CPL=0 access only, meaning that the process isn't performing a process context-switch when it calls the kernel, it just switches privilege level and call the kernel code it needs to run (which generally occurs in a single step to minimize the risks of malicious or buggy userland code calling something in the kernel it shouldn't have access to). At that point, the process is the kernel, so there usually isn't one primary 'kernel process'.

Even when it isn't done this way, it is generally useful (or even necessary) to have at least a 'kernel stub' that is part of the process and serves as a gatekeeper to the rest of the kernel. In other words, there really is no such thing as a 'user-mode process'; rather, there are parts of the process which are CPL=3, and parts which are CPL=0.

_________________
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: Switching between Ring3 and Ring0 tasks
PostPosted: Sat Mar 04, 2017 1:17 pm 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
Looks like everything is good at Ring0 <-> Ring3 switches now, yay!
I would mark the thread as 'Solved', but I had another problem and I didn't want to open a new thread for it.

And then I added v8086 task support, it fails (triple fault) after 2-3 switches with no reason.
I debugged in Bochs, and couldn't find anything strange or wrong.

v8086 task is just a infinite loop (0xFEEB, x: jmp x) that runs at 0x7C00 (I don't know why I love that address so much :) ), so it doesn't execute any privilege instructions.

I don't know why I do lots of mistakes even I read documentations, learn things, not copy and paste codes. :roll:
I opened lots of threads here, and my mistakes were such silly ones. I have to be careful while coding #-o

Thanks in advance.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Last edited by Agola on Sun Mar 05, 2017 2:27 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Switching between Ring3 and Ring0 tasks
PostPosted: Sun Mar 05, 2017 2:01 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
While I was debugging more, I saw that:

Quote:
00808511372e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00808511372e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)


At least that explains the triple fault. Looks like firstly it called #GP handler, then it failed, so it called #DF handler, then it failed too, then boom! Triple fault...

Then:

Quote:
00801480972i[CPU0 ] CPU is in protected mode (active)
00801480972i[CPU0 ] CS.mode = 32 bit
00801480972i[CPU0 ] SS.mode = 32 bit
00801480972i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
00801480972i[CPU0 ] | DS:0000( 0000| 0| 3) 00000000 0000ffff 0 0
00801480972i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00801480972i[CPU0 ] | ES:0000( 0000| 0| 3) 00004100 0000ffff 0 0
00801480972i[CPU0 ] | FS:0000( 0000| 0| 3) 000089e0 0000ffff 0 0
00801480972i[CPU0 ] | GS:0000( 0000| 0| 3) 00043090 0000ffff 0 0


Selectors wrecked with no reason...

And, do I need a new TSS for v8086 mode tasks? I'm using only one TSS that stores ESP0 and SS0 when an interrupt occurs for both user and v8086 mode (lol v8086 mode tasks are also user mode) tasks.

This is how I set the TSS:

Code:
   tss0.ss0 = 0x10;

   tss0.cs = 0x08;
   tss0.ss = 0x10;
   tss0.ds = 0x10;
   tss0.es = 0x10;
   tss0.fs = 0x10;
   tss0.gs = 0x10;


Looks like setting ss, ds, es, fs, gs has no effect.

That is the info tss just before the triple fault:

Quote:
tr:s=0x2b, base=0x000000000014f060, valid=1
ss:esp(0): 0x0010:0x00155360
ss:esp(1): 0x0000:0x00000000
ss:esp(2): 0x0000:0x00000000
cr3: 0x00000000
eip: 0x00000000
eflags: 0x00000000
cs: 0x0008 ds: 0x0010 ss: 0x0010
es: 0x0010 fs: 0x0010 gs: 0x0010
eax: 0x00000000 ebx: 0x00000000 ecx: 0x00000000 edx: 0x00000000
esi: 0x00000000 edi: 0x00000000 ebp: 0x00000000 esp: 0x00000000
ldt: 0x0000
i/o map: 0x0068


And this is how the GDT looks like:
Quote:
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x03]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x05]=32-Bit TSS (Busy) at 0x0014f060, length 0x00068


If I set all segment selectors to their correct values in Bochs with set reg = 16, then continue executing, it results with a #GP, with that:

Quote:
00794446885e[CPU0 ] iret: return CS selector null


Looks like I'm getting closer to fully understand whats going wrong, I'm going to look at the task switch code again :|

Thanks in advance...

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: v8086 task switching problems
PostPosted: Tue Mar 07, 2017 9:40 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
Okay, interesting but it is solved...

I tried everything and nothing worked, then I tried to rewrite switching code hopelessly.
Magically it worked! :D

I'm really happy, probably I was handling segments wrong while change or I initialized a segment with wrong value.

Now v8086 mode tasks are working, and my v8086 Monitor is almost working. Yaay! :)

Thanks.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


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: No registered users and 13 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