Skip to content

Commit

Permalink
Build the hypercall system by imitate the syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
Yourens committed May 27, 2014
1 parent b553492 commit 0ffd971
Show file tree
Hide file tree
Showing 16 changed files with 350 additions and 12 deletions.
20 changes: 10 additions & 10 deletions examples/rtems-guest/hello.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

#include <libc/stdio.h>
#include <core/syscall.h>
#include <core/hypercall.h>

#include "virtualizationlayerbsp.h"
#include "virtualizationlayercpu.h"
Expand Down Expand Up @@ -51,7 +51,7 @@ void interrupt_middleman( unsigned vector, void* frame )

C_dispatch_isr(vector);

pok_syscall1( POK_SYSCALL_IRQ_PARTITION_ACK, vector );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_ACK, vector );
// recover frame, restore registers, place return eip;
asm volatile( "movl %%esp, %%eax \t\n"
"1: \t\n"
Expand Down Expand Up @@ -133,7 +133,7 @@ _BSP_Virtual_getworkspacearea( void )
int
_CPU_Virtual_Irq_request( int vector )
{
pok_ret_t ret = pok_syscall2( POK_SYSCALL_IRQ_REGISTER_HANDLER, vector, (uint32_t)&interrupt_middleman );
pok_ret_t ret = pok_hypercall2( POK_HYPERCALL_IRQ_REGISTER_HANDLER, vector, (uint32_t)&interrupt_middleman );
if( ret != POK_ERRNO_OK )
{
printf( "Couldn't register handler\n");
Expand All @@ -146,7 +146,7 @@ _CPU_Virtual_Irq_request( int vector )
void
_CPU_Virtual_Irq_detach( int vector )
{
pok_syscall1( POK_SYSCALL_IRQ_UNREGISTER_HANDLER, vector);
pok_hypercall1( POK_HYPERCALL_IRQ_UNREGISTER_HANDLER, vector);
}

/**
Expand All @@ -158,15 +158,15 @@ _CPU_Virtual_Irq_detach( int vector )
void
_CPU_Virtual_Interrupts_enable( int _level )
{
pok_syscall1( POK_SYSCALL_IRQ_PARTITION_ENABLE, _level );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_ENABLE, _level );
}
/**
* \brief disables interrupts and returns previous level
*/
void
_CPU_Virtual_Interrupts_disable( int _level )
{
pok_syscall1( POK_SYSCALL_IRQ_PARTITION_DISABLE, _level );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_DISABLE, _level );
}

/**
Expand All @@ -176,8 +176,8 @@ _CPU_Virtual_Interrupts_disable( int _level )
void
_CPU_Virtual_Interrupts_flash( int _level )
{
pok_syscall1( POK_SYSCALL_IRQ_PARTITION_ENABLE, _level );
pok_syscall1( POK_SYSCALL_IRQ_PARTITION_DISABLE, _level );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_ENABLE, _level );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_DISABLE, _level );
}

/**
Expand All @@ -186,7 +186,7 @@ _CPU_Virtual_Interrupts_flash( int _level )
void
_CPU_Virtual_Interrupts_open( void )
{
pok_syscall1( POK_SYSCALL_IRQ_PARTITION_ENABLE, 0 );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_ENABLE, 0 );
}

/**
Expand All @@ -195,7 +195,7 @@ _CPU_Virtual_Interrupts_open( void )
void
_CPU_Virtual_Interrupts_close( void )
{
pok_syscall1( POK_SYSCALL_IRQ_PARTITION_DISABLE, 1 );
pok_hypercall1( POK_HYPERCALL_IRQ_PARTITION_DISABLE, 1 );
}

int
Expand Down
3 changes: 2 additions & 1 deletion kernel/arch/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ LO_OBJS= arch.o \

ifeq ($(BSP),x86-qemu-vmm)

LO_OBJS+= interrupt_prologue.o
LO_OBJS+= interrupt_prologue.o \
hypercall.o

endif
LO_DEPS= $(BSP)/$(BSP).lo
Expand Down
4 changes: 3 additions & 1 deletion kernel/arch/x86/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <types.h>
#include <errno.h>
#include <core/syscall.h>
#include <core/hypercall.h>

#include "event.h"
#include "sysdesc.h"
Expand All @@ -36,8 +37,9 @@ pok_ret_t pok_event_init ()
pok_exception_init ();
#endif

pok_syscall_init ();
pok_syscall_init (); //syscall register IDT index POK_SYSCALL_INT_NUMBER, i.e., 42;

pok_hypercall_init(); //hypercall register IDT index POK_HYPERCALL_INT_NUMBER, i.e,24;
return (POK_ERRNO_OK);
}

Expand Down
59 changes: 59 additions & 0 deletions kernel/arch/x86/hypercall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <errno.h>
#include <core/debug.h>
#include <core/partition.h>
#include <core/hypercall.h>

#include "event.h"
#include "gdt.h"

#define PARTITION_ID(cs) (((cs >> 3) - 4 ) / 2)

/*
* Define the hypercall handler function
*/

INTERRUPT_HANDLER_hypercall(hypercall_gate)
{
pok_hypercall_info_t hypercall_info;
pok_ret_t hypercall_ret;
pok_hypercall_args_t* hypercall_args;
pok_hypercall_id_t hypercall_id;

hypercall_info.partition = PARTITION_ID (frame->cs);
hypercall_info.base_addr = pok_partitions[hypercall_info.partition].base_addr;
hypercall_info.thread = POK_SCHED_CURRENT_THREAD;

hypercall_args = (pok_hypercall_args_t * ) (frame->ebx + hypercall_info.base_addr);

hypercall_id = (pok_hypercall_id_t) frame->eax;

if (POK_CHECK_PTR_IN_PARTITION(hypercall_info.partition, hypercall_args) == 0)
{
hypercall_ret = POK_ERRNO_EINVAL;
}
else
{
// perform the hypercall;
hypercall_ret = pok_core_hypercall ( hypercall_id, hypercall_args, & hypercall_info);
}
/*
* put the return value in eax register
*/
asm ( "movl %0, %%eax \n"
:
: "m" (hypercall_ret));
}

/*
* Init Hypercall system
*/

pok_ret_t pok_hypercall_init()
{
pok_idt_set_gate (POK_HYPERCALL_INT_NUMBER,

This comment has been minimized.

Copy link
@phipse

phipse May 27, 2014

You are not allowed to use the first 32 lines in the IDT! These are reserved by INTEL.
More on interrupts:
http://www.brokenthorn.com/Resources/OSDev15.html

This comment has been minimized.

Copy link
@Yourens

Yourens May 27, 2014

Author Owner

Thank you for your rectify my error. I confuse with other operating system which will automatically subtract 32.
I will adjust it.

GDT_CORE_CODE_SEGMENT << 3,
(uint32_t) hypercall_gate,
IDTE_INTERRUPT,
3);
return (POK_ERRNO_OK);
}
3 changes: 3 additions & 0 deletions kernel/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ LO_OBJS= partition.o \
boot.o \
cons.o

ifeq ($(BSP),x86-qemu-vmm)
LO_OBJS+= hypercall.o
endif
LO_DEPS=

all: $(LO_TARGET)
Expand Down
85 changes: 85 additions & 0 deletions kernel/core/hypercall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

#include <bsp.h>
#include <types.h>
#include <libc.h>
#include <arch/x86/ioports.h>
#include <arch/x86/pci.h>

#include <errno.h>
#include <core/debug.h>
#include <core/hypercall.h>
#include <core/partition.h>
#include <core/thread.h>
#include <core/lockobj.h>
#include <core/time.h>
#include <core/error.h>

#include <middleware/port.h>



pok_ret_t pok_core_hypercall (const pok_hypercall_id_t hypercall_id,
const pok_hypercall_args_t* args,
const pok_hypercall_info_t* infos)
{
switch (hypercall_id)
{
#if defined (POK_NEEDS_CONSOLE) || defined (POK_NEEDS_DEBUG)
case POK_HYPERCALL_CONSWRITE:
POK_CHECK_PTR_OR_RETURN(infos->partition, args->arg1 + infos->base_addr)
if (pok_cons_write ((const char*)args->arg1 + infos->base_addr, args->arg2))
{
return POK_ERRNO_OK;
}
else
{
return POK_ERRNO_EINVAL;
}
break;
#endif

#ifdef POK_NEEDS_X86_VMM
/**
* This shall register an irq handler with the meta_handler for the
* requested interrupt number.
* arg1: vector nubmer,
* arg2: handler/callback function
*/
case POK_HYPERCALL_IRQ_REGISTER_HANDLER:
POK_CHECK_PTR_OR_RETURN(infos->partition, args->arg2 + infos->base_addr)
/* arg1 is just a number, arg2 is a pointer to a function in the
* partition, therefore the partitions base_addr must be added to become
* a valid pointer for the kernel.
*/
return pok_bsp_irq_register_hw (args->arg1,
(void(*)(unsigned, void*)) ((args->arg2 + infos->base_addr)) );
break;

case POK_HYPERCALL_IRQ_UNREGISTER_HANDLER:
return pok_bsp_irq_unregister_hw (args->arg1);
break;
/* enable/disable interrupt delivery to a partition */
case POK_HYPERCALL_IRQ_PARTITION_ENABLE:
return pok_bsp_irq_partition_enable (args->arg1);
break;
case POK_HYPERCALL_IRQ_PARTITION_DISABLE:
return pok_bsp_irq_partition_disable (args->arg1);
break;
case POK_HYPERCALL_IRQ_PARTITION_ACK:
return pok_bsp_irq_partition_ack(args->arg1);
break;
#endif /* POK_NEEDS_X86_VMM */
default:
#ifdef POK_NEEDS_ERROR_HANDLING
pok_error_declare( POK_ERROR_KIND_ILLEGAL_REQUEST);
pok_sched_activate_error_thread ();
#else
#ifdef POK_NEEDS_DEBUG
printf("Tried to use hypercall %d\n", hypercall_id);
#endif
POK_FATAL ("Unknown hypercall");
#endif
break;
}
return POK_ERRNO_EINVAL;
}
Binary file added kernel/core/hypercall.o
Binary file not shown.
36 changes: 36 additions & 0 deletions kernel/include/arch/x86/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,42 @@ void name##_handler(interrupt_frame* frame); \
); \
void name##_handler(interrupt_frame* frame)

/* Add for paravirtualization */

#ifdef POK_NEEDS_X86_VMM /* The guard of virtualization */

#define INTERRUPT_HANDLER_hypercall(name) \
int name (void); \
void name##_handler(interrupt_frame* frame); \
asm ( \
".global "#name " \n" \
"\t.type "#name",@function \n" \
#name": \n" \
"cli \n" \
"subl $4, %esp \n" \
"pusha \n" \
"push %ds \n" \
"push %es \n" \
"push %esp \n" \
"mov $0x10, %ax \n" \
"mov %ax, %ds \n" \
"mov %ax, %es \n" \
"call " #name"_handler \n" \
"movl %eax, 40(%esp) \n" /* return value */ \
"call update_tss \n" \
"addl $4, %esp \n" \
"pop %es \n" \
"pop %ds \n" \
"popa \n" \
"addl $4, %esp \n" \
"sti \n" \
"iret \n" \
); \
void name##_handler(interrupt_frame* frame)

#endif


struct meta_handler
{
unsigned vector;
Expand Down
Binary file added kernel/include/core/.hypercall.h.swp
Binary file not shown.
42 changes: 42 additions & 0 deletions kernel/include/core/hypercall.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef __POK_HYPERCALL_H__
#define __POK_HYPERCALL_H__

#include <types.h>
#include <errno.h>

typedef enum
{
POK_HYPERCALL_CONSWRITE =10,
POK_HYPERCALL_INT_NUMBER =24,

This comment has been minimized.

Copy link
@phipse

phipse May 27, 2014

Why did you omit gettick?

This comment has been minimized.

Copy link
@Yourens

Yourens May 27, 2014

Author Owner

I want to separate apart the normal function and hypervisor function in POK kernel. So I want to just keep necessary function in hypercall. Of course the gettick function will be necessary, but I'd like to add it when implement it.

/* Register an irq handler from a partition */
POK_HYPERCALL_IRQ_REGISTER_HANDLER = 25,
POK_HYPERCALL_IRQ_UNREGISTER_HANDLER = 26,
/* enable/disable interrupt delivery to a partition */
POK_HYPERCALL_IRQ_PARTITION_ENABLE = 27,
POK_HYPERCALL_IRQ_PARTITION_DISABLE = 28,
POK_HYPERCALL_IRQ_PARTITION_ACK = 29,
} pok_hypercall_id_t;

typedef struct
{
pok_partition_id_t partition;
uint32_t thread;
uint32_t base_addr;
}pok_hypercall_info_t;

typedef struct
{
uint32_t nargs;
uint32_t arg1;
uint32_t arg2;
uint32_t arg3;
uint32_t arg4;
uint32_t arg5;
} pok_hypercall_args_t;

pok_ret_t pok_core_hypercall(const pok_hypercall_id_t hypercall_id,
const pok_hypercall_args_t* args,
const pok_hypercall_info_t* infos);

pok_ret_t pok_hypercall_init();
#endif /* __POK_HYPERCALL_H__ */
Binary file added libpok/arch/x86/.hypercall.c.swp
Binary file not shown.
6 changes: 6 additions & 0 deletions libpok/arch/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ LO_OBJS= arch.o \
pci.o \
syscall.o

ifeq ($(BSP),x86-qemu-vmm)

LO_OBJS+= hypercall.o

endif
LO_DEPS=

all: $(LO_TARGET)
Expand All @@ -20,6 +25,7 @@ clean: common-clean

distclean: clean
$(RM) .depend.mk
$(RM) hypercall.o

This comment has been minimized.

Copy link
@phipse

phipse May 27, 2014

Can't you delete all .o files?


depend:
$(if $(LO_OBJS), $(CC) $(CFLAGS) -MM $(wildcard *.c) $(wildcard *.S) > .depend.mk,)
Expand Down
24 changes: 24 additions & 0 deletions libpok/arch/x86/hypercall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

#include <core/syscall.h>
#include <types.h>

pok_ret_t pok_do_hypercall (pok_syscall_id_t syscall_id, pok_syscall_args_t* args)

This comment has been minimized.

Copy link
@phipse

phipse May 27, 2014

why do we do hypercalls with syscall ids? I know this is copy paste, but if you introduce a new mechanism, then keep the naming consistent!

{
pok_ret_t ret;
uint32_t args_addr;
uint32_t id;

args_addr = (uint32_t) args;
id = (uint32_t) syscall_id;

asm volatile ( "movl %1,%%eax \n\t"
"movl %2,%%ebx \n\t"
"int $24 \n\t"
"movl %%eax, %0"
:"=g"(ret)
:"g"(id), "g"(args_addr)
: "%eax" , "%ebx"
);
return ret;
}

Binary file added libpok/include/core/.hypercall.h.swp
Binary file not shown.
Binary file added libpok/include/core/.syscall.h.swp
Binary file not shown.
Loading

0 comments on commit 0ffd971

Please sign in to comment.