modify file names and create directories
This commit is contained in:
85
executer/include/uprotocol.h
Normal file
85
executer/include/uprotocol.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef HEADER_UPROTOCOL_H
|
||||
#define HEADER_UPROTOCOL_H
|
||||
|
||||
#define MCEXEC_UP_PREPARE_IMAGE 0x30a02900
|
||||
#define MCEXEC_UP_LOAD_IMAGE 0x30a02901
|
||||
#define MCEXEC_UP_START_IMAGE 0x30a02902
|
||||
#define MCEXEC_UP_WAIT_SYSCALL 0x30a02903
|
||||
#define MCEXEC_UP_RET_SYSCALL 0x30a02904
|
||||
#define MCEXEC_UP_LOAD_SYSCALL 0x30a02905
|
||||
|
||||
#define MCEXEC_UP_PREPARE_DMA 0x30a02910
|
||||
#define MCEXEC_UP_FREE_DMA 0x30a02911
|
||||
|
||||
struct program_transfer {
|
||||
unsigned long dest;
|
||||
void *src;
|
||||
unsigned long sz;
|
||||
};
|
||||
|
||||
struct program_image_section {
|
||||
unsigned long vaddr;
|
||||
unsigned long len;
|
||||
unsigned long remote_pa;
|
||||
unsigned long filesz, offset;
|
||||
void *source;
|
||||
};
|
||||
|
||||
struct program_load_desc {
|
||||
int num_sections;
|
||||
int status;
|
||||
int cpu;
|
||||
int pid;
|
||||
unsigned long entry;
|
||||
unsigned long rprocess;
|
||||
unsigned long at_phdr;
|
||||
unsigned long at_phent;
|
||||
unsigned long at_phnum;
|
||||
char *args;
|
||||
unsigned long args_len;
|
||||
char *envs;
|
||||
unsigned long envs_len;
|
||||
struct program_image_section sections[0];
|
||||
};
|
||||
|
||||
struct syscall_request {
|
||||
unsigned long valid;
|
||||
unsigned long number;
|
||||
unsigned long args[6];
|
||||
};
|
||||
|
||||
struct syscall_wait_desc {
|
||||
unsigned long cpu;
|
||||
struct syscall_request sr;
|
||||
};
|
||||
|
||||
struct syscall_load_desc {
|
||||
unsigned long cpu;
|
||||
unsigned long src;
|
||||
unsigned long dest;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct syscall_response {
|
||||
unsigned long status;
|
||||
long ret;
|
||||
};
|
||||
|
||||
struct syscall_ret_desc {
|
||||
long cpu;
|
||||
long ret;
|
||||
unsigned long src;
|
||||
unsigned long dest;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct prepare_dma_desc {
|
||||
unsigned long size;
|
||||
unsigned long pa;
|
||||
};
|
||||
struct free_dma_desc {
|
||||
unsigned long pa;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
#endif
|
||||
24
executer/kernel/Makefile
Normal file
24
executer/kernel/Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
#ifeq ($(K),"current")
|
||||
KDIR=/lib/modules/`uname -r `/build
|
||||
#else
|
||||
#KDIR=../target
|
||||
#endif
|
||||
|
||||
|
||||
obj-m += mcctrl.o
|
||||
|
||||
mcctrl-objs := driver.o control.o ikc.o syscall.o
|
||||
|
||||
AALBASE ?= $(src)/../../../aal
|
||||
EXTRA_CFLAGS = -I$(AALBASE)/host/include -I$(AALBASE)/host/driver/knf -I$(AALBASE)/include -I$(AALBASE)/ikc/include -I$(src)/../include
|
||||
|
||||
.PHONY: clean install
|
||||
|
||||
modules:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
$(RM) .*.cmd *.mod.c *.o *.ko* Module.symvers modules.order -r .tmp*
|
||||
|
||||
install:
|
||||
513
executer/kernel/control.c
Normal file
513
executer/kernel/control.c
Normal file
@@ -0,0 +1,513 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/io.h>
|
||||
#include <sysdeps/knf/mic/mic_type.h>
|
||||
#include "mcctrl.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintk printk
|
||||
#else
|
||||
#define dprintk(...)
|
||||
#endif
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(wq_prepare);
|
||||
extern struct mcctrl_channel *channels;
|
||||
int mcctrl_ikc_set_recv_cpu(int cpu);
|
||||
|
||||
static long mcexec_prepare_image(aal_os_t os,
|
||||
struct program_load_desc * __user udesc)
|
||||
{
|
||||
struct program_load_desc desc, *pdesc;
|
||||
struct ikc_scd_packet isp;
|
||||
void *args, *envs;
|
||||
long ret = 0;
|
||||
|
||||
if (copy_from_user(&desc, udesc,
|
||||
sizeof(struct program_load_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
if (desc.num_sections <= 0 || desc.num_sections > 16) {
|
||||
printk("# of sections: %d\n", desc.num_sections);
|
||||
return -EINVAL;
|
||||
}
|
||||
pdesc = kmalloc(sizeof(struct program_load_desc) +
|
||||
sizeof(struct program_image_section)
|
||||
* desc.num_sections, GFP_KERNEL);
|
||||
memcpy(pdesc, &desc, sizeof(struct program_load_desc));
|
||||
if (copy_from_user(pdesc->sections, udesc->sections,
|
||||
sizeof(struct program_image_section)
|
||||
* desc.num_sections)) {
|
||||
kfree(pdesc);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
pdesc->pid = task_tgid_vnr(current);
|
||||
|
||||
args = kmalloc(pdesc->args_len, GFP_KERNEL);
|
||||
if (copy_from_user(args, pdesc->args, pdesc->args_len)) {
|
||||
kfree(args);
|
||||
kfree(pdesc);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
envs = kmalloc(pdesc->envs_len, GFP_KERNEL);
|
||||
if (copy_from_user(envs, pdesc->envs, pdesc->envs_len)) {
|
||||
ret = -EFAULT;
|
||||
goto free_out;
|
||||
}
|
||||
|
||||
pdesc->args = (void*)virt_to_phys(args);
|
||||
printk("args: 0x%lX\n", (unsigned long)pdesc->args);
|
||||
printk("argc: %d\n", *(int*)args);
|
||||
pdesc->envs = (void*)virt_to_phys(envs);
|
||||
printk("envs: 0x%lX\n", (unsigned long)pdesc->envs);
|
||||
printk("envc: %d\n", *(int*)envs);
|
||||
|
||||
isp.msg = SCD_MSG_PREPARE_PROCESS;
|
||||
isp.ref = pdesc->cpu;
|
||||
isp.arg = virt_to_phys(pdesc);
|
||||
|
||||
printk("# of sections: %d\n", pdesc->num_sections);
|
||||
printk("%p (%lx)\n", pdesc, isp.arg);
|
||||
|
||||
pdesc->status = 0;
|
||||
mcctrl_ikc_send(pdesc->cpu, &isp);
|
||||
|
||||
wait_event_interruptible(wq_prepare, pdesc->status);
|
||||
|
||||
if (copy_to_user(udesc, pdesc, sizeof(struct program_load_desc) +
|
||||
sizeof(struct program_image_section) * desc.num_sections)) {
|
||||
ret = -EFAULT;
|
||||
goto free_out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
free_out:
|
||||
kfree(args);
|
||||
kfree(pdesc);
|
||||
kfree(envs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mcexec_load_image(aal_os_t os, struct program_transfer *__user upt)
|
||||
{
|
||||
struct program_transfer pt;
|
||||
unsigned long phys, ret = 0;
|
||||
void *rpm;
|
||||
#if 0
|
||||
unsigned long dma_status = 0;
|
||||
aal_dma_channel_t channel;
|
||||
struct aal_dma_request request;
|
||||
void *p;
|
||||
|
||||
channel = aal_device_get_dma_channel(aal_os_to_dev(os), 0);
|
||||
if (!channel) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (copy_from_user(&pt, upt, sizeof(pt))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
phys = aal_device_map_memory(aal_os_to_dev(os), pt.dest, PAGE_SIZE);
|
||||
#ifdef CONFIG_KNF
|
||||
rpm = ioremap_wc(phys, PAGE_SIZE);
|
||||
#else
|
||||
rpm = aal_device_map_virtual(aal_os_to_dev(os), phys, PAGE_SIZE, NULL, 0);
|
||||
#endif
|
||||
|
||||
if (copy_from_user(rpm, pt.src, PAGE_SIZE)) {
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KNF
|
||||
iounmap(rpm);
|
||||
#else
|
||||
aal_device_unmap_virtual(aal_os_to_dev(os), rpm, PAGE_SIZE);
|
||||
#endif
|
||||
aal_device_unmap_memory(aal_os_to_dev(os), phys, PAGE_SIZE);
|
||||
|
||||
return ret;
|
||||
|
||||
#if 0
|
||||
p = (void *)__get_free_page(GFP_KERNEL);
|
||||
|
||||
if (copy_from_user(p, pt.src, PAGE_SIZE)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.src_os = NULL;
|
||||
request.src_phys = virt_to_phys(p);
|
||||
request.dest_os = os;
|
||||
request.dest_phys = pt.dest;
|
||||
request.size = PAGE_SIZE;
|
||||
request.notify = (void *)virt_to_phys(&dma_status);
|
||||
request.priv = (void *)1;
|
||||
|
||||
aal_dma_request(channel, &request);
|
||||
|
||||
while (!dma_status) {
|
||||
mb();
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
free_page((unsigned long)p);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern unsigned long last_thread_exec;
|
||||
|
||||
static long mcexec_start_image(aal_os_t os,
|
||||
struct program_load_desc * __user udesc)
|
||||
{
|
||||
struct program_load_desc desc;
|
||||
struct ikc_scd_packet isp;
|
||||
struct mcctrl_channel *c;
|
||||
|
||||
if (copy_from_user(&desc, udesc,
|
||||
sizeof(struct program_load_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
c = channels + desc.cpu;
|
||||
|
||||
mcctrl_ikc_set_recv_cpu(desc.cpu);
|
||||
|
||||
last_thread_exec = desc.cpu;
|
||||
|
||||
isp.msg = SCD_MSG_SCHEDULE_PROCESS;
|
||||
isp.ref = desc.cpu;
|
||||
isp.arg = desc.rprocess;
|
||||
|
||||
mcctrl_ikc_send(desc.cpu, &isp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcexec_syscall(struct mcctrl_channel *c, unsigned long arg)
|
||||
{
|
||||
c->req = 1;
|
||||
wake_up(&c->wq_syscall);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DO_USER_MODE
|
||||
int __do_in_kernel_syscall(aal_os_t os, struct mcctrl_channel *c,
|
||||
struct syscall_request *sc);
|
||||
static int remaining_job, base_cpu, job_pos;
|
||||
#endif
|
||||
|
||||
extern int num_channels;
|
||||
extern int mcctrl_dma_abort;
|
||||
|
||||
int mcexec_wait_syscall(aal_os_t os, struct syscall_wait_desc *__user req)
|
||||
{
|
||||
struct syscall_wait_desc swd;
|
||||
struct mcctrl_channel *c;
|
||||
|
||||
if (copy_from_user(&swd, req, sizeof(swd.cpu))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
c = channels + swd.cpu;
|
||||
|
||||
#ifdef DO_USER_MODE
|
||||
wait_event_interruptible(c->wq_syscall, c->req);
|
||||
c->req = 0;
|
||||
#else
|
||||
while (1) {
|
||||
c = channels + swd.cpu;
|
||||
rdtscll(s);
|
||||
if (!remaining_job) {
|
||||
while (!(*c->param.doorbell_va)) {
|
||||
mb();
|
||||
cpu_relax();
|
||||
rdtscll(w);
|
||||
if (w > s + 1024UL * 1024 * 1024 * 10) {
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
d = (*c->param.doorbell_va) - 1;
|
||||
*c->param.doorbell_va = 0;
|
||||
|
||||
if (d < 0 || d >= num_channels) {
|
||||
d = 0;
|
||||
}
|
||||
base_cpu = d;
|
||||
job_pos = 0;
|
||||
remaining_job = 1;
|
||||
} else {
|
||||
job_pos++;
|
||||
}
|
||||
|
||||
for (; job_pos < num_channels; job_pos++) {
|
||||
if (base_cpu + job_pos >= num_channels) {
|
||||
c = channels +
|
||||
(base_cpu + job_pos - num_channels);
|
||||
} else {
|
||||
c = channels + base_cpu + job_pos;
|
||||
}
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (c->param.request_va &&
|
||||
c->param.request_va->valid) {
|
||||
c->param.request_va->valid = 0; /* ack */
|
||||
dprintk("SC #%lx, %lx\n",
|
||||
c->param.request_va->number,
|
||||
c->param.request_va->args[0]);
|
||||
if (__do_in_kernel_syscall(os, c, c->param.request_va)) {
|
||||
#endif
|
||||
if (copy_to_user(&req->sr, c->param.request_va,
|
||||
sizeof(struct syscall_request))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
#ifndef DO_USER_MODE
|
||||
return 0;
|
||||
}
|
||||
if (mcctrl_dma_abort) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
remaining_job = 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_pin_region(aal_os_t os, unsigned long *__user arg)
|
||||
{
|
||||
struct prepare_dma_desc desc;
|
||||
int pin_shift = 16;
|
||||
int order;
|
||||
unsigned long a;
|
||||
|
||||
if (copy_from_user(&desc, arg, sizeof(struct prepare_dma_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
order = pin_shift - PAGE_SHIFT;
|
||||
if(desc.size > 0){
|
||||
order = get_order (desc.size);
|
||||
}
|
||||
|
||||
a = __get_free_pages(GFP_KERNEL, order);
|
||||
if (!a) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
a = virt_to_phys((void *)a);
|
||||
|
||||
if (copy_to_user((void*)desc.pa, &a, sizeof(unsigned long))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_free_region(aal_os_t os, unsigned long *__user arg)
|
||||
{
|
||||
struct free_dma_desc desc;
|
||||
int pin_shift = 16;
|
||||
int order;
|
||||
|
||||
if (copy_from_user(&desc, arg, sizeof(struct free_dma_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
order = pin_shift - PAGE_SHIFT;
|
||||
if(desc.size > 0){
|
||||
order = get_order (desc.size);
|
||||
}
|
||||
|
||||
if(desc.pa > 0){
|
||||
free_pages((unsigned long)phys_to_virt(desc.pa), order);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_load_syscall(aal_os_t os, struct syscall_load_desc *__user arg)
|
||||
{
|
||||
struct syscall_load_desc desc;
|
||||
unsigned long phys;
|
||||
void *rpm;
|
||||
|
||||
if (copy_from_user(&desc, arg, sizeof(struct syscall_load_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
phys = aal_device_map_memory(aal_os_to_dev(os), desc.src, desc.size);
|
||||
#ifdef CONFIG_KNF
|
||||
rpm = ioremap_wc(phys, desc.size);
|
||||
#else
|
||||
rpm = aal_device_map_virtual(aal_os_to_dev(os), phys, desc.size, NULL, 0);
|
||||
#endif
|
||||
|
||||
dprintk("mcexec_load_syscall: %s (desc.size: %d)\n", rpm, desc.size);
|
||||
|
||||
if (copy_to_user((void *__user)desc.dest, rpm, desc.size)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KNF
|
||||
iounmap(rpm);
|
||||
#else
|
||||
aal_device_unmap_virtual(aal_os_to_dev(os), rpm, desc.size);
|
||||
#endif
|
||||
|
||||
aal_device_unmap_memory(aal_os_to_dev(os), phys, desc.size);
|
||||
|
||||
/*
|
||||
aal_dma_channel_t channel;
|
||||
struct aal_dma_request request;
|
||||
unsigned long dma_status = 0;
|
||||
|
||||
channel = aal_device_get_dma_channel(aal_os_to_dev(os), 0);
|
||||
if (!channel) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.src_os = os;
|
||||
request.src_phys = desc.src;
|
||||
request.dest_os = NULL;
|
||||
request.dest_phys = desc.dest;
|
||||
request.size = desc.size;
|
||||
request.notify = (void *)virt_to_phys(&dma_status);
|
||||
request.priv = (void *)1;
|
||||
|
||||
aal_dma_request(channel, &request);
|
||||
|
||||
while (!dma_status) {
|
||||
mb();
|
||||
udelay(1);
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_ret_syscall(aal_os_t os, struct syscall_ret_desc *__user arg)
|
||||
{
|
||||
struct syscall_ret_desc ret;
|
||||
struct mcctrl_channel *mc;
|
||||
#if 0
|
||||
aal_dma_channel_t channel;
|
||||
struct aal_dma_request request;
|
||||
|
||||
channel = aal_device_get_dma_channel(aal_os_to_dev(os), 0);
|
||||
if (!channel) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (copy_from_user(&ret, arg, sizeof(struct syscall_ret_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
mc = channels + ret.cpu;
|
||||
if (!mc) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mc->param.response_va->ret = ret.ret;
|
||||
|
||||
if (ret.size > 0) {
|
||||
/* Host => Accel. Write is fast. */
|
||||
unsigned long phys;
|
||||
void *rpm;
|
||||
|
||||
phys = aal_device_map_memory(aal_os_to_dev(os), ret.dest,
|
||||
ret.size);
|
||||
#ifdef CONFIG_KNF
|
||||
rpm = ioremap_wc(phys, ret.size);
|
||||
#else
|
||||
rpm = aal_device_map_virtual(aal_os_to_dev(os), phys,
|
||||
ret.size, NULL, 0);
|
||||
#endif
|
||||
|
||||
if (copy_from_user(rpm, (void *__user)ret.src, ret.size)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
mc->param.response_va->status = 1;
|
||||
|
||||
#ifdef CONFIG_KNF
|
||||
iounmap(rpm);
|
||||
#else
|
||||
aal_device_unmap_virtual(aal_os_to_dev(os), rpm, ret.size);
|
||||
#endif
|
||||
aal_device_unmap_memory(aal_os_to_dev(os), phys, ret.size);
|
||||
|
||||
/*
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.src_os = NULL;
|
||||
request.src_phys = ret.src;
|
||||
request.dest_os = os;
|
||||
request.dest_phys = ret.dest;
|
||||
request.size = ret.size;
|
||||
request.notify_os = os;
|
||||
request.notify = (void *)mc->param.response_rpa;
|
||||
request.priv = (void *)1;
|
||||
|
||||
aal_dma_request(channel, &request);
|
||||
*/
|
||||
} else {
|
||||
mc->param.response_va->status = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long __mcctrl_control(aal_os_t os, unsigned int req, unsigned long arg)
|
||||
{
|
||||
switch (req) {
|
||||
case MCEXEC_UP_PREPARE_IMAGE:
|
||||
return mcexec_prepare_image(os,
|
||||
(struct program_load_desc *)arg);
|
||||
case MCEXEC_UP_LOAD_IMAGE:
|
||||
return mcexec_load_image(os, (struct program_transfer *)arg);
|
||||
|
||||
case MCEXEC_UP_START_IMAGE:
|
||||
return mcexec_start_image(os, (struct program_load_desc *)arg);
|
||||
|
||||
case MCEXEC_UP_WAIT_SYSCALL:
|
||||
return mcexec_wait_syscall(os, (struct syscall_wait_desc *)arg);
|
||||
|
||||
case MCEXEC_UP_RET_SYSCALL:
|
||||
return mcexec_ret_syscall(os, (struct syscall_ret_desc *)arg);
|
||||
|
||||
case MCEXEC_UP_LOAD_SYSCALL:
|
||||
return mcexec_load_syscall(os, (struct syscall_load_desc *)arg);
|
||||
|
||||
case MCEXEC_UP_PREPARE_DMA:
|
||||
return mcexec_pin_region(os, (unsigned long *)arg);
|
||||
|
||||
case MCEXEC_UP_FREE_DMA:
|
||||
return mcexec_free_region(os, (unsigned long *)arg);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void mcexec_prepare_ack(unsigned long arg)
|
||||
{
|
||||
struct program_load_desc *desc = phys_to_virt(arg);
|
||||
|
||||
desc->status = 1;
|
||||
|
||||
wake_up_all(&wq_prepare);
|
||||
}
|
||||
|
||||
65
executer/kernel/driver.c
Normal file
65
executer/kernel/driver.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sysdeps/knf/mic/mic_type.h>
|
||||
#include "mcctrl.h"
|
||||
|
||||
extern long __mcctrl_control(aal_os_t, unsigned int, unsigned long);
|
||||
extern int prepare_ikc_channels(aal_os_t os);
|
||||
extern void destroy_ikc_channels(aal_os_t os);
|
||||
|
||||
static long mcctrl_ioctl(aal_os_t os, unsigned int request, void *priv,
|
||||
unsigned long arg)
|
||||
{
|
||||
return __mcctrl_control(os, request, arg);
|
||||
}
|
||||
|
||||
static struct aal_os_user_call_handler mcctrl_uchs[] = {
|
||||
{ .request = MCEXEC_UP_PREPARE_IMAGE, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_LOAD_IMAGE, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_START_IMAGE, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_WAIT_SYSCALL, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_RET_SYSCALL, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_LOAD_SYSCALL, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_PREPARE_DMA, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_FREE_DMA, .func = mcctrl_ioctl },
|
||||
};
|
||||
|
||||
static struct aal_os_user_call mcctrl_uc = {
|
||||
.num_handlers = sizeof(mcctrl_uchs) / sizeof(mcctrl_uchs[0]),
|
||||
.handlers = mcctrl_uchs,
|
||||
};
|
||||
|
||||
static aal_os_t os;
|
||||
|
||||
static int __init mcctrl_init(void)
|
||||
{
|
||||
os = aal_host_find_os(0, NULL);
|
||||
if (!os) {
|
||||
printk("OS #0 not found.\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (prepare_ikc_channels(os) != 0) {
|
||||
printk("Preparing syscall channels failed.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return aal_os_register_user_call_handlers(os, &mcctrl_uc);
|
||||
}
|
||||
|
||||
static void __exit mcctrl_exit(void)
|
||||
{
|
||||
printk("mcctrl: unregistered.\n");
|
||||
aal_os_unregister_user_call_handlers(os, &mcctrl_uc);
|
||||
destroy_ikc_channels(os);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
module_init(mcctrl_init);
|
||||
module_exit(mcctrl_exit);
|
||||
258
executer/kernel/ikc.c
Normal file
258
executer/kernel/ikc.c
Normal file
@@ -0,0 +1,258 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include "mcctrl.h"
|
||||
#include <aal/ikc.h>
|
||||
#include <ikc/master.h>
|
||||
#include <sysdeps/knf/mic/micconst.h>
|
||||
|
||||
#define REQUEST_SHIFT 16
|
||||
|
||||
int num_channels;
|
||||
|
||||
struct mcctrl_channel *channels;
|
||||
|
||||
void mcexec_prepare_ack(unsigned long arg);
|
||||
static void mcctrl_ikc_init(aal_os_t os, int cpu, unsigned long rphys);
|
||||
int mcexec_syscall(struct mcctrl_channel *c, unsigned long arg);
|
||||
|
||||
static int syscall_packet_handler(struct aal_ikc_channel_desc *c,
|
||||
void *__packet, void *__os)
|
||||
{
|
||||
struct ikc_scd_packet *pisp = __packet;
|
||||
|
||||
switch (pisp->msg) {
|
||||
case SCD_MSG_INIT_CHANNEL:
|
||||
mcctrl_ikc_init(__os, pisp->ref, pisp->arg);
|
||||
break;
|
||||
|
||||
case SCD_MSG_PREPARE_PROCESS_ACKED:
|
||||
mcexec_prepare_ack(pisp->arg);
|
||||
break;
|
||||
|
||||
case SCD_MSG_SYSCALL_ONESIDE:
|
||||
mcexec_syscall(channels + pisp->ref, pisp->arg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcctrl_ikc_send(int cpu, struct ikc_scd_packet *pisp)
|
||||
{
|
||||
if (cpu < 0 || cpu >= num_channels || !channels[cpu].c) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return aal_ikc_send(channels[cpu].c, pisp, 0);
|
||||
}
|
||||
|
||||
int mcctrl_ikc_send_msg(int cpu, int msg, int ref, unsigned long arg)
|
||||
{
|
||||
struct ikc_scd_packet packet;
|
||||
|
||||
if (cpu < 0 || cpu >= num_channels || !channels[cpu].c) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
packet.msg = msg;
|
||||
packet.ref = ref;
|
||||
packet.arg = arg;
|
||||
|
||||
return aal_ikc_send(channels[cpu].c, &packet, 0);
|
||||
}
|
||||
|
||||
int mcctrl_ikc_set_recv_cpu(int cpu)
|
||||
{
|
||||
aal_ikc_channel_set_cpu(channels[cpu].c,
|
||||
aal_ikc_get_processor_id());
|
||||
kprintf("Setting the target to %d\n",
|
||||
aal_ikc_get_processor_id());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcctrl_ikc_is_valid_thread(int cpu)
|
||||
{
|
||||
if (cpu < 0 || cpu >= num_channels || !channels[cpu].c) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long *mcctrl_doorbell_va;
|
||||
unsigned long mcctrl_doorbell_pa;
|
||||
|
||||
static void mcctrl_ikc_init(aal_os_t os, int cpu, unsigned long rphys)
|
||||
{
|
||||
struct ikc_scd_packet packet;
|
||||
struct mcctrl_channel *pmc = channels + cpu;
|
||||
unsigned long phys;
|
||||
struct ikc_scd_init_param *rpm;
|
||||
|
||||
if (!pmc) {
|
||||
return;
|
||||
}
|
||||
|
||||
printk("IKC init: %d\n", cpu);
|
||||
|
||||
phys = aal_device_map_memory(aal_os_to_dev(os), rphys,
|
||||
sizeof(struct ikc_scd_init_param));
|
||||
#ifdef CONFIG_KNF
|
||||
rpm = ioremap_wc(phys, sizeof(struct ikc_scd_init_param));
|
||||
#else
|
||||
rpm = aal_device_map_virtual(aal_os_to_dev(os), phys,
|
||||
sizeof(struct ikc_scd_init_param),
|
||||
NULL, 0);
|
||||
#endif
|
||||
|
||||
pmc->param.request_va =
|
||||
(void *)__get_free_pages(GFP_KERNEL,
|
||||
REQUEST_SHIFT - PAGE_SHIFT);
|
||||
pmc->param.request_pa = virt_to_phys(pmc->param.request_va);
|
||||
pmc->param.doorbell_va = mcctrl_doorbell_va;
|
||||
pmc->param.doorbell_pa = mcctrl_doorbell_pa;
|
||||
pmc->param.post_va = (void *)__get_free_page(GFP_KERNEL);
|
||||
pmc->param.post_pa = virt_to_phys(pmc->param.post_va);
|
||||
memset(pmc->param.doorbell_va, 0, PAGE_SIZE);
|
||||
memset(pmc->param.request_va, 0, PAGE_SIZE);
|
||||
memset(pmc->param.post_va, 0, PAGE_SIZE);
|
||||
|
||||
pmc->param.response_rpa = rpm->response_page;
|
||||
pmc->param.response_pa
|
||||
= aal_device_map_memory(aal_os_to_dev(os),
|
||||
pmc->param.response_rpa,
|
||||
PAGE_SIZE);
|
||||
#ifdef CONFIG_KNF
|
||||
pmc->param.response_va = ioremap_cache(pmc->param.response_pa,
|
||||
PAGE_SIZE);
|
||||
#else
|
||||
pmc->param.response_va = aal_device_map_virtual(aal_os_to_dev(os),
|
||||
pmc->param.response_pa,
|
||||
PAGE_SIZE, NULL, 0);
|
||||
#endif
|
||||
|
||||
pmc->dma_buf = (void *)__get_free_pages(GFP_KERNEL,
|
||||
DMA_PIN_SHIFT - PAGE_SHIFT);
|
||||
|
||||
rpm->request_page = pmc->param.request_pa;
|
||||
rpm->doorbell_page = pmc->param.doorbell_pa;
|
||||
rpm->post_page = pmc->param.post_pa;
|
||||
|
||||
packet.msg = SCD_MSG_INIT_CHANNEL_ACKED;
|
||||
packet.ref = cpu;
|
||||
packet.arg = rphys;
|
||||
|
||||
printk("Request: %lx, Response: %lx, Doorbell: %lx\n",
|
||||
pmc->param.request_pa, pmc->param.response_rpa,
|
||||
pmc->param.doorbell_pa);
|
||||
printk("Request: %p, Response: %p, Doorbell: %p\n",
|
||||
pmc->param.request_va, pmc->param.response_va,
|
||||
pmc->param.doorbell_va);
|
||||
|
||||
aal_ikc_send(pmc->c, &packet, 0);
|
||||
|
||||
#ifdef CONFIG_KNF
|
||||
iounmap(rpm);
|
||||
#else
|
||||
aal_device_unmap_virtual(aal_os_to_dev(os), rpm,
|
||||
sizeof(struct ikc_scd_init_param));
|
||||
#endif
|
||||
|
||||
aal_device_unmap_memory(aal_os_to_dev(os), phys,
|
||||
sizeof(struct ikc_scd_init_param));
|
||||
}
|
||||
|
||||
static int connect_handler(struct aal_ikc_channel_info *param)
|
||||
{
|
||||
struct aal_ikc_channel_desc *c;
|
||||
int cpu;
|
||||
|
||||
c = param->channel;
|
||||
cpu = c->send.queue->read_cpu;
|
||||
|
||||
if (cpu < 0 || cpu >= num_channels) {
|
||||
kprintf("Invalid connect source processor: %d\n", cpu);
|
||||
return 1;
|
||||
}
|
||||
param->packet_handler = syscall_packet_handler;
|
||||
init_waitqueue_head(&channels[cpu].wq_syscall);
|
||||
|
||||
channels[cpu].c = c;
|
||||
kprintf("syscall: MC CPU %d connected.\n", cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct aal_ikc_listen_param listen_param = {
|
||||
.port = 501,
|
||||
.handler = connect_handler,
|
||||
.pkt_size = sizeof(struct ikc_scd_packet),
|
||||
.queue_size = PAGE_SIZE,
|
||||
.magic = 0x1129,
|
||||
};
|
||||
|
||||
int prepare_ikc_channels(aal_os_t os)
|
||||
{
|
||||
struct aal_cpu_info *info;
|
||||
|
||||
mcctrl_doorbell_va = (void *)__get_free_page(GFP_KERNEL);
|
||||
mcctrl_doorbell_pa = virt_to_phys(mcctrl_doorbell_va);
|
||||
|
||||
info = aal_os_get_cpu_info(os);
|
||||
if (!info) {
|
||||
printk("Error: cannot retrieve CPU info.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (info->n_cpus < 1) {
|
||||
printk("Error: # of cpu is invalid.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_channels = info->n_cpus;
|
||||
channels = kzalloc(sizeof(struct mcctrl_channel) * num_channels,
|
||||
GFP_KERNEL);
|
||||
if (!channels) {
|
||||
printk("Error: cannot allocate channels.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
aal_ikc_listen_port(os, &listen_param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __destroy_ikc_channel(aal_os_t os, struct mcctrl_channel *pmc)
|
||||
{
|
||||
free_pages((unsigned long)pmc->param.request_va,
|
||||
REQUEST_SHIFT - PAGE_SHIFT);
|
||||
free_page((unsigned long)pmc->param.post_va);
|
||||
|
||||
#ifdef CONFIG_KNF
|
||||
iounmap(pmc->param.response_va);
|
||||
#else
|
||||
aal_device_unmap_virtual(aal_os_to_dev(os), pmc->param.response_va,
|
||||
PAGE_SIZE);
|
||||
#endif
|
||||
aal_device_unmap_memory(aal_os_to_dev(os),
|
||||
pmc->param.response_pa, PAGE_SIZE);
|
||||
free_pages((unsigned long)pmc->dma_buf,
|
||||
DMA_PIN_SHIFT - PAGE_SHIFT);
|
||||
}
|
||||
|
||||
void destroy_ikc_channels(aal_os_t os)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_channels; i++) {
|
||||
if (channels[i].c) {
|
||||
// aal_ikc_disconnect(channels[i].c);
|
||||
aal_ikc_free_channel(channels[i].c);
|
||||
__destroy_ikc_channel(os, channels + i);
|
||||
printk("Channel #%d freed.\n", i);
|
||||
}
|
||||
}
|
||||
free_page((unsigned long)mcctrl_doorbell_va);
|
||||
|
||||
kfree(channels);
|
||||
}
|
||||
68
executer/kernel/mcctrl.h
Normal file
68
executer/kernel/mcctrl.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef HEADER_MCCTRL_H
|
||||
#define HEADER_MCCTRL_H
|
||||
|
||||
#include <aal/aal_host_driver.h>
|
||||
#include <uprotocol.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#define SCD_MSG_PREPARE_PROCESS 0x1
|
||||
#define SCD_MSG_PREPARE_PROCESS_ACKED 0x2
|
||||
#define SCD_MSG_SCHEDULE_PROCESS 0x3
|
||||
|
||||
#define SCD_MSG_INIT_CHANNEL 0x5
|
||||
#define SCD_MSG_INIT_CHANNEL_ACKED 0x6
|
||||
|
||||
#define SCD_MSG_SYSCALL_ONESIDE 0x4
|
||||
|
||||
#define DMA_PIN_SHIFT 21
|
||||
|
||||
#define DO_USER_MODE
|
||||
|
||||
struct ikc_scd_packet {
|
||||
int msg;
|
||||
int ref;
|
||||
unsigned long arg;
|
||||
};
|
||||
|
||||
struct mcctrl_priv {
|
||||
aal_os_t os;
|
||||
struct program_load_desc *desc;
|
||||
};
|
||||
|
||||
struct ikc_scd_init_param {
|
||||
unsigned long request_page;
|
||||
unsigned long response_page;
|
||||
unsigned long doorbell_page;
|
||||
unsigned long post_page;
|
||||
};
|
||||
|
||||
struct syscall_post {
|
||||
unsigned long v[8];
|
||||
};
|
||||
|
||||
struct syscall_params {
|
||||
unsigned long request_pa;
|
||||
struct syscall_request *request_va;
|
||||
unsigned long response_rpa, response_pa;
|
||||
struct syscall_response *response_va;
|
||||
unsigned long post_pa;
|
||||
struct syscall_post *post_va;
|
||||
|
||||
unsigned long doorbell_pa;
|
||||
unsigned long *doorbell_va;
|
||||
};
|
||||
|
||||
struct mcctrl_channel {
|
||||
struct aal_ikc_channel_desc *c;
|
||||
struct syscall_params param;
|
||||
struct ikc_scd_init_param init;
|
||||
void *dma_buf;
|
||||
|
||||
int req;
|
||||
wait_queue_head_t wq_syscall;
|
||||
};
|
||||
|
||||
int mcctrl_ikc_send(int cpu, struct ikc_scd_packet *pisp);
|
||||
int mcctrl_ikc_send_msg(int cpu, int msg, int ref, unsigned long arg);
|
||||
int mcctrl_ikc_is_valid_thread(int cpu);
|
||||
#endif
|
||||
236
executer/kernel/syscall.c
Normal file
236
executer/kernel/syscall.c
Normal file
@@ -0,0 +1,236 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include "mcctrl.h"
|
||||
|
||||
#define ALIGN_WAIT_BUF(z) (((z + 63) >> 6) << 6)
|
||||
|
||||
//#define SC_DEBUG
|
||||
#ifdef SC_DEBUG
|
||||
static struct aal_dma_request last_request;
|
||||
|
||||
static void print_dma_lastreq(void)
|
||||
{
|
||||
printk("SRC OS : %p | %lx\nDESTOS : %p | %lx\n", last_request.src_os,
|
||||
last_request.src_phys, last_request.dest_os,
|
||||
last_request.dest_phys);
|
||||
printk("SIZE : %lx | NOTIFY : %p | PRIV : %p\n",
|
||||
last_request.size, last_request.notify, last_request.priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long last_thread_exec = 0;
|
||||
|
||||
#ifndef DO_USER_MODE
|
||||
static int do_async_copy(aal_os_t os, unsigned long dest, unsigned long src,
|
||||
unsigned long size, unsigned int inbound)
|
||||
{
|
||||
struct aal_dma_request request;
|
||||
aal_dma_channel_t channel;
|
||||
unsigned long asize = ALIGN_WAIT_BUF(size);
|
||||
|
||||
channel = aal_device_get_dma_channel(aal_os_to_dev(os), 0);
|
||||
if (!channel) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.src_os = inbound ? os : NULL;
|
||||
request.src_phys = src;
|
||||
request.dest_os = inbound ? NULL : os;
|
||||
request.dest_phys = dest;
|
||||
request.size = size;
|
||||
request.notify = (void *)(inbound ? dest + asize : src + asize);
|
||||
request.priv = (void *)1;
|
||||
|
||||
*(unsigned long *)phys_to_virt((unsigned long)request.notify) = 0;
|
||||
#ifdef SC_DEBUG
|
||||
last_request = request;
|
||||
#endif
|
||||
|
||||
aal_dma_request(channel, &request);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcctrl_dma_abort;
|
||||
|
||||
static void async_wait(unsigned char *p, int size)
|
||||
{
|
||||
int asize = ALIGN_WAIT_BUF(size);
|
||||
unsigned long long s, w;
|
||||
|
||||
rdtscll(s);
|
||||
while (!p[asize]) {
|
||||
mb();
|
||||
cpu_relax();
|
||||
rdtscll(w);
|
||||
if (w > s + 1024UL * 1024 * 1024 * 10) {
|
||||
printk("DMA Timed out : %p (%p + %d) => %d\n",
|
||||
p + asize, p, size, p[asize]);
|
||||
print_dma_lastreq();
|
||||
mcctrl_dma_abort = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void clear_wait(unsigned char *p, int size)
|
||||
{
|
||||
//int asize = ALIGN_WAIT_BUF(size);
|
||||
p[size] = 0;
|
||||
}
|
||||
|
||||
static void __return_syscall(struct mcctrl_channel *c, int ret)
|
||||
{
|
||||
c->param.response_va->ret = ret;
|
||||
c->param.response_va->status = 1;
|
||||
}
|
||||
|
||||
static unsigned long translate_remote_va(struct mcctrl_channel *c,
|
||||
unsigned long rva)
|
||||
{
|
||||
int i, n;
|
||||
struct syscall_post *p;
|
||||
|
||||
p = c->param.post_va;
|
||||
|
||||
n = (int)p->v[0];
|
||||
if (n < 0 || n >= PAGE_SIZE / sizeof(struct syscall_post)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
if (p[i + 1].v[0] != 1) {
|
||||
continue;
|
||||
}
|
||||
if (rva >= p[i + 1].v[1] && rva < p[i + 1].v[2]) {
|
||||
return p[i + 1].v[3] + (rva - p[i + 1].v[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
extern struct mcctrl_channel *channels;
|
||||
|
||||
int __do_in_kernel_syscall(aal_os_t os, struct mcctrl_channel *c,
|
||||
struct syscall_request *sc)
|
||||
{
|
||||
int ret;
|
||||
mm_segment_t fs;
|
||||
unsigned long pa;
|
||||
|
||||
switch (sc->number) {
|
||||
case 0: /* read */
|
||||
case 1024:
|
||||
if (sc->number & 1024) {
|
||||
sc->args[1] = translate_remote_va(c, sc->args[1]);
|
||||
if ((long)sc->args[1] < 0) {
|
||||
__return_syscall(c, -EFAULT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
clear_wait(c->dma_buf, sc->args[2]);
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_read(sc->args[0], c->dma_buf, sc->args[2]);
|
||||
if (ret > 0) {
|
||||
do_async_copy(os, sc->args[1], virt_to_phys(c->dma_buf),
|
||||
sc->args[2], 0);
|
||||
set_fs(fs);
|
||||
|
||||
async_wait(c->dma_buf, sc->args[2]);
|
||||
}
|
||||
__return_syscall(c, ret);
|
||||
return 0;
|
||||
|
||||
case 1: /* write */
|
||||
case 1025:
|
||||
if (sc->number & 1024) {
|
||||
sc->args[1] = translate_remote_va(c, sc->args[1]);
|
||||
if ((long)sc->args[1] < 0) {
|
||||
__return_syscall(c, -EFAULT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
clear_wait(c->dma_buf, sc->args[2]);
|
||||
do_async_copy(os, virt_to_phys(c->dma_buf), sc->args[1],
|
||||
sc->args[2], 1);
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
async_wait(c->dma_buf, sc->args[2]);
|
||||
|
||||
ret = sys_write(sc->args[0], c->dma_buf, sc->args[2]);
|
||||
set_fs(fs);
|
||||
|
||||
__return_syscall(c, ret);
|
||||
return 0;
|
||||
|
||||
case 2: /* open */
|
||||
case 1026:
|
||||
if (sc->number & 1024) {
|
||||
sc->args[0] = translate_remote_va(c, sc->args[0]);
|
||||
if ((long)sc->args[0] < 0) {
|
||||
__return_syscall(c, -EFAULT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
clear_wait(c->dma_buf, 256);
|
||||
do_async_copy(os, virt_to_phys(c->dma_buf), sc->args[0],
|
||||
256, 1);
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
async_wait(c->dma_buf, 256);
|
||||
|
||||
ret = do_sys_open(AT_FDCWD, c->dma_buf, sc->args[1],
|
||||
sc->args[2]);
|
||||
set_fs(fs);
|
||||
|
||||
__return_syscall(c, ret);
|
||||
return 0;
|
||||
|
||||
case 3: /* Close */
|
||||
ret = sys_close(sc->args[0]);
|
||||
__return_syscall(c, ret);
|
||||
return 0;
|
||||
|
||||
case 8: /* lseek */
|
||||
ret = sys_lseek(sc->args[0], sc->args[1], sc->args[2]);
|
||||
__return_syscall(c, ret);
|
||||
return 0;
|
||||
|
||||
case 56: /* Clone */
|
||||
last_thread_exec++;
|
||||
if (mcctrl_ikc_is_valid_thread(last_thread_exec)) {
|
||||
printk("Clone notification: %lx\n", sc->args[0]);
|
||||
if (channels[last_thread_exec].param.post_va) {
|
||||
memcpy(channels[last_thread_exec].param.post_va,
|
||||
c->param.post_va, PAGE_SIZE);
|
||||
}
|
||||
mcctrl_ikc_send_msg(last_thread_exec,
|
||||
SCD_MSG_SCHEDULE_PROCESS,
|
||||
last_thread_exec, sc->args[0]);
|
||||
}
|
||||
|
||||
__return_syscall(c, 0);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
if (sc->number & 1024) {
|
||||
__return_syscall(c, -EFAULT);
|
||||
return 0;
|
||||
} else {
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !DO_USER_MODE */
|
||||
9
executer/user/Makefile
Normal file
9
executer/user/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
CFLAGS = -O3 -Wall -g -pthread
|
||||
|
||||
all: mcexec
|
||||
|
||||
mcexec: mcexec.c
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ $^ $(EXTRA_OBJS)
|
||||
|
||||
clean:
|
||||
rm -f mcexec
|
||||
803
executer/user/mcexec.c
Normal file
803
executer/user/mcexec.c
Normal file
@@ -0,0 +1,803 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <asm/unistd.h>
|
||||
#include "../include/uprotocol.h"
|
||||
#include <sched.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifndef DEBUG
|
||||
#define __dprint(msg, ...)
|
||||
#define __dprintf(arg, ...)
|
||||
#define __eprint(msg, ...)
|
||||
#define __eprintf(format, ...)
|
||||
#else
|
||||
#define __dprint(msg, ...) {printf("%s: " msg, __FUNCTION__);fflush(stdout);}
|
||||
#define __dprintf(format, ...) {printf("%s: " format, __FUNCTION__, \
|
||||
__VA_ARGS__);fflush(stdout);}
|
||||
#define __eprint(msg, ...) {fprintf(stderr, "%s: " msg, __FUNCTION__);fflush(stderr);}
|
||||
#define __eprintf(format, ...) {fprintf(stderr, "%s: " format, __FUNCTION__, \
|
||||
__VA_ARGS__);fflush(stderr);}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SYSCALL_MOD_CALL
|
||||
extern int mc_cmd_server_init();
|
||||
extern void mc_cmd_server_exit();
|
||||
extern void mc_cmd_handle(int fd, int cpu, unsigned long args[6]);
|
||||
|
||||
int __glob_argc = -1;
|
||||
char **__glob_argv = 0;
|
||||
#endif
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
#ifdef NCCS
|
||||
#undef NCCS
|
||||
#endif
|
||||
|
||||
#define NCCS 19
|
||||
struct kernel_termios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_line; /* line discipline */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
};
|
||||
|
||||
int main_loop(int fd, int cpu, pthread_mutex_t *lock);
|
||||
|
||||
struct program_load_desc *load_elf(FILE *fp)
|
||||
{
|
||||
Elf64_Ehdr hdr;
|
||||
Elf64_Phdr phdr;
|
||||
int i, j, nhdrs = 0;
|
||||
struct program_load_desc *desc;
|
||||
unsigned long load_addr = 0;
|
||||
int load_addr_set = 0;
|
||||
|
||||
if (fread(&hdr, sizeof(hdr), 1, fp) < 1) {
|
||||
__eprint("Cannot read Ehdr.\n");
|
||||
return NULL;
|
||||
}
|
||||
if (memcmp(hdr.e_ident, ELFMAG, SELFMAG)) {
|
||||
__eprint("ELFMAG mismatched.\n");
|
||||
return NULL;
|
||||
}
|
||||
fseek(fp, hdr.e_phoff, SEEK_SET);
|
||||
for (i = 0; i < hdr.e_phnum; i++) {
|
||||
if (fread(&phdr, sizeof(phdr), 1, fp) < 1) {
|
||||
__eprintf("Loading phdr failed (%d)\n", i);
|
||||
return NULL;
|
||||
}
|
||||
if (phdr.p_type == PT_LOAD) {
|
||||
nhdrs++;
|
||||
}
|
||||
}
|
||||
|
||||
desc = malloc(sizeof(struct program_load_desc)
|
||||
+ sizeof(struct program_image_section) * nhdrs);
|
||||
fseek(fp, hdr.e_phoff, SEEK_SET);
|
||||
j = 0;
|
||||
desc->num_sections = nhdrs;
|
||||
for (i = 0; i < hdr.e_phnum; i++) {
|
||||
if (fread(&phdr, sizeof(phdr), 1, fp) < 1) {
|
||||
__eprintf("Loading phdr failed (%d)\n", i);
|
||||
return NULL;
|
||||
}
|
||||
if (phdr.p_type == PT_LOAD) {
|
||||
desc->sections[j].vaddr = phdr.p_vaddr;
|
||||
desc->sections[j].filesz = phdr.p_filesz;
|
||||
desc->sections[j].offset = phdr.p_offset;
|
||||
desc->sections[j].len = phdr.p_memsz;
|
||||
|
||||
__dprintf("%d: (%s) %lx, %lx, %lx, %lx\n",
|
||||
j, (phdr.p_type == PT_LOAD ? "PT_LOAD" : "PT_TLS"),
|
||||
desc->sections[j].vaddr,
|
||||
desc->sections[j].filesz,
|
||||
desc->sections[j].offset,
|
||||
desc->sections[j].len);
|
||||
j++;
|
||||
|
||||
if (!load_addr_set) {
|
||||
load_addr_set = 1;
|
||||
load_addr = phdr.p_vaddr - phdr.p_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
desc->pid = getpid();
|
||||
desc->entry = hdr.e_entry;
|
||||
|
||||
desc->at_phdr = load_addr + hdr.e_phoff;
|
||||
desc->at_phent = sizeof(phdr);
|
||||
desc->at_phnum = hdr.e_phnum;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
unsigned char *dma_buf;
|
||||
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_MASK ~((unsigned long)PAGE_SIZE - 1)
|
||||
|
||||
void transfer_image(FILE *fp, int fd, struct program_load_desc *desc)
|
||||
{
|
||||
struct program_transfer pt;
|
||||
unsigned long s, e, flen, rpa;
|
||||
int i, l, lr;
|
||||
|
||||
for (i = 0; i < desc->num_sections; i++) {
|
||||
s = (desc->sections[i].vaddr) & PAGE_MASK;
|
||||
e = (desc->sections[i].vaddr + desc->sections[i].len
|
||||
+ PAGE_SIZE - 1) & PAGE_MASK;
|
||||
rpa = desc->sections[i].remote_pa;
|
||||
|
||||
fseek(fp, desc->sections[i].offset, SEEK_SET);
|
||||
flen = desc->sections[i].filesz;
|
||||
|
||||
__dprintf("seeked to %lx | size %ld\n",
|
||||
desc->sections[i].offset, flen);
|
||||
|
||||
while (s < e) {
|
||||
pt.dest = rpa;
|
||||
pt.src = dma_buf;
|
||||
pt.sz = PAGE_SIZE;
|
||||
lr = 0;
|
||||
|
||||
memset(dma_buf, 0, PAGE_SIZE);
|
||||
if (s < desc->sections[i].vaddr) {
|
||||
l = desc->sections[i].vaddr
|
||||
& (PAGE_SIZE - 1);
|
||||
lr = PAGE_SIZE - l;
|
||||
if (lr > flen) {
|
||||
lr = flen;
|
||||
}
|
||||
fread(dma_buf + l, 1, lr, fp);
|
||||
flen -= lr;
|
||||
}
|
||||
else if (flen > 0) {
|
||||
if (flen > PAGE_SIZE) {
|
||||
lr = PAGE_SIZE;
|
||||
} else {
|
||||
lr = flen;
|
||||
}
|
||||
fread(dma_buf, 1, lr, fp);
|
||||
flen -= lr;
|
||||
}
|
||||
s += PAGE_SIZE;
|
||||
rpa += PAGE_SIZE;
|
||||
|
||||
/* No more left to upload.. */
|
||||
if (lr == 0 && flen == 0) break;
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_LOAD_IMAGE,
|
||||
(unsigned long)&pt)) {
|
||||
perror("dma");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_desc(struct program_load_desc *desc)
|
||||
{
|
||||
int i;
|
||||
|
||||
__dprintf("Desc (%p)\n", desc);
|
||||
__dprintf("Status = %d, CPU = %d, pid = %d, entry = %lx, rp = %lx\n",
|
||||
desc->status, desc->cpu, desc->pid, desc->entry,
|
||||
desc->rprocess);
|
||||
for (i = 0; i < desc->num_sections; i++) {
|
||||
__dprintf("vaddr: %lx, mem_len: %lx, remote_pa: %lx, files: %lx\n",
|
||||
desc->sections[i].vaddr, desc->sections[i].len,
|
||||
desc->sections[i].remote_pa, desc->sections[i].filesz);
|
||||
}
|
||||
}
|
||||
|
||||
#define PIN_SHIFT 28
|
||||
#define PIN_SIZE (1 << PIN_SHIFT)
|
||||
#define PIN_MASK ~(unsigned long)(PIN_SIZE - 1)
|
||||
|
||||
#if 0
|
||||
unsigned long dma_buf_pa;
|
||||
#endif
|
||||
|
||||
|
||||
void print_flat(char *flat)
|
||||
{
|
||||
char **string;
|
||||
|
||||
__dprintf("counter: %d\n", *((int *)flat));
|
||||
|
||||
string = (char **)(flat + sizeof(int));
|
||||
while (*string) {
|
||||
|
||||
__dprintf("%s\n", (flat + (unsigned long)(*string)));
|
||||
|
||||
++string;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flatten out a (char **) string array into the following format:
|
||||
* [nr_strings][char *offset of string_0]...[char *offset of string_n-1][NULL][string0]...[stringn_1]
|
||||
* if nr_strings == -1, we assume the last item is NULL
|
||||
*
|
||||
* NOTE: copy this string somewhere, add the address of the string to each offset
|
||||
* and we get back a valid argv or envp array.
|
||||
*
|
||||
* returns the total length of the flat string and updates flat to
|
||||
* point to the beginning.
|
||||
*/
|
||||
int flatten_strings(int nr_strings, char **strings, char **flat)
|
||||
{
|
||||
int full_len, string_i;
|
||||
unsigned long flat_offset;
|
||||
char *_flat;
|
||||
|
||||
/* How many strings do we have? */
|
||||
if (nr_strings == -1) {
|
||||
for (nr_strings = 0; strings[nr_strings]; ++nr_strings);
|
||||
}
|
||||
|
||||
/* Count full length */
|
||||
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
|
||||
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
||||
// Pointer + actual value
|
||||
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
|
||||
}
|
||||
|
||||
_flat = (char *)malloc(full_len);
|
||||
if (!_flat) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(_flat, 0, full_len);
|
||||
|
||||
/* Number of strings */
|
||||
*((int*)_flat) = nr_strings;
|
||||
|
||||
// Actual offset
|
||||
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1);
|
||||
|
||||
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
||||
|
||||
/* Fabricate the string */
|
||||
*((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset;
|
||||
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
|
||||
flat_offset += strlen(strings[string_i]) + 1;
|
||||
|
||||
}
|
||||
|
||||
*flat = _flat;
|
||||
return full_len;
|
||||
}
|
||||
|
||||
#define NUM_HANDLER_THREADS 64
|
||||
|
||||
struct thread_data_s {
|
||||
pthread_t thread_id;
|
||||
int fd;
|
||||
int cpu;
|
||||
int ret;
|
||||
pthread_mutex_t *lock;
|
||||
} thread_data[NUM_HANDLER_THREADS];
|
||||
|
||||
static void *main_loop_thread_func(void *arg)
|
||||
{
|
||||
struct thread_data_s *td = (struct thread_data_s *)arg;
|
||||
|
||||
td->ret = main_loop(td->fd, td->cpu, td->lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
#if 0
|
||||
int fdm;
|
||||
long r;
|
||||
#endif
|
||||
FILE *fp;
|
||||
struct program_load_desc *desc;
|
||||
char *envs;
|
||||
char *args;
|
||||
int i;
|
||||
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#ifdef USE_SYSCALL_MOD_CALL
|
||||
__glob_argc = argc;
|
||||
__glob_argv = argv;
|
||||
#endif
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s (program) [args...]\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error: Failed to open %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
desc = load_elf(fp);
|
||||
if (!desc) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "Error: Failed to parse ELF!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
__dprintf("# of sections: %d\n", desc->num_sections);
|
||||
|
||||
desc->envs_len = flatten_strings(-1, environ, &envs);
|
||||
desc->envs = envs;
|
||||
//print_flat(envs);
|
||||
|
||||
desc->args_len = flatten_strings(-1, argv + 1, &args);
|
||||
desc->args = args;
|
||||
//print_flat(args);
|
||||
|
||||
fd = open("/dev/mcos0", O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error: Failed to open /dev/mcctrl.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
fdm = open("/dev/fmem", O_RDWR);
|
||||
if (fdm < 0) {
|
||||
fprintf(stderr, "Error: Failed to open /dev/fmem.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((r = ioctl(fd, MCEXEC_UP_PREPARE_DMA,
|
||||
(unsigned long)&dma_buf_pa)) < 0) {
|
||||
perror("prepare_dma");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dma_buf = mmap(NULL, PIN_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fdm, dma_buf_pa);
|
||||
__dprintf("DMA Buffer: %lx, %p\n", dma_buf_pa, dma_buf);
|
||||
#endif
|
||||
|
||||
dma_buf = mmap(0, PIN_SIZE, PROT_READ | PROT_WRITE,
|
||||
(MAP_ANONYMOUS | MAP_PRIVATE), -1, 0);
|
||||
if (!dma_buf) {
|
||||
__dprint("error: allocating DMA area\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* PIN buffer */
|
||||
if (mlock(dma_buf, (size_t)PIN_SIZE)) {
|
||||
__dprint("ERROR: locking dma_buf\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_PREPARE_IMAGE, (unsigned long)desc) != 0) {
|
||||
perror("prepare");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_desc(desc);
|
||||
transfer_image(fp, fd, desc);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
#ifdef USE_SYSCALL_MOD_CALL
|
||||
/**
|
||||
* TODO: need mutex for static structures
|
||||
*/
|
||||
if(mc_cmd_server_init()){
|
||||
fprintf(stderr, "Error: cmd server init failed\n");
|
||||
return 1;
|
||||
}
|
||||
__dprint("mccmd server initialized\n");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_HANDLER_THREADS; ++i) {
|
||||
int ret;
|
||||
|
||||
thread_data[i].fd = fd;
|
||||
thread_data[i].cpu = i;
|
||||
thread_data[i].lock = &lock;
|
||||
ret = pthread_create(&thread_data[i].thread_id, NULL,
|
||||
&main_loop_thread_func, &thread_data[i]);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("ERROR: creating syscall threads\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_START_IMAGE, (unsigned long)desc) != 0) {
|
||||
perror("exec");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_HANDLER_THREADS; ++i) {
|
||||
int ret;
|
||||
ret = pthread_join(thread_data[i].thread_id, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void do_syscall_return(int fd, int cpu,
|
||||
int ret, int n, unsigned long src, unsigned long dest,
|
||||
unsigned long sz)
|
||||
{
|
||||
struct syscall_ret_desc desc;
|
||||
|
||||
desc.cpu = cpu;
|
||||
desc.ret = ret;
|
||||
desc.src = src;
|
||||
desc.dest = dest;
|
||||
desc.size = sz;
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_RET_SYSCALL, (unsigned long)&desc) != 0) {
|
||||
perror("ret");
|
||||
}
|
||||
}
|
||||
|
||||
void do_syscall_load(int fd, int cpu, unsigned long dest, unsigned long src,
|
||||
unsigned long sz)
|
||||
{
|
||||
struct syscall_load_desc desc;
|
||||
|
||||
desc.cpu = cpu;
|
||||
desc.src = src;
|
||||
desc.dest = dest;
|
||||
desc.size = sz;
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_LOAD_SYSCALL, (unsigned long)&desc) != 0){
|
||||
perror("load");
|
||||
}
|
||||
}
|
||||
|
||||
#define SET_ERR(ret) if (ret == -1) ret = -errno
|
||||
|
||||
int main_loop(int fd, int cpu, pthread_mutex_t *lock)
|
||||
{
|
||||
struct syscall_wait_desc w;
|
||||
int ret;
|
||||
|
||||
w.cpu = cpu;
|
||||
|
||||
while (ioctl(fd, MCEXEC_UP_WAIT_SYSCALL, (unsigned long)&w) == 0) {
|
||||
|
||||
/* Don't print when got a msg to stdout */
|
||||
if (!(w.sr.number == __NR_write && w.sr.args[0] == 1))
|
||||
__dprintf("[%d] got syscall: %ld\n", cpu, w.sr.number);
|
||||
|
||||
pthread_mutex_lock(lock);
|
||||
|
||||
switch (w.sr.number) {
|
||||
case __NR_open:
|
||||
dma_buf[256] = 0;
|
||||
|
||||
do_syscall_load(fd, cpu, (unsigned long)dma_buf, w.sr.args[0], 256);
|
||||
/*
|
||||
while (!dma_buf[256]) {
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
*/
|
||||
|
||||
__dprintf("open: %s\n", dma_buf);
|
||||
|
||||
ret = open((char *)dma_buf, w.sr.args[1], w.sr.args[2]);
|
||||
SET_ERR(ret);
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case __NR_close:
|
||||
__dprintf("mcexec.c,close,fd=%lx\n", w.sr.args[0]);
|
||||
ret = close(w.sr.args[0]);
|
||||
SET_ERR(ret);
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case __NR_read:
|
||||
ret = read(w.sr.args[0], dma_buf, w.sr.args[2]);
|
||||
SET_ERR(ret);
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[1], w.sr.args[2]);
|
||||
break;
|
||||
|
||||
case __NR_write:
|
||||
dma_buf[w.sr.args[2]] = 0;
|
||||
SET_ERR(ret);
|
||||
do_syscall_load(fd, cpu, (unsigned long)dma_buf,
|
||||
w.sr.args[1], w.sr.args[2]);
|
||||
|
||||
/*
|
||||
while (!dma_buf[w.sr.args[2]]) {
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
*/
|
||||
|
||||
ret = write(w.sr.args[0], dma_buf, w.sr.args[2]);
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case __NR_lseek:
|
||||
ret = lseek64(w.sr.args[0], w.sr.args[1], w.sr.args[2]);
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case __NR_pread64:
|
||||
ret = pread(w.sr.args[0], dma_buf, w.sr.args[2],
|
||||
w.sr.args[3]);
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[1], w.sr.args[2]);
|
||||
break;
|
||||
|
||||
case __NR_pwrite64:
|
||||
dma_buf[w.sr.args[2]] = 0;
|
||||
do_syscall_load(fd, cpu, (unsigned long)dma_buf,
|
||||
w.sr.args[1], w.sr.args[2]);
|
||||
|
||||
/*
|
||||
while (!dma_buf[w.sr.args[2]]) {
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
*/
|
||||
|
||||
ret = pwrite(w.sr.args[0], dma_buf, w.sr.args[2],
|
||||
w.sr.args[3]);
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
|
||||
case __NR_stat:
|
||||
{
|
||||
char filename[256];
|
||||
|
||||
do_syscall_load(fd, cpu, (unsigned long)&filename[0],
|
||||
w.sr.args[0], 256);
|
||||
|
||||
ret = stat(filename, (void *)dma_buf);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[1], sizeof(struct stat));
|
||||
break;
|
||||
}
|
||||
case __NR_fstat:
|
||||
ret = fstat(w.sr.args[0], (void *)dma_buf);
|
||||
__dprintf("mcexec.c:main_loop,arg[0]=%ld,ret=%d\n", w.sr.args[0], ret);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[1], sizeof(struct stat));
|
||||
break;
|
||||
|
||||
case __NR_ioctl:
|
||||
if (w.sr.args[1] == TCGETS) {
|
||||
ret = ioctl(w.sr.args[0], w.sr.args[1],
|
||||
(unsigned long)dma_buf);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[2],
|
||||
sizeof(struct kernel_termios)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
glibc-2.14.90/sysdeps/unix/sysv/linux/x86_64/time.S
|
||||
linux-2.6.34.13/arch/x86/kernel/vsyscall_64.c
|
||||
/usr/include/time.h
|
||||
/usr/include/bits/types.h
|
||||
/usr/include/bits/typesizes.h
|
||||
#define __TIME_T_TYPE __SLONGWORD_TYPE
|
||||
*/
|
||||
case __NR_time: {
|
||||
time_t ret;
|
||||
if(w.sr.args[0]) {
|
||||
ret = time((time_t *)dma_buf);
|
||||
} else {
|
||||
ret = time(NULL);
|
||||
}
|
||||
SET_ERR(ret);
|
||||
__dprintf("time=%ld\n", ret);
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[0], sizeof(time_t));
|
||||
break; }
|
||||
|
||||
case __NR_gettimeofday:
|
||||
ret = gettimeofday((struct timeval *)dma_buf, NULL);
|
||||
SET_ERR(ret);
|
||||
__dprintf("gettimeofday=%016ld,%09ld\n", ((struct timeval *)dma_buf)->tv_sec, ((struct timeval *)dma_buf)->tv_usec);
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf,
|
||||
w.sr.args[0], sizeof(struct timeval));
|
||||
break;
|
||||
|
||||
|
||||
case __NR_getgid:
|
||||
case __NR_getuid:
|
||||
case __NR_geteuid:
|
||||
case __NR_getegid:
|
||||
case __NR_getppid:
|
||||
case __NR_getpgrp:
|
||||
ret = syscall(w.sr.number);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case __NR_clone:
|
||||
|
||||
__dprintf("MIC clone(), new thread's cpu_id: %ld\n", w.sr.args[0]);
|
||||
|
||||
|
||||
do_syscall_return(fd, cpu, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
|
||||
case __NR_exit:
|
||||
case __NR_exit_group:
|
||||
do_syscall_return(fd, cpu, 0, 0, 0, 0, 0);
|
||||
|
||||
__dprintf("__NR_exit/__NR_exit_group: %ld (cpu_id: %d)\n",
|
||||
w.sr.args[0], cpu);
|
||||
|
||||
#ifdef USE_SYSCALL_MOD_CALL
|
||||
mc_cmd_server_exit();
|
||||
__dprint("mccmd server exited\n");
|
||||
#endif
|
||||
exit(0);
|
||||
|
||||
pthread_mutex_unlock(lock);
|
||||
return w.sr.args[0];
|
||||
|
||||
case __NR_uname:
|
||||
ret = uname((void *)dma_buf);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
do_syscall_return(fd,
|
||||
cpu, ret, 1, (unsigned long)dma_buf, w.sr.args[0],
|
||||
sizeof(struct utsname));
|
||||
break;
|
||||
|
||||
case __NR_getcwd: {
|
||||
// note that return type is different between glibc-getcwd and sys_getcwd
|
||||
char* c = getcwd((void *)dma_buf, w.sr.args[1]);
|
||||
ret = (c == 0) ? -errno : strnlen((const char*)dma_buf, w.sr.args[1]);
|
||||
__dprintf("getcwd result: %s\n", dma_buf);
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf, w.sr.args[0], c == 0 ? 0 : ret + 1);
|
||||
break; }
|
||||
|
||||
// see linux-2.6.34.13/fs/open.c
|
||||
case __NR_access: {
|
||||
dma_buf[256] = 0;
|
||||
do_syscall_load(fd, cpu, (unsigned long)dma_buf, w.sr.args[0], 256);
|
||||
__dprintf("access: %s\n", dma_buf);
|
||||
int c = access((void *)dma_buf, w.sr.args[1]);
|
||||
ret = (c < 0) ? -errno : c;
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break; }
|
||||
|
||||
case __NR_fcntl: {
|
||||
int c;
|
||||
switch(w.sr.args[1]) {
|
||||
case F_GETFD:
|
||||
c = fcntl(w.sr.args[0], w.sr.args[1]);
|
||||
__dprintf("fcntl,F_GETFD,c=%x\n", c);
|
||||
ret = (c < 0) ? -errno : c;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break; }
|
||||
|
||||
case __NR_getdents64: { // linux-2.6.34.13/fs/readdir.c
|
||||
long c = syscall((int)__NR_getdents64, (unsigned int)w.sr.args[0], (void *)dma_buf, (unsigned int)w.sr.args[2]);
|
||||
ret = (c < 0) ? -errno : c;
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf, w.sr.args[1], c < 0 ? 0 : c);
|
||||
break; }
|
||||
|
||||
case __NR_readlink: {
|
||||
dma_buf[256] = 0;
|
||||
do_syscall_load(fd, cpu, (unsigned long)dma_buf, w.sr.args[0], 256);
|
||||
__dprintf("readlink: %s\n", dma_buf);
|
||||
char* dup = strndup((char *)dma_buf, 256);
|
||||
int c = readlink(dup, (void *)dma_buf, w.sr.args[2]);
|
||||
free(dup);
|
||||
ret = (c < 0) ? -errno : c;
|
||||
if(c > 0) {
|
||||
dup = strndup((char *)dma_buf, c); // readlink does not append NULL at the end
|
||||
// printf("readlink result:c=%d,s=%s\n", c, dup);
|
||||
free(dup);
|
||||
} else {
|
||||
// printf("readlink result: c=%d,s=<NULL>\n", c);
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf, w.sr.args[1], c < 0 ? 0 : c);
|
||||
break; }
|
||||
|
||||
case __NR_mmap: {
|
||||
// w.sr.args[0] is converted to MIC physical address
|
||||
__dprintf("mcexec.c,mmap,MIC-paddr=%lx,len=%lx,prot=%lx,flags=%lx,fd=%lx,offset=%lx\n",
|
||||
w.sr.args[0], w.sr.args[1], w.sr.args[2], w.sr.args[3], w.sr.args[4], w.sr.args[5]);
|
||||
off_t old_off = lseek(w.sr.args[4], 0, SEEK_CUR);
|
||||
if(old_off == -1) { __dprint("mcexec.c,mmap,lseek failed\n"); ret = -errno; goto mmap_out; }
|
||||
off_t rlseek = lseek(w.sr.args[4], w.sr.args[5], SEEK_SET);
|
||||
if(rlseek == -1) { __dprint("mcexec.c,mmap,lseek failed\n"); ret = -errno; goto mmap_out; }
|
||||
ssize_t toread = w.sr.args[1];
|
||||
ret = 0;
|
||||
while(toread > 0) {
|
||||
__dprintf("mcexec.c,mmap,read,addr=%lx,len=%lx\n", (long int)((void *)dma_buf + w.sr.args[1] - toread), toread);
|
||||
ssize_t rread = read(w.sr.args[4], (void *)dma_buf + w.sr.args[1] - toread, toread);
|
||||
if(rread == 0) {
|
||||
__dprint("mcexec.c,mmap,read==0\n");
|
||||
goto mmap_zero_out;
|
||||
} else if(rread < 0) {
|
||||
__dprint("mcexec.c,mmap,read failed\n"); ret = -errno; break;
|
||||
}
|
||||
toread -= rread;
|
||||
}
|
||||
mmap_zero_out:
|
||||
rlseek = lseek(w.sr.args[4], old_off, SEEK_SET);
|
||||
if(rlseek == -1) { __dprint("mcexec.c,mmap,lseek failed\n"); ret = -errno; }
|
||||
mmap_out:
|
||||
do_syscall_return(fd, cpu, ret, 1, (unsigned long)dma_buf, w.sr.args[0], w.sr.args[1]);
|
||||
break; }
|
||||
|
||||
#ifdef USE_SYSCALL_MOD_CALL
|
||||
case 303:{
|
||||
__dprintf("mcexec.c,mod_cal,mod=%ld,cmd=%ld\n", w.sr.args[0], w.sr.args[1]);
|
||||
mc_cmd_handle(fd, cpu, w.sr.args);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
__dprintf("Unhandled system calls: %ld\n", w.sr.number);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(lock);
|
||||
}
|
||||
__dprint("timed out.\n");
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user