1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

Support for forwarding command line parameters and environment variables

to uhyve
This commit is contained in:
Pierre Olivier 2017-11-07 19:51:57 -05:00
parent 3ee4a48728
commit cfd208d266
10 changed files with 173 additions and 4 deletions

View file

@ -36,6 +36,9 @@ foreach(MODULE ${KERNEL_MODULES})
target_compile_definitions(${MODULE}
PRIVATE -D__KERNEL__)
target_compile_definitions(${MODULE}
PRIVATE -DMAX_ARGC_ENVC=${MAX_ARGC_ENVC})
target_compile_options(${MODULE}
PRIVATE ${HERMIT_KERNEL_FLAGS})

View file

@ -19,6 +19,10 @@ set(KERNEL_STACK_SIZE 8192 CACHE STRING
set(DEFAULT_STACK_SIZE 262144 CACHE STRING
"Task stack size in bytes")
set(MAX_ARGC_ENVC 128 CACHE STRING
"Maximum number of command line parameters and enviroment variables
forwarded to uhyve")
option(DYNAMIC_TICKS
"Don't use a periodic timer event to keep track of time" ON)

View file

@ -99,6 +99,7 @@ function(build_external NAME PATH DEPENDS)
-DLOCAL_PREFIX_BASE_DIR=${LOCAL_PREFIX_BASE_DIR}
-DCMAKE_INSTALL_MESSAGE=NEVER
-DCMAKE_EXPORT_COMPILE_COMMANDS=true
-DMAX_ARGC_ENVC=${MAX_ARGC_ENVC}
--no-warn-unused-cli
${DO_PROFILING}
${CMD_VARS}

View file

@ -41,6 +41,7 @@
#include <asm/page.h>
#include <asm/uart.h>
#include <asm/multiboot.h>
#include <asm/uhyve.h>
#include <lwip/init.h>
#include <lwip/sys.h>
@ -65,6 +66,22 @@
#define HERMIT_PORT 0x494E
#define HERMIT_MAGIC 0x7E317
/* Ports and data structures for command line args + envp forwarding to uhyve */
#define UHYVE_PORT_CMDSIZE 0x509
#define UHYVE_PORT_CMDVAL 0x510
typedef struct {
int argc;
int argsz[MAX_ARGC_ENVC];
int envc;
int envsz[MAX_ARGC_ENVC];
} __attribute__ ((packed)) uhyve_cmdsize_t;
typedef struct {
char **argv;
char **envp;
} __attribute__ ((packed)) uhyve_cmdval_t;
static struct netif default_netif;
static const int sobufsize = 131072;
@ -370,6 +387,37 @@ static int initd(void* arg)
// initialize network
err = init_netifs();
if(is_uhyve()) {
int i;
uhyve_cmdsize_t uhyve_cmdsize;
uhyve_cmdval_t uhyve_cmdval;
uhyve_send(UHYVE_PORT_CMDSIZE,
(unsigned)virt_to_phys((size_t)&uhyve_cmdsize));
uhyve_cmdval.argv = kmalloc(uhyve_cmdsize.argc * sizeof(char *));
for(i=0; i<uhyve_cmdsize.argc; i++)
uhyve_cmdval.argv[i] = kmalloc(uhyve_cmdsize.argsz[i] * sizeof(char));
uhyve_cmdval.envp = kmalloc(uhyve_cmdsize.envc * sizeof(char *));
for(i=0; i<uhyve_cmdsize.envc; i++)
uhyve_cmdval.envp[i] = kmalloc(uhyve_cmdsize.envsz[i] * sizeof(char));
uhyve_send(UHYVE_PORT_CMDVAL,
(unsigned)virt_to_phys((size_t)&uhyve_cmdval));
LOG_INFO("Boot time: %d ms\n", (get_clock_tick() * 1000) / TIMER_FREQ);
libc_start(uhyve_cmdsize.argc, uhyve_cmdval.argv, uhyve_cmdval.envp);
for(i=0; i<argc; i++)
kfree(uhyve_cmdval.argv[i]);
kfree(uhyve_cmdval.argv);
for(i=0; i<envc; i++)
kfree(uhyve_cmdval.envp[i]);
kfree(uhyve_cmdval.envp);
return 0;
}
if ((err != 0) || !is_proxy())
{
char* dummy[] = {"app_name", NULL};

View file

@ -7,6 +7,7 @@ add_compile_options(-std=c99)
add_executable(proxy proxy.c utils.c uhyve.c uhyve-net.c)
target_compile_options(proxy PUBLIC -pthread)
target_compile_options(proxy PUBLIC -DMAX_ARGC_ENVC=${MAX_ARGC_ENVC})
target_link_libraries(proxy -pthread)
install(TARGETS proxy

View file

@ -1028,7 +1028,7 @@ int main(int argc, char **argv)
switch(monitor) {
case UHYVE:
return uhyve_loop();
return uhyve_loop(argc, argv);
case BAREMETAL:
case QEMU:

View file

@ -46,7 +46,7 @@
#define __HERMIT_lseek 5
int uhyve_init(char *path);
int uhyve_loop(void);
int uhyve_loop(int argc, char **argv);
// define some helper functions
uint32_t get_cpufreq(void);

View file

@ -190,6 +190,29 @@ static __thread struct kvm_run *run = NULL;
static __thread int vcpufd = -1;
static __thread uint32_t cpuid = 0;
int uhyve_argc = -1;
int uhyve_envc = -1;
char **uhyve_argv = NULL;
extern char **environ;
char **uhyve_envp = NULL;
/* Ports and data structures for uhyve command line arguments and envp
* forwarding */
#define UHYVE_PORT_CMDSIZE 0x509
#define UHYVE_PORT_CMDVAL 0x510
typedef struct {
int argc;
int argsz[128];
int envc;
int envsz[128];
} __attribute__ ((packed)) uhyve_cmdsize_t;
typedef struct {
char **argv;
char **envp;
} __attribute__ ((packed)) uhyve_cmdval_t;
static uint64_t memparse(const char *ptr)
{
// local pointer to end of parsed string
@ -894,6 +917,65 @@ static int vcpu_loop(void)
break;
}
case UHYVE_PORT_CMDSIZE: {
int i;
unsigned data = *((unsigned*)((size_t)run+run->io.data_offset));
uhyve_cmdsize_t *val = (uhyve_cmdsize_t *) (guest_mem+data);
val->argc = uhyve_argc;
for(i=0; i<uhyve_argc; i++)
val->argsz[i] = strlen(uhyve_argv[i]);
val->envc = uhyve_envc;
for(i=0; i<uhyve_envc; i++)
val->envsz[i] = strlen(uhyve_envp[i]);
break;
}
case UHYVE_PORT_CMDVAL: {
int i;
char **argv_ptr, **env_ptr;
struct kvm_translation kt;
unsigned data = *((unsigned*)((size_t)run+run->io.data_offset));
uhyve_cmdval_t *val = (uhyve_cmdval_t *) (guest_mem+data);
/* buffers inside uhyve_cmdval are not directlty mapped
* (they are allocated through kmalloc) so we cannot
* used a simple offset as the guest to host, we have to
* walk the guest page table to find the physical address,
* then we can use the offset
*/
/* argv */
kt.linear_address = (unsigned long long)val->argv;
kvm_ioctl(vcpufd, KVM_TRANSLATE, &kt);
argv_ptr = (char **)(guest_mem +
(size_t)kt.physical_address);
for(i=0; i<uhyve_argc; i++) {
kt.linear_address = (unsigned long long)argv_ptr[i];
kvm_ioctl(vcpufd, KVM_TRANSLATE, &kt);
strcpy(guest_mem + (size_t)kt.physical_address,
uhyve_argv[i]);
}
/* env */
kt.linear_address = (unsigned long long)val->envp;
kvm_ioctl(vcpufd, KVM_TRANSLATE, &kt);
env_ptr = (char **)(guest_mem +
(size_t)kt.physical_address);
for(i=0; i<uhyve_envc; i++) {
kt.linear_address = (unsigned long long)env_ptr[i];
kvm_ioctl(vcpufd, KVM_TRANSLATE, &kt);
strcpy(guest_mem + (size_t)kt.physical_address,
uhyve_envp[i]);
}
break;
}
default:
err(1, "KVM: unhandled KVM_EXIT_IO at port 0x%x, direction %d\n", run->io.port, run->io.direction);
break;
@ -1510,10 +1592,18 @@ nextslot:
no_checkpoint++;
}
int uhyve_loop(void)
int uhyve_loop(int argc, char **argv)
{
const char* hermit_check = getenv("HERMIT_CHECKPOINT");
int ts = 0;
int ts = 0, i = 0;
/* argv[0] is 'proxy', do not count it */
uhyve_argc = argc-1;
uhyve_argv = &argv[1];
uhyve_envp = environ;
while(uhyve_envp[i] != NULL)
i++;
uhyve_envc = i;
if (hermit_check)
ts = atoi(hermit_check);

View file

@ -5,6 +5,7 @@ project(hermit_tests C CXX Fortran Go)
add_executable(hello hello.c)
add_executable(jacobi jacobi.c)
add_executable(argv_envp argv_envp.c)
add_executable(hello++ hello++.cpp)
add_executable(hellof hellof.f90)
add_executable(pi pi.go)

21
usr/tests/argv_envp.c Normal file
View file

@ -0,0 +1,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern char **environ;
int main(int argc, char **argv) {
int i;
printf("argc: %d\n", argc);
for(i=0; i<argc; i++) {
printf(" argv[%d]: %s\n", i, argv[i]);
}
printf("environ: %x\n", environ);
i = 0;
while(environ[i] != NULL)
printf("%s\n", environ[i++]);
return 0;
}