Virtual 8086 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
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Virtual 8086 Mode

Post by Jeko »

This is my code for the creation of a task in virtual 8086 mode. Is it good?

kernel_stack is the kernel stack, esp0 in the TSS
user_stack is the user stack
esp is the stack
ss0 in the TSS is the kernel data selector

Code: Select all

//Interrupt enable flag in EFLAGS register.
#define EFLAGS_IF	0x200

//I/O privilege level 0.
//Only the kernel can perform I/O operations.
#define EFLAGS_IOPL0	0x0000

#define EFLAGS_VM	0x20000

//Extract the segment part of a linear address.
#define SEGMENT(linear)		( (unsigned short)(((unsigned int)(linear) & 0xFFFF0000) >> 4) )
//Extract the offset part of a linear address.
#define OFFSET(linear)		( (unsigned short)((unsigned int)(linear) & 0xFFFF) )
//Make a linear address from a segment:offset address.
#define LINEAR(seg, off)	( (unsigned int)(((unsigned short)(seg) << 4) + (unsigned short)(off)) )


void new_v86_task(void *entry, void *stack_top, const char *nome)
{
	asm("cli");
	int i;
	unsigned int *stacksetup;

	struct task_t *newtask;
	newtask = (struct task_t*)kmalloc(sizeof(struct task_t));

	newtask->kernel_stack = (unsigned int*)kmalloc(4096);
	newtask->init_kstack = newtask->kernel_stack;
	newtask->kernel_stack += 4096;

	stacksetup = newtask->kernel_stack;

	*stacksetup--;

	newtask->user_stack = (unsigned int*)kmalloc(4096);
	newtask->init_ustack = newtask->user_stack;

	newtask->user_stack += 4096;
	*newtask->user_stack--;
	*newtask->user_stack = (unsigned int)end_task;

	*stacksetup-- = SEGMENT((unsigned int)stack_top-sizeof(unsigned int)); //SS3
	*stacksetup-- = OFFSET((unsigned int)(stack_top-sizeof(unsigned int))); //ESP3

	*stacksetup-- = EFLAGS_IOPL0 | EFLAGS_VM | EFLAGS_IF | 0x02; //EFlags

	*stacksetup-- = SEGMENT((unsigned int)entry); //CS

	*stacksetup-- = OFFSET((unsigned int)entry); //EIP

	*stacksetup-- = 0; //EDI
	*stacksetup-- = 0; //ESI
	*stacksetup-- = 0; //EBP
	*stacksetup-- = 0; //Offset
	*stacksetup-- = 0; //EBX
	*stacksetup-- = 0; //EDX
	*stacksetup-- = 0; //ECX
	*stacksetup-- = 0; //EAX

	*stacksetup-- = SEGMENT((unsigned int)entry); //DS
	*stacksetup-- = SEGMENT((unsigned int)entry); //ES
	*stacksetup-- = SEGMENT((unsigned int)entry); //FS
	*stacksetup = SEGMENT((unsigned int)entry); //GS	

	newtask->esp = (unsigned int)stacksetup;
	newtask->privilege = USER;

...

Post Reply