v0.2.0 - Hypervisor loading images
@add * overwrite Gint "hypervisor" properly (gint_switch) * load ELF (pie) images into "world context". * add "environments" manager (used to load Casio or Gint drivers' contexts) * add "world queue" to manage properly multiple world contexts @update * "hyp" builtin: add "os" module * "hyp" builtin: add "os ls" commands * "hyp" builtin: fix display alignment
This commit is contained in:
parent
63db69e784
commit
759a8bd876
|
@ -29,6 +29,7 @@ struct hworld {
|
|||
/* hardware context */
|
||||
struct {
|
||||
struct cpuctx cpu;
|
||||
void *drivers;
|
||||
} context;
|
||||
|
||||
/* memory information */
|
||||
|
@ -42,7 +43,17 @@ struct hworld {
|
|||
/* private information (used by the hypeviseur) */
|
||||
struct {
|
||||
struct smemfs_inode *inode;
|
||||
struct worldctx *next;
|
||||
struct hworld *next;
|
||||
enum {
|
||||
HYPERVISOR_STATUS_CREATED = 0,
|
||||
HYPERVISOR_STATUS_INIT = 1,
|
||||
HYPERVISOR_STATUS_RUNNING = 2,
|
||||
HYPERVISOR_STATUS_DEAD = 3,
|
||||
} status;
|
||||
enum {
|
||||
HYPERVISOR_ENV_GINT = 0,
|
||||
HYPERVISOR_ENV_CASIO = 1,
|
||||
} env;
|
||||
} private;
|
||||
};
|
||||
|
||||
|
@ -104,4 +115,19 @@ extern int hypervisor_loader_list(struct himage **list);
|
|||
(out) list List that will be destroyed and set to NULL */
|
||||
extern void hypervisor_loader_list_destroy(struct himage **list);
|
||||
|
||||
|
||||
//---
|
||||
// World interface
|
||||
//---
|
||||
/* */
|
||||
extern struct hworld *hypervisor_wswitch_create(void);
|
||||
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);
|
||||
|
||||
//---
|
||||
// Environment interface
|
||||
//---
|
||||
extern int hypervisor_env_set(struct hworld *hworld);
|
||||
#endif /*__FXBOOT_LOADER_H__*/
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/std/stdio.h>
|
||||
#include <gint/gint.h>
|
||||
|
||||
/* internal structiure used to handle the hypervisor module */
|
||||
|
@ -65,7 +66,7 @@ static struct smemfs_inode *smemfs_get(struct smemfs_inode *inode,
|
|||
//---
|
||||
// Module management
|
||||
//---
|
||||
|
||||
/* hyp_img_module(): Handle argument for the image module part */
|
||||
static int hyp_img_module(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
|
@ -80,31 +81,29 @@ static int hyp_img_module(int argc, char **argv)
|
|||
}
|
||||
return (0);
|
||||
}
|
||||
#if 0
|
||||
if (strcmp(argv[2], "load") == 0) {
|
||||
if (argc < 3) {
|
||||
terminal_write("image ID missing\n");
|
||||
return (84);
|
||||
}
|
||||
int id = 0;
|
||||
struct smemfs_inode *file;
|
||||
int id = atoi(argv[3]);
|
||||
int counter = 0;
|
||||
id = atoi(argv[3]);
|
||||
file = smemfs_get(smemfs_superblock.root_inode,
|
||||
&counter, id);
|
||||
if (file == NULL) {
|
||||
struct himage *img = hypinfo.images;
|
||||
while (img != NULL) {
|
||||
if (counter == id)
|
||||
break;
|
||||
counter = counter + 1;
|
||||
img = img->next;
|
||||
}
|
||||
if (img == NULL) {
|
||||
terminal_write("image ID invalid\n");
|
||||
return (84);
|
||||
}
|
||||
struct worldctx *worldctx = calloc(sizeof(struct worldctx), 1);
|
||||
if (hypervisor_loader(worldctx, file) != 0)
|
||||
if (hypervisor_loader(img) != 0)
|
||||
return (84);
|
||||
worldctx->private.next = hyp_info.os_list;
|
||||
hyp_info.os_list = worldctx;
|
||||
terminal_write("image successfully loaded\n");
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
error:
|
||||
terminal_write("\"hyp img\" requires at least 1 argument\n");
|
||||
|
@ -117,33 +116,35 @@ error:
|
|||
return (1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* hyp_os_module(): Handle argument for the os module part */
|
||||
static int hyp_os_module(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
goto error;
|
||||
if (strcmp(argv[2], "ls") == 0) {
|
||||
int counter = 0;
|
||||
struct worldctx *worldctx = hyp_info.os_list;
|
||||
while (worldctx != NULL) {
|
||||
terminal_write("[%d] - %s\n", counter, worldctx->private.file->name);
|
||||
terminal_write("|-- cpu context:\n");
|
||||
for (int i = 0; i < 16; ++i)
|
||||
terminal_write("| |-- r%d: %p\n", i, worldctx->context.cpu.reg[i]);
|
||||
terminal_write("| |-- gbr: %p\n", worldctx->context.cpu.gbr);
|
||||
terminal_write("| |-- macl: %p\n", worldctx->context.cpu.macl);
|
||||
terminal_write("| |-- mach: %p\n", worldctx->context.cpu.mach);
|
||||
terminal_write("| |-- ssr: %p\n", worldctx->context.cpu.ssr);
|
||||
terminal_write("| |-- spc: %p\n", worldctx->context.cpu.spc);
|
||||
terminal_write("| `-- pr: %p\n", worldctx->context.cpu.pr);
|
||||
terminal_write("`-- memory:\n");
|
||||
terminal_write(" |-- entry: %p\n", worldctx->memory.program.start);
|
||||
terminal_write(" `-- size : %do\n", worldctx->memory.program.size);
|
||||
worldctx = worldctx->private.next;
|
||||
char line[32];
|
||||
struct hworld *world = hypervisor_wswitch_queue_get();
|
||||
int sp = (terminal.winsize.ws_col - 4) / 3;
|
||||
snprintf(line, 32, "%%-3s%%-%ds%%-%ds%%s\n", sp, sp);
|
||||
terminal_write(line, "ID", "NAME", "ENV", "SIZE");
|
||||
snprintf(line, 32, "%%-3d%%-%ds%%-%ds%%do\n", sp, sp);
|
||||
const char *env = NULL;
|
||||
while (world != NULL) {
|
||||
env = "Casio";
|
||||
if (world->private.env == HYPERVISOR_ENV_GINT)
|
||||
env = "Gint";
|
||||
terminal_write(line,
|
||||
counter,
|
||||
world->private.inode->name,
|
||||
env,
|
||||
world->memory.program.size);
|
||||
world = world->private.next;
|
||||
counter = counter + 1;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#if 0
|
||||
if (strcmp(argv[2], "run") == 0) {
|
||||
if (argc < 3) {
|
||||
terminal_write("OS ID missing\n");
|
||||
|
@ -172,6 +173,7 @@ static int hyp_os_module(int argc, char **argv)
|
|||
gint_switch_to_gint();
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
error:
|
||||
terminal_write("\"hyp os\" requiere at least 1 argument\n");
|
||||
|
@ -184,6 +186,7 @@ error:
|
|||
return (1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* install the hypervisor */
|
||||
static int hyp_install(void)
|
||||
{
|
||||
|
@ -223,8 +226,8 @@ int hyp_main(int argc, char **argv)
|
|||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "img") == 0)
|
||||
return (hyp_img_module(argc, argv));
|
||||
//if (strcmp(argv[1], "os") == 0)
|
||||
// return (hyp_os_module(argc, argv));
|
||||
if (strcmp(argv[1], "os") == 0)
|
||||
return (hyp_os_module(argc, argv));
|
||||
//if (strcmp(argv[1], "install") == 0)
|
||||
// return (hyp_install());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
//---
|
||||
// hypervisor:env - Environment manager
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/std/string.h>
|
||||
|
||||
/* hidden Gint world information */
|
||||
extern void *kernel_env_casio;
|
||||
extern void *kernel_env_gint;
|
||||
|
||||
//---
|
||||
// Env API
|
||||
//---
|
||||
/* hypervisor_env_set(): Set the appropriate environment */
|
||||
int hypervisor_env_set(struct hworld *world)
|
||||
{
|
||||
if (world == NULL)
|
||||
return (-1);
|
||||
void *env = NULL;
|
||||
switch (world->private.env) {
|
||||
case HYPERVISOR_ENV_CASIO: env = kernel_env_casio; break;
|
||||
case HYPERVISOR_ENV_GINT: env = kernel_env_gint; break;
|
||||
default:
|
||||
return (-2);
|
||||
}
|
||||
drivers_context_duplicate(world->context.drivers, env);
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
//---
|
||||
// fxBoot:hypervisor:gint - Gint workaround
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
|
||||
#include <gint/atomic.h>
|
||||
#include <gint/drivers.h>
|
||||
|
||||
/* external symbols */
|
||||
extern void *kernel_env_casio;
|
||||
extern void *kernel_env_gint;
|
||||
|
||||
/* gint_switch_to_casio(): Restore Casio's environment */
|
||||
void gint_switch_to_casio(void)
|
||||
{
|
||||
drivers_wait();
|
||||
drivers_switch(kernel_env_gint, kernel_env_casio);
|
||||
//hypervisor_install();
|
||||
}
|
||||
|
||||
/* gint_switch_to_gint(): Restore Gint's environment */
|
||||
void gint_switch_to_gint(void)
|
||||
{
|
||||
drivers_wait();
|
||||
drivers_switch(kernel_env_casio, kernel_env_gint);
|
||||
//hypervisor_install();
|
||||
}
|
||||
|
||||
/* gint_switch(): Temporarily switch out of gint */
|
||||
void gint_switch(void (*function)(void))
|
||||
{
|
||||
gint_switch_to_casio();
|
||||
if(function != NULL)
|
||||
function();
|
||||
gint_switch_to_gint();
|
||||
}
|
||||
|
|
@ -7,6 +7,11 @@
|
|||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
//---
|
||||
// Main API
|
||||
//---
|
||||
extern int hypervisor_elf_loader(struct hworld *, struct smemfs_inode *);
|
||||
|
||||
//---
|
||||
// Error helpers
|
||||
//---
|
||||
|
|
|
@ -45,11 +45,17 @@ anchor:
|
|||
/* hypervisor_loader(): Load a ELF (must be PIE) and start it */
|
||||
int hypervisor_loader(struct himage *image)
|
||||
{
|
||||
(void)image;
|
||||
//TODO: create a new world context
|
||||
//TODO: try to load the image
|
||||
//TODO: link the new world context
|
||||
//TODO: perform a world switch.
|
||||
struct hworld *world;
|
||||
|
||||
world = hypervisor_wswitch_create();
|
||||
if (world == NULL)
|
||||
return (-1);
|
||||
if (hypervisor_elf_loader(world, image->private) != 0) {
|
||||
hypervisor_wswitch_destroy(world);
|
||||
return (-2);
|
||||
}
|
||||
hypervisor_wswitch_queue_register(world);
|
||||
hypervisor_env_set(world);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,99 @@
|
|||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/atomic.h>
|
||||
#include <gint/drivers.h>
|
||||
|
||||
/* internal globals information */
|
||||
HYPERVISOR_BSS void *hypervisor_current_vbr = NULL;
|
||||
HYPERVISOR_BSS struct hworld *hypervisor_world_queue = NULL;
|
||||
|
||||
//---
|
||||
// World API
|
||||
//---
|
||||
/* hypervisor_wswitch_create(): Create a new world */
|
||||
struct hworld *hypervisor_wswitch_create(void)
|
||||
{
|
||||
struct hworld *world;
|
||||
|
||||
world = hypervisor_world_queue;
|
||||
while (world != NULL) {
|
||||
if (world->private.status != HYPERVISOR_STATUS_DEAD) {
|
||||
world = world->private.next;
|
||||
continue;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/* void hypervisor_wswitch_destroy(): Destroy the world */
|
||||
int hypervisor_wswitch_destroy(struct hworld *world)
|
||||
{
|
||||
if (world == NULL)
|
||||
return (-1);
|
||||
if (world->private.status != HYPERVISOR_STATUS_CREATED
|
||||
&&world->private.status != HYPERVISOR_STATUS_INIT) {
|
||||
return (-2);
|
||||
}
|
||||
if (world->memory.program.start != NULL) // <-- move me
|
||||
free(world->memory.program.start); // <-- loader unload
|
||||
if (world->context.drivers != NULL)
|
||||
drivers_context_destroy(world->context.drivers);
|
||||
world->private.inode = NULL;
|
||||
if (world->private.status == HYPERVISOR_STATUS_INIT) {
|
||||
world->private.status = HYPERVISOR_STATUS_DEAD;
|
||||
return (0);
|
||||
}
|
||||
free(world);
|
||||
return (0);
|
||||
}
|
||||
|
||||
//---
|
||||
// Queue API
|
||||
//---
|
||||
/* hypervisor_wswitch_queue_register(): Register the new world */
|
||||
int hypervisor_wswitch_queue_register(struct hworld *world)
|
||||
{
|
||||
if (world == NULL)
|
||||
return (-1);
|
||||
world->private.next = hypervisor_world_queue;
|
||||
hypervisor_world_queue = world;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* hypervisor_wswich_queue_get(): Get the world queue */
|
||||
struct hworld *hypervisor_wswitch_queue_get(void)
|
||||
{
|
||||
return (hypervisor_world_queue);
|
||||
}
|
||||
|
||||
/* hypervisor_wswitch_queue_unregister(): Unregister a world */
|
||||
int hypervisor_wswitch_queue_unregister(struct hworld *target)
|
||||
{
|
||||
struct hworld **world;
|
||||
|
||||
world = &hypervisor_world_queue;
|
||||
while (*world != NULL) {
|
||||
if (*world != target) {
|
||||
world = &(*world)->private.next;
|
||||
continue;
|
||||
}
|
||||
*world = (*world)->private.next;
|
||||
if (target->private.status != HYPERVISOR_STATUS_DEAD)
|
||||
hypervisor_wswitch_destroy(target);
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
//---
|
||||
// User API
|
||||
//---
|
||||
|
|
Loading…
Reference in New Issue