Programs can use io ports in user mode.

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.
Post Reply
yoshi65
Posts: 11
Joined: Sun Mar 11, 2012 8:49 pm

Programs can use io ports in user mode.

Post by yoshi65 »

Hey guys,
Right now I am in the progress of making a small microkernel. I am going to have it so that programs can run in a normal mode or in a server mode. For the server mode the programs will be able to use the I/O port commands (in and out) to access hardware. I went and tested this by loading a program I compiled that had an in and out instruction in it and I load it and the program runs fine without the eflags having the io flags set in them (bit 12 and bit 13 if I remember correctly) Here is my code for the parts that are relevant:

Code: Select all




task_t * new_task(char * name, void (*start)(), bool io_privilege){
	asm volatile ("cli");
	task_t *ntask = (task_t*)kmalloc(sizeof(task_t),0,0);
	memset(ntask, 0, sizeof(task_t));
	
	strcpy(ntask->name, name);
	
	ntask->dir = copy_page_directory(current_directory);
	
	ntask->pid = npid++;
	ntask->start = (uint32_t)start;
	ntask->sleep = 0;
	ntask->in_buff = cb_new(64);
	
	
	ntask->files[0].used = 1;
	ntask->files[0].node = &stdin_node;
	
	ntask->files[1].used = 1;
	ntask->files[1].node = &stdout_node;
	
	ntask->magic = 0xDEADC0DE;
	uint32_t * new_stack = (uint32_t*)(kmalloc(0x1000, 1, 0) + 0x1000);
	if(io_privilege)kprintf("Privilege\n");
	else kprintf("No privilege.\n");
	if(io_privilege) *--new_stack = (0x00003202); // eflags
	else *--new_stack = 0x00000202; // eflags
	*--new_stack = 0x08;  // Kerenel code
	*--new_stack = (uint32_t)&run;
	
	*--new_stack = 0x00;  // edi
	*--new_stack = 0x00;  // esi
	*--new_stack = 0x00;  // ebp
	*--new_stack = 0x00;  // empty
	
	*--new_stack = 0x00;  // ebx
	*--new_stack = 0x00;  // edx
	*--new_stack = 0x00;  // ecx
	*--new_stack = 0x00;  // eax
	// data segments
    *--new_stack = 0x10;  // ds
    *--new_stack = 0x10;  // es
    *--new_stack = 0x10;  // fs
    *--new_stack = 0x10;  // gs
    ntask->esp0 = (uint32_t)new_stack;
	ntask->esp3 = (uint32_t)ustack;
	asm volatile ("sti");	
	return ntask;


}





[global enter_user_mode]
enter_user_mode:
	cli
    mov ax, 0x23
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov eax, stack
    push 0x23
    push eax
    pushf
    pop eax
    or eax, 0x200
    push eax
    push 0x1B
    mov eax, [esp + 20]
    push eax
    iret


[global gdt32_install]
gdt32_install:


	GDT_ENTRY GDT32.Null, 0, 0, 0, 0
	GDT_ENTRY GDT32.Kernel_Code, 0, 0xFFFFFFFF, 0x9A, 0xCF
	GDT_ENTRY GDT32.Kernel_Data, 0, 0xFFFFFFFF, 0x92, 0xCF
	GDT_ENTRY GDT32.User_Code,   0, 0xFFFFFFFF, 0xFA, 0xCF
	GDT_ENTRY GDT32.User_Data,   0, 0xFFFFFFFF, 0xF2, 0xCF
	GDT_ENTRY GDT32.TSS, TSS32, TSS32+26*4, 0xE9, 0
	
	mov word [GDT32.Pointer], 6*8
	mov dword [GDT32.Pointer+2], GDT32
	
	lgdt [GDT32.Pointer]         ; Load 32-bit GDT
	mov ax, GDT32.Kernel_Data    
    mov ds, ax                   ; Load all data segment selectors
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    jmp 0x08: GDT32Loaded       ; Set the code segment and do a far jump!
	
GDT32Loaded:

	call tss32_init

	ret


Any input would be greatly appreciated because this one has got me stumped I just create a new task and make it so it isn't a server and doesn't have those bits set and the loaded programs that use the in and out don't cause the General Protection Fault like I thought they would.

Thanks,
Alex
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Programs can use io ports in user mode.

Post by Brendan »

Hi,
yoshi65 wrote:Any input would be greatly appreciated because this one has got me stumped I just create a new task and make it so it isn't a server and doesn't have those bits set and the loaded programs that use the in and out don't cause the General Protection Fault like I thought they would.
In that case, either the new task is running at CPL=0 (so that CPL <= IOPL regardless of what IOPL is), or the TSS has an IO permission bitmap that allows it.


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