User context

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
Whatever5k

User context

Post by Whatever5k »

One more question concerning that topic:
I managed to create a kernel context (including cs, ds & co., eax & co., eip and so on). Now I want to go on with creating user processes. Therefore, I need a user context. It's quite similar to the kernel's one - but there's a difference, actually two: the user ESP and the user SS.
What do I need those two for? Are they used to identify the user's stack? If yes, what do I need the "normal" stack pointer for? Isn't it sufficient to have one user stack?
Tim

Re:User context

Post by Tim »

Each thread must have two stacks: a kernel stack and a user stack.

The kernel stack is used while in ring 0. SS0 and ESP0 are stored in the TSS and the CPU switches to the kernel stack automatically when an interrupt occurs.

The user stack is used while in ring 3 and is the only stack that applications see. Set a pointer to the user stack at the end of the thread's context.
Whatever5k

Re:User context

Post by Whatever5k »

Tim Robinson wrote: The kernel stack is used while in ring 0.
That is, when an interrupt occurs/a system call is made, right?
Well, that makes sense after all. Both, kernel and user stack, work completely independent from each other, correct? By the way, do I have to care about the values stored in the TSS after a ring-switch occured?
Tim

Re:User context

Post by Tim »

If you're using software switching, you will need to update TSS.ESP0 on every thread switch.
Whatever5k

Re:User context

Post by Whatever5k »

I see... - ESP0 is the stack pointer of ring0 thread, that is the kernel - right? But back to the user context: could I do s.th. similar to following?

Code: Select all

base = malloc(4096);
user_esp = base + 8192 - sizeof(context);
But what do I need the user SS for? I don't have a stack segment in my GDT, not even for the kernel. Is it necessary to have one?
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:User context

Post by distantvoices »

the ss is the segment in which your stack resides. If you don't have an extra stack segment, you can indicate the selector for your data segment here, be it the user data segment be it the kernel data segment.

The user ss you need for distinction and protection issues: Imagine you do interruptses and all this stuff on one and the same stack. I think, you would come to a very mess at the end because the different processes don't know whether they return to their own function or to an other. and task switching would be something difficult too. With user and kernel stacks you have two different environments available: one active whilst normal operation in user space, and one active, when the process is interrupted, performs a system call or similar.

these are my thoughts.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
Whatever5k

Re:User context

Post by Whatever5k »

I see.
Now can I do s.th. like following?

Code: Select all

void create_user_context(void)
{
   ...
   proc->base = malloc(..);
   proc->stack = proc->base + STACK_SIZE - sizeof(context);
   ctx = (context*) proc->stack;
   
   /* fill context */
   ctx->ds = ... = (int) &USER_DS;
   ctx->cs = (int) &USER_CS;
   ...

   proc->kernel_base = malloc(...);
   proc->kernel_esp = proc->kernel_base + SIZE;
}

void schedule()
{
  /* take another process */
 ....
  /* process p is next to run */
  system_tss.esp0 = (unsigned long) p->kernel_esp; /* update TSS */
  return p->stack;
}
I know this is just a quick-and-dirty version - but what about the basic idea?
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:User context

Post by distantvoices »

It is like this. I'd only prefer to do the tss patching in the isr-stub. Make the TSS known to your interrupt handler layer. you can access the elements by adding an offset
to the base adress of it. sort of [tss+4] for esp0,[tss+56] for esp.

Thus I imagine you pass a pointer to a structure to the asm stub which contains esp and esp0.

In the asm-stub you then have this pointer in eax and:
... save regs ...
push esp
call... [your isr]
add esp,4 (to skip the previously pushed esp?)
mov esp,[eax] -> first 4 bytes -> esp
mov [sys_tss+4],[eax+4] -> second 4 bytes - esp0
...eoi instructions ...
...restore registers and so forth ...
iretd

If I write entirely and utterly weird crap pls tell me so that I can learn something of it.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
Whatever5k

Re:User context

Post by Whatever5k »

Well, it doesn't really matter where I change my TSS stuff - I can also change in the scheduler, no problem with that.
Whatever5k

Re:User context

Post by Whatever5k »

Hm, it doesn't work yet: I get a GPF. I've got a question concerning that. when a privilege change occurs on a exception, user_ss and user_esp are pushed on the stack, too. But how can I deal with that so that I can handle both, kernel and user exceptions. I have something like this:

Code: Select all

gpf_fault:
   PUSH_REGS
   call fault

typedef struct {
   gs
   fs
   ...
   eflags
   user_esp;
   user_ss;
}

void fault(regs_t regs)
{
  printf("regs->eax = ....");
  printf("regs->user_ss = ...");
}
Now when user_ss and user_esp are *not* pushed on the stack, I will get funny results because my regs_t structure includes user_ss and user_esp. So, what to do?
Tim

Re:User context

Post by Tim »

You must ignore the user SS and user ESP fields when the RPL of EIP is equal to zero.

pype: Tim means, "the RPL of CS", of course ;)
Post Reply