still problems with semaphore code and smp

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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,
mystran wrote:Remember that any userspace code can load the null-descriptor into any segment register if they feel like it, so you can't rely on those in your kernel. Ofcourse that is only an issue when you are coming from userspace to kernel.
It is possible to rely on the segment registers from user-space if you're tricky.

In general you need to arrange things such that any incorrect value that could be loaded into a segment register by CPL=3 code will cause an exception if the kernel tries to use it, and then correct the segment register within the exception handler.

If the GDT only contains 2 descriptors that could be loaded by CPL=3 code (one for CPL=3 code and one for CPL=3 data), then CPL=3 code won't be able to change CS without crashing, and data segment registers could only be changed to the NULL descriptor.

If the kernel tries to use a null segment it'd cause a GPF. In this case it's relatively easy to detect this problem in the GPF handler, correct the segment register and return to kernel code.

This means you don't need to check segment registers (or save and restore them) each time the CPU switches from CPL=3 to CPL=0, which makes the kernel API and interrupt handlers faster.

The same thinking can be applied in other cases. For example my last kernel used GS to point to a data structure that describes the current CPU. This meant that CPL=3 code could load GS with a null descriptor or with the data segment descriptor. Detecting "GS set to null" is easy (same as detecting any other segment register set to null).

To detect if GS had been set to the normal data segment I used paging. The data structure that described the current CPU was 2048 bytes, so I made the first page in all address spaces "not present". This means that if CPL=3 code loaded the normal data descriptor into GS the kernel would get a page fault when it tried to access the CPU data structure via. GS. The page fault handler detected this problem, corrected GS and returned.


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.
Post Reply