big commit
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
DEST=$(O)/kboot
|
||||
OBJS=$(DEST)/main.o $(DEST)/data.o
|
||||
CFLAGS=-mno-sse -mno-mmx -mno-sse2 -mno-3dnow
|
||||
CFLAGS=-mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mcmodel=large
|
||||
|
||||
$(if $(O),,$(error Specify the target directory))
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
AALDIR=$(AALBASE)/$(TARGET)
|
||||
OBJS=init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o
|
||||
OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
|
||||
OBJS += process.o
|
||||
DEPSRCS=$(wildcard $(SRC)/*.c)
|
||||
|
||||
include $(SRC)/configs/config.$(TARGET)
|
||||
|
||||
@@ -47,6 +47,7 @@ void ap_init(void)
|
||||
|
||||
kprintf("BSP HW ID = %d, ", bsp_hw_id);
|
||||
kprintf("AP Booting :");
|
||||
|
||||
for (i = 0; i < cpu_info->ncpus; i++) {
|
||||
if (cpu_info->hw_ids[i] == bsp_hw_id) {
|
||||
continue;
|
||||
|
||||
184
kernel/host.c
Normal file
184
kernel/host.c
Normal file
@@ -0,0 +1,184 @@
|
||||
#include <types.h>
|
||||
#include <kmsg.h>
|
||||
#include <aal/cpu.h>
|
||||
#include <aal/mm.h>
|
||||
#include <aal/debug.h>
|
||||
#include <aal/ikc.h>
|
||||
#include <ikc/master.h>
|
||||
#include <syscall.h>
|
||||
#include <cls.h>
|
||||
#include <process.h>
|
||||
#include <page.h>
|
||||
|
||||
/*
|
||||
* Communication with host
|
||||
*/
|
||||
static void process_msg_prepare_process(unsigned long rphys)
|
||||
{
|
||||
unsigned long phys, sz, s, e, up;
|
||||
struct program_load_desc *p, *pn;
|
||||
int i, npages, n;
|
||||
struct process *proc;
|
||||
|
||||
sz = sizeof(struct program_load_desc)
|
||||
+ sizeof(struct program_image_section) * 16;
|
||||
npages = (sz + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
|
||||
phys = aal_mc_map_memory(NULL, rphys, sz);
|
||||
p = aal_mc_map_virtual(phys, npages, PTATTR_WRITABLE);
|
||||
|
||||
n = p->num_sections;
|
||||
kprintf("# of sections: %d\n", n);
|
||||
|
||||
pn = aal_mc_allocate(sizeof(struct program_load_desc)
|
||||
+ sizeof(struct program_image_section) * n, 0);
|
||||
memcpy_long(pn, p, sizeof(struct program_load_desc)
|
||||
+ sizeof(struct program_image_section) * n);
|
||||
|
||||
proc = create_process(p->entry);
|
||||
proc->pid = p->pid;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
s = (pn->sections[i].vaddr) & PAGE_MASK;
|
||||
e = (pn->sections[i].vaddr + pn->sections[i].len
|
||||
+ PAGE_SIZE - 1) & PAGE_MASK;
|
||||
up = virt_to_phys(aal_mc_alloc_pages((e - s) >> PAGE_SHIFT, 0));
|
||||
|
||||
add_process_memory_range(proc, s, e, up, 0);
|
||||
p->sections[i].remote_pa = up;
|
||||
|
||||
/* TODO: Maybe we need flag */
|
||||
if (i == 0) {
|
||||
proc->region.text_start = s;
|
||||
proc->region.text_end = e;
|
||||
} else if (i == 1) {
|
||||
proc->region.data_start = s;
|
||||
proc->region.data_end = e;
|
||||
} else {
|
||||
proc->region.data_start =
|
||||
(s < proc->region.data_start ?
|
||||
s : proc->region.data_start);
|
||||
proc->region.data_end =
|
||||
(e > proc->region.data_end ?
|
||||
e : proc->region.data_end);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
p->rprocess = (unsigned long)proc;
|
||||
init_process_stack(proc);
|
||||
|
||||
kprintf("new process : %p [%d] / table : %p\n", proc, proc->pid,
|
||||
proc->page_table);
|
||||
|
||||
aal_mc_free(pn);
|
||||
|
||||
aal_mc_unmap_virtual(p, npages);
|
||||
aal_mc_unmap_memory(NULL, phys, sz);
|
||||
}
|
||||
|
||||
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_pa = virt_to_phys(lparam->response_va);
|
||||
|
||||
pcp->request_page = 0;
|
||||
pcp->doorbell_page = 0;
|
||||
pcp->response_page = lparam->response_pa;
|
||||
}
|
||||
|
||||
static void process_msg_init_acked(unsigned long pphys)
|
||||
{
|
||||
struct ikc_scd_init_param *param = (void *)pphys;
|
||||
struct syscall_params *lparam;
|
||||
|
||||
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,
|
||||
PTATTR_WRITABLE);
|
||||
|
||||
lparam->doorbell_rpa = param->doorbell_page;
|
||||
lparam->doorbell_pa = aal_mc_map_memory(NULL, param->doorbell_page,
|
||||
PAGE_SIZE);
|
||||
lparam->doorbell_va = aal_mc_map_virtual(lparam->doorbell_pa, 1,
|
||||
PTATTR_WRITABLE);
|
||||
|
||||
kprintf("Syscall parameters:\n");
|
||||
kprintf(" Response: %lx, %p\n",
|
||||
lparam->response_pa, lparam->response_va);
|
||||
kprintf(" Request : %lx, %lx, %p\n",
|
||||
lparam->request_pa, lparam->request_rpa, lparam->request_va);
|
||||
kprintf(" Doorbell: %lx, %lx, %p\n",
|
||||
lparam->doorbell_pa, lparam->doorbell_rpa, lparam->doorbell_va);
|
||||
|
||||
}
|
||||
|
||||
static void syscall_channel_send(struct aal_ikc_channel_desc *c,
|
||||
struct ikc_scd_packet *packet)
|
||||
{
|
||||
aal_ikc_send(c, packet, 0);
|
||||
}
|
||||
|
||||
static int syscall_packet_handler(struct aal_ikc_channel_desc *c,
|
||||
void *__packet, void *aal_os)
|
||||
{
|
||||
struct ikc_scd_packet *packet = __packet;
|
||||
struct ikc_scd_packet pckt;
|
||||
|
||||
switch (packet->msg) {
|
||||
case SCD_MSG_INIT_CHANNEL_ACKED:
|
||||
kprintf("init channel acked!\n");
|
||||
process_msg_init_acked(packet->arg);
|
||||
return 0;
|
||||
|
||||
case SCD_MSG_PREPARE_PROCESS:
|
||||
process_msg_prepare_process(packet->arg);
|
||||
|
||||
pckt.msg = SCD_MSG_PREPARE_PROCESS_ACKED;
|
||||
pckt.ref = packet->ref;
|
||||
pckt.arg = packet->arg;
|
||||
syscall_channel_send(c, &pckt);
|
||||
|
||||
return 0;
|
||||
|
||||
case SCD_MSG_SCHEDULE_PROCESS:
|
||||
kprintf("next one : %lx\n", packet->arg);
|
||||
cpu_local_var(next) = (struct process *)packet->arg;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_host_syscall_channel(void)
|
||||
{
|
||||
struct aal_ikc_connect_param param;
|
||||
struct ikc_scd_packet pckt;
|
||||
|
||||
param.port = 501;
|
||||
param.pkt_size = sizeof(struct ikc_scd_packet);
|
||||
param.queue_size = PAGE_SIZE;
|
||||
param.magic = 0x1129;
|
||||
param.handler = syscall_packet_handler;
|
||||
|
||||
kprintf("(syscall) Trying to connect host ...");
|
||||
while (aal_ikc_connect(NULL, ¶m) != 0) {
|
||||
kprintf(".");
|
||||
aal_mc_delay_us(1000 * 1000);
|
||||
}
|
||||
kprintf("connected.\n");
|
||||
|
||||
get_this_cpu_local_var()->syscall_channel = param.channel;
|
||||
|
||||
process_msg_init(&cpu_local_var(iip));
|
||||
pckt.msg = SCD_MSG_INIT_CHANNEL;
|
||||
pckt.ref = aal_mc_get_processor_id();
|
||||
pckt.arg = virt_to_phys(&cpu_local_var(iip));
|
||||
syscall_channel_send(param.channel, &pckt);
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
#ifndef __HEADER_CLS_H
|
||||
#define __HEADER_CLS_H
|
||||
|
||||
#include <process.h>
|
||||
#include <syscall.h>
|
||||
/*
|
||||
* CPU Local Storage (cls)
|
||||
*/
|
||||
@@ -12,7 +15,16 @@ struct malloc_header {
|
||||
struct cpu_local_var {
|
||||
/* malloc */
|
||||
struct malloc_header free_list;
|
||||
/* Align to 64-byte */
|
||||
|
||||
struct process idle;
|
||||
|
||||
struct process *current;
|
||||
struct process *next;
|
||||
|
||||
struct aal_ikc_channel_desc *syscall_channel;
|
||||
|
||||
struct syscall_params scp;
|
||||
struct ikc_scd_init_param iip;
|
||||
} __attribute__((aligned(64)));
|
||||
|
||||
|
||||
|
||||
52
kernel/include/process.h
Normal file
52
kernel/include/process.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef HEADER_PROCESS_H
|
||||
#define HEADER_PROCESS_H
|
||||
|
||||
#include <aal/context.h>
|
||||
#include <aal/cpu.h>
|
||||
#include <aal/mm.h>
|
||||
#include <list.h>
|
||||
|
||||
#define VR_STACK 1
|
||||
|
||||
struct vm_range {
|
||||
struct list_head list;
|
||||
unsigned long start, end;
|
||||
unsigned long phys;
|
||||
unsigned long flag;
|
||||
};
|
||||
|
||||
struct vm_regions {
|
||||
unsigned long text_start, text_end;
|
||||
unsigned long data_start, data_end;
|
||||
unsigned long brk_start, brk_end;
|
||||
unsigned long map_start, map_end;
|
||||
unsigned long stack_start, stack_end;
|
||||
};
|
||||
|
||||
struct process {
|
||||
int pid;
|
||||
int status;
|
||||
|
||||
struct page_table *page_table;
|
||||
struct list_head vm_range_list;
|
||||
|
||||
struct vm_regions region;
|
||||
|
||||
aal_mc_kernel_context_t ctx;
|
||||
aal_mc_user_context_t *uctx;
|
||||
};
|
||||
|
||||
struct process *create_process(unsigned long user_pc);
|
||||
int add_process_memory_range(struct process *process,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long phys, unsigned long flag);
|
||||
int remove_process_region(struct process *proc,
|
||||
unsigned long start, unsigned long end);
|
||||
void init_process_stack(struct process *process);
|
||||
unsigned long extend_process_region(struct process *proc,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long address);
|
||||
|
||||
void schedule(void);
|
||||
|
||||
#endif
|
||||
65
kernel/include/syscall.h
Normal file
65
kernel/include/syscall.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef __HEADER_SYSCALL_H
|
||||
#define __HEADER_SYSCALL_H
|
||||
|
||||
#define NUM_SYSCALLS 255
|
||||
|
||||
#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
|
||||
|
||||
struct ikc_scd_packet {
|
||||
int msg;
|
||||
int ref;
|
||||
unsigned long arg;
|
||||
};
|
||||
|
||||
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;
|
||||
struct program_image_section sections[0];
|
||||
};
|
||||
|
||||
struct ikc_scd_init_param {
|
||||
unsigned long request_page;
|
||||
unsigned long response_page;
|
||||
unsigned long doorbell_page;
|
||||
};
|
||||
|
||||
struct syscall_request {
|
||||
unsigned long number;
|
||||
unsigned long args[5];
|
||||
};
|
||||
|
||||
struct syscall_response {
|
||||
unsigned long status;
|
||||
long ret;
|
||||
};
|
||||
|
||||
struct syscall_params {
|
||||
unsigned long request_rpa, request_pa;
|
||||
struct syscall_request *request_va;
|
||||
unsigned long response_pa;
|
||||
struct syscall_response *response_va;
|
||||
|
||||
unsigned long doorbell_rpa, doorbell_pa;
|
||||
unsigned long *doorbell_va;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <aal/cpu.h>
|
||||
#include <aal/mm.h>
|
||||
#include <aal/debug.h>
|
||||
#include <aal/dma.h>
|
||||
#include <aal/perfctr.h>
|
||||
#include <process.h>
|
||||
#include <cls.h>
|
||||
|
||||
extern struct aal_kmsg_buf kmsg_buf;
|
||||
@@ -18,36 +21,98 @@ extern void mc_ikc_init(void);
|
||||
extern void cpu_local_var_init(void);
|
||||
extern void kmalloc_init(void);
|
||||
extern void ap_start(void);
|
||||
extern void aal_mc_dma_init(void);
|
||||
extern void init_host_syscall_channel(void);
|
||||
extern void sched_init(void);
|
||||
|
||||
static aal_mc_kernel_context_t idle_ctx;
|
||||
|
||||
static void idle(void)
|
||||
{
|
||||
while (1) {
|
||||
cpu_enable_interrupt();
|
||||
cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
extern int syscall(int, aal_mc_user_context_t *);
|
||||
extern long syscall(int, aal_mc_user_context_t *);
|
||||
|
||||
static void handler_init(void)
|
||||
{
|
||||
aal_mc_set_syscall_handler(syscall);
|
||||
}
|
||||
|
||||
unsigned long data[1024] __attribute__((aligned(64)));
|
||||
|
||||
static void dma_test(void)
|
||||
{
|
||||
struct aal_dma_request req;
|
||||
unsigned long fin = 0;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.src_phys = virt_to_phys(data);
|
||||
req.dest_phys = virt_to_phys(data + 256);
|
||||
req.size = 64;
|
||||
req.notify = (void *)virt_to_phys(&fin);
|
||||
req.priv = (void *)0x2984;
|
||||
|
||||
aal_mc_dma_request(0, &req);
|
||||
|
||||
while (!fin) {
|
||||
barrier();
|
||||
}
|
||||
}
|
||||
|
||||
static void pc_test(void)
|
||||
{
|
||||
int i;
|
||||
int kmode = PERFCTR_USER_MODE;
|
||||
int x[2][4] = { { APT_TYPE_L1D_MISS, APT_TYPE_L1I_MISS,
|
||||
APT_TYPE_L2_MISS, APT_TYPE_INSTRUCTIONS, },
|
||||
{ APT_TYPE_STALL, APT_TYPE_L1I_MISS,
|
||||
APT_TYPE_L2_MISS, APT_TYPE_INSTRUCTIONS, }};
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
aal_mc_perfctr_init(i, x[1][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)
|
||||
{
|
||||
handler_init();
|
||||
|
||||
aal_mc_dma_init();
|
||||
dma_test();
|
||||
pc_test();
|
||||
|
||||
ap_init();
|
||||
cpu_local_var_init();
|
||||
kmalloc_init();
|
||||
|
||||
ikc_master_init();
|
||||
mc_ikc_init();
|
||||
|
||||
sched_init();
|
||||
ap_start();
|
||||
}
|
||||
|
||||
int host_ikc_inited = 0;
|
||||
|
||||
static void post_init(void)
|
||||
{
|
||||
cpu_enable_interrupt();
|
||||
|
||||
while (!host_ikc_inited) {
|
||||
barrier();
|
||||
cpu_pause();
|
||||
}
|
||||
|
||||
init_host_syscall_channel();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
kmsg_init();
|
||||
@@ -58,16 +123,15 @@ int main(void)
|
||||
|
||||
mem_init();
|
||||
|
||||
ikc_master_init();
|
||||
|
||||
rest_init();
|
||||
|
||||
arch_ready();
|
||||
|
||||
post_init();
|
||||
|
||||
kputs("MCK/AAL booted.\n");
|
||||
|
||||
aal_mc_init_context(&idle_ctx, NULL, idle);
|
||||
aal_mc_switch_context(NULL, &idle_ctx);
|
||||
schedule();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ static int test_packet_handler(struct aal_ikc_channel_desc *c,
|
||||
{
|
||||
struct ikc_test_packet *packet = __packet;
|
||||
struct ikc_test_packet p;
|
||||
int i;
|
||||
unsigned long a, pp, *v;
|
||||
|
||||
if (packet->msg == 0x11110011) {
|
||||
@@ -56,7 +57,9 @@ static int test_packet_handler(struct aal_ikc_channel_desc *c,
|
||||
aal_mc_unmap_memory(NULL, pp, 4 * 1024 * 1024);
|
||||
} else if (packet->msg == 0x11110012) {
|
||||
p.msg = 0x11110013;
|
||||
aal_ikc_send(c, &p, 0);
|
||||
for (i = 0; i < 10; i++) {
|
||||
aal_ikc_send(c, &p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -100,7 +100,10 @@ void *aal_mc_map_virtual(unsigned long phys, int npages,
|
||||
enum aal_mc_pt_attribute attr)
|
||||
{
|
||||
void *p;
|
||||
unsigned long i;
|
||||
unsigned long i, offset;
|
||||
|
||||
offset = (phys & (PAGE_SIZE - 1));
|
||||
phys = phys & PAGE_MASK;
|
||||
|
||||
p = (void *)aal_pagealloc_alloc(vmap_allocator, npages);
|
||||
if (!p) {
|
||||
@@ -110,13 +113,14 @@ void *aal_mc_map_virtual(unsigned long phys, int npages,
|
||||
aal_mc_pt_set_page(NULL, (char *)p + (i << PAGE_SHIFT),
|
||||
phys + (i << PAGE_SHIFT), attr);
|
||||
}
|
||||
return p;
|
||||
return (char *)p + offset;
|
||||
}
|
||||
|
||||
void aal_mc_unmap_virtual(void *va, int npages)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
va = (void *)((unsigned long)va & PAGE_MASK);
|
||||
for (i = 0; i < npages; i++) {
|
||||
aal_mc_pt_clear_page(NULL, (char *)va + (i << PAGE_SHIFT));
|
||||
}
|
||||
|
||||
189
kernel/process.c
Normal file
189
kernel/process.c
Normal file
@@ -0,0 +1,189 @@
|
||||
#include <process.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <kmalloc.h>
|
||||
#include <cls.h>
|
||||
#include <aal/debug.h>
|
||||
#include <page.h>
|
||||
|
||||
struct process *create_process(unsigned long user_pc)
|
||||
{
|
||||
struct process *proc;
|
||||
|
||||
proc = aal_mc_alloc_pages(1, 0);
|
||||
|
||||
memset(proc, 0, sizeof(struct process));
|
||||
|
||||
aal_mc_init_user_process(&proc->ctx, &proc->uctx,
|
||||
((char *)proc) + PAGE_SIZE, user_pc, 0);
|
||||
|
||||
INIT_LIST_HEAD(&proc->vm_range_list);
|
||||
proc->page_table = aal_mc_pt_create();
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
void update_process_page_table(struct process *process, struct vm_range *range)
|
||||
{
|
||||
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 += PAGE_SIZE;
|
||||
p += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int add_process_memory_range(struct process *process,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long phys, unsigned long flag)
|
||||
{
|
||||
struct vm_range *range;
|
||||
|
||||
range = kmalloc(sizeof(struct vm_range), 0);
|
||||
if (!range) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_LIST_HEAD(&range->list);
|
||||
range->start = start;
|
||||
range->end = end;
|
||||
range->phys = phys;
|
||||
range->flag = flag;
|
||||
|
||||
kprintf("range: %lx - %lx => %lx - %lx\n",
|
||||
range->start, range->end, range->phys, range->phys +
|
||||
range->end - range->start);
|
||||
|
||||
update_process_page_table(process, range);
|
||||
|
||||
list_add_tail(&range->list, &process->vm_range_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_process_stack(struct process *process)
|
||||
{
|
||||
char *stack = aal_mc_alloc_pages(1, 0);
|
||||
unsigned long *p = (unsigned long *)(stack + PAGE_SIZE);
|
||||
|
||||
memset(stack, 0, PAGE_SIZE);
|
||||
|
||||
add_process_memory_range(process, USER_END - PAGE_SIZE,
|
||||
USER_END,
|
||||
virt_to_phys(p), 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 */
|
||||
|
||||
aal_mc_modify_user_context(process->uctx, AAL_UCR_STACK_POINTER,
|
||||
USER_END - sizeof(unsigned long) * 6);
|
||||
process->region.stack_end = USER_END;
|
||||
process->region.stack_start = USER_END - PAGE_SIZE;
|
||||
}
|
||||
|
||||
|
||||
unsigned long extend_process_region(struct process *proc,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long aligned_end, aligned_new_end;
|
||||
void *p;
|
||||
|
||||
if (!address || address < start || address >= USER_END) {
|
||||
return end;
|
||||
}
|
||||
|
||||
aligned_end = ((end + PAGE_SIZE - 1) & PAGE_MASK);
|
||||
|
||||
if (aligned_end >= address) {
|
||||
return address;
|
||||
}
|
||||
|
||||
aligned_new_end = (address + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
p = allocate_pages((aligned_new_end - aligned_end) >> PAGE_SHIFT,
|
||||
0);
|
||||
if (!p) {
|
||||
return end;
|
||||
}
|
||||
|
||||
add_process_memory_range(proc, aligned_end, aligned_new_end,
|
||||
virt_to_phys(p), 0);
|
||||
return address;
|
||||
}
|
||||
|
||||
int remove_process_region(struct process *proc,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
if ((start & (PAGE_SIZE - 1)) || (end & (PAGE_SIZE - 1))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (start < end) {
|
||||
aal_mc_pt_clear_page(proc->page_table, (void *)start);
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void idle(void)
|
||||
{
|
||||
while (1) {
|
||||
cpu_enable_interrupt();
|
||||
schedule();
|
||||
cpu_halt();
|
||||
}
|
||||
}
|
||||
|
||||
void sched_init(void)
|
||||
{
|
||||
struct process *idle_process = &cpu_local_var(idle);
|
||||
|
||||
memset(idle_process, 0, sizeof(struct process));
|
||||
|
||||
aal_mc_init_context(&idle_process->ctx, NULL, idle);
|
||||
|
||||
cpu_local_var(next) = idle_process;
|
||||
}
|
||||
|
||||
void schedule(void)
|
||||
{
|
||||
struct cpu_local_var *v = get_this_cpu_local_var();
|
||||
struct process *next, *prev;
|
||||
int switch_ctx = 0;
|
||||
|
||||
cpu_disable_interrupt();
|
||||
if (v->next && v->next != v->current) {
|
||||
prev = v->current;
|
||||
next = v->next;
|
||||
|
||||
switch_ctx = 1;
|
||||
|
||||
v->current = next;
|
||||
v->next = NULL;
|
||||
}
|
||||
cpu_enable_interrupt();
|
||||
|
||||
if (switch_ctx) {
|
||||
kprintf("schedule: %p => %p \n", prev, next);
|
||||
aal_mc_load_page_table(next->page_table);
|
||||
|
||||
if (prev) {
|
||||
aal_mc_switch_context(&prev->ctx, &next->ctx);
|
||||
} else {
|
||||
aal_mc_switch_context(NULL, &next->ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ set -e
|
||||
O=`pwd`
|
||||
|
||||
make -C $3/../kboot O=$O clean
|
||||
make -C $3/../kboot O=$O KIMAGE="$O/$1" LOAD_PA=0x3a001000
|
||||
#make -C $3/../kboot O=$O KIMAGE="$O/$1" LOAD_PA=0x3a001000
|
||||
#make -C $3/../kboot O=$O KIMAGE="$O/$1" LOAD_PA=0x101001000
|
||||
make -C $3/../kboot O=$O KIMAGE="$O/$1" LOAD_PA=0x901001000
|
||||
|
||||
cat $3/../elfboot/elfboot kboot/kboot.elf > $2
|
||||
|
||||
303
kernel/syscall.c
303
kernel/syscall.c
@@ -3,11 +3,308 @@
|
||||
#include <aal/cpu.h>
|
||||
#include <aal/mm.h>
|
||||
#include <aal/debug.h>
|
||||
#include <aal/ikc.h>
|
||||
#include <errno.h>
|
||||
#include <cls.h>
|
||||
#include <syscall.h>
|
||||
#include <page.h>
|
||||
|
||||
int syscall(int num, aal_mc_user_context_t *ctx)
|
||||
static void send_syscall(struct syscall_request *req)
|
||||
{
|
||||
kprintf("System call #%d\n", num);
|
||||
struct ikc_scd_packet packet;
|
||||
struct syscall_response *res = cpu_local_var(scp).response_va;
|
||||
|
||||
return -ENOSYS;
|
||||
res->status = 0;
|
||||
/* TODO: copy by DMA */
|
||||
memcpy_long(cpu_local_var(scp).request_va, req, sizeof(*req));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int do_syscall(struct syscall_request *req)
|
||||
{
|
||||
struct syscall_response *res = cpu_local_var(scp).response_va;
|
||||
|
||||
send_syscall(req);
|
||||
|
||||
while (!res->status) {
|
||||
cpu_pause();
|
||||
}
|
||||
|
||||
return res->ret;
|
||||
}
|
||||
|
||||
long sys_brk(int n, aal_mc_user_context_t *ctx)
|
||||
{
|
||||
unsigned long address = aal_mc_syscall_arg0(ctx);
|
||||
struct vm_regions *region = &cpu_local_var(current)->region;
|
||||
|
||||
region->brk_end =
|
||||
extend_process_region(cpu_local_var(current),
|
||||
region->brk_start, region->brk_end,
|
||||
address);
|
||||
return region->brk_end;
|
||||
|
||||
}
|
||||
|
||||
#define SYSCALL_DECLARE(name) long sys_##name(int n, aal_mc_user_context_t *ctx)
|
||||
#define SYSCALL_HEADER struct syscall_request request; \
|
||||
request.number = n
|
||||
#define SYSCALL_ARG_D(n) request.args[n] = aal_mc_syscall_arg##n(ctx)
|
||||
#define SYSCALL_ARG_MO(n) \
|
||||
do { \
|
||||
unsigned long __phys; \
|
||||
if (aal_mc_pt_virt_to_phys(cpu_local_var(current)->page_table, \
|
||||
(void *)aal_mc_syscall_arg##n(ctx),\
|
||||
&__phys)) { \
|
||||
return -EFAULT; \
|
||||
}\
|
||||
request.args[n] = __phys; \
|
||||
} while(0)
|
||||
#define SYSCALL_ARG_MI(n) \
|
||||
do { \
|
||||
unsigned long __phys; \
|
||||
if (aal_mc_pt_virt_to_phys(cpu_local_var(current)->page_table, \
|
||||
(void *)aal_mc_syscall_arg##n(ctx),\
|
||||
&__phys)) { \
|
||||
return -EFAULT; \
|
||||
}\
|
||||
request.args[n] = __phys; \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define SYSCALL_ARGS_1(a0) SYSCALL_ARG_##a0(0)
|
||||
#define SYSCALL_ARGS_2(a0, a1) SYSCALL_ARG_##a0(0); SYSCALL_ARG_##a1(1)
|
||||
#define SYSCALL_ARGS_3(a0, a1, a2) SYSCALL_ARG_##a0(0); SYSCALL_ARG_##a1(1); \
|
||||
SYSCALL_ARG_##a2(2)
|
||||
#define SYSCALL_ARGS_4(a0, a1, a2, a3) \
|
||||
SYSCALL_ARG_##a0(0); SYSCALL_ARG_##a1(1); \
|
||||
SYSCALL_ARG_##a2(2); SYSCALL_ARG_##a3(3)
|
||||
|
||||
#define SYSCALL_FOOTER return do_syscall(&request)
|
||||
|
||||
SYSCALL_DECLARE(fstat)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_2(D, MO);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
static int stop(void)
|
||||
{
|
||||
while(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(open)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
|
||||
SYSCALL_ARGS_3(MI, D, D);
|
||||
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(ioctl)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
|
||||
/* Very ad-hoc for termios */
|
||||
switch(aal_mc_syscall_arg1(ctx)) {
|
||||
case 0x5401:
|
||||
SYSCALL_ARGS_3(D, D, MO);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(read)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_3(D, MO, D);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(pread)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_4(D, MO, D, D);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(write)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_3(D, MI, D);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(pwrite)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_4(D, MI, D, D);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(close)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_1(D);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(lseek)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
SYSCALL_ARGS_3(D, D, D);
|
||||
SYSCALL_FOOTER;
|
||||
}
|
||||
|
||||
|
||||
SYSCALL_DECLARE(exit_group)
|
||||
{
|
||||
SYSCALL_HEADER;
|
||||
send_syscall(&request);
|
||||
|
||||
cpu_local_var(current) = NULL;
|
||||
cpu_local_var(next) = &cpu_local_var(idle);
|
||||
schedule();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(mmap)
|
||||
{
|
||||
unsigned long address, ret;
|
||||
struct vm_regions *region = &cpu_local_var(current)->region;
|
||||
|
||||
/* anonymous */
|
||||
if (aal_mc_syscall_arg3(ctx) & 0x22) {
|
||||
ret = region->map_end;
|
||||
address = region->map_end + aal_mc_syscall_arg1(ctx);
|
||||
|
||||
region->map_end =
|
||||
extend_process_region(cpu_local_var(current),
|
||||
region->map_start,
|
||||
region->map_end,
|
||||
address);
|
||||
if (region->map_end == address) {
|
||||
return ret;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
kprintf("Non-anonymous mmap: fd = %lx, %lx\n",
|
||||
aal_mc_syscall_arg4(ctx), aal_mc_syscall_arg5(ctx));
|
||||
while(1);
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(munmap)
|
||||
{
|
||||
unsigned long address, len;
|
||||
|
||||
address = aal_mc_syscall_arg0(ctx);
|
||||
len = aal_mc_syscall_arg1(ctx);
|
||||
|
||||
return remove_process_region(cpu_local_var(current), address,
|
||||
address + len);
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(getpid)
|
||||
{
|
||||
return cpu_local_var(current)->pid;
|
||||
}
|
||||
|
||||
long sys_uname(int n, aal_mc_user_context_t *ctx)
|
||||
{
|
||||
struct syscall_request request;
|
||||
unsigned long phys;
|
||||
|
||||
if (aal_mc_pt_virt_to_phys(cpu_local_var(current)->page_table,
|
||||
(void *)aal_mc_syscall_arg0(ctx), &phys)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
request.number = n;
|
||||
request.args[0] = phys;
|
||||
|
||||
return do_syscall(&request);
|
||||
}
|
||||
|
||||
long sys_getxid(int n, aal_mc_user_context_t *ctx)
|
||||
{
|
||||
struct syscall_request request;
|
||||
|
||||
request.number = n;
|
||||
|
||||
return do_syscall(&request);
|
||||
}
|
||||
|
||||
long sys_arch_prctl(int n, aal_mc_user_context_t *ctx)
|
||||
{
|
||||
unsigned long code = aal_mc_syscall_arg0(ctx);
|
||||
unsigned long address = aal_mc_syscall_arg1(ctx);
|
||||
|
||||
switch (code) {
|
||||
case 0x1002:
|
||||
return aal_mc_arch_set_special_register(AAL_ASR_X86_FS,
|
||||
address);
|
||||
|
||||
case 0x1003:
|
||||
return aal_mc_arch_get_special_register(AAL_ASR_X86_FS,
|
||||
(unsigned long *)
|
||||
address);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static long (*syscall_table[])(int, aal_mc_user_context_t *) = {
|
||||
[0] = sys_read,
|
||||
[1] = sys_write,
|
||||
[2] = sys_open,
|
||||
[3] = sys_close,
|
||||
[5] = sys_fstat,
|
||||
[8] = sys_lseek,
|
||||
[9] = sys_mmap,
|
||||
[11] = sys_munmap,
|
||||
[12] = sys_brk,
|
||||
[16] = sys_ioctl,
|
||||
[17] = sys_pread,
|
||||
[18] = sys_pwrite,
|
||||
[39] = sys_getpid,
|
||||
[63] = sys_uname,
|
||||
[102] = sys_getxid,
|
||||
[104] = sys_getxid,
|
||||
[107] = sys_getxid,
|
||||
[108] = sys_getxid,
|
||||
[110] = sys_getxid,
|
||||
[111] = sys_getxid,
|
||||
[158] = sys_arch_prctl,
|
||||
[231] = sys_exit_group,
|
||||
};
|
||||
|
||||
long syscall(int num, aal_mc_user_context_t *ctx)
|
||||
{
|
||||
long l;
|
||||
|
||||
cpu_enable_interrupt();
|
||||
|
||||
if (syscall_table[num]) {
|
||||
l = syscall_table[num](num, ctx);
|
||||
return l;
|
||||
} else {
|
||||
kprintf("USC[%3d](%lx, %lx, %lx, %lx, %lx) @ %lx | %lx\n", num,
|
||||
aal_mc_syscall_arg0(ctx), aal_mc_syscall_arg1(ctx),
|
||||
aal_mc_syscall_arg2(ctx), aal_mc_syscall_arg3(ctx),
|
||||
aal_mc_syscall_arg4(ctx), aal_mc_syscall_pc(ctx),
|
||||
aal_mc_syscall_sp(ctx));
|
||||
while(1);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
6
linux/executer/Makefile
Normal file
6
linux/executer/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
CFLAGS = -O3
|
||||
|
||||
all: mcexec
|
||||
|
||||
mcexec: mcexec.c
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
418
linux/executer/mcexec.c
Normal file
418
linux/executer/mcexec.c
Normal file
@@ -0,0 +1,418 @@
|
||||
#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>
|
||||
|
||||
#ifndef DEBUG
|
||||
#define __dprint(msg, ...)
|
||||
#define __dprintf(arg, ...)
|
||||
#define __eprint(msg, ...)
|
||||
#define __eprinf(format, ...)
|
||||
#else
|
||||
#define __dprint(msg, ...) printf("%s: " msg, __FUNCTION__)
|
||||
#define __dprintf(format, ...) printf("%s: " format, __FUNCTION__, \
|
||||
__VA_ARGS__)
|
||||
#define __eprint(msg, ...) fprintf(stderr, "%s: " msg, __FUNCTION__)
|
||||
#define __eprintf(format, ...) fprintf(stderr, "%s: " format, __FUNCTION__, \
|
||||
__VA_ARGS__)
|
||||
#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);
|
||||
|
||||
struct program_load_desc *load_elf(FILE *fp)
|
||||
{
|
||||
Elf64_Ehdr hdr;
|
||||
Elf64_Phdr phdr;
|
||||
int i, j, nhdrs = 0;
|
||||
struct program_load_desc *desc;
|
||||
|
||||
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: %lx, %lx, %lx, %lx\n",
|
||||
j, desc->sections[j].vaddr,
|
||||
desc->sections[j].filesz,
|
||||
desc->sections[j].offset,
|
||||
desc->sections[j].len);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
desc->pid = getpid();
|
||||
desc->entry = hdr.e_entry;
|
||||
|
||||
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 %lx\n",
|
||||
desc->sections[i].offset, flen);
|
||||
|
||||
while (s < e) {
|
||||
pt.dest = rpa;
|
||||
pt.src = dma_buf;
|
||||
pt.sz = PAGE_SIZE;
|
||||
|
||||
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;
|
||||
|
||||
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("%lx, %lx, %lx\n", desc->sections[i].vaddr,
|
||||
desc->sections[i].len, desc->sections[i].remote_pa);
|
||||
}
|
||||
}
|
||||
|
||||
#define PIN_SHIFT 16
|
||||
#define PIN_SIZE (1 << PIN_SHIFT)
|
||||
#define PIN_MASK ~(unsigned long)(PIN_SIZE - 1)
|
||||
|
||||
unsigned long dma_buf_pa;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, fdm;
|
||||
FILE *fp;
|
||||
struct program_load_desc *desc;
|
||||
long r;
|
||||
|
||||
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);
|
||||
|
||||
fd = open("/dev/mcos0", O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error: Failed to open /dev/mcctrl.\n");
|
||||
return 1;
|
||||
}
|
||||
fdm = open("/dev/mem", O_RDWR);
|
||||
if (fdm < 0) {
|
||||
fprintf(stderr, "Error: Failed to open /dev/mem.\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);
|
||||
|
||||
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);
|
||||
|
||||
if (ioctl(fd, MCEXEC_UP_START_IMAGE, (unsigned long)desc) != 0) {
|
||||
perror("exec");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return main_loop(fd, desc->cpu);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
int main_loop(int fd, int cpu)
|
||||
{
|
||||
struct syscall_wait_desc w;
|
||||
int ret;
|
||||
|
||||
w.cpu = cpu;
|
||||
|
||||
while (ioctl(fd, MCEXEC_UP_WAIT_SYSCALL, (unsigned long)&w) == 0) {
|
||||
switch (w.sr.number) {
|
||||
case __NR_open:
|
||||
dma_buf[256] = 0;
|
||||
do_syscall_load(fd, cpu, dma_buf_pa, w.sr.args[0], 256);
|
||||
|
||||
while (!dma_buf[256]) {
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
ret = open(dma_buf, w.sr.args[1], w.sr.args[2]);
|
||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case __NR_close:
|
||||
ret = close(w.sr.args[0]);
|
||||
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]);
|
||||
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;
|
||||
do_syscall_load(fd, cpu, dma_buf_pa,
|
||||
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, dma_buf_pa,
|
||||
w.sr.args[1], w.sr.args[2]);
|
||||
break;
|
||||
|
||||
case __NR_pwrite64:
|
||||
dma_buf[w.sr.args[2]] = 0;
|
||||
do_syscall_load(fd, cpu, dma_buf_pa,
|
||||
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_fstat:
|
||||
ret = fstat(w.sr.args[0], (void *)dma_buf);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
do_syscall_return(fd, cpu, ret, 1, dma_buf_pa,
|
||||
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, dma_buf_pa,
|
||||
w.sr.args[2],
|
||||
sizeof(struct kernel_termios)
|
||||
);
|
||||
}
|
||||
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_exit:
|
||||
case __NR_exit_group:
|
||||
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, dma_buf_pa, w.sr.args[0],
|
||||
sizeof(struct utsname));
|
||||
break;
|
||||
default:
|
||||
printf("Unhandled system calls: %ld\n", w.sr.number);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
67
linux/include/uprotocol.h
Normal file
67
linux/include/uprotocol.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#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
|
||||
|
||||
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;
|
||||
struct program_image_section sections[0];
|
||||
};
|
||||
|
||||
struct syscall_request {
|
||||
unsigned long number;
|
||||
unsigned long args[5];
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@ endif
|
||||
|
||||
obj-m += mcctrl.o
|
||||
|
||||
mcctrl-objs := driver.o control.o
|
||||
mcctrl-objs := driver.o control.o ikc.o
|
||||
|
||||
AAL_BASE=$(src)/../../../aal
|
||||
EXTRA_CFLAGS = -I$(AAL_BASE)/host/include -I$(AAL_BASE)/ikc/include -I$(src)/../include
|
||||
|
||||
@@ -1,51 +1,279 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/delay.h>
|
||||
#include "mcctrl.h"
|
||||
|
||||
static struct aal_ikc_listen_param __listen_param = {
|
||||
.port = 501,
|
||||
.handler = test_handler,
|
||||
.pkt_size = sizeof(struct ikc_test_packet),
|
||||
.queue_size = 4096,
|
||||
.magic = 0x29,
|
||||
};
|
||||
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(struct mcctrl_priv *data,
|
||||
static long mcexec_prepare_image(aal_os_t os,
|
||||
struct program_load_desc * __user udesc)
|
||||
{
|
||||
struct program_load_desc desc;
|
||||
struct program_load_desc desc, *pdesc;
|
||||
struct ikc_scd_packet isp;
|
||||
|
||||
if (!copy_from_user(&desc, udesc,
|
||||
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;
|
||||
}
|
||||
data->desc = kmalloc(sizeof(struct program_load_desc) +
|
||||
sizeof(struct program_image_section)
|
||||
* desc.num_sections, GFP_KERNEL);
|
||||
memcpy(data->desc, &desc, sizeof(struct program_load_desc));
|
||||
if (!copy_from_user(data->desc->sections, udesc->sections,
|
||||
sizeof(struct program_image_section)
|
||||
* desc.num_sections)) {
|
||||
kfree(data->desc);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
copy_to_user(udesc, pdesc, sizeof(struct program_load_desc) +
|
||||
sizeof(struct program_image_section) * desc.num_sections);
|
||||
|
||||
kfree(pdesc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mcexec_load_image(aal_os_t os, struct program_transfer *__user upt)
|
||||
{
|
||||
struct program_transfer pt;
|
||||
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;
|
||||
}
|
||||
|
||||
if (copy_from_user(&pt, upt, sizeof(pt))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (copy_from_user(&desc, udesc,
|
||||
sizeof(struct program_load_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
mcctrl_ikc_set_recv_cpu(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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long __mcctrl_control(struct mcctrl_priv *data, unsigned int req,
|
||||
unsigned long arg)
|
||||
long mcexec_pin_region(aal_os_t os, unsigned long *__user uaddress)
|
||||
{
|
||||
int pin_shift = 16;
|
||||
unsigned long a;
|
||||
|
||||
a = __get_free_pages(GFP_KERNEL, pin_shift - PAGE_SHIFT);
|
||||
if (!a) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
a = virt_to_phys((void *)a);
|
||||
|
||||
if (copy_to_user(uaddress, &a, sizeof(unsigned long))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_load_syscall(aal_os_t os, struct syscall_load_desc *__user arg)
|
||||
{
|
||||
struct syscall_load_desc desc;
|
||||
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;
|
||||
}
|
||||
|
||||
if (copy_from_user(&desc, arg, sizeof(struct syscall_load_desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
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 *)(desc.dest + desc.size);
|
||||
request.priv = (void *)1;
|
||||
|
||||
aal_dma_request(channel, &request);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_ret_syscall(aal_os_t os, struct syscall_ret_desc *__user arg)
|
||||
{
|
||||
struct syscall_ret_desc ret;
|
||||
aal_dma_channel_t channel;
|
||||
struct aal_dma_request request;
|
||||
struct mcctrl_channel *mc;
|
||||
|
||||
channel = aal_device_get_dma_channel(aal_os_to_dev(os), 0);
|
||||
if (!channel) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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) {
|
||||
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 = (void *)mc->param.response_pa;
|
||||
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((struct mcctrl_priv *)data,
|
||||
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);
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,63 +9,51 @@
|
||||
#include <linux/slab.h>
|
||||
#include "mcctrl.h"
|
||||
|
||||
extern long __mcctrl_control(struct mcctrl_priv *, unsigned int, unsigned long);
|
||||
extern long __mcctrl_control(aal_os_t, unsigned int, unsigned long);
|
||||
extern int prepare_ikc_channels(aal_os_t os);
|
||||
|
||||
static int mcctrl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct mcctrl_priv *mcc_data;
|
||||
|
||||
mcc_data = kzalloc(sizeof(struct mcctrl_priv), GFP_KERNEL);
|
||||
if (!mcc_data) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
file->private_data = mcc_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcctrl_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct mcctrl_priv *mcc_data = file->private_data;
|
||||
|
||||
if (mcc_data) {
|
||||
if (mcc_data->desc) {
|
||||
kfree(mcc_data->desc);
|
||||
}
|
||||
kfree(mcc_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long mcctrl_ioctl(struct file *file, unsigned int request,
|
||||
static long mcctrl_ioctl(aal_os_t os, unsigned int request, void *priv,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct mcctrl_priv *mcc_data = file->private_data;
|
||||
|
||||
return __mcctrl_control(mcc_data, request, arg);
|
||||
return __mcctrl_control(os, request, arg);
|
||||
}
|
||||
|
||||
static struct file_operations mcctrl_ops = {
|
||||
.open = mcctrl_open,
|
||||
.unlocked_ioctl = mcctrl_ioctl,
|
||||
.release = mcctrl_release,
|
||||
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 },
|
||||
};
|
||||
|
||||
static struct miscdevice mcctrl_dev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mcctrl",
|
||||
.fops = &mcctrl_ops,
|
||||
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)
|
||||
{
|
||||
return misc_register(&mcctrl_dev);
|
||||
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)
|
||||
{
|
||||
misc_deregister(&mcctrl_dev);
|
||||
aal_os_unregister_user_call_handlers(os, &mcctrl_uc);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
153
linux/mod_mcctrl/ikc.c
Normal file
153
linux/mod_mcctrl/ikc.c
Normal file
@@ -0,0 +1,153 @@
|
||||
#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>
|
||||
|
||||
static 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_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
phys = aal_device_map_memory(aal_os_to_dev(os), 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_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.response_rpa = rpm->response_page;
|
||||
pmc->param.response_pa
|
||||
= aal_device_map_memory(aal_os_to_dev(os),
|
||||
pmc->param.response_rpa,
|
||||
PAGE_SIZE);
|
||||
pmc->param.response_va = ioremap_wc(pmc->param.response_pa,
|
||||
PAGE_SIZE);
|
||||
|
||||
rpm->request_page = pmc->param.request_pa;
|
||||
rpm->doorbell_page = pmc->param.doorbell_pa;
|
||||
|
||||
packet.msg = SCD_MSG_INIT_CHANNEL_ACKED;
|
||||
packet.ref = cpu;
|
||||
packet.arg = rphys;
|
||||
|
||||
aal_ikc_send(pmc->c, &packet, 0);
|
||||
|
||||
iounmap(rpm);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -3,10 +3,53 @@
|
||||
|
||||
#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
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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 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;
|
||||
|
||||
int req;
|
||||
wait_queue_head_t wq_syscall;
|
||||
};
|
||||
|
||||
int mcctrl_ikc_send(int cpu, struct ikc_scd_packet *pisp);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user