a commit
This commit is contained in:
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,3 +1,16 @@
|
|||||||
*.o
|
*.o
|
||||||
*.elf
|
*.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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
AALDIR=$(AALBASE)/$(TARGET)
|
AALDIR=$(AALBASE)/$(TARGET)
|
||||||
OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
|
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)
|
DEPSRCS=$(wildcard $(SRC)/*.c)
|
||||||
|
|
||||||
include $(SRC)/configs/config.$(TARGET)
|
include $(SRC)/configs/config.$(TARGET)
|
||||||
|
|||||||
32
kernel/copy.c
Normal file
32
kernel/copy.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -36,6 +36,9 @@ int kprintf(const char *format, ...)
|
|||||||
va_start(va, format);
|
va_start(va, format);
|
||||||
|
|
||||||
flags = aal_mc_spinlock_lock(&kmsg_lock);
|
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,
|
len = vsnprintf(kmsg_buf.str + kmsg_buf.tail,
|
||||||
kmsg_buf.len - kmsg_buf.tail, format, va);
|
kmsg_buf.len - kmsg_buf.tail, format, va);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ static void process_msg_prepare_process(unsigned long rphys)
|
|||||||
struct program_load_desc *p, *pn;
|
struct program_load_desc *p, *pn;
|
||||||
int i, npages, n;
|
int i, npages, n;
|
||||||
struct process *proc;
|
struct process *proc;
|
||||||
|
unsigned long addr;
|
||||||
|
|
||||||
sz = sizeof(struct program_load_desc)
|
sz = sizeof(struct program_load_desc)
|
||||||
+ sizeof(struct program_image_section) * 16;
|
+ 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 = create_process(p->entry);
|
||||||
proc->pid = p->pid;
|
proc->pid = p->pid;
|
||||||
|
|
||||||
|
/* TODO: Clear it at the proper timing */
|
||||||
|
cpu_local_var(scp).post_idx = 0;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
s = (pn->sections[i].vaddr) & PAGE_MASK;
|
s = (pn->sections[i].vaddr) & PAGE_MASK;
|
||||||
e = (pn->sections[i].vaddr + pn->sections[i].len
|
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.brk_start = proc->region.brk_end = proc->region.data_end;
|
||||||
proc->region.map_start = proc->region.map_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;
|
p->rprocess = (unsigned long)proc;
|
||||||
init_process_stack(proc);
|
init_process_stack(proc);
|
||||||
|
|
||||||
@@ -84,7 +105,7 @@ static void process_msg_init(struct ikc_scd_init_param *pcp)
|
|||||||
struct syscall_params *lparam;
|
struct syscall_params *lparam;
|
||||||
|
|
||||||
lparam = &cpu_local_var(scp);
|
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);
|
lparam->response_pa = virt_to_phys(lparam->response_va);
|
||||||
|
|
||||||
pcp->request_page = 0;
|
pcp->request_page = 0;
|
||||||
@@ -100,16 +121,27 @@ static void process_msg_init_acked(unsigned long pphys)
|
|||||||
lparam = &cpu_local_var(scp);
|
lparam = &cpu_local_var(scp);
|
||||||
lparam->request_rpa = param->request_page;
|
lparam->request_rpa = param->request_page;
|
||||||
lparam->request_pa = aal_mc_map_memory(NULL, param->request_page,
|
lparam->request_pa = aal_mc_map_memory(NULL, param->request_page,
|
||||||
PAGE_SIZE);
|
REQUEST_PAGE_COUNT * PAGE_SIZE);
|
||||||
lparam->request_va = aal_mc_map_virtual(lparam->request_pa, 1,
|
lparam->request_va = aal_mc_map_virtual(lparam->request_pa,
|
||||||
|
REQUEST_PAGE_COUNT,
|
||||||
PTATTR_WRITABLE);
|
PTATTR_WRITABLE);
|
||||||
|
|
||||||
lparam->doorbell_rpa = param->doorbell_page;
|
lparam->doorbell_rpa = param->doorbell_page;
|
||||||
lparam->doorbell_pa = aal_mc_map_memory(NULL, param->doorbell_page,
|
lparam->doorbell_pa = aal_mc_map_memory(NULL, param->doorbell_page,
|
||||||
|
DOORBELL_PAGE_COUNT *
|
||||||
PAGE_SIZE);
|
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);
|
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("Syscall parameters:\n");
|
||||||
kprintf(" Response: %lx, %p\n",
|
kprintf(" Response: %lx, %p\n",
|
||||||
lparam->response_pa, lparam->response_va);
|
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);
|
lparam->request_pa, lparam->request_rpa, lparam->request_va);
|
||||||
kprintf(" Doorbell: %lx, %lx, %p\n",
|
kprintf(" Doorbell: %lx, %lx, %p\n",
|
||||||
lparam->doorbell_pa, lparam->doorbell_rpa, lparam->doorbell_va);
|
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,
|
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:
|
case SCD_MSG_SCHEDULE_PROCESS:
|
||||||
kprintf("next one : %lx\n", packet->arg);
|
kprintf("next one : %lx\n", packet->arg);
|
||||||
|
|
||||||
cpu_local_var(next) = (struct process *)packet->arg;
|
cpu_local_var(next) = (struct process *)packet->arg;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
16
kernel/include/amemcpy.h
Normal file
16
kernel/include/amemcpy.h
Normal 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
|
||||||
@@ -6,7 +6,12 @@
|
|||||||
#include <aal/mm.h>
|
#include <aal/mm.h>
|
||||||
#include <list.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 vm_range {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -37,6 +42,9 @@ struct process {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct process *create_process(unsigned long user_pc);
|
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,
|
int add_process_memory_range(struct process *process,
|
||||||
unsigned long start, unsigned long end,
|
unsigned long start, unsigned long end,
|
||||||
unsigned long phys, unsigned long flag);
|
unsigned long phys, unsigned long flag);
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
#define NUM_SYSCALLS 255
|
#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 0x1
|
||||||
#define SCD_MSG_PREPARE_PROCESS_ACKED 0x2
|
#define SCD_MSG_PREPARE_PROCESS_ACKED 0x2
|
||||||
#define SCD_MSG_SCHEDULE_PROCESS 0x3
|
#define SCD_MSG_SCHEDULE_PROCESS 0x3
|
||||||
@@ -40,6 +46,7 @@ struct ikc_scd_init_param {
|
|||||||
unsigned long request_page;
|
unsigned long request_page;
|
||||||
unsigned long response_page;
|
unsigned long response_page;
|
||||||
unsigned long doorbell_page;
|
unsigned long doorbell_page;
|
||||||
|
unsigned long post_page;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct syscall_request {
|
struct syscall_request {
|
||||||
@@ -52,6 +59,10 @@ struct syscall_response {
|
|||||||
long ret;
|
long ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct syscall_post {
|
||||||
|
unsigned long v[4];
|
||||||
|
};
|
||||||
|
|
||||||
struct syscall_params {
|
struct syscall_params {
|
||||||
unsigned long request_rpa, request_pa;
|
unsigned long request_rpa, request_pa;
|
||||||
struct syscall_request *request_va;
|
struct syscall_request *request_va;
|
||||||
@@ -60,6 +71,12 @@ struct syscall_params {
|
|||||||
|
|
||||||
unsigned long doorbell_rpa, doorbell_pa;
|
unsigned long doorbell_rpa, doorbell_pa;
|
||||||
unsigned long *doorbell_va;
|
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
|
#endif
|
||||||
|
|||||||
@@ -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)
|
static void pc_test(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int kmode = PERFCTR_USER_MODE;
|
int kmode = PERFCTR_KERNEL_MODE;
|
||||||
int x[2][4] = { { APT_TYPE_L1D_MISS, APT_TYPE_L1I_MISS,
|
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_L2_MISS, APT_TYPE_INSTRUCTIONS, },
|
||||||
{ APT_TYPE_STALL, APT_TYPE_L1I_MISS,
|
{ APT_TYPE_L1I_MISS, APT_TYPE_LLC_MISS,
|
||||||
APT_TYPE_L2_MISS, APT_TYPE_INSTRUCTIONS, }};
|
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++) {
|
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_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)
|
static void rest_init(void)
|
||||||
|
|||||||
27
kernel/mem.c
27
kernel/mem.c
@@ -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 cpu_local_var *v = get_this_cpu_local_var();
|
||||||
struct malloc_header *h = &v->free_list, *prev, *p;
|
struct malloc_header *h = &v->free_list, *prev, *p;
|
||||||
int u, req_page;
|
int u, req_page;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
|
||||||
if (size >= PAGE_SIZE * 4) {
|
if (size >= PAGE_SIZE * 4) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -158,6 +160,8 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
|
|||||||
|
|
||||||
u = (size + sizeof(*h) - 1) / sizeof(*h);
|
u = (size + sizeof(*h) - 1) / sizeof(*h);
|
||||||
|
|
||||||
|
flags = cpu_disable_interrupt_save();
|
||||||
|
|
||||||
prev = h;
|
prev = h;
|
||||||
h = h->next;
|
h = h->next;
|
||||||
|
|
||||||
@@ -172,12 +176,15 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
|
|||||||
/* Guard entry */
|
/* Guard entry */
|
||||||
p = h + h->size + 1;
|
p = h + h->size + 1;
|
||||||
p->next = &v->free_list;
|
p->next = &v->free_list;
|
||||||
|
p->size = 0;
|
||||||
h->next = p;
|
h->next = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->size >= u) {
|
if (h->size >= u) {
|
||||||
if (h->size == u || h->size == u + 1) {
|
if (h->size == u || h->size == u + 1) {
|
||||||
prev->next = h->next;
|
prev->next = h->next;
|
||||||
|
|
||||||
|
cpu_restore_interrupt(flags);
|
||||||
return h + 1;
|
return h + 1;
|
||||||
} else { /* Divide */
|
} else { /* Divide */
|
||||||
h->size -= u + 1;
|
h->size -= u + 1;
|
||||||
@@ -185,6 +192,7 @@ void *kmalloc(int size, enum aal_mc_ap_flag flag)
|
|||||||
p = h + h->size + 1;
|
p = h + h->size + 1;
|
||||||
p->size = u;
|
p->size = u;
|
||||||
|
|
||||||
|
cpu_restore_interrupt(flags);
|
||||||
return p + 1;
|
return p + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +206,9 @@ void kfree(void *ptr)
|
|||||||
struct cpu_local_var *v = get_this_cpu_local_var();
|
struct cpu_local_var *v = get_this_cpu_local_var();
|
||||||
struct malloc_header *h = &v->free_list, *p = ptr;
|
struct malloc_header *h = &v->free_list, *p = ptr;
|
||||||
int combined = 0;
|
int combined = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
flags = cpu_disable_interrupt_save();
|
||||||
h = h->next;
|
h = h->next;
|
||||||
|
|
||||||
p--;
|
p--;
|
||||||
@@ -212,14 +222,19 @@ void kfree(void *ptr)
|
|||||||
h->size += p->size + 1;
|
h->size += p->size + 1;
|
||||||
}
|
}
|
||||||
if (h->next == p + p->size + 1 && h->next->size != 0) {
|
if (h->next == p + p->size + 1 && h->next->size != 0) {
|
||||||
combined = 1;
|
if (combined) {
|
||||||
h->size += h->next->size + 1;
|
h->size += h->next->size + 1;
|
||||||
h->next = h->next->next;
|
h->next = h->next->next;
|
||||||
}
|
} else {
|
||||||
if (!combined) {
|
p->size += h->next->size + 1;
|
||||||
|
p->next = h->next->next;
|
||||||
|
h->next = p;
|
||||||
|
}
|
||||||
|
} else if (!combined) {
|
||||||
p->next = h->next;
|
p->next = h->next;
|
||||||
h->next = p;
|
h->next = p;
|
||||||
}
|
}
|
||||||
|
cpu_restore_interrupt(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_free_list(void)
|
void print_free_list(void)
|
||||||
|
|||||||
@@ -23,14 +23,18 @@ struct process *create_process(unsigned long user_pc)
|
|||||||
return proc;
|
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;
|
unsigned long p, pa = range->phys;
|
||||||
|
|
||||||
p = range->start;
|
p = range->start;
|
||||||
while (p < range->end) {
|
while (p < range->end) {
|
||||||
aal_mc_pt_set_page(process->page_table, (void *)p,
|
aal_mc_pt_set_page(process->page_table, (void *)p,
|
||||||
pa, PTATTR_WRITABLE | PTATTR_USER);
|
pa, PTATTR_WRITABLE | PTATTR_USER | flag);
|
||||||
|
|
||||||
pa += PAGE_SIZE;
|
pa += PAGE_SIZE;
|
||||||
p += 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->start, range->end, range->phys, range->phys +
|
||||||
range->end - range->start);
|
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);
|
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,
|
add_process_memory_range(process, USER_END - PAGE_SIZE,
|
||||||
USER_END,
|
USER_END,
|
||||||
virt_to_phys(p), VR_STACK);
|
virt_to_phys(stack), VR_STACK);
|
||||||
|
|
||||||
/* TODO: fill with actual value of argc, argv, envp */
|
/* TODO: fill with actual value of argc, argv, envp */
|
||||||
|
kprintf("%lx, %p\n", virt_to_phys(stack), p);
|
||||||
p[-1] = 0; /* env: "" */
|
|
||||||
p[-2] = 0x41; /* argv(0): "a" */
|
p[-1] = 0; /* AT_NULL */
|
||||||
p[-3] = USER_END - sizeof(unsigned long); /* envp: END - 8 */
|
p[-2] = 0;
|
||||||
p[-4] = 0; /* argv[1] = NULL */
|
p[-3] = USER_END - sizeof(unsigned long) * 2;
|
||||||
p[-5] = USER_END - sizeof(unsigned long) * 2; /* argv[0] = END - 16 */
|
p[-4] = 0; /* env: "" */
|
||||||
p[-6] = 1; /* argc */
|
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,
|
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_end = USER_END;
|
||||||
process->region.stack_start = USER_END - PAGE_SIZE;
|
process->region.stack_start = USER_END - PAGE_SIZE;
|
||||||
}
|
}
|
||||||
@@ -128,6 +146,7 @@ int remove_process_region(struct process *proc,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We defer freeing to the time of exit */
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
aal_mc_pt_clear_page(proc->page_table, (void *)start);
|
aal_mc_pt_clear_page(proc->page_table, (void *)start);
|
||||||
start += PAGE_SIZE;
|
start += PAGE_SIZE;
|
||||||
@@ -136,6 +155,32 @@ int remove_process_region(struct process *proc,
|
|||||||
return 0;
|
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)
|
static void idle(void)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -175,7 +220,8 @@ void schedule(void)
|
|||||||
cpu_enable_interrupt();
|
cpu_enable_interrupt();
|
||||||
|
|
||||||
if (switch_ctx) {
|
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);
|
aal_mc_load_page_table(next->page_table);
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
|
|||||||
@@ -8,21 +8,36 @@
|
|||||||
#include <cls.h>
|
#include <cls.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
#include <page.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)
|
static void send_syscall(struct syscall_request *req)
|
||||||
{
|
{
|
||||||
struct ikc_scd_packet packet;
|
struct ikc_scd_packet packet;
|
||||||
struct syscall_response *res = cpu_local_var(scp).response_va;
|
struct syscall_response *res = cpu_local_var(scp).response_va;
|
||||||
|
unsigned long fin;
|
||||||
|
|
||||||
res->status = 0;
|
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.msg = SCD_MSG_SYSCALL_ONESIDE;
|
||||||
packet.ref = aal_mc_get_processor_id();
|
packet.ref = aal_mc_get_processor_id();
|
||||||
packet.arg = cpu_local_var(scp).request_rpa;
|
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)
|
static int do_syscall(struct syscall_request *req)
|
||||||
@@ -103,9 +118,7 @@ static int stop(void)
|
|||||||
SYSCALL_DECLARE(open)
|
SYSCALL_DECLARE(open)
|
||||||
{
|
{
|
||||||
SYSCALL_HEADER;
|
SYSCALL_HEADER;
|
||||||
|
|
||||||
SYSCALL_ARGS_3(MI, D, D);
|
SYSCALL_ARGS_3(MI, D, D);
|
||||||
|
|
||||||
SYSCALL_FOOTER;
|
SYSCALL_FOOTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,10 +182,11 @@ SYSCALL_DECLARE(lseek)
|
|||||||
SYSCALL_DECLARE(exit_group)
|
SYSCALL_DECLARE(exit_group)
|
||||||
{
|
{
|
||||||
SYSCALL_HEADER;
|
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);
|
cpu_local_var(next) = &cpu_local_var(idle);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -308,3 +322,34 @@ long syscall(int num, aal_mc_user_context_t *ctx)
|
|||||||
return -ENOSYS;
|
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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
int main_loop(int fd, int cpu)
|
||||||
{
|
{
|
||||||
struct syscall_wait_desc w;
|
struct syscall_wait_desc w;
|
||||||
@@ -306,22 +308,26 @@ int main_loop(int fd, int cpu)
|
|||||||
asm volatile ("" : : : "memory");
|
asm volatile ("" : : : "memory");
|
||||||
}
|
}
|
||||||
ret = open(dma_buf, w.sr.args[1], w.sr.args[2]);
|
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);
|
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case __NR_close:
|
case __NR_close:
|
||||||
ret = close(w.sr.args[0]);
|
ret = close(w.sr.args[0]);
|
||||||
|
SET_ERR(ret);
|
||||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case __NR_read:
|
case __NR_read:
|
||||||
ret = read(w.sr.args[0], dma_buf, w.sr.args[2]);
|
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,
|
do_syscall_return(fd, cpu, ret, 1, dma_buf_pa,
|
||||||
w.sr.args[1], w.sr.args[2]);
|
w.sr.args[1], w.sr.args[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case __NR_write:
|
case __NR_write:
|
||||||
dma_buf[w.sr.args[2]] = 0;
|
dma_buf[w.sr.args[2]] = 0;
|
||||||
|
SET_ERR(ret);
|
||||||
do_syscall_load(fd, cpu, dma_buf_pa,
|
do_syscall_load(fd, cpu, dma_buf_pa,
|
||||||
w.sr.args[1], w.sr.args[2]);
|
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:
|
||||||
case __NR_exit_group:
|
case __NR_exit_group:
|
||||||
|
do_syscall_return(fd, cpu, 0, 0, 0, 0, 0);
|
||||||
return w.sr.args[0];
|
return w.sr.args[0];
|
||||||
|
|
||||||
case __NR_uname:
|
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
|
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
|
AAL_BASE=$(src)/../../../aal
|
||||||
EXTRA_CFLAGS = -I$(AAL_BASE)/host/include -I$(AAL_BASE)/ikc/include -I$(src)/../include
|
EXTRA_CFLAGS = -I$(AAL_BASE)/host/include -I$(AAL_BASE)/ikc/include -I$(src)/../include
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/delay.h>
|
#include <asm/delay.h>
|
||||||
|
#include <asm/msr.h>
|
||||||
#include "mcctrl.h"
|
#include "mcctrl.h"
|
||||||
|
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(wq_prepare);
|
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 program_load_desc desc;
|
||||||
struct ikc_scd_packet isp;
|
struct ikc_scd_packet isp;
|
||||||
|
struct mcctrl_channel *c;
|
||||||
|
|
||||||
if (copy_from_user(&desc, udesc,
|
if (copy_from_user(&desc, udesc,
|
||||||
sizeof(struct program_load_desc))) {
|
sizeof(struct program_load_desc))) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = channels + desc.cpu;
|
||||||
|
|
||||||
mcctrl_ikc_set_recv_cpu(desc.cpu);
|
mcctrl_ikc_set_recv_cpu(desc.cpu);
|
||||||
|
|
||||||
isp.msg = SCD_MSG_SCHEDULE_PROCESS;
|
isp.msg = SCD_MSG_SCHEDULE_PROCESS;
|
||||||
@@ -131,25 +135,48 @@ int mcexec_syscall(struct mcctrl_channel *c, unsigned long arg)
|
|||||||
return 0;
|
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)
|
int mcexec_wait_syscall(aal_os_t os, struct syscall_wait_desc *__user req)
|
||||||
{
|
{
|
||||||
struct syscall_wait_desc swd;
|
struct syscall_wait_desc swd;
|
||||||
struct mcctrl_channel *c;
|
struct mcctrl_channel *c;
|
||||||
|
unsigned long s, w;
|
||||||
|
|
||||||
if (copy_from_user(&swd, req, sizeof(swd.cpu))) {
|
if (copy_from_user(&swd, req, sizeof(swd.cpu))) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = channels + swd.cpu;
|
c = channels + swd.cpu;
|
||||||
|
|
||||||
|
#ifdef DO_USER_MODE
|
||||||
wait_event_interruptible(c->wq_syscall, c->req);
|
wait_event_interruptible(c->wq_syscall, c->req);
|
||||||
c->req = 0;
|
c->req = 0;
|
||||||
|
#else
|
||||||
if (copy_to_user(&req->sr, c->param.request_va,
|
while (1) {
|
||||||
sizeof(struct syscall_request))) {
|
rdtscll(s);
|
||||||
return -EFAULT;
|
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;
|
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));
|
sizeof(struct ikc_scd_init_param));
|
||||||
rpm = ioremap_wc(phys, 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.request_pa = virt_to_phys(pmc->param.request_va);
|
||||||
pmc->param.doorbell_va = (void *)__get_free_page(GFP_KERNEL);
|
pmc->param.doorbell_va = (void *)__get_free_page(GFP_KERNEL);
|
||||||
pmc->param.doorbell_pa = virt_to_phys(pmc->param.doorbell_va);
|
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_rpa = rpm->response_page;
|
||||||
pmc->param.response_pa
|
pmc->param.response_pa
|
||||||
= aal_device_map_memory(aal_os_to_dev(os),
|
= 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,
|
pmc->param.response_va = ioremap_wc(pmc->param.response_pa,
|
||||||
PAGE_SIZE);
|
PAGE_SIZE);
|
||||||
|
|
||||||
|
pmc->dma_buf = (void *)__get_free_pages(GFP_KERNEL,
|
||||||
|
DMA_PIN_SHIFT - PAGE_SHIFT);
|
||||||
|
|
||||||
rpm->request_page = pmc->param.request_pa;
|
rpm->request_page = pmc->param.request_pa;
|
||||||
rpm->doorbell_page = pmc->param.doorbell_pa;
|
rpm->doorbell_page = pmc->param.doorbell_pa;
|
||||||
|
rpm->post_page = pmc->param.post_pa;
|
||||||
|
|
||||||
packet.msg = SCD_MSG_INIT_CHANNEL_ACKED;
|
packet.msg = SCD_MSG_INIT_CHANNEL_ACKED;
|
||||||
packet.ref = cpu;
|
packet.ref = cpu;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#define SCD_MSG_SYSCALL_ONESIDE 0x4
|
#define SCD_MSG_SYSCALL_ONESIDE 0x4
|
||||||
|
|
||||||
|
#define DMA_PIN_SHIFT 16
|
||||||
|
|
||||||
struct ikc_scd_packet {
|
struct ikc_scd_packet {
|
||||||
int msg;
|
int msg;
|
||||||
int ref;
|
int ref;
|
||||||
@@ -29,6 +31,11 @@ struct ikc_scd_init_param {
|
|||||||
unsigned long request_page;
|
unsigned long request_page;
|
||||||
unsigned long response_page;
|
unsigned long response_page;
|
||||||
unsigned long doorbell_page;
|
unsigned long doorbell_page;
|
||||||
|
unsigned long post_page;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct syscall_post {
|
||||||
|
unsigned long v[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct syscall_params {
|
struct syscall_params {
|
||||||
@@ -36,7 +43,9 @@ struct syscall_params {
|
|||||||
struct syscall_request *request_va;
|
struct syscall_request *request_va;
|
||||||
unsigned long response_rpa, response_pa;
|
unsigned long response_rpa, response_pa;
|
||||||
struct syscall_response *response_va;
|
struct syscall_response *response_va;
|
||||||
|
unsigned long post_pa;
|
||||||
|
struct syscall_post *post_va;
|
||||||
|
|
||||||
unsigned long doorbell_pa;
|
unsigned long doorbell_pa;
|
||||||
unsigned long *doorbell_va;
|
unsigned long *doorbell_va;
|
||||||
};
|
};
|
||||||
@@ -45,6 +54,7 @@ struct mcctrl_channel {
|
|||||||
struct aal_ikc_channel_desc *c;
|
struct aal_ikc_channel_desc *c;
|
||||||
struct syscall_params param;
|
struct syscall_params param;
|
||||||
struct ikc_scd_init_param init;
|
struct ikc_scd_init_param init;
|
||||||
|
void *dma_buf;
|
||||||
|
|
||||||
int req;
|
int req;
|
||||||
wait_queue_head_t wq_syscall;
|
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