a commit
This commit is contained in:
@ -289,6 +289,8 @@ void do_syscall_load(int fd, int cpu, unsigned long dest, unsigned long src,
|
||||
}
|
||||
}
|
||||
|
||||
#define SET_ERR(ret) if (ret == -1) ret = -errno
|
||||
|
||||
int main_loop(int fd, int cpu)
|
||||
{
|
||||
struct syscall_wait_desc w;
|
||||
@ -306,22 +308,26 @@ int main_loop(int fd, int cpu)
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
ret = open(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:
|
||||
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, dma_buf_pa,
|
||||
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, dma_buf_pa,
|
||||
w.sr.args[1], w.sr.args[2]);
|
||||
|
||||
@ -398,6 +404,7 @@ int main_loop(int fd, int cpu)
|
||||
|
||||
case __NR_exit:
|
||||
case __NR_exit_group:
|
||||
do_syscall_return(fd, cpu, 0, 0, 0, 0, 0);
|
||||
return w.sr.args[0];
|
||||
|
||||
case __NR_uname:
|
||||
@ -415,4 +422,6 @@ int main_loop(int fd, int cpu)
|
||||
|
||||
}
|
||||
}
|
||||
printf("timed out.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ endif
|
||||
|
||||
obj-m += mcctrl.o
|
||||
|
||||
mcctrl-objs := driver.o control.o ikc.o
|
||||
mcctrl-objs := driver.o control.o ikc.o syscall.o
|
||||
|
||||
AAL_BASE=$(src)/../../../aal
|
||||
EXTRA_CFLAGS = -I$(AAL_BASE)/host/include -I$(AAL_BASE)/ikc/include -I$(src)/../include
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/msr.h>
|
||||
#include "mcctrl.h"
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(wq_prepare);
|
||||
@ -106,12 +107,15 @@ static long mcexec_start_image(aal_os_t os,
|
||||
{
|
||||
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);
|
||||
|
||||
isp.msg = SCD_MSG_SCHEDULE_PROCESS;
|
||||
@ -131,25 +135,48 @@ int mcexec_syscall(struct mcctrl_channel *c, unsigned long arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int __do_in_kernel_syscall(aal_os_t os, struct mcctrl_channel *c,
|
||||
struct syscall_request *sc);
|
||||
|
||||
int mcexec_wait_syscall(aal_os_t os, struct syscall_wait_desc *__user req)
|
||||
{
|
||||
struct syscall_wait_desc swd;
|
||||
struct mcctrl_channel *c;
|
||||
|
||||
unsigned long s, w;
|
||||
|
||||
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;
|
||||
|
||||
if (copy_to_user(&req->sr, c->param.request_va,
|
||||
sizeof(struct syscall_request))) {
|
||||
return -EFAULT;
|
||||
#else
|
||||
while (1) {
|
||||
rdtscll(s);
|
||||
while (!(*c->param.doorbell_va)) {
|
||||
mb();
|
||||
cpu_relax();
|
||||
rdtscll(w);
|
||||
if (w > s + 1024 * 1024 * 1024 * 1) {
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
*c->param.doorbell_va = 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
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -69,11 +69,15 @@ static void mcctrl_ikc_init(aal_os_t os, int cpu, unsigned long rphys)
|
||||
sizeof(struct ikc_scd_init_param));
|
||||
rpm = ioremap_wc(phys, sizeof(struct ikc_scd_init_param));
|
||||
|
||||
pmc->param.request_va = (void *)__get_free_page(GFP_KERNEL);
|
||||
pmc->param.request_va = (void *)__get_free_pages(GFP_KERNEL, 4);
|
||||
pmc->param.request_pa = virt_to_phys(pmc->param.request_va);
|
||||
pmc->param.doorbell_va = (void *)__get_free_page(GFP_KERNEL);
|
||||
pmc->param.doorbell_pa = virt_to_phys(pmc->param.doorbell_va);
|
||||
|
||||
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.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),
|
||||
@ -82,8 +86,12 @@ static void mcctrl_ikc_init(aal_os_t os, int cpu, unsigned long rphys)
|
||||
pmc->param.response_va = ioremap_wc(pmc->param.response_pa,
|
||||
PAGE_SIZE);
|
||||
|
||||
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;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
#define SCD_MSG_SYSCALL_ONESIDE 0x4
|
||||
|
||||
#define DMA_PIN_SHIFT 16
|
||||
|
||||
struct ikc_scd_packet {
|
||||
int msg;
|
||||
int ref;
|
||||
@ -29,6 +31,11 @@ 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[4];
|
||||
};
|
||||
|
||||
struct syscall_params {
|
||||
@ -36,7 +43,9 @@ struct syscall_params {
|
||||
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;
|
||||
};
|
||||
@ -45,6 +54,7 @@ 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;
|
||||
|
||||
171
linux/mod_mcctrl/syscall.c
Normal file
171
linux/mod_mcctrl/syscall.c
Normal file
@ -0,0 +1,171 @@
|
||||
#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 "mcctrl.h"
|
||||
|
||||
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;
|
||||
|
||||
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 = src;
|
||||
request.dest_os = NULL;
|
||||
request.dest_phys = dest;
|
||||
request.size = size;
|
||||
request.notify = (void *)(inbound ? dest + size : src + size);
|
||||
request.priv = (void *)1;
|
||||
|
||||
aal_dma_request(channel, &request);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void async_wait(unsigned char *p, int size)
|
||||
{
|
||||
while (!p[size]) {
|
||||
mb();
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
static void clear_wait(unsigned char *p, int 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;
|
||||
}
|
||||
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
ret = sys_close(sc->args[0]);
|
||||
__return_syscall(c, ret);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
if (sc->number & 1024) {
|
||||
__return_syscall(c, -EFAULT);
|
||||
return 0;
|
||||
} else {
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user