This commit is contained in:
Taku Shimosawa
2011-12-02 12:35:38 +09:00
parent 5fdb3b2bb2
commit 7999653a00
18 changed files with 536 additions and 64 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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
View 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;
}
}
}