Page 1 of 1

After TSS is loaded: SS selector null.

Posted: Thu Jan 22, 2015 8:59 am
by ExeTwezz
Hi,

I'm trying to enter usermode for 3 hours. And finally, I did it. But

Code: Select all

00118395332e[CPU0  ] interrupt(): SS selector null
00118395332e[CPU0  ] interrupt(): SS selector null
is given by Bochs after calling

Code: Select all

; Enter the userspace.
global enter_userspace
enter_userspace:
    pop ebx             ; 2nd argument (stack)
    pop eax             ; 1st argument (eip)

    push 0x23
    push ebx
    push 0
    push 0x1B
    push eax

    mov ax, 0x23
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    iret
Please, don't pay attention to the fact that I'm not saving any registers. I don't have multitasking yet, so this function is called once.

Let me introduce what's going on (as I suppose). After `iret` the code execution is successfully transferred to

Code: Select all

; Userspace thread (test).
global thread_userspace
thread_userspace:
    hlt
After this, the PF would occur (privilege violation, ring3 code is running in ring0 pages). I've the PF handler that prints that privilege violation has occurred if it so. Therefore, the execution should be transferred to the PF handler. But it isn't so. Instead, I get the above error in Bochs. This error means that SS segment in TSS is set to zero (as I understand), but I'm setting this value to 0x10:

Code: Select all

// Setup the TSS.
void setup_tss (void)
{
    tss = &_tss; // These variables are defined above.

    // Fill in the TSS.
    memset ((uint8_t *) tss, 0, sizeof (tss_t));
    tss->ss0 = 0x10;
    tss->esp0 = 0;

    // Put the TSS into the GDT.
    set_gdt_entry (5, (uint32_t) tss, sizeof (tss_t) - 1, 0xE9, 0x40);
}
Logs:

Code: Select all

00053464865i[BIOS  ] Booting from 07c0:0000
00118395339e[CPU0  ] interrupt(): SS selector null
00118395339e[CPU0  ] interrupt(): SS selector null
00118395339i[CPU0  ] CPU is in protected mode (active)
00118395339i[CPU0  ] CS.mode = 32 bit
00118395339i[CPU0  ] SS.mode = 32 bit
00118395339i[CPU0  ] EFER   = 0x00000000
00118395339i[CPU0  ] | EAX=00100023  EBX=0010087f  ECX=00000008  EDX=20001008
00118395339i[CPU0  ] | ESP=0010087f  EBP=00106fec  ESI=00000000  EDI=00000000
00118395339i[CPU0  ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00118395339i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
00118395339i[CPU0  ] |  CS:001b( 0003| 0|  3) 00000000 ffffffff 1 1
00118395339i[CPU0  ] |  DS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00118395339i[CPU0  ] |  SS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00118395339i[CPU0  ] |  ES:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00118395339i[CPU0  ] |  FS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00118395339i[CPU0  ] |  GS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00118395339i[CPU0  ] | EIP=001007a0 (001007a0)
00118395339i[CPU0  ] | CR0=0xe0000011 CR2=0x001007a0
00118395339i[CPU0  ] | CR3=0x0009b000 CR4=0x00000000
(0).[118395339] [0x0000001007a0] 001b:001007a0 (unk. ctxt): hlt                       ; f4
00118395339e[CPU0  ] exception(): 3rd (10) exception with no resolution, shutdown status is 00h, resetting
Why is it printing that SS is null? If I didn't provide you enough information, please request it.

Also, is `hlt` privileged instruction? P.S. I've also tried `jmp $`.

Re: After TSS is loaded: SS selector null.

Posted: Thu Jan 22, 2015 2:53 pm
by Icee
1. Have you actually loaded the task register (TR) with the TSS selector?
2. You forgot to initialize the IOPB Base field in the TSS. I doubt this to have any influence on this situation, but still.

Re: After TSS is loaded: SS selector null.

Posted: Thu Jan 22, 2015 10:11 pm
by ExeTwezz
Icee wrote:1. Have you actually loaded the task register (TR) with the TSS selector?
Yes,

Code: Select all

; Load the TSS.
global load_tss
load_tss:
    mov ax, 0x2B
    ltr ax
    ret
This procedure is called after loading the GDT.
Icee wrote:2. You forgot to initialize the IOPB Base field in the TSS. I doubt this to have any influence on this situation, but still.
I'm not sure that it is neccessary, but I set it to 108 (`sizeof (tss_t)`, as at http://wiki.osdev.org/TSS) in `setup_tss()`. Also I've changed the TSS structure: added a new 32-bit element `prev` at the beginning of the structure, and changed the size of the last 2 elements from 16-bit to 32-bit. But it didn't help (the error is the same).

Code: Select all

typedef struct
{
    uint32_t prev;
    uint32_t esp0;
    uint32_t ss0;
    uint32_t esp1;
    uint32_t ss1;
    uint32_t esp2;
    uint32_t ss2;
    uint32_t cr3;
    uint32_t eip;
    uint32_t eflags;
    uint32_t eax;
    uint32_t ecx;
    uint32_t edx;
    uint32_t ebx;
    uint32_t esp;
    uint32_t ebp;
    uint32_t esi;
    uint32_t edi;
    uint32_t es;
    uint32_t cs;
    uint32_t ss;
    uint32_t ds;
    uint32_t fs;
    uint32_t gs;
    uint32_t ldt;
    uint32_t trap;
    uint32_t iobp_offset;
} __attribute__ ((packed)) tss_t;
Also, I'm confused with PL values. What `Privl` value do I need in access byte in the TSS descriptor? What PL value do I need to set in the segment register while loading the TSS?

Re: After TSS is loaded: SS selector null.

Posted: Fri Jan 23, 2015 4:26 am
by Combuster
Since SS is 0x23 and CS=0x1B, we know that we've actually arrived in userspace, and that the SS=null comes from a later moment. Since the cause is an interrupt (read: exception) it means SS=0 because of entering ring 0, not leaving it.

Essentially, it means that TSS.SS0 and TSS.ESP0 are not properly available, either because TSS points to the wrong address or SS0/ESP0 have not been filled with the correct values. If that doesn't point you to the problem, post the relevant code to setting TSS and the fields in the TSS.

Re: After TSS is loaded: SS selector null.

Posted: Fri Jan 23, 2015 5:34 am
by xenos
Bochs' debugger has a very helpful command info tss which can help you here.

Re: After TSS is loaded: SS selector null.

Posted: Fri Jan 23, 2015 6:20 am
by ExeTwezz
Combuster wrote:Essentially, it means that TSS.SS0 and TSS.ESP0 are not properly available, either because TSS points to the wrong address or SS0/ESP0 have not been filled with the correct values.
XenOS wrote:Bochs' debugger has a very helpful command info tss which can help you here.
Thank you. The problem was that I've changed the TSS structure in one file, and kernel main wasn't recompiled so it was setting to incorrect addresses. Now SS0 = 0x10 and ESP0 = 0x00. There are no longer `SS selector null` error and Invalid TSS exception, but there is PF exception without resolution. I suppose that it is caused by empty ESP0.

Upd: Pheew ;) Really didn't think that this problem will be solved. Thank you!