tss and user space

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.
JAAman

Re:tss and user space

Post 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
GLneo

Re:tss and user space

Post 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
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

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

Re:tss and user space

Post 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???
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

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

Re:tss and user space

Post 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
OZ

Re:tss and user space

Post 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.
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

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

Re:tss and user space

Post by GLneo »

what should my esp0 be set to???, my current esp as of the middle of my task crator code???, thx
Crazed123

Re:tss and user space

Post 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.
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

Post by kataklinger »

esp0 will be the address of saved state of CPU registers as well.
OZ

Re:tss and user space

Post 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?
GLneo

Re:tss and user space

Post by GLneo »

so how should i point it to my empty stack?? were can i find this value???, thx
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

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

Re:tss and user space

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