Commit 290dfa65 authored by Jithu Joseph's avatar Jithu Joseph Committed by Vikram Narayanan
Browse files

Sync IPC changes. Locking to be added.

parent 5c7887d9
......@@ -13,6 +13,7 @@
#include <linux/init.h> /* Needed for the macros */
#include <asm/vmx.h>
#include "../lcd_defs.h"
#include "../ipc_common_defs.h"
......@@ -22,6 +23,8 @@
typedef unsigned int uint;
// The idea is to get the shared page which is
// to be used for IPC . It is the lowest page
// the bottom of the 4 Page Stack block.
......@@ -88,15 +91,27 @@ lcd_putc(char c)
}
#if 1
static void
lcd_ipc()
{
asm volatile("push %rax");
//asm volatile("mov $0xdeadbeef, %rax");
// DIR : 2 (RCV) and peer capid 2
asm volatile("mov $0x0000000200000002, %rax");
asm volatile("vmcall");
asm volatile("pop %rax");
// printk(KERN_ERR "%c", c);
}
static void
printint(int xx, int base, int sgn)
printint(long xx, int base, int sgn)
{
static char digits[] = "0123456789ABCDEF";
char buf[16];
int i, neg;
uint x;
u64 x;
neg = 0;
if(sgn && xx < 0){
......@@ -117,75 +132,7 @@ printint(int xx, int base, int sgn)
while(--i >= 0)
lcd_putc(buf[i]);
}
#endif
#if 0
static void
printint(int xx, int base, int sgn)
{
char buf[16];
int i, neg;
int int_digs[16];
uint x;
neg = 0;
if(sgn && xx < 0){
neg = 1;
x = -xx;
} else {
x = xx;
}
i = 0;
do{
int_digs[i++] = x % base;
}while((x /= base) != 0);
if(neg)
buf[i++] = '-';
while(--i >= 0) {
switch(int_digs[i]) {
case 0: lcd_putc('0');
break;
case 1: lcd_putc('1');
break;
case 2: lcd_putc('2');
break;
case 3: lcd_putc('3');
break;
case 4: lcd_putc('4');
break;
case 5: lcd_putc('5');
break;
case 6: lcd_putc('6');
break;
case 7: lcd_putc('7');
break;
case 8: lcd_putc('8');
break;
case 9: lcd_putc('9');
break;
case 10: lcd_putc('a');
break;
case 11: lcd_putc('b');
break;
case 12: lcd_putc('c');
break;
case 13: lcd_putc('d');
break;
case 14: lcd_putc('e');
break;
case 15: lcd_putc('f');
break;
default:
lcd_putc('-');
break;
}
}
}
#endif
// Print to the given fd. Only understands %d, %x, %p, %s.
void
......@@ -207,9 +154,9 @@ my_printf(char *fmt, ...)
}
} else if(state == '%'){
if(c == 'd'){
printint(va_arg(ap, int), 10, 1);
printint(va_arg(ap, long), 10, 1);
} else if(c == 'x' || c == 'p'){
printint(va_arg(ap, int), 16, 0);
printint(va_arg(ap, long), 16, 0);
} else if(c == 's'){
s = va_arg(ap, char*);
if(s == 0)
......@@ -232,11 +179,24 @@ my_printf(char *fmt, ...)
}
}
#if 1
void temp_fn(int var) {
int check = 107;
utcb_t *p_utcb = (utcb_t *) get_shared();
int hex = 0xdeadbeef;
my_printf("Temp %d here %d and %x\n", check, var, hex);
char my_str[] = "lcdstr";
p_utcb->mr[0] = 20;
p_utcb->mr[1] = 21;
p_utcb->mr[2] = 22;
p_utcb->mr[3] = 23;
p_utcb->mr[4] = 24;
p_utcb->mr[5] = 25;
// my_printf("Temp %d and %s n %x\n", var, my_str, hex);
//my_printf("shared pg 0x%x\n", p_utcb);
lcd_ipc();
}
......@@ -273,27 +233,4 @@ static void __exit hello_2_exit(void)
module_init(hello_2_init);
module_exit(hello_2_exit);
#endif
#if 0
static int __init hello_print_init(void)
{
int check = 107;
u64 pp = 45;
printk(KERN_ERR "Hello, world 2\n");
my_printf("Hellow %d World %d done\n", check, pp);
// temp_fn();
return 0;
}
static void __exit hello_print_exit(void)
{
printk(KERN_INFO "Goodbye, world 2\n");
}
module_init(hello_print_init);
module_exit(hello_print_exit);
#endif
#ifndef LCD_GUEST_DEFS_H
#define LCD_GUEST_DEFS_H
typedef struct {
u32 mr[6]; /* MRs that are mapped to real registers */
u32 saved_tag; /* Saved tag field for stacked ipcs */
u32 saved_sender; /* Saved sender field for stacked ipcs */
u32 notify[8]; /* Irq notification slots */
u32 mr_rest[2]; /* Complete the utcb for up to 64 words */
} utcb_t;
typedef struct {
uint mr0;
uint mr1;
uint mr2;
uint mr3;
uint mr4;
uint mr5;
} msg_regs_t;
//#define IPC_SEND_SND 1
//#define IPC_SEND_RCV 2
//#define IPC_SEND_SND_RCV 3
#define IPC_PEER_ANY 0xffffffff
#define LCD_IPC_DIR(x) (x >> 32)
#define LCD_IPC_PEER(x) (x & 0xffffffff)
enum IPC_DIR {
IPC_INVALID = 0,
IPC_SEND = 1,
IPC_RECV = 2,
IPC_SENDRECV = 3,
};
/* Per thread kernel stack unified on a single page. */
union utcb_union {
utcb_t utcb;
char kstack[PAGE_SIZE];
};
void display_mr(utcb_t *p_utcb) {
printk(KERN_ERR "Message Regs at utcb %p - %d ,%d , %d\n", p_utcb, p_utcb->mr[0], p_utcb->mr[1], p_utcb->mr[3]);
}
#endif
......@@ -146,6 +146,27 @@ struct lcd_tss_struct {
u8 io_bitmap[1];
} __attribute__((packed));
struct ipc_waitq {
u32 partner_id;
struct list_head list;
};
typedef struct {
u32 peer;
struct list_head list;
struct task_struct *task;
} ipc_wait_list_elem;
/* Task states */
enum ipc_state {
IPC_DONT_CARE = 0,
IPC_RCV_WAIT = 1,
IPC_SND_WAIT = 2,
IPC_RUNNING = 3,
};
typedef struct {
int cpu;
int vpid;
......@@ -191,10 +212,28 @@ typedef struct {
struct vmx_msr_entry host[NR_AUTOLOAD_MSRS];
} msr_autoload;
struct vmcs *vmcs;
struct sync_ipc {
// either we put an explicit capid here
// so that given the capid we can fetch
// the peers sync_ipc or lcd_struct
u32 state;
u32 my_capid;
//u32 dir;
u32 expected_sender;
// void *waiting_on; -> this might not be reqd as we are modelling spl states
//struct lcd_struct *lcd_mine;
//struct lcd_struct *lcd_partner;
// some waitq
spinlock_t snd_lock;
u32 snd_sleepers;
struct list_head snd_q;
struct task_struct *task;
//spinlock_t rcv_lock;
// struct list_head rcv_q;
} sync_ipc;
struct boot_params *bp;
struct start_info *si;
struct vmcs *vmcs;
void *shared;
struct module *mod;
} lcd_struct;
......
......@@ -42,6 +42,7 @@ MODULE_PARM_DESC(vmlinux_file, "vmlinux or vmlinuz path");
/* #include "lcd.h" */
#include "lcd_defs.h"
#include "ipc_common_defs.h"
MODULE_AUTHOR("Weibin Sun");
MODULE_LICENSE("GPL");
......@@ -1421,6 +1422,20 @@ static void setup_idt(lcd_struct* vcpu) {
}
}
// Some temporary capability functions for IPC testing
// To be replaced while interfacing with capability module
static u32 curr_cap = 1;
void * cap_arr[10]= {0};
void * get_cap_obj(u32 cap_id){
return cap_arr[cap_id];
}
u32 set_cap(void *obj){
cap_arr[curr_cap] = obj;
return curr_cap++;
}
static lcd_struct * vmx_create_vcpu(void) {
lcd_struct *vcpu = kmalloc(sizeof(lcd_struct), GFP_KERNEL);
if (!vcpu)
......@@ -1498,6 +1513,15 @@ static lcd_struct * vmx_create_vcpu(void) {
setup_idt(vcpu);
vmx_put_cpu(vcpu);
//IPC queues
INIT_LIST_HEAD(&vcpu->sync_ipc.snd_q);
vcpu->sync_ipc.task = current;
vcpu->sync_ipc.state = IPC_DONT_CARE;
vcpu->sync_ipc.expected_sender = 0;
vcpu->sync_ipc.my_capid = set_cap(vcpu);
// printk(KERN_ERR "=========%d======\n", vcpu->sync_ipc.my_capid);
return vcpu;
fail_si:
......@@ -1935,7 +1959,6 @@ static int map_host_page_at_guest_va(lcd_struct *lcd, void* hva,
}
static char *my_shared;
static int lcd_setup_stack(lcd_struct *lcd) {
char *sp = NULL;
char *stack_top = NULL;
......@@ -1949,9 +1972,10 @@ static int lcd_setup_stack(lcd_struct *lcd) {
return -ENOMEM;
}
my_shared = sp;
//We use low addr page of this block for passing message registers
lcd->shared = sp;
stack_top = (sp + (PAGE_SIZE * 4) - 1);
printk (KERN_ERR "lcd : stack bootm %p , stack top %p and myshare %p", sp, stack_top, my_shared);
printk (KERN_ERR "lcd : stack bootm %p , stack top %p and myshare %p", sp, stack_top, sp);
// map the stack in the LCD address space
ret = __move_host_mapping(lcd, (void *)sp , (PAGE_SIZE * 4), 0);
......@@ -2062,9 +2086,146 @@ static void vmx_handle_external_interrupt(lcd_struct *lcd) {
}
}
int ipc_send(u32 myself, u32 recv_capid)
{
lcd_struct *recv_lcd, *snd_lcd;
ipc_wait_list_elem stack_elem;
printk(KERN_ERR "ipc_send : myself %d reciever %d\n", myself, recv_capid);
//chk if the reciever is ready
// fetch the reciever task struct from if
recv_lcd = (lcd_struct *) get_cap_obj(recv_capid);
if (recv_lcd == NULL) {
printk(KERN_ERR "ipc_send : Cant get object for reciever %d\n", recv_capid);
return -1;
}
snd_lcd = (lcd_struct *) get_cap_obj(myself);
if (snd_lcd == NULL) {
printk(KERN_ERR "ipc_send : Cant get object for myself %d\n", myself);
return -1;
}
if (recv_lcd->sync_ipc.state == IPC_RCV_WAIT && \
recv_lcd->sync_ipc.expected_sender == myself) {
printk(KERN_ERR "ipc_send : partner %d expecting me\n", current);
//copy the message registers
memcpy(recv_lcd->shared, snd_lcd->shared, sizeof(utcb_t));
//awaken the thread
wake_up_process(recv_lcd->sync_ipc.task);
//looks like there is no need for a reciever queue
//as if a process invokes a recv and finds no
//corresponding senders , then it puts itself to sleep
recv_lcd->sync_ipc.state = IPC_DONT_CARE;
recv_lcd->sync_ipc.expected_sender = 0;
//No case of
} else {
// put him in the Q
recv_lcd->sync_ipc.snd_sleepers++;
set_current_state(TASK_INTERRUPTIBLE);
stack_elem.peer = myself;
stack_elem.task = current;
// recv_lcd->sync_ipc.status = IPC_SND_WAIT;
list_add_tail(&stack_elem.list, &recv_lcd->sync_ipc.snd_q);
printk(KERN_ERR "ipc_send : putting myself to sleep %p\n", current);
schedule();
}
printk(KERN_ERR "ipc_send : Finished\n");
return 0;
}
int ipc_recv(u32 myself, u32 send_capid)
{
lcd_struct *recv_lcd, *snd_lcd;
struct list_head *ptr;
ipc_wait_list_elem *entry;
printk(KERN_ERR "ipc_recv : myself %d sender %d\n", myself, send_capid);
recv_lcd = (lcd_struct *) get_cap_obj(myself);
if (recv_lcd == NULL) {
printk(KERN_ERR "ipc_recv : Cant get object for my id %d\n", myself);
return -1;
}
snd_lcd = (lcd_struct *) get_cap_obj(send_capid);
if (snd_lcd == NULL) {
printk(KERN_ERR "ipc_recv : Cant get object for peer id %d\n", send_capid);
//return -1;
}
//check if one of the senders in the snd q is our intended
// recipient
if (recv_lcd->sync_ipc.snd_sleepers > 0) {
printk(KERN_ERR "ipc_recv : Num of senders in Q %d \n", \
recv_lcd->sync_ipc.snd_sleepers);
list_for_each(ptr, &recv_lcd->sync_ipc.snd_q) {
entry = list_entry(ptr, ipc_wait_list_elem, list);
if (entry->peer == send_capid) {
printk(KERN_ERR "ipc_recv : Found expected sender %d\n", send_capid);
recv_lcd->sync_ipc.snd_sleepers--;
//copy the message registers
memcpy(recv_lcd->shared, snd_lcd->shared, sizeof(utcb_t));
//remove the entry
list_del(ptr);
//wakeup
wake_up_process(entry->task);
// we dont care for state in snd_wait
//recv_lcd->sync_ipc.status = IPC_RUNNING;
printk(KERN_ERR "ipc_recv : Returning after waking up sender\n");
return 0;
}
}
}
printk(KERN_ERR "ipc_recv : Scheduling out myself\n");
// we cant proceed further
recv_lcd->sync_ipc.state = IPC_RCV_WAIT ;
recv_lcd->sync_ipc.expected_sender = send_capid;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
printk(KERN_ERR "ipc_recv : Somebody woke me\n");
return 0;
}
static void vmx_handle_vmcall(lcd_struct *lcd) {
u32 ipc_dir, ipc_peer;
//printk(KERN_ERR "%c", lcd->regs[VCPU_REGS_RAX]);
printk(KERN_ERR "%016llx", lcd->regs[VCPU_REGS_RAX]);
ipc_dir = LCD_IPC_DIR(lcd->regs[VCPU_REGS_RAX]);
ipc_peer = LCD_IPC_PEER(lcd->regs[VCPU_REGS_RAX]);
printk(KERN_ERR "vmx_handle_vmcall - dir %d peer %d\n", ipc_dir, ipc_peer);
switch(ipc_dir) {
case IPC_SEND:
ipc_send(lcd->sync_ipc.my_capid, ipc_peer);
break;
case IPC_RECV:
ipc_recv(lcd->sync_ipc.my_capid, ipc_peer);
break;
}
#if 0
//printk(KERN_ERR "lcd_run: got vmcall %llu and %c\n", lcd->regs[VCPU_REGS_RAX], lcd->regs[VCPU_REGS_RAX]);
printk(KERN_ERR "%c", lcd->regs[VCPU_REGS_RAX]);
if (lcd->regs[VCPU_REGS_RAX] == 0xdeadbeef) {
display_mr((utcb_t *)lcd->shared);
return;
}
#endif
}
static void vmx_handle_page_fault(lcd_struct *lcd) {
......
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