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

13
.gitignore vendored
View File

@@ -1,3 +1,16 @@
*.o
*.elf
*.bin
*.ko
*.cmd
*.unsigned
*.mod.c
Module.symvers
*.order
.tmp_versions
elfboot/elfboot
elfboot/elfboot_test
linux/executer/mcexec
linux/mod_test*
linux/target

View File

@@ -1,6 +1,6 @@
AALDIR=$(AALBASE)/$(TARGET)
OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
OBJS += process.o
OBJS += process.o copy.o
DEPSRCS=$(wildcard $(SRC)/*.c)
include $(SRC)/configs/config.$(TARGET)

32
kernel/copy.c Normal file
View File

@@ -0,0 +1,32 @@
#include <aal/dma.h>
#include <amemcpy.h>
int memcpy_async(unsigned long dest, unsigned long src,
unsigned long len, int wait, unsigned long *notify)
{
struct aal_dma_request req;
unsigned long fin = 0;
if (notify)
*notify = 0;
memset(&req, 0, sizeof(req));
req.src_phys = src;
req.dest_phys = dest;
req.size = len;
if (notify) {
req.notify = (void *)virt_to_phys(notify);
req.priv = (void *)1;
} else if (wait) {
req.notify = (void *)virt_to_phys(&fin);
req.priv = (void *)1;
}
aal_mc_dma_request(0, &req);
if (wait) {
while (!fin) {
barrier();
}
}
return 0;
}

View File

@@ -36,6 +36,9 @@ int kprintf(const char *format, ...)
va_start(va, format);
flags = aal_mc_spinlock_lock(&kmsg_lock);
if (kmsg_buf.tail >= kmsg_buf.len - 1) {
kmsg_buf.tail = 0;
}
len = vsnprintf(kmsg_buf.str + kmsg_buf.tail,
kmsg_buf.len - kmsg_buf.tail, format, va);

View File

@@ -19,6 +19,7 @@ static void process_msg_prepare_process(unsigned long rphys)
struct program_load_desc *p, *pn;
int i, npages, n;
struct process *proc;
unsigned long addr;
sz = sizeof(struct program_load_desc)
+ sizeof(struct program_image_section) * 16;
@@ -38,6 +39,9 @@ static void process_msg_prepare_process(unsigned long rphys)
proc = create_process(p->entry);
proc->pid = p->pid;
/* TODO: Clear it at the proper timing */
cpu_local_var(scp).post_idx = 0;
for (i = 0; i < n; i++) {
s = (pn->sections[i].vaddr) & PAGE_MASK;
e = (pn->sections[i].vaddr + pn->sections[i].len
@@ -65,8 +69,25 @@ static void process_msg_prepare_process(unsigned long rphys)
}
proc->region.brk_start = proc->region.brk_end = proc->region.data_end;
proc->region.map_start = proc->region.map_end =
(USER_END / 3) & PAGE_MASK;
(USER_END / 3) & LARGE_PAGE_MASK;
/* Map system call stuffs */
addr = proc->region.map_start - PAGE_SIZE * SCD_RESERVED_COUNT;
e = addr + PAGE_SIZE * DOORBELL_PAGE_COUNT;
add_process_memory_range(proc, addr, e,
cpu_local_var(scp).doorbell_pa,
VR_REMOTE | VR_RESERVED);
addr = e;
e = addr + PAGE_SIZE * REQUEST_PAGE_COUNT;
add_process_memory_range(proc, addr, e,
cpu_local_var(scp).request_pa,
VR_REMOTE | VR_RESERVED);
addr = e;
e = addr + PAGE_SIZE * RESPONSE_PAGE_COUNT;
add_process_memory_range(proc, addr, e,
cpu_local_var(scp).response_pa,
VR_RESERVED);
p->rprocess = (unsigned long)proc;
init_process_stack(proc);
@@ -84,7 +105,7 @@ static void process_msg_init(struct ikc_scd_init_param *pcp)
struct syscall_params *lparam;
lparam = &cpu_local_var(scp);
lparam->response_va = allocate_pages(1, 0);
lparam->response_va = allocate_pages(RESPONSE_PAGE_COUNT, 0);
lparam->response_pa = virt_to_phys(lparam->response_va);
pcp->request_page = 0;
@@ -100,16 +121,27 @@ static void process_msg_init_acked(unsigned long pphys)
lparam = &cpu_local_var(scp);
lparam->request_rpa = param->request_page;
lparam->request_pa = aal_mc_map_memory(NULL, param->request_page,
PAGE_SIZE);
lparam->request_va = aal_mc_map_virtual(lparam->request_pa, 1,
REQUEST_PAGE_COUNT * PAGE_SIZE);
lparam->request_va = aal_mc_map_virtual(lparam->request_pa,
REQUEST_PAGE_COUNT,
PTATTR_WRITABLE);
lparam->doorbell_rpa = param->doorbell_page;
lparam->doorbell_pa = aal_mc_map_memory(NULL, param->doorbell_page,
DOORBELL_PAGE_COUNT *
PAGE_SIZE);
lparam->doorbell_va = aal_mc_map_virtual(lparam->doorbell_pa, 1,
lparam->doorbell_va = aal_mc_map_virtual(lparam->doorbell_pa,
DOORBELL_PAGE_COUNT,
PTATTR_WRITABLE);
lparam->post_rpa = param->post_page;
lparam->post_pa = aal_mc_map_memory(NULL, param->post_page,
PAGE_SIZE);
lparam->post_va = aal_mc_map_virtual(lparam->post_pa, 1,
PTATTR_WRITABLE);
lparam->post_fin = 1;
kprintf("Syscall parameters:\n");
kprintf(" Response: %lx, %p\n",
lparam->response_pa, lparam->response_va);
@@ -117,7 +149,8 @@ static void process_msg_init_acked(unsigned long pphys)
lparam->request_pa, lparam->request_rpa, lparam->request_va);
kprintf(" Doorbell: %lx, %lx, %p\n",
lparam->doorbell_pa, lparam->doorbell_rpa, lparam->doorbell_va);
kprintf(" Post: %lx, %lx, %p\n",
lparam->post_pa, lparam->post_rpa, lparam->post_va);
}
static void syscall_channel_send(struct aal_ikc_channel_desc *c,
@@ -150,6 +183,7 @@ static int syscall_packet_handler(struct aal_ikc_channel_desc *c,
case SCD_MSG_SCHEDULE_PROCESS:
kprintf("next one : %lx\n", packet->arg);
cpu_local_var(next) = (struct process *)packet->arg;
return 0;
}

16
kernel/include/amemcpy.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef HEADER_AMEMCPY_H
#define HEADER_AMEMCPY_H
#include <aal/cpu.h>
static void memcpy_async_wait(unsigned long *notify)
{
while (!*notify) {
cpu_pause();
}
}
int memcpy_async(unsigned long dest, unsigned long src,
unsigned long len, int wait, unsigned long *notify);
#endif

View File

@@ -6,7 +6,12 @@
#include <aal/mm.h>
#include <list.h>
#define VR_STACK 1
#define VR_STACK 0x1
#define VR_RESERVED 0x2
#define VR_IO_NOCACHE 0x100
#define VR_REMOTE 0x200
#define PS_ZOMBIE 0x1
struct vm_range {
struct list_head list;
@@ -37,6 +42,9 @@ struct process {
};
struct process *create_process(unsigned long user_pc);
void destroy_process(struct process *proc);
void free_process_memory(struct process *proc);
int add_process_memory_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long phys, unsigned long flag);

View File

@@ -3,6 +3,12 @@
#define NUM_SYSCALLS 255
#define REQUEST_PAGE_COUNT 16
#define RESPONSE_PAGE_COUNT 16
#define DOORBELL_PAGE_COUNT 1
#define SCD_RESERVED_COUNT \
(REQUEST_PAGE_COUNT + RESPONSE_PAGE_COUNT + DOORBELL_PAGE_COUNT)
#define SCD_MSG_PREPARE_PROCESS 0x1
#define SCD_MSG_PREPARE_PROCESS_ACKED 0x2
#define SCD_MSG_SCHEDULE_PROCESS 0x3
@@ -40,6 +46,7 @@ struct ikc_scd_init_param {
unsigned long request_page;
unsigned long response_page;
unsigned long doorbell_page;
unsigned long post_page;
};
struct syscall_request {
@@ -52,6 +59,10 @@ struct syscall_response {
long ret;
};
struct syscall_post {
unsigned long v[4];
};
struct syscall_params {
unsigned long request_rpa, request_pa;
struct syscall_request *request_va;
@@ -60,6 +71,12 @@ struct syscall_params {
unsigned long doorbell_rpa, doorbell_pa;
unsigned long *doorbell_va;
unsigned int post_idx;
unsigned long post_rpa, post_pa;
struct syscall_post *post_va;
unsigned long post_fin;
struct syscall_post post_buf;
};
#endif

View File

@@ -53,31 +53,49 @@ static void dma_test(void)
}
}
extern char *aal_mc_get_kernel_args(void);
char *find_command_line(char *name)
{
char *cmdline = aal_mc_get_kernel_args();
if (!cmdline) {
return NULL;
}
return strstr(cmdline, name);
}
static void pc_test(void)
{
int i;
int kmode = PERFCTR_USER_MODE;
int x[2][4] = { { APT_TYPE_L1D_MISS, APT_TYPE_L1I_MISS,
int kmode = PERFCTR_KERNEL_MODE;
int imode = 1;
char *p;
int x[2][4] = { { APT_TYPE_L1D_REQUEST,
APT_TYPE_L1D_MISS,
APT_TYPE_L2_MISS, APT_TYPE_INSTRUCTIONS, },
{ APT_TYPE_STALL, APT_TYPE_L1I_MISS,
APT_TYPE_L2_MISS, APT_TYPE_INSTRUCTIONS, }};
{ APT_TYPE_L1I_MISS, APT_TYPE_LLC_MISS,
APT_TYPE_STALL, APT_TYPE_CYCLE },
};
if (!(p = find_command_line("perfctr"))) {
kprintf("perfctr not initialized.\n");
return;
}
if (p[7] == '=' && p[8] >= '0' && p[8] <= '5') {
i = p[8] - '0';
kmode = (i >> 1) + 1;
imode = (i & 1);
} else {
kprintf("perfctr not initialized.\n");
return;
}
kprintf("perfctr mode : priv = %d, set = %d\n", kmode, imode);
for (i = 0; i < 4; i++) {
aal_mc_perfctr_init(i, x[1][i], kmode);
aal_mc_perfctr_init(i, x[imode][i], kmode);
}
aal_mc_perfctr_start(0xf);
/*
aal_mc_perfctr_read_mask(0x0f, st);
for (i = 0; i < 100000; i++) {
data[i & 1023] += i;
asm volatile("" : : : "memory");
}
aal_mc_perfctr_read_mask(0x0f, ed);
aal_mc_perfctr_stop(1);
kprintf("INS = %ld, %ld, %ld\n", st[0], ed[0], ed[0] - st[0]);
kprintf("L2M = %ld, %ld, %ld\n", st[1], ed[1], ed[1] - st[1]);
*/
}
static void rest_init(void)

View File

@@ -151,6 +151,8 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
struct cpu_local_var *v = get_this_cpu_local_var();
struct malloc_header *h = &v->free_list, *prev, *p;
int u, req_page;
unsigned long flags;
if (size >= PAGE_SIZE * 4) {
return NULL;
@@ -158,6 +160,8 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
u = (size + sizeof(*h) - 1) / sizeof(*h);
flags = cpu_disable_interrupt_save();
prev = h;
h = h->next;
@@ -172,12 +176,15 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
/* Guard entry */
p = h + h->size + 1;
p->next = &v->free_list;
p->size = 0;
h->next = p;
}
if (h->size >= u) {
if (h->size == u || h->size == u + 1) {
prev->next = h->next;
cpu_restore_interrupt(flags);
return h + 1;
} else { /* Divide */
h->size -= u + 1;
@@ -185,6 +192,7 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
p = h + h->size + 1;
p->size = u;
cpu_restore_interrupt(flags);
return p + 1;
}
}
@@ -198,7 +206,9 @@ void kfree(void *ptr)
struct cpu_local_var *v = get_this_cpu_local_var();
struct malloc_header *h = &v->free_list, *p = ptr;
int combined = 0;
unsigned long flags;
flags = cpu_disable_interrupt_save();
h = h->next;
p--;
@@ -212,14 +222,19 @@ void kfree(void *ptr)
h->size += p->size + 1;
}
if (h->next == p + p->size + 1 && h->next->size != 0) {
combined = 1;
h->size += h->next->size + 1;
h->next = h->next->next;
}
if (!combined) {
if (combined) {
h->size += h->next->size + 1;
h->next = h->next->next;
} else {
p->size += h->next->size + 1;
p->next = h->next->next;
h->next = p;
}
} else if (!combined) {
p->next = h->next;
h->next = p;
}
cpu_restore_interrupt(flags);
}
void print_free_list(void)

View File

@@ -23,14 +23,18 @@ struct process *create_process(unsigned long user_pc)
return proc;
}
void update_process_page_table(struct process *process, struct vm_range *range)
extern void __host_update_process_range(struct process *process,
struct vm_range *range);
void update_process_page_table(struct process *process, struct vm_range *range,
enum aal_mc_pt_attribute flag)
{
unsigned long p, pa = range->phys;
p = range->start;
while (p < range->end) {
aal_mc_pt_set_page(process->page_table, (void *)p,
pa, PTATTR_WRITABLE | PTATTR_USER);
pa, PTATTR_WRITABLE | PTATTR_USER | flag);
pa += PAGE_SIZE;
p += PAGE_SIZE;
@@ -57,7 +61,17 @@ int add_process_memory_range(struct process *process,
range->start, range->end, range->phys, range->phys +
range->end - range->start);
update_process_page_table(process, range);
if (flag & VR_REMOTE) {
update_process_page_table(process, range, AAL_PTA_REMOTE);
} else if (flag & VR_IO_NOCACHE) {
update_process_page_table(process, range, PTATTR_UNCACHABLE);
} else {
update_process_page_table(process, range, 0);
}
if (!(flag & VR_REMOTE)) {
__host_update_process_range(process, range);
}
list_add_tail(&range->list, &process->vm_range_list);
@@ -73,19 +87,23 @@ void init_process_stack(struct process *process)
add_process_memory_range(process, USER_END - PAGE_SIZE,
USER_END,
virt_to_phys(p), VR_STACK);
virt_to_phys(stack), VR_STACK);
/* TODO: fill with actual value of argc, argv, envp */
p[-1] = 0; /* env: "" */
p[-2] = 0x41; /* argv(0): "a" */
p[-3] = USER_END - sizeof(unsigned long); /* envp: END - 8 */
p[-4] = 0; /* argv[1] = NULL */
p[-5] = USER_END - sizeof(unsigned long) * 2; /* argv[0] = END - 16 */
p[-6] = 1; /* argc */
kprintf("%lx, %p\n", virt_to_phys(stack), p);
p[-1] = 0; /* AT_NULL */
p[-2] = 0;
p[-3] = USER_END - sizeof(unsigned long) * 2;
p[-4] = 0; /* env: "" */
p[-5] = 0x41; /* argv(0): "a" */
p[-6] = USER_END - sizeof(unsigned long) * 4; /* envp: END - 8 */
p[-7] = 0; /* argv[1] = NULL */
p[-8] = USER_END - sizeof(unsigned long) * 5; /* argv[0] = END - 16 */
p[-9] = 1; /* argc */
aal_mc_modify_user_context(process->uctx, AAL_UCR_STACK_POINTER,
USER_END - sizeof(unsigned long) * 6);
USER_END - sizeof(unsigned long) * 8);
process->region.stack_end = USER_END;
process->region.stack_start = USER_END - PAGE_SIZE;
}
@@ -128,6 +146,7 @@ int remove_process_region(struct process *proc,
return -EINVAL;
}
/* We defer freeing to the time of exit */
while (start < end) {
aal_mc_pt_clear_page(proc->page_table, (void *)start);
start += PAGE_SIZE;
@@ -136,6 +155,32 @@ int remove_process_region(struct process *proc,
return 0;
}
extern void print_free_list(void);
void free_process_memory(struct process *proc)
{
struct vm_range *range, *next;
list_for_each_entry_safe(range, next, &proc->vm_range_list,
list) {
if (!(range->flag & VR_REMOTE) &&
!(range->flag & VR_IO_NOCACHE) &&
!(range->flag & VR_RESERVED)) {
aal_mc_free_pages(phys_to_virt(range->phys),
(range->end - range->start)
>> PAGE_SHIFT);
}
list_del(&range->list);
aal_mc_free(range);
}
/* TODO: Free page tables */
proc->status = PS_ZOMBIE;
}
void destroy_process(struct process *proc)
{
aal_mc_free_pages(proc, 1);
}
static void idle(void)
{
while (1) {
@@ -175,7 +220,8 @@ void schedule(void)
cpu_enable_interrupt();
if (switch_ctx) {
kprintf("schedule: %p => %p \n", prev, next);
kprintf("schedule: %p (%p) => %p (%p) \n", prev,
prev->page_table, next, next->page_table);
aal_mc_load_page_table(next->page_table);
if (prev) {

View File

@@ -8,21 +8,36 @@
#include <cls.h>
#include <syscall.h>
#include <page.h>
#include <amemcpy.h>
int memcpy_async(unsigned long dest, unsigned long src,
unsigned long len, int wait, unsigned long *notify);
static void send_syscall(struct syscall_request *req)
{
struct ikc_scd_packet packet;
struct syscall_response *res = cpu_local_var(scp).response_va;
unsigned long fin;
res->status = 0;
/* TODO: copy by DMA */
memcpy_long(cpu_local_var(scp).request_va, req, sizeof(*req));
memcpy_async(cpu_local_var(scp).request_pa,
virt_to_phys(req), sizeof(*req), 0, &fin);
memcpy_async_wait(&cpu_local_var(scp).post_fin);
cpu_local_var(scp).post_va->v[0] = cpu_local_var(scp).post_idx;
memcpy_async_wait(&fin);
*(unsigned int *)cpu_local_var(scp).doorbell_va = 1;
#ifdef SYSCALL_BY_IKC
packet.msg = SCD_MSG_SYSCALL_ONESIDE;
packet.ref = aal_mc_get_processor_id();
packet.arg = cpu_local_var(scp).request_rpa;
aal_ikc_send(cpu_local_var(syscall_channel), &packet, 0);
aal_ikc_send(cpu_local_var(syscall_channel), &packet, 0);
#endif
}
static int do_syscall(struct syscall_request *req)
@@ -103,9 +118,7 @@ static int stop(void)
SYSCALL_DECLARE(open)
{
SYSCALL_HEADER;
SYSCALL_ARGS_3(MI, D, D);
SYSCALL_FOOTER;
}
@@ -169,10 +182,11 @@ SYSCALL_DECLARE(lseek)
SYSCALL_DECLARE(exit_group)
{
SYSCALL_HEADER;
send_syscall(&request);
do_syscall(&request);
cpu_local_var(current) = NULL;
free_process_memory(cpu_local_var(current));
cpu_local_var(next) = &cpu_local_var(idle);
schedule();
return 0;
@@ -308,3 +322,34 @@ long syscall(int num, aal_mc_user_context_t *ctx)
return -ENOSYS;
}
}
void __host_update_process_range(struct process *process,
struct vm_range *range)
{
struct syscall_post *post;
int idx;
memcpy_async_wait(&cpu_local_var(scp).post_fin);
post = &cpu_local_var(scp).post_buf;
post->v[0] = 1;
post->v[1] = range->start;
post->v[2] = range->end;
post->v[3] = range->phys;
cpu_disable_interrupt();
if (cpu_local_var(scp).post_idx >=
PAGE_SIZE / sizeof(struct syscall_post)) {
/* XXX: Wait until it is consumed */
} else {
idx = ++(cpu_local_var(scp).post_idx);
cpu_local_var(scp).post_fin = 0;
memcpy_async(cpu_local_var(scp).post_pa +
idx * sizeof(*post),
virt_to_phys(post), sizeof(*post), 0,
&cpu_local_var(scp).post_fin);
}
cpu_enable_interrupt();
}

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