Page 5 of 6

Re:tss and user space

Posted: Thu Jan 05, 2006 8:34 am
by JAAman
not necessarily, you could still share much space, but yet still protect them from each other by isolation

but you are right, this would make threads simply a special case of processes

in my OS, every process will have the user stack at the same address, but that isn't important, what is important is that the split thread must have a stack, and that stack must contain the same data, the simplest method of doing this, is COW the stack, and place it on the same space, if you don't do this, then you will have to move the stack, (and could cause broken code within the user code --- bad pointers, bad stack manipulation, etc), and also take a lot more memory -- remember, the programs with lots of threads, will be the same ones that are likly to use more memory, so this also serves as an optimization, because you are no longer must support multiple stacks within a single address space (of course for x86-64 it isn't a huge deal), the cost of switching pages doesn't have to be really great, as you can share many pages, and don't have to reload CR3 -- most of the time, you will only need to repage the first stack page, and the kernel stack page, not really a lot of overhead here

Re:tss and user space

Posted: Thu Jan 05, 2006 1:02 pm
by GLneo
ok heres the GDT code:

Code: Select all

struct gdt_entry
{
    unsigned short limit;
    unsigned short basel;
    unsigned char basem;
    unsigned char access;
    unsigned char granularity;
    unsigned char baseh;
}__attribute__((packed));

struct gdt_entry gdt[3];
struct tab_ptr gp;

void set_a_gdt(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
    gdt[num].basel = (base & 0xFFFF);
    gdt[num].basem = (base >> 16) & 0xFF;
    gdt[num].baseh = (base >> 24) & 0xFF;
    gdt[num].limit = (limit & 0xFFFF);
    gdt[num].granularity = ((limit >> 16) & 0x0F);
    gdt[num].granularity |= (gran & 0xF0);
    gdt[num].access = access;
}

asm:

_setup_gdt:
     lgdt [_gp]
     mov ax, 0x10
     mov ds, ax
     mov es, ax
     mov fs, ax
     mov gs, ax
     jmp 0x08:flush
 flush:
     ret

 _setup_tss:
     push ax
     mov ax, 5 * 8 ;GDT #5
     ltr ax
     pop ax
_setup_tss is called in posted c code, thx

Re:tss and user space

Posted: Thu Jan 05, 2006 1:18 pm
by kataklinger
I gusess your tab_ptr struct looks something like this:

Code: Select all

struct tab_ptr
{
    unsinged short limit;
    void* address;
};
So you must do this before you load GDTR:

Code: Select all

gp.limit = number_of_gdt_enteries * 8 - 1;
That means you must know size of GDT before you load it. And instead creating your GDT(&IDT also) staticlly, try creating it at runtime .

Re:tss and user space

Posted: Thu Jan 05, 2006 4:11 pm
by GLneo
ok, thx i see, so i did this:

Code: Select all

void set_gdt()
{
    gp.limit = (sizeof(struct gdt_entry) * 6) - 1;
    gp.base = (unsigned int) &gdt;
    set_a_gdt(0, 0, 0, 0, 0);
    set_a_gdt(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // kernel code
    set_a_gdt(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // kernel data
    set_a_gdt(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // user code
    set_a_gdt(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // user data
    set_a_gdt(5, (unsigned long)&TSS, sizeof(TSS), 0x89, 0xCF);
    setup_gdt();
}
as you can see i made the entery but now i get this:

Code: Select all

00006409976p[CPU  ] >>PANIC<< iret: return CS selector null
i would be glad to post any code you want to see, thx

EDIT: p.s. do i need to fill the tss with any thing other than esp0, ss0, and bitmap, do i have to fill cs and stuff???

Re:tss and user space

Posted: Thu Jan 05, 2006 6:21 pm
by kataklinger
Where did you get IRET? Did you set IDT & enable interrupts?

When you return from interrupt handler (execute IRET instruction) you must provide return address (EIP), code selector (CS) and EFLAG on stack, respectively.

Re:tss and user space

Posted: Fri Jan 06, 2006 7:57 am
by GLneo
well i had a working kernel space switcher:

Code: Select all

 _task_timer:
    pushad
    push ds
    push es
    push fs
    push gs
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
;    cli
    push esp
    mov eax, _task_timer_c
    call eax
;    sti
    pop esp
    mov esp, eax
    pop gs
    pop fs
    pop es
    pop ds
    popad
    iretd
but now i'm making it compatible with user tasks, is there any thing i need to modify, thx

Re:tss and user space

Posted: Fri Jan 06, 2006 3:15 pm
by OZ
depending on the rest of your implementation all what you might need to add is fixing esp0 in the tss according to your current process.

Re:tss and user space

Posted: Fri Jan 06, 2006 4:40 pm
by kataklinger
How does your PCB looks like? And you must change tss.esp0 at every task switch so when interrupt happens processor will use correct stack.

Re:tss and user space

Posted: Fri Jan 06, 2006 8:02 pm
by GLneo
what should my esp0 be set to???, my current esp as of the middle of my task crator code???, thx

Re:tss and user space

Posted: Sat Jan 07, 2006 1:18 am
by Crazed123
Esp0 should be set to the "beginning", the bottom, of the kernel stack. The place that the kernel's esp will be at when there is nothing (or as close to nothing as your kernel gets) on the stack. Ideally, once you switch to userspace nothing should go onto the kernel stack outside of a system call or interrupt, and so the bottom of the stack is where you would first put things into kernel space.

Re:tss and user space

Posted: Sat Jan 07, 2006 7:20 am
by kataklinger
esp0 will be the address of saved state of CPU registers as well.

Re:tss and user space

Posted: Sat Jan 07, 2006 8:18 am
by OZ
[GS] << current ESP pointing here
[FS]
[ES]
[DS]
[EDI]
[ESI]
[EBP]
[ESP]
[EBX]
[EDX]
[ECX]
[EAX]
[EIP]
[CS]
[EFLAGS]
[ESP?]
[SS?] << kstack pointing at stackend should be put in esp0 of tss

if your 'userspace kernel stack' starts always at the same address you might only need to set it at initialising your userspace environment otherwise you need to adjust it each switch.
@ kataklinger - when does it hold the saved state? or is that related to using the hardware based switching?

Re:tss and user space

Posted: Sat Jan 07, 2006 9:51 am
by GLneo
so how should i point it to my empty stack?? were can i find this value???, thx

Re:tss and user space

Posted: Sat Jan 07, 2006 10:38 am
by kataklinger
@OZ:
When CPU goes from RING3 to RING0 it puts value of tss.esp0 in ESP register and tss.ss0 to SS register, so if you use POP(A) instructions to save state of registers at beginning of interrupt handler it meens that tss.esp0 points to saved state. ;)

@GLneo:

Code: Select all

 tss.esp0 = current_thread_kernel_stack; 
And first you must allocate memory for the stack ofcorse.

Re:tss and user space

Posted: Sat Jan 07, 2006 11:36 am
by GLneo
well i have something like that:

Code: Select all

TSS.esp0 = (int)rrq[front].stack;
but i still get errors in bochs:

Code: Select all

00006409601p[CPU  ] >>PANIC<< iret: return CS selector null
00006409601i[SYS  ] Last time is 1136655276
00006409601i[CPU  ] protected mode
00006409601i[CPU  ] CS.d_b = 32 bit
00006409601i[CPU  ] SS.d_b = 32 bit
00006409601i[CPU  ] | EAX=00000002  EBX=00007a00  ECX=000046ee  EDX=00000003
00006409601i[CPU  ] | ESP=0008ffcc  EBP=0008ffe8  ESI=00000000  EDI=0000739c
00006409601i[CPU  ] | IOPL=0 NV UP DI PL NZ NA PE NC
00006409601i[CPU  ] | SEG selector     base    limit G D
00006409601i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00006409601i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00006409601i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00006409601i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00006409601i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00006409601i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00006409601i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00006409601i[CPU  ] | EIP=00001a5a (00001a59)
00006409601i[CPU  ] | CR0=0x60000011 CR1=0x00000000 CR2=0x00000000
00006409601i[CPU  ] | CR3=0x00000000 CR4=0x00000000
00006409601i[     ] restoring default signal behavior
00006409601i[CTRL ] quit_sim called with exit code 1
, thx