diff --git a/include/fxBoot/hypervisor.h b/include/fxBoot/hypervisor.h index c7c2f5e..cd34ac3 100644 --- a/include/fxBoot/hypervisor.h +++ b/include/fxBoot/hypervisor.h @@ -25,11 +25,25 @@ struct cpuctx { uint32_t pr; }; +#define HYPERVISOR_STACK_KERNEL_SIZE (2 * 1024) +#define HYPERVISOR_STACK_USER_SIZE (10 * 1024) + +/* hworld: Wolrd context, used by the hypervisor + + Be careful, many information are completely hardcoded in some assembly + sources. So, if you may change or update this structur, check all assembly + file. */ struct hworld { - /* hardware context */ + /* stack information (NEVER CHANGE THE ORDER )*/ + struct { + void *kernel; + void *user; + } stack; + + /* hardware context (NEVER CHANGE THE ORDER OF "drivers" AND "cpu") */ struct { - struct cpuctx cpu; void *drivers; + struct cpuctx cpu; } context; /* memory information */ @@ -38,6 +52,14 @@ struct hworld { void *start; size_t size; } program; + struct { + void *kernel; + void *user; + struct { + size_t kernel; + size_t user; + } size; + } stack; } memory; /* private information (used by the hypeviseur) */ @@ -119,15 +141,28 @@ extern void hypervisor_loader_list_destroy(struct himage **list); //--- // World interface //--- -/* */ extern struct hworld *hypervisor_wswitch_create(void); +extern int hypervisor_wswitch(struct hworld *world); extern int hypervisor_wswitch_destroy(struct hworld *world); extern int hypervisor_wswitch_queue_register(struct hworld *world); extern int hypervisor_wswitch_queue_unregister(struct hworld *world); extern struct hworld *hypervisor_wswitch_queue_get(void); +extern struct hworld *hypervisor_wswitch_world_alloc(void); +extern void hypervisor_wswitch_world_free(struct hworld **world); //--- // Environment interface //--- extern int hypervisor_env_set(struct hworld *hworld); + +//--- +// Installer interface +//--- +extern int hypervisor_install(void); + +//--- +// "Kernel" interface +//--- +//extern int hypervisor_kernel_world_yield(struct hworld*c, struct hworld *n); +//extern int hypervisor_kernel_world_switch(struct hworld*c, struct hworld *n); #endif /*__FXBOOT_LOADER_H__*/ diff --git a/src/builtin/hyp.c b/src/builtin/hyp.c index 2d0f506..7ea6fbd 100644 --- a/src/builtin/hyp.c +++ b/src/builtin/hyp.c @@ -19,50 +19,6 @@ struct { uint32_t installed; } hypinfo; -#if 0 -//--- -// SMEM abstraction -//--- -static void smemfs_find(struct smemfs_inode *inode, char *buffer, int *counter) -{ - const char *ext; - - if (inode == NULL) - return; - smemfs_find(inode->child, buffer, counter); - ext = strrchr(inode->name, '.'); - if (ext != NULL) { - if (strcmp(ext, ".elf") == 0) { - terminal_write("[%d] %s\n", *counter, inode->name); - *counter += 1; - } - } - smemfs_find(inode->sibling, buffer, counter); -} - -static struct smemfs_inode *smemfs_get(struct smemfs_inode *inode, - int *counter, int id) -{ - struct smemfs_inode *file; - const char *ext; - - if (inode == NULL) - return (NULL); - file = smemfs_get(inode->child, counter, id); - if (file != NULL) - return (file); - ext = strrchr(inode->name, '.'); - if (ext != NULL) { - if (strcmp(ext, ".elf") == 0) { - if (*counter == id) - return (inode); - *counter += 1; - } - } - return (smemfs_get(inode->sibling, counter, id)); -} -#endif - //--- // Module management //--- @@ -86,8 +42,8 @@ static int hyp_img_module(int argc, char **argv) terminal_write("image ID missing\n"); return (84); } - int id = atoi(argv[3]); int counter = 0; + int id = atoi(argv[3]); struct himage *img = hypinfo.images; while (img != NULL) { if (counter == id) @@ -144,36 +100,28 @@ static int hyp_os_module(int argc, char **argv) } return (0); } -#if 0 if (strcmp(argv[2], "run") == 0) { if (argc < 3) { terminal_write("OS ID missing\n"); return (84); } - int id = atoi(argv[3]); int counter = 0; - struct worldctx *worldctx = hyp_info.os_list; - while (worldctx != NULL) { + int id = atoi(argv[3]); + struct hworld *world = hypervisor_wswitch_queue_get(); + while (world != NULL) { if (counter == id) break; - worldctx = worldctx->private.next; counter = counter + 1; + world = world->private.next; } - if (worldctx == NULL) { - terminal_write("OS ID invalid\n"); + if (world == NULL) { + terminal_write("image ID invalid\n"); return (84); } - /* Switch from gint to the OS after a short wait */ - gint_switch_to_casio(); - - /* call Casio's specific code */ - ((void(*)(void))(uintptr_t)worldctx->context.cpu.spc)(); - - /* Then switch back to gint once the OS finishes working */ - gint_switch_to_gint(); + if (hypervisor_wswitch(world) != 0) + return (84); return (0); } -#endif error: terminal_write("\"hyp os\" requiere at least 1 argument\n"); @@ -186,28 +134,37 @@ error: return (1); } -#if 0 -/* install the hypervisor */ -static int hyp_install(void) +/* hyp_install(): Installer interface */ +static int hyp_install(int argc, char **argv) { -/* extern void *bhyp_rom; - extern void *bhyp_ram; - extern void *zhyp; + extern void *hypervisor_vbr_exch; + extern void *hypervisor_vbr_tlbh; + extern void *hypervisor_vbr_inth; + extern void *hypervisor_vbr; - // check if the hypervisor is already installed. - if (hyp_info.installed == 0xdeb0cad0) { - terminal_write("hypervisor already installed\n"); - return (1); + if (argc < 2) + goto error; + if (strcmp(argv[2], "debug") == 0) { + terminal_write("VBR: %p\n", hypervisor_vbr_exch - 0x100); + terminal_write("exch: %p\n", hypervisor_vbr_exch); + terminal_write("tlbh: %p\n", hypervisor_vbr_tlbh); + terminal_write("inth: %p\n", hypervisor_vbr_inth); + return (0); } - - // install the hypervisor - if (hyperisor_install() != 0) { - terminal_write("hypervisor installation fail :(\n"); - return (84); - }*/ + if (strcmp(argv[2], "now") == 0) { + hypervisor_install(); + terminal_write("installed at <%p>\n", hypervisor_vbr); + return (0); + } +error: + terminal_write("\"hyp install\" requiere at least 1 argument\n"); + terminal_write("\n"); + terminal_write("Hypervisor installer\n"); + terminal_write("\n"); + terminal_write("commands:\n"); + terminal_write(" debug Display hypervisor low level information\n"); return (0); } -#endif //--- // Entry @@ -228,8 +185,13 @@ int hyp_main(int argc, char **argv) return (hyp_img_module(argc, argv)); if (strcmp(argv[1], "os") == 0) return (hyp_os_module(argc, argv)); - //if (strcmp(argv[1], "install") == 0) - // return (hyp_install()); + if (strcmp(argv[1], "install") == 0) + return (hyp_install(argc, argv)); + if (strcmp(argv[1], "trap") == 0) { + int allo; + __asm__ volatile ("trapa #0; mov r0, %0":"=r"(allo)); + return (allo); + } } /* error or helper */ diff --git a/src/hypervisor/gint.c b/src/hypervisor/gint.c index cd19b7c..98b4a02 100644 --- a/src/hypervisor/gint.c +++ b/src/hypervisor/gint.c @@ -34,4 +34,3 @@ void gint_switch(void (*function)(void)) function(); gint_switch_to_gint(); } - diff --git a/src/hypervisor/install.S b/src/hypervisor/install.S deleted file mode 100644 index e96b4aa..0000000 --- a/src/hypervisor/install.S +++ /dev/null @@ -1,35 +0,0 @@ -#if 0 -.section .hypervisor.text, "ax" -.global _hypervisor_install - -.align 2 -_hypervisor_install: - /* check if the hypervisor is installed */ - stc vbr, r0 - mov.l hypervisor_vbr, r1 - cmp/eq r1, r0 - bf install - rts - mov #-1, r0 - -install: - /* Block all interrupts by setting IMASK=15 */ - mov #0xf, r0 - shll2 r0 - shll2 r0 - stc sr, r2 - or r2, r0 - ldc r0, sr - - /* install the hypervisor */ - ldc r1, vbr - - /* restore VBR then exit */ - ldc r2, sr - rts - xor r0, r0 - -.align 4 -hypervisor_vbr: - .long _hypervisor_vbr -#endif diff --git a/src/hypervisor/install.c b/src/hypervisor/install.c index 0a1665d..e2d9aa7 100644 --- a/src/hypervisor/install.c +++ b/src/hypervisor/install.c @@ -3,12 +3,39 @@ //--- #include "fxBoot/hypervisor.h" +#include +#include +#include + +/* external VBR information */ +extern void *hypervisor_vbr_inth; +extern void *hypervisor_vbr_exch; +extern void *hypervisor_vbr_tlbh; + +/* internal information */ +struct hworld *hypervisor_world_current; +struct hworld *hypervisor_world; +void *hypervisor_vbr_redirect; +void *hypervisor_vbr; + //--- // User API //--- /* hypervisor_install(): Install the hypervisor */ int hypervisor_install(void) { - //TODO:generate the world context for the interface - //TODO: switch VBR + /* generate the world context for the interface */ + if (hypervisor_world == NULL) { + hypervisor_world = hypervisor_wswitch_world_alloc(); + if (hypervisor_world == NULL) + return (-1); + hypervisor_world_current = hypervisor_world; + } + + /* switch the VBR */ + hypervisor_vbr = (void*)(hypervisor_vbr_exch - 0x100); + void * tmp = cpu_getVBR(); + if (tmp != hypervisor_vbr) + hypervisor_vbr_redirect = cpu_setVBR(hypervisor_vbr); + return (0); } diff --git a/src/hypervisor/internal/elf.h b/src/hypervisor/internal/elf.h index d22f929..d7de71b 100644 --- a/src/hypervisor/internal/elf.h +++ b/src/hypervisor/internal/elf.h @@ -4,6 +4,7 @@ #include #include +#include "fxBoot/hypervisor.h" #include "fxBoot/fs/smemfs.h" #include "fxBoot/elf.h" diff --git a/src/hypervisor/kernel.S b/src/hypervisor/kernel.S new file mode 100644 index 0000000..8f27bdb --- /dev/null +++ b/src/hypervisor/kernel.S @@ -0,0 +1,128 @@ +/* +** hypervisor:kernel - low level world manipulation +*/ +.section .gint.mapped, "ax" +.align 2 + +.global _hypervisor_kernel_abi +.global _hypervisor_kernel_world_switch + +/* hypervisor_kernel_abi(): Kernel ABI entry */ +_hypervisor_kernel_abi: + /* check trapa validity */ + mov.l abi_trapa_reg, r1 + mov.l @r1, r1 + shlr2 r1 + mov #1, r2 + cmp/hi r1, r2 + bf abi_error + + /* involve syscall if possible */ + shll2 r1 + mova abi_syscall_table, r0 + mov.l @(r0, r1), r3 + tst r3, r3 + bt abi_error + jmp @r3 + nop + + /* error handling */ +abi_error: + mov #-1, r0 + ldc r0, R0_BANK + rte + nop + +.align 4 +abi_trapa_reg: + .long 0xff000020 +abi_syscall_table: + .long 0x00000000 ! _hypervisor_kernel_world_switch + .long 0x00000000 + + + +#if 0 +/* hypervisor world_switch(): Performs a world switch */ +_hypervisor_kernel_world_switch: + /* check potential error */ + tst r4, r4 + bt kernel_world_error + tst r5, r5 + bt kernel_world_error + + /* save the current context */ + sts.l pr, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l drivers_context_save, r0 + jsr @r0 + mov.l @r4, r4 + mov.l @r15+, r5 + mov.l @r15+, r4 + ldc.l @r15+, pr + + /* save cpu context */ + add #92, r4 + mov.l pr, @-r4 + stc.l spc, @-r4 + stc.l ssr, @-r4 + sts.l mach, @-r4 + sts.l macl, @-r4 + stc.l gbr, @-r4 + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + stc.l R7_BANK, @-r4 + stc.l R6_BANK, @-r4 + stc.l R5_BANK, @-r4 + stc.l R4_BANK, @-r4 + stc.l R3_BANK, @-r4 + stc.l R2_BANK, @-r4 + stc.l R1_BANK, @-r4 + stc.l R0_BANK, @-r4 + + /* restore cpu context */ + add #4, r5 + ldc.l @r5+, R0_BANK + ldc.l @r5+, R1_BANK + ldc.l @r5+, R2_BANK + ldc.l @r5+, R3_BANK + ldc.l @r5+, R4_BANK + ldc.l @r5+, R5_BANK + ldc.l @r5+, R6_BANK + ldc.l @r5+, R7_BANK + mov.l @r5+, r8 + mov.l @r5+, r9 + mov.l @r5+, r10 + mov.l @r5+, r11 + mov.l @r5+, r12 + mov.l @r5+, r13 + mov.l @r5+, r14 + mov.l @r5+, r15 + ldc.l @r5+, gbr + lds.l @r5+, macl + lds.l @r5+, mach + ldc.l @r5+, ssr + ldc.l @r5+, spc + lds.l @r5+, pr + + /* restore drivers context */ + /* TODO */ + + /* force install hypervisor */ + /* TODO */ + + /* perform the world switch */ + rte + nop + +kernel_world_error: + rts + mov #-2, r0 +#endif diff --git a/src/hypervisor/vbr.S b/src/hypervisor/vbr.S index 9b2ac8c..75ff794 100644 --- a/src/hypervisor/vbr.S +++ b/src/hypervisor/vbr.S @@ -1,59 +1,232 @@ -#if 0 -.section .hypervisor.interrupt, "ax" -.global _hypervisor_inth - +/* +** hypervisor:vbr - VBR handling +*/ +.section .gint.mapped, "ax" .align 2 -_hypervisor_inth: - /* save interrupt related information */ + +.global _hypervisor_vbr_exch_reloc +.global _hypervisor_vbr_tlbh_reloc +.global _hypervisor_vbr_inth_reloc + +/* hypervisor_vbr_exch_reloc(): Relocalized exception handler */ +_hypervisor_vbr_exch_reloc: + /* check if it's a hypervisor call */ + mov.l exch_hypervisor_world_current, r4 + mov.l exch_hypervisor_world, r3 + mov.l @r4, r4 + mov.l @r3, r3 + cmp/eq r3, r4 + bf exch_normal_behaviour + +exch_trap_behaviour: + /* check trapa exception and involve kernel ABI if needed */ + mov.l exch_expevt_reg, r0 + mov.l @r0, r0 + mov #0x16, r1 + shll2 r1 + shll2 r1 + cmp/eq r0, r1 + bf exch_normal_behaviour + mov.l exch_kernel_abi, r0 + jmp @r0 + nop + +exch_normal_behaviour: + /* normal behaviour */ + stc.l spc, @-r4 + stc.l ssr, @-r4 + + /* get the "real" tlb handler address */ + mov.l exch_hypervisor_vbr_redirect, r1 + mov.l @r1, r1 + ldc r1, vbr + mov #0x01, r2 + shll8 r2 + add r2, r1 + + /* jump into the "real" tlb handler and be sure that it will + return here with the same invoromnent */ + !stc sr, r2 + mova exch_jmp_over, r0 + ldc r0, spc + !ldc r2, ssr + jmp @r1 + nop + +.align 4 +exch_jmp_over: + /* get kernel stack and restore tlb event related information */ + mov.l exch_hypervisor_world_current, r4 + mov.l @r4, r4 + ldc.l @r4+, ssr + ldc.l @r4+, spc + + /* force hypervisor VBR re-installation, because it possible that the + VBR has been changed during the handler */ + mov.l exch_hypervisor_vbr_redirect, r0 + mov.l exch_hypervisor_vbr, r1 + stc vbr, r2 + mov.l r2, @r0 + ldc.l @r1+, vbr + + /* clean return */ + rte + nop + +.align 4 +exch_expevt_reg: .long 0xff000024 +exch_kernel_abi: .long _hypervisor_kernel_abi +exch_hypervisor_world: .long _hypervisor_world +exch_hypervisor_world_current: .long _hypervisor_world_current +exch_hypervisor_vbr_redirect: .long _hypervisor_vbr_redirect +exch_hypervisor_vbr: .long _hypervisor_vbr +exch_end: + .zero 0x300 - (exch_end - _hypervisor_vbr_exch_reloc) + + + + +/* hypervisor_vbr_tlbh_reloc(): Relocalized TLB handler */ +_hypervisor_vbr_tlbh_reloc: + /* get kernel stack and save tlb event related information */ + mov.l tlbh_hypervisor_current_world, r4 + mov.l @r4, r4 + stc.l spc, @-r4 + stc.l ssr, @-r4 + + /* get the "real" tlb handler address */ + mov.l tlbh_hypervisor_vbr_redirect, r1 + mov.l @r1, r1 + ldc r1, vbr + mov #0x04, r2 + shll8 r2 + add r2, r1 + + /* jump into the "real" interrupt handler and be sure that it will + return here with the same invoromnent */ + stc sr, r2 + mova tlbh_jmp_over, r0 + ldc r0, spc + ldc r2, ssr + jmp @r1 + nop + +.align 4 +tlbh_jmp_over: + /* get kernel stack and restore tlb event related information */ + mov.l tlbh_hypervisor_current_world, r4 + mov.l @r4, r4 + ldc.l @r4+, ssr + ldc.l @r4+, spc + + /* force hypervisor VBR re-installation, because it possible that the + VBR has been changed during the handler */ + mov.l tlbh_hypervisor_vbr_redirect, r0 + mov.l tlbh_hypervisor_vbr, r1 + stc vbr, r2 + mov.l r2, @r0 + ldc.l @r1+, vbr + + /* clean return */ + rte + nop + +.align 4 +tlbh_hypervisor_vbr_redirect: .long _hypervisor_vbr_redirect +tlbh_hypervisor_vbr: .long _hypervisor_vbr +tlbh_hypervisor_current_world: .long _hypervisor_world_current +tlbh_end: + .zero 0x200 - (tlbh_end - _hypervisor_vbr_tlbh_reloc) + + + + +/* hypervisor_vbr_inth_reloc(): Relocalized interrupt handler */ +_hypervisor_vbr_inth_reloc: + /* switch kernel stack */ + mov.l inth_hypervisor_current_world, r4 + mov.l @r4, r4 + mov.l r15, @(4, r4) + mov.l @r4, r15 + + /* save interrupt information */ + stc.l gbr, @-r15 sts.l mach, @-r15 sts.l macl, @-r15 - stc.l gbr, @-r15 stc.l spc, @-r15 stc.l ssr, @-r15 sts.l pr, @-r15 - /* check manually the keyboard status to see if the we need to - perform a world switch */ - mov.l hypervisor_wswitch_check, r0 - jsr @r0 - nop - mov.l r0, @-r15 + /* TODO: involve keyboard scanner */ + /* TODO: involved world switch to the hypervisor if needed */ - /* involve the "real" vbr handler */ - mov.l hypervisor_inth_second_part, r0 - ldc r0, vbr - mov.l hypervisor_current_vbr, r0 - mov.l @r0, r0 - mov #0x06, r1 - shll8 r1 - add r1, r0 - jsr @r0 + /* switch stack before calling the real handler */ + mov.l r15, @r4 + mov.l @(4, r4), r15 + + /* get the "real" VBR interrupt handler address */ + mov.l inth_hypervisor_vbr_redirect, r1 + mov.l @r1, r1 + ldc r1, vbr + mov #0x06, r2 + shll8 r2 + add r2, r1 + + /* jump into the "real" interrupt handler and be sure that it will + return here with the same invoromnent */ + stc sr, r2 + mova inth_jmp_over, r0 + ldc r0, spc + ldc r2, ssr + jmp @r1 nop -hypervisor_inth_prologue: - /* check if world switch is requested */ - mov.l @r15+, r0 - tst r0, r0 - bf.s hypervisor_inth_exit - mov.l hypervisor_wswitch, r0 - jsr @r0 - nop +.align 4 +inth_jmp_over: + /* switch stack */ + mov.l inth_hypervisor_current_world, r4 + mov.l @r4, r4 + mov.l r15, @(4, r4) + mov.l @r4, r15 + /* force hypervisor VBR re-installation, because it possible that the + VBR has been changed during the handler */ + mov.l inth_hypervisor_vbr_redirect, r0 + mov.l inth_hypervisor_vbr, r1 + stc vbr, r2 + mov.l r2, @r0 + ldc.l @r1+, vbr -hypervisor_inth_exit: - /* restore the saved information */ + /* restore interrupt information */ lds.l @r15+, pr ldc.l @r15+, ssr ldc.l @r15+, spc - ldc.l @r15+, gbr lds.l @r15+, macl - rte lds.l @r15+, mach + ldc.l @r15+, gbr + + /* switch stack and exit */ + mov.l r15, @r4 + mov.l @(4, r4), r15 + + /* Salut mon pote ! */ + rte + nop .align 4 -hypervisor_wswitch_check: .long _hypervisor_worldswitch_check -hypervisor_wswitch: .long _hypervisor_worldswitch -hypervisor_current_vbr: .long _hypervisor_current_vbr -hypervisor_vbr: .long _hypervisor_vbr -hypervisor_inth_second_part: .long hypervisor_inth_prologue -#endif +inth_hypervisor_vbr: .long _hypervisor_vbr +inth_hypervisor_vbr_redirect: .long _hypervisor_vbr_redirect +inth_hypervisor_current_world: .long _hypervisor_world_current + + + + +/* define all symbols */ +.section .gint.mappedrel, "aw" +.align 4 +.global _hypervisor_vbr_exch +.global _hypervisor_vbr_tlbh +.global _hypervisor_vbr_inth +_hypervisor_vbr_exch: .long _hypervisor_vbr_exch_reloc +_hypervisor_vbr_tlbh: .long _hypervisor_vbr_tlbh_reloc +_hypervisor_vbr_inth: .long _hypervisor_vbr_inth_reloc diff --git a/src/hypervisor/wswitch.c b/src/hypervisor/wswitch.c index 63aca9d..7cb731f 100644 --- a/src/hypervisor/wswitch.c +++ b/src/hypervisor/wswitch.c @@ -10,10 +10,57 @@ /* internal globals information */ HYPERVISOR_BSS void *hypervisor_current_vbr = NULL; HYPERVISOR_BSS struct hworld *hypervisor_world_queue = NULL; +extern struct hworld *hypervisor_world; //--- // World API //--- +/* hypervisor_wswitch_world_free(): Free'd allocated world */ +void hypervisor_wswitch_world_free(struct hworld **world) +{ + if (world == NULL || *world == NULL) + return; + if ((*world)->memory.stack.kernel != NULL) + free((*world)->memory.stack.kernel); + if ((*world)->memory.stack.user != NULL) + free((*world)->memory.stack.user); + if ((*world)->context.drivers != NULL) + drivers_context_destroy((*world)->context.drivers); + free(*world); + *world = NULL; +} + +/* hypervisor_wswitch_world_alloc(): Allocate a new world */ +struct hworld *hypervisor_wswitch_world_alloc(void) +{ + struct hworld *world; + + world = calloc(sizeof(struct hworld), 1); + if (world == NULL) + return (NULL); + world->private.status = HYPERVISOR_STATUS_CREATED; + world->private.env = HYPERVISOR_ENV_CASIO; + world->memory.stack.user = malloc(HYPERVISOR_STACK_USER_SIZE); + world->memory.stack.kernel = malloc(HYPERVISOR_STACK_KERNEL_SIZE); + world->context.drivers = drivers_context_create(); + if (world->memory.stack.user == NULL + || world->memory.stack.kernel == NULL + || world->context.drivers == NULL) { + hypervisor_wswitch_world_free(&world); + return (NULL); + } + world->memory.stack.size.user = HYPERVISOR_STACK_USER_SIZE; + world->memory.stack.size.kernel = HYPERVISOR_STACK_USER_SIZE; + world->stack.kernel = world->memory.stack.kernel; + world->stack.kernel += HYPERVISOR_STACK_KERNEL_SIZE; + world->stack.kernel = (void*)((uintptr_t)world->stack.kernel & ~3); + world->stack.user = world->memory.stack.user; + world->stack.user += HYPERVISOR_STACK_USER_SIZE; + world->stack.user = (void*)((uintptr_t)world->stack.user & ~3); + return (world); +} + + /* hypervisor_wswitch_create(): Create a new world */ struct hworld *hypervisor_wswitch_create(void) { @@ -28,12 +75,7 @@ struct hworld *hypervisor_wswitch_create(void) world->private.status = HYPERVISOR_STATUS_INIT; return (world); } - world = calloc(sizeof(struct hworld), 1); - if (world != NULL) { - world->private.status = HYPERVISOR_STATUS_CREATED; - world->private.env = HYPERVISOR_ENV_CASIO; - } - return (world); + return (hypervisor_wswitch_world_alloc()); } /* void hypervisor_wswitch_destroy(): Destroy the world */ @@ -68,6 +110,7 @@ int hypervisor_wswitch_queue_register(struct hworld *world) return (-1); world->private.next = hypervisor_world_queue; hypervisor_world_queue = world; + world->private.status = HYPERVISOR_STATUS_INIT; return (0); } @@ -99,15 +142,14 @@ int hypervisor_wswitch_queue_unregister(struct hworld *target) //--- // User API //--- -/* hypervisor_wswitch_check(): Check if a world switch is needed */ -int hypervisor_wswitch_check(void) -{ - //TODO: scan the KEYSC registers -} - /* hypervisor_wswitch(): Perform a world switch */ -int hypervisor_wswitch(void) +int hypervisor_wswitch(struct hworld *world) { - //TODO: display menu - //TODO: perform a world switch woth the next world context + if (world == NULL) + return (-1); + if (world->private.status != HYPERVISOR_STATUS_INIT) + return (-2); + hypervisor_install(); + //hypervisor_kernel_world_yield(hypervisor_world, world); + return (0); }