1
votes

I have read that the TSS contains information about registers, etc. Right now, I am trying to implement the switch from kernel to user mode and back. I have read the the Intel 80386 manual, and was looking at this resource: http://www.brokenthorn.com/Resources/OSDev23.html for a general workflow. They do this:

void install_tss (uint32_t idx, uint16_t kernelSS, uint16_t kernelESP) {

    //! install TSS descriptor
    uint32_t base = (uint32_t) &TSS;
    gdt_set_descriptor (idx, base, base + sizeof (tss_entry),
        I86_GDT_DESC_ACCESS|I86_GDT_DESC_EXEC_CODE|I86_GDT_DESC_DPL|I86_GDT_DESC_MEMORY,
        0);

    //! initialize TSS
    memset ((void*) &TSS, 0, sizeof (tss_entry));

    TSS.ss0 = kernelSS;
    TSS.esp0 = kernelESP;

    TSS.cs=0x0b;
    TSS.ss = 0x13;
    TSS.es = 0x13;
    TSS.ds = 0x13;
    TSS.fs = 0x13;
    TSS.gs = 0x13;

    //! flush tss
    flush_tss (idx * sizeof (gdt_descriptor));
}

I am confused as to why RPL = 3

In my case, when I am in user mode and I want to use a trap gate to get to kernel mode, the cs segment in the trap gate would have RPL 0 (the last 2 bits of the 16 bit segment) and the GDT entry corresponding to the cs segment would also have DPL 0. And I've read that an inter-level privilege switch switches stacks (only??) looking at the TSS. I'm guessing that the above piece of code must have a TSS.ss = 0x10.

Note: We're assuming the classic 0x08 = Kernel code, 0x10 = Kernel data, .... GDT structure here

1

1 Answers

3
votes

The TSS structure has a lot of fields that are used for hardware task switching (e.g. TSS.ss, which is where the ss register's contents would be saved/loaded if a hardware task switch happened), plus a few fields that are used for switching the task to a higher privilege level ((e.g. (e.g.TSS.ss0` for switching to CPL=0).

You're looking at fields that are used for hardware task switching (which typically aren't worth bothering with because it's faster to do software task switching instead); and I'd guess someone shoved some "hardware task switch compatible" values in there (even though they're not used) to avoid uninitialized values.

Instead, you want to look at the TSS.esp0 and TSS.ss0 fields of the TSS, which are the only 2 fields of the TSS that matter for switching to CPL=0 (and might be the only 2 fields of the TSS you ever use).