Commit 3b8910b9 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan
Browse files

liblcd-v2: Add missing syscalls, adjust liblcd syscall interfacing.

I'm using registers now instead of cheating with the utcb. This
is good in the end because it was getting ugly using the utcb
for syscall arguments (e.g., during a sync ipc send, the higher
level code needed to know that one of the utcb registers would
be used for the actual syscall - that's pretty bad).
parent ff2560df
/*
* liblcd.h
*
* Low-level arch-dependent liblcd details.
*
* Copyright: University of Utah
*/
#ifndef ASM_LCD_DOMAINS_LIBLCD_H
#define ASM_LCD_DOMAINS_LIBLCD_H
#include <lcd_domains/types.h>
#include <liblcd/syscall.h>
/* LOW LEVEL SYSCALLS -------------------------------------------------- */
/* Bit of redundancy. But trying not to get macro crazy. */
static inline int lcd_syscall_no_args(int id)
{
long ret;
asm(
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id)
: "rax");
return (int)ret;
}
static inline int lcd_syscall_one_arg(int id, unsigned long arg0)
{
long ret;
asm(
"movq %2, %%r8 \n\t"
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id), "g" (arg0)
: "rax");
return (int)ret;
}
static inline int lcd_syscall_two_args(int id,
unsigned long arg0,
unsigned long arg1)
{
long ret;
asm(
"movq %3, %%r9 \n\t"
"movq %2, %%r8 \n\t"
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id), "g" (arg0), "g" (arg1)
: "rax");
return (int)ret;
}
static inline int lcd_syscall_three_args(int id,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2)
{
long ret;
asm(
"movq %4, %%r10 \n\t"
"movq %3, %%r9 \n\t"
"movq %2, %%r8 \n\t"
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id), "g" (arg0), "g" (arg1), "g" (arg2)
: "rax");
return (int)ret;
}
static inline int lcd_syscall_four_args(int id,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2,
unsigned long arg3)
{
long ret;
asm(
"movq %5, %%r11 \n\t"
"movq %4, %%r10 \n\t"
"movq %3, %%r9 \n\t"
"movq %2, %%r8 \n\t"
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id), "g" (arg0), "g" (arg1), "g" (arg2), "g" (arg3)
: "rax");
return (int)ret;
}
static inline int lcd_syscall_five_args(int id,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4)
{
long ret;
asm(
"movq %6, %%r12 \n\t"
"movq %5, %%r11 \n\t"
"movq %4, %%r10 \n\t"
"movq %3, %%r9 \n\t"
"movq %2, %%r8 \n\t"
"movq %1, %%rax \n\t"
"vmcall \n\t"
"movq %%rax, %0 \n\t"
: "=g" (ret)
: "g" (id), "g" (arg0), "g" (arg1), "g" (arg2), "g" (arg3),
"g" (arg4)
: "rax");
return (int)ret;
}
static inline void lcd_syscall_cap_delete(cptr_t cptr)
{
lcd_syscall_one_arg(LCD_SYSCALL_CAP_DELETE, cptr_val(cptr));
}
static inline int lcd_syscall_cap_revoke(cptr_t cptr)
{
return lcd_syscall_one_arg(LCD_SYSCALL_CAP_REVOKE, cptr_val(cptr));
}
static inline int lcd_syscall_cap_grant(cptr_t lcd, cptr_t src, cptr_t dest)
{
return lcd_syscall_three_args(LCD_SYSCALL_CAP_GRANT,
cptr_val(lcd), cptr_val(src), cptr_val(dest));
}
static inline int lcd_syscall_put_char(char c)
{
return lcd_syscall_one_arg(LCD_SYSCALL_PUT_CHAR, c);
}
static inline int lcd_syscall_create(cptr_t lcd_slot)
{
return lcd_syscall_one_arg(LCD_SYSCALL_CREATE, cptr_val(lcd_slot));
}
static inline int lcd_syscall_config_registers(cptr_t lcd, gva_t pc,
gva_t sp, gpa_t gva_root,
gpa_t utcb_page)
{
return lcd_syscall_five_args(LCD_SYSCALL_CONFIG_REGISTERS,
cptr_val(lcd), gva_val(pc), gva_val(sp),
gpa_val(gva_root), gpa_val(utcb_page));
}
static inline int lcd_syscall_memory_grant_and_map(cptr_t lcd,
cptr_t mo_cptr,
cptr_t dest_slot,
gpa_t base)
{
return lcd_syscall_four_args(LCD_SYSCALL_MEMORY_GRANT_AND_MAP,
cptr_val(lcd), cptr_val(mo_cptr),
cptr_val(dest_slot), gpa_val(base));
}
static inline int lcd_syscall_run(cptr_t lcd)
{
return lcd_syscall_one_arg(LCD_SYSCALL_RUN, cptr_val(lcd));
}
static inline void __noreturn lcd_syscall_exit(int retval)
{
for(;;)
lcd_syscall_one_arg(LCD_SYSCALL_EXIT, retval);
}
static inline int lcd_syscall_sync_send(cptr_t endpoint)
{
return lcd_syscall_one_arg(LCD_SYSCALL_SYNC_SEND, cptr_val(endpoint));
}
static inline int lcd_syscall_sync_recv(cptr_t endpoint)
{
return lcd_syscall_one_arg(LCD_SYSCALL_SYNC_RECV, cptr_val(endpoint));
}
static inline int lcd_syscall_sync_call(cptr_t endpoint)
{
return lcd_syscall_one_arg(LCD_SYSCALL_SYNC_CALL, cptr_val(endpoint));
}
static inline int lcd_syscall_sync_reply(void)
{
return lcd_syscall_no_args(LCD_SYSCALL_SYNC_REPLY);
}
static inline int lcd_syscall_create_sync_ep(cptr_t slot)
{
return lcd_syscall_one_arg(LCD_SYSCALL_CREATE_SYNC_EP, cptr_val(slot));
}
static inline int lcd_syscall_pages_alloc_exact_node(cptr_t slot, int nid,
unsigned int flags,
unsigned int order)
{
return lcd_syscall_four_args(LCD_SYSCALL_PAGES_ALLOC_EXACT_NODE,
cptr_val(slot), nid, flags, order);
}
static inline int lcd_syscall_pages_alloc(cptr_t slot,
unsigned int flags,
unsigned int order)
{
return lcd_syscall_three_args(LCD_SYSCALL_PAGES_ALLOC,
cptr_val(slot), flags, order);
}
static inline int lcd_syscall_vmalloc(cptr_t slot,
unsigned int order)
{
return lcd_syscall_two_args(LCD_SYSCALL_VMALLOC,
cptr_val(slot), order);
}
static inline int lcd_syscall_mmap(cptr_t mo_cptr, gpa_t base)
{
return lcd_syscall_two_args(LCD_SYSCALL_MMAP,
cptr_val(mo_cptr), gpa_val(base));
}
static inline int lcd_syscall_munmap(cptr_t mo_cptr)
{
return lcd_syscall_one_arg(LCD_SYSCALL_MUNMAP, cptr_val(mo_cptr));
}
#endif /* ASM_LCD_DOMAINS_LIBLCD_H */
......@@ -388,6 +388,10 @@ static inline u64 lcd_arch_get_syscall_arg3(struct lcd_arch *lcd)
{
return lcd->regs[LCD_ARCH_REGS_R11];
}
static inline u64 lcd_arch_get_syscall_arg4(struct lcd_arch *lcd)
{
return lcd->regs[LCD_ARCH_REGS_R12];
}
static inline void lcd_arch_set_syscall_ret(struct lcd_arch *lcd, u64 val)
{
lcd->regs.rax = val;
......
......@@ -75,42 +75,6 @@ static inline void lcd_set_debug_reg(u64 val) \
__lcd_set_debug_reg(lcd_get_utcb(), val); \
} \
/* LOW LEVEL SYSCALLS -------------------------------------------------- */
/**
* Low level syscall routines.
*/
#define __LCD_MK_SYSCALL(num) \
static inline int lcd_syscall_##num(void) \
{ \
long ret; \
asm volatile( \
"movq $" #num ", %%rax \n\t" /* move syscall into rax */\
"vmcall \n\t" /* do vmcall (exit vm) */\
"movq %%rax, %0 \n\t" /* get return value */\
: "=g" (ret) \
: \
: "rax"); \
return (int)ret; \
}
#define LCD_MK_SYSCALL(name) __LCD_MK_SYSCALL(name)
LCD_MK_SYSCALL(LCD_SYSCALL_EXIT)
LCD_MK_SYSCALL(LCD_SYSCALL_SEND)
LCD_MK_SYSCALL(LCD_SYSCALL_RECV)
LCD_MK_SYSCALL(LCD_SYSCALL_CALL)
LCD_MK_SYSCALL(LCD_SYSCALL_REPLY)
LCD_MK_SYSCALL(LCD_SYSCALL_PUTCHAR)
LCD_MK_SYSCALL(LCD_SYSCALL_PAGE_ALLOC)
LCD_MK_SYSCALL(LCD_SYSCALL_PAGE_MAP)
LCD_MK_SYSCALL(LCD_SYSCALL_PAGE_UNMAP)
LCD_MK_SYSCALL(LCD_SYSCALL_CAP_DELETE)
LCD_MK_SYSCALL(LCD_SYSCALL_SYNC_EP)
#define __LCD_DO_SYSCALL(num) lcd_syscall_##num()
#define LCD_DO_SYSCALL(name) __LCD_DO_SYSCALL(name)
/* ENTER / EXIT FROM LCD -------------------------------------------------- */
......
......@@ -7,19 +7,25 @@
#define LCD_DOMAINS_SYSCALL_H
enum lcd_syscall {
LCD_SYSCALL_EXIT,
LCD_SYSCALL_CAP_DELETE,
LCD_SYSCALL_CAP_REVOKE,
LCD_SYSCALL_CAP_GRANT,
LCD_SYSCALL_PUTCHAR,
LCD_SYSCALL_SEND,
LCD_SYSCALL_RECV,
LCD_SYSCALL_CALL,
LCD_SYSCALL_REPLY,
LCD_SYSCALL_CREATE,
LCD_SYSCALL_CONFIG_REGISTERS,
LCD_SYSCALL_MEMORY_GRANT_AND_MAP,
LCD_SYSCALL_RUN,
LCD_SYSCALL_EXIT,
LCD_SYSCALL_SYNC_SEND,
LCD_SYSCALL_SYNC_RECV,
LCD_SYSCALL_SYNC_CALL,
LCD_SYSCALL_SYNC_REPLY,
LCD_SYSCALL_CREATE_SYNC_EP,
LCD_SYSCALL_PAGES_ALLOC_EXACT_NODE,
LCD_SYSCALL_PAGES_ALLOC,
LCD_SYSCALL_VMALLOC,
LCD_SYSCALL_MMAP,
LCD_SYSCALL_MUNMAP,
LCD_SYSCALL_CAP_DELETE,
LCD_SYSCALL_CAP_REVOKE,
};
#endif /* LCD_DOMAINS_SYSCALL_H */
/*
* console.c
*
* Printk to the host kernel logs.
*
* Copyright: University of Utah
*/
#include <lcd_config/pre_hook.h>
#include <linux/kernel.h> /* for vsnprintf */
#include <lcd_config/post_hook.h>
static lcd_sys_put_char(char c)
{
lcd_set_debug_reg(c);
return LCD_DO_SYSCALL(LCD_SYSCALL_PUTCHAR);
}
void lcd_printk(char *fmt, ...)
{
va_list args;
char buf[512]; /* this is probably a bit big ... */
char *p;
/*
* Convert fmt string to chars
*/
va_start(args, fmt);
vsnprintf(buf, 512, fmt, args);
va_end(args);
/*
* Write char by char
*/
for (p = buf; *p; p++)
lcd_put_char(*p);
/*
* Write null char
*/
lcd_put_char(0);
}
......@@ -24,6 +24,34 @@ static int handle_syscall_create_sync_ep(struct lcd *lcd)
return __lcd_create_sync_endpoint(lcd, slot);
}
static int handle_syscall_create(struct lcd *lcd)
{
cptr_t lcd_slot;
/*
* Args
*/
lcd_slot = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
/*
* Do create
*/
return __lcd_create(lcd, lcd_slot);
}
static int handle_syscall_cap_grant(struct lcd *lcd)
{
cptr_t lcd, src, dest;
/*
* Args
*/
dest_lcd = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
src = __cptr(lcd_arch_get_syscall_arg1(lcd->lcd_arch));
dest = __cptr(lcd_arch_get_syscall_arg2(lcd->lcd_arch));
/*
* Do grant
*/
return __lcd_cap_grant(lcd, dest_lcd, src, dest);
}
static int handle_syscall_cap_revoke(struct lcd *lcd)
{
cptr_t object;
......@@ -52,6 +80,44 @@ static int handle_syscall_cap_delete(struct lcd *lcd)
return 0;
}
static int handle_syscall_config_registers(struct lcd *lcd)
{
cptr_t dest_lcd;
gva_t pc, sp;
gpa_t gva_root, utcb_page;
/*
* Args
*/
dest_lcd = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
pc = __gva(lcd_arch_get_syscall_arg1(lcd->lcd_arch));
sp = __gva(lcd_arch_get_syscall_arg2(lcd->lcd_arch));
gva_root = __gpa(lcd_arch_get_syscall_arg3(lcd->lcd_arch));
utcb_page = __gpa(lcd_arch_get_syscall_arg4(lcd->lcd_arch));
/*
* Do config
*/
return __lcd_config_registers(lcd, dest_lcd, pc, sp, gva_root,
utcb_page);
}
static int handle_syscall_memory_grant_and_map(struct lcd *lcd)
{
cptr_t dest_lcd, mo_cptr, dest_slot;
gpa_t base;
/*
* Args
*/
dest_lcd = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
mo_cptr = __cptr(lcd_arch_get_syscall_arg1(lcd->lcd_arch));
dest_slot = __cptr(lcd_arch_get_syscall_arg2(lcd->lcd_arch));
base = __gpa(lcd_arch_get_syscall_arg3(lcd->lcd_arch));
/*
* Do grant map
*/
return __lcd_memory_grant_and_map(lcd, dest_lcd, mo_cptr,
dest_slot, base);
}
static int handle_syscall_munmap(struct lcd *lcd)
{
cptr_t mem_object;
......@@ -83,6 +149,21 @@ static int handle_syscall_mmap(struct lcd *lcd)
return __lcd_map_memory_object(lcd, mem_object, base);
}
static int handle_syscall_vmalloc(struct lcd *lcd)
{
cptr_t slot;
unsigned int order;
/*
* Get slot where to store alloc'd pages and order
*/
slot = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
order = (unsigned int)lcd_arch_get_syscall_arg1(lcd->lcd_arch);
/*
* Do vmalloc
*/
return __lcd_vmalloc(lcd, slot, order);
}
static int handle_syscall_pages_alloc(struct lcd *lcd)
{
cptr_t slot;
......@@ -121,7 +202,7 @@ static int handle_syscall_pages_alloc_exact_node(struct lcd *lcd)
return __lcd_alloc_pages_exact_node(lcd, slot, nid, flags, order);
}
static int handle_syscall_reply(struct lcd *lcd)
static int handle_syscall_sync_reply(struct lcd *lcd)
{
/*
* No endpoint arg; just do reply
......@@ -129,7 +210,7 @@ static int handle_syscall_reply(struct lcd *lcd)
return __lcd_reply(lcd);
}
static int handle_syscall_call(struct lcd *lcd)
static int handle_syscall_sync_call(struct lcd *lcd)
{
cptr_t endpoint;
/*
......@@ -142,7 +223,7 @@ static int handle_syscall_call(struct lcd *lcd)
return __lcd_call(lcd, endpoint);
}
static int handle_syscall_recv(struct lcd *lcd)
static int handle_syscall_sync_recv(struct lcd *lcd)
{
cptr_t endpoint;
/*
......@@ -155,7 +236,7 @@ static int handle_syscall_recv(struct lcd *lcd)
return __lcd_recv(lcd, endpoint);
}
static int handle_syscall_send(struct lcd *lcd)
static int handle_syscall_sync_send(struct lcd *lcd)
{
cptr_t endpoint;
/*
......@@ -168,6 +249,19 @@ static int handle_syscall_send(struct lcd *lcd)
return __lcd_send(lcd, endpoint);
}
static int handle_syscall_run(struct lcd *lcd)
{
cptr_t dest_lcd;
/*
* Args
*/
dest_lcd = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
/*
* Run it
*/
return __lcd_run(lcd, dest_lcd);
}
static int handle_syscall_putchar(struct lcd *lcd)
{
char c;
......@@ -198,23 +292,44 @@ static int handle_syscall(struct lcd *lcd, int *lcd_ret)
"got syscall %d from lcd %p", syscall_id, lcd);
switch (syscall_id) {
case LCD_SYSCALL_EXIT:
ret = handle_syscall_exit(lcd, lcd_ret);
case LCD_SYSCALL_CAP_DELETE:
ret = handle_syscall_cap_delete(lcd);
break;
case LCD_SYSCALL_CAP_REVOKE:
ret = handle_syscall_cap_revoke(lcd);
break;
case LCD_SYSCALL_CAP_GRANT:
ret = handle_syscall_cap_grant(lcd);
break;
case LCD_SYSCALL_PUTCHAR:
ret = handle_syscall_putchar(lcd);
break;
case LCD_SYSCALL_SEND:
ret = handle_syscall_send(lcd);
case LCD_SYSCALL_CREATE:
ret = handle_syscall_create(lcd);
break;
case LCD_SYSCALL_CONFIG_REGISTERS:
ret = handle_syscall_config_registers(lcd);
break;
case LCD_SYSCALL_MEMORY_GRANT_AND_MAP:
ret = handle_syscall_memory_grant_and_map(lcd);
break;
case LCD_SYSCALL_RUN:
ret = handle_syscall_run(lcd);
break;
case LCD_SYSCALL_EXIT:
ret = handle_syscall_exit(lcd, lcd_ret);
break;
case LCD_SYSCALL_RECV:
ret = handle_syscall_recv(lcd);
case LCD_SYSCALL_SYNC_SEND:
ret = handle_syscall_sync_send(lcd);
break;
case LCD_SYSCALL_CALL:
ret = handle_syscall_call(lcd);
case LCD_SYSCALL_SYNC_RECV:
ret = handle_syscall_sync_recv(lcd);
break;
case LCD_SYSCALL_REPLY:
ret = handle_syscall_reply(lcd);
case LCD_SYSCALL_SYNC_CALL:
ret = handle_syscall_sync_call(lcd);
break;
case LCD_SYSCALL_SYNC_REPLY:
ret = handle_syscall_sync_reply(lcd);
break;
case LCD_SYSCALL_CREATE_SYNC_EP:
ret = handle_syscall_create_sync_ep(lcd);
......@@ -225,18 +340,15 @@ static int handle_syscall(struct lcd *lcd, int *lcd_ret)
case LCD_SYSCALL_PAGES_ALLOC:
ret = handle_syscall_pages_alloc(lcd);
break;
case LCD_SYSCALL_VMALLOC:
ret = handle_syscall_vmalloc(lcd);
break;
case LCD_SYSCALL_MMAP:
ret = handle_syscall_mmap(lcd);
break;
case LCD_SYSCALL_MUNMAP:
ret = handle_syscall_munmap(lcd);
break;
case LCD_SYSCALL_CAP_DELETE:
ret = handle_syscall_cap_delete(lcd);
break;
case LCD_SYSCALL_CAP_REVOKE:
ret = handle_syscall_cap_revoke(lcd);
break;
default:
LCD_ERR("unimplemented syscall %d", syscall_id);
ret = -ENOSYS;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment