Integrate libdyld and libunwind.

It is currently possible to run the idle experiment, and it
can raise and catch exceptions, but exceptions are not yet
propagated across RPC boundaries.
This commit is contained in:
whitequark 2015-08-02 06:41:05 +03:00
parent 6db93b34e8
commit 62fdc75d2d
23 changed files with 433 additions and 732 deletions

View File

@ -16,7 +16,7 @@ class _H2DMsgType(Enum):
IDENT_REQUEST = 2 IDENT_REQUEST = 2
SWITCH_CLOCK = 3 SWITCH_CLOCK = 3
LOAD_OBJECT = 4 LOAD_LIBRARY = 4
RUN_KERNEL = 5 RUN_KERNEL = 5
RPC_REPLY = 6 RPC_REPLY = 6
@ -124,7 +124,7 @@ class CommGeneric:
raise IOError("Incorrect reply from device: {}".format(ty)) raise IOError("Incorrect reply from device: {}".format(ty))
def load(self, kcode): def load(self, kcode):
self._write_header(len(kcode) + 9, _H2DMsgType.LOAD_OBJECT) self._write_header(len(kcode) + 9, _H2DMsgType.LOAD_LIBRARY)
self.write(kcode) self.write(kcode)
_, ty = self._read_header() _, ty = self._read_header()
if ty != _D2HMsgType.LOAD_COMPLETED: if ty != _D2HMsgType.LOAD_COMPLETED:

View File

@ -1,9 +1,15 @@
include $(MSCDIR)/software/common.mak include $(MSCDIR)/software/common.mak
OBJECTS := isr.o flash_storage.o clock.o rtiocrg.o elf_loader.o services.o session.o log.o test_mode.o kloader.o bridge_ctl.o mailbox.o ksupport_data.o net_server.o moninj.o main.o OBJECTS := isr.o clock.o rtiocrg.o flash_storage.o mailbox.o \
OBJECTS_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o ttl.o dds.o session.o log.o moninj.o net_server.o bridge_ctl.o \
ksupport_data.o kloader.o test_mode.o main.o
OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \
bridge.o rtio.o ttl.o dds.o
CFLAGS += -Ilwip/src/include -Iliblwip CFLAGS += -I$(MSCDIR)/software/include/dyld \
-I$(MSCDIR)/software/unwinder/include \
-I$(MSCDIR)/software/libunwind \
-Ilwip/src/include -Iliblwip
all: runtime.bin runtime.fbi all: runtime.bin runtime.fbi
@ -19,7 +25,7 @@ all: runtime.bin runtime.fbi
runtime.elf: $(OBJECTS) libs runtime.elf: $(OBJECTS) libs
$(LD) $(LDFLAGS) \ $(LD) $(LDFLAGS) \
-T linker.ld \ -T runtime.ld \
-N -o $@ \ -N -o $@ \
$(MSCDIR)/software/libbase/crt0-$(CPU).o \ $(MSCDIR)/software/libbase/crt0-$(CPU).o \
$(OBJECTS) \ $(OBJECTS) \
@ -29,24 +35,23 @@ runtime.elf: $(OBJECTS) libs
-lbase -lcompiler-rt -llwip -lbase -lcompiler-rt -llwip
@chmod -x $@ @chmod -x $@
ksupport.elf: $(OBJECTS_KSUPPORT) ksupport.elf: $(OBJECTS_KSUPPORT) libs
$(LD) $(LDFLAGS) \ $(LD) $(LDFLAGS) \
--eh-frame-hdr \
-T ksupport.ld \ -T ksupport.ld \
-N -o $@ \ -N -o $@ \
$(MSCDIR)/software/libbase/crt0-$(CPU).o \ $(MSCDIR)/software/libbase/crt0-$(CPU).o \
$^ \ $(OBJECTS_KSUPPORT) \
-L$(MSCDIR)/software/libbase \
-L$(MSCDIR)/software/libcompiler-rt \ -L$(MSCDIR)/software/libcompiler-rt \
-lcompiler-rt -L$(MSCDIR)/software/libunwind \
-L$(MSCDIR)/software/libdyld \
-lbase -lcompiler-rt -lunwind -ldyld
@chmod -x $@ @chmod -x $@
ksupport_data.o: ksupport.bin ksupport_data.o: ksupport.elf
$(LD) -r -b binary -o $@ $< $(LD) -r -b binary -o $@ $<
service_table.h: ksupport.elf gen_service_table.py
@echo " GEN " $@ && ./gen_service_table.py ksupport.elf > $@
services.c: service_table.h
main.o: main.c main.o: main.c
$(compile-dep) $(compile-dep)
@ -58,13 +63,15 @@ main.o: main.c
libs: libs:
$(MAKE) -C $(MSCDIR)/software/libcompiler-rt $(MAKE) -C $(MSCDIR)/software/libcompiler-rt
$(MAKE) -C $(MSCDIR)/software/libunwind
$(MAKE) -C $(MSCDIR)/software/libbase $(MAKE) -C $(MSCDIR)/software/libbase
$(MAKE) -C $(MSCDIR)/software/libdyld
$(MAKE) -C liblwip $(MAKE) -C liblwip
clean: clean:
$(MAKE) -C liblwip clean $(MAKE) -C liblwip clean
$(RM) $(OBJECTS) $(OBJECTS:.o=.d) $(OBJECTS_KSUPPORT) $(OBJECTS_KSUPPORT:.o=.d) $(RM) $(OBJECTS) $(OBJECTS:.o=.d) $(OBJECTS_KSUPPORT) $(OBJECTS_KSUPPORT:.o=.d)
$(RM) runtime.elf runtime.bin runtime.fbi .*~ *~ $(RM) runtime.elf runtime.bin runtime.fbi .*~ *~
$(RM) service_table.h ksupport.elf ksupport.bin $(RM) ksupport.elf ksupport.bin
.PHONY: all main.o clean libs load .PHONY: all main.o clean libs load

View File

@ -246,7 +246,9 @@ struct artiq_raised_exception {
static struct artiq_raised_exception inflight; static struct artiq_raised_exception inflight;
void __artiq_raise(struct artiq_exception *artiq_exn) { void __artiq_raise(struct artiq_exception *artiq_exn) {
EH_LOG("===> raise (name=%s)", artiq_exn->name); EH_LOG("===> raise (name=%s, msg=%s, params=[%lld,%lld,%lld])",
artiq_exn->name, artiq_exn->message,
artiq_exn->param[0], artiq_exn->param[1], artiq_exn->param[2]);
memmove(&inflight.artiq, artiq_exn, sizeof(struct artiq_exception)); memmove(&inflight.artiq, artiq_exn, sizeof(struct artiq_exception));
inflight.unwind.exception_class = ARTIQ_EXCEPTION_CLASS; inflight.unwind.exception_class = ARTIQ_EXCEPTION_CLASS;

View File

@ -1,7 +1,7 @@
#include <generated/csr.h> #include <generated/csr.h>
#include <stdio.h> #include <stdio.h>
#include "exceptions.h" #include "artiq_personality.h"
#include "rtio.h" #include "rtio.h"
#include "log.h" #include "log.h"
#include "dds.h" #include "dds.h"
@ -179,7 +179,7 @@ static struct dds_set_params batch[DDS_MAX_BATCH];
void dds_batch_enter(long long int timestamp) void dds_batch_enter(long long int timestamp)
{ {
if(batch_mode) if(batch_mode)
exception_raise(EID_DDS_BATCH_ERROR); artiq_raise_from_c("DDSBatchError", "DDS batch error", 0, 0, 0);
batch_mode = 1; batch_mode = 1;
batch_count = 0; batch_count = 0;
batch_ref_time = timestamp; batch_ref_time = timestamp;
@ -191,7 +191,7 @@ void dds_batch_exit(void)
int i; int i;
if(!batch_mode) if(!batch_mode)
exception_raise(EID_DDS_BATCH_ERROR); artiq_raise_from_c("DDSBatchError", "DDS batch error", 0, 0, 0);
rtio_chan_sel_write(RTIO_DDS_CHANNEL); rtio_chan_sel_write(RTIO_DDS_CHANNEL);
/* + FUD time */ /* + FUD time */
now = batch_ref_time - batch_count*(DURATION_PROGRAM + DURATION_WRITE); now = batch_ref_time - batch_count*(DURATION_PROGRAM + DURATION_WRITE);
@ -208,7 +208,7 @@ void dds_set(long long int timestamp, int channel,
{ {
if(batch_mode) { if(batch_mode) {
if(batch_count >= DDS_MAX_BATCH) if(batch_count >= DDS_MAX_BATCH)
exception_raise(EID_DDS_BATCH_ERROR); artiq_raise_from_c("DDSBatchError", "DDS batch error", 0, 0, 0);
/* timestamp parameter ignored (determined by batch) */ /* timestamp parameter ignored (determined by batch) */
batch[batch_count].channel = channel; batch[batch_count].channel = channel;
batch[batch_count].ftw = ftw; batch[batch_count].ftw = ftw;

View File

@ -1,240 +0,0 @@
#include <string.h>
#include "log.h"
#include "elf_loader.h"
#define EI_NIDENT 16
struct elf32_ehdr {
unsigned char ident[EI_NIDENT]; /* ident bytes */
unsigned short type; /* file type */
unsigned short machine; /* target machine */
unsigned int version; /* file version */
unsigned int entry; /* start address */
unsigned int phoff; /* phdr file offset */
unsigned int shoff; /* shdr file offset */
unsigned int flags; /* file flags */
unsigned short ehsize; /* sizeof ehdr */
unsigned short phentsize; /* sizeof phdr */
unsigned short phnum; /* number phdrs */
unsigned short shentsize; /* sizeof shdr */
unsigned short shnum; /* number shdrs */
unsigned short shstrndx; /* shdr string index */
} __attribute__((packed));
static const unsigned char elf_magic_header[] = {
0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
0x01, /* Only 32-bit objects. */
0x02, /* Only big-endian. */
0x01, /* Only ELF version 1. */
};
#define ET_NONE 0 /* Unknown type. */
#define ET_REL 1 /* Relocatable. */
#define ET_EXEC 2 /* Executable. */
#define ET_DYN 3 /* Shared object. */
#define ET_CORE 4 /* Core file. */
#define EM_OR1K 0x005c
struct elf32_shdr {
unsigned int name; /* section name */
unsigned int type; /* SHT_... */
unsigned int flags; /* SHF_... */
unsigned int addr; /* virtual address */
unsigned int offset; /* file offset */
unsigned int size; /* section size */
unsigned int link; /* misc info */
unsigned int info; /* misc info */
unsigned int addralign; /* memory alignment */
unsigned int entsize; /* entry size if table */
} __attribute__((packed));
struct elf32_name {
char name[12];
} __attribute__((packed));
struct elf32_rela {
unsigned int offset; /* Location to be relocated. */
unsigned int info; /* Relocation type and symbol index. */
int addend; /* Addend. */
} __attribute__((packed));
#define ELF32_R_SYM(info) ((info) >> 8)
#define ELF32_R_TYPE(info) ((unsigned char)(info))
#define R_OR1K_INSN_REL_26 6
struct elf32_sym {
unsigned int name; /* String table index of name. */
unsigned int value; /* Symbol value. */
unsigned int size; /* Size of associated object. */
unsigned char info; /* Type and binding information. */
unsigned char other; /* Reserved (not used). */
unsigned short shndx; /* Section index of symbol. */
} __attribute__((packed));
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define ELF32_ST_TYPE(info) ((info) & 0x0f)
#define SANITIZE_OFFSET_SIZE(offset, size) \
if(offset > 0x10000000) { \
log("Incorrect offset in ELF data"); \
return 0; \
} \
if((offset + size) > elf_length) { \
log("Attempted to access past the end of ELF data"); \
return 0; \
}
#define GET_POINTER_SAFE(target, target_type, offset) \
SANITIZE_OFFSET_SIZE(offset, sizeof(target_type)); \
target = (target_type *)((char *)elf_data + offset)
void *find_symbol(const struct symbol *symbols, const char *name)
{
int i;
i = 0;
while((symbols[i].name != NULL) && (strcmp(symbols[i].name, name) != 0))
i++;
return symbols[i].target;
}
static int fixup(void *dest, int dest_length, struct elf32_rela *rela, void *target)
{
int type, offset;
unsigned int *_dest = dest;
unsigned int *_target = target;
type = ELF32_R_TYPE(rela->info);
offset = rela->offset/4;
if(type == R_OR1K_INSN_REL_26) {
int val;
val = _target - (_dest + offset);
_dest[offset] = (_dest[offset] & 0xfc000000) | (val & 0x03ffffff);
} else
log("Unsupported relocation type: %d", type);
return 1;
}
int load_elf(symbol_resolver resolver, symbol_callback callback, void *elf_data, int elf_length, void *dest, int dest_length)
{
struct elf32_ehdr *ehdr;
struct elf32_shdr *strtable;
unsigned int shdrptr;
int i;
unsigned int textoff, textsize;
unsigned int textrelaoff, textrelasize;
unsigned int symtaboff, symtabsize;
unsigned int strtaboff, strtabsize;
/* validate ELF */
GET_POINTER_SAFE(ehdr, struct elf32_ehdr, 0);
if(memcmp(ehdr->ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
log("Incorrect ELF header");
return 0;
}
if(ehdr->type != ET_REL) {
log("ELF is not relocatable");
return 0;
}
if(ehdr->machine != EM_OR1K) {
log("ELF is for a different machine");
return 0;
}
/* extract section info */
GET_POINTER_SAFE(strtable, struct elf32_shdr, ehdr->shoff + ehdr->shentsize*ehdr->shstrndx);
textoff = textsize = 0;
textrelaoff = textrelasize = 0;
symtaboff = symtabsize = 0;
strtaboff = strtabsize = 0;
shdrptr = ehdr->shoff;
for(i=0;i<ehdr->shnum;i++) {
struct elf32_shdr *shdr;
struct elf32_name *name;
GET_POINTER_SAFE(shdr, struct elf32_shdr, shdrptr);
GET_POINTER_SAFE(name, struct elf32_name, strtable->offset + shdr->name);
if(strncmp(name->name, ".text", 5) == 0) {
textoff = shdr->offset;
textsize = shdr->size;
} else if(strncmp(name->name, ".rela.text", 10) == 0) {
textrelaoff = shdr->offset;
textrelasize = shdr->size;
} else if(strncmp(name->name, ".symtab", 7) == 0) {
symtaboff = shdr->offset;
symtabsize = shdr->size;
} else if(strncmp(name->name, ".strtab", 7) == 0) {
strtaboff = shdr->offset;
strtabsize = shdr->size;
}
shdrptr += ehdr->shentsize;
}
SANITIZE_OFFSET_SIZE(textoff, textsize);
SANITIZE_OFFSET_SIZE(textrelaoff, textrelasize);
SANITIZE_OFFSET_SIZE(symtaboff, symtabsize);
SANITIZE_OFFSET_SIZE(strtaboff, strtabsize);
/* load .text section */
if(textsize > dest_length) {
log(".text section is too large");
return 0;
}
memcpy(dest, (char *)elf_data + textoff, textsize);
/* process .text relocations */
for(i=0;i<textrelasize;i+=sizeof(struct elf32_rela)) {
struct elf32_rela *rela;
struct elf32_sym *sym;
GET_POINTER_SAFE(rela, struct elf32_rela, textrelaoff + i);
GET_POINTER_SAFE(sym, struct elf32_sym, symtaboff + sizeof(struct elf32_sym)*ELF32_R_SYM(rela->info));
if(sym->name != 0) {
char *name;
void *target;
name = (char *)elf_data + strtaboff + sym->name;
target = resolver(name);
if(target == NULL) {
log("Undefined symbol: %s", name);
return 0;
}
if(!fixup(dest, dest_length, rela, target))
return 0;
} else {
log("Unsupported relocation");
return 0;
}
}
/* list provided functions via callback */
for(i=0;i<symtabsize;i+=sizeof(struct elf32_sym)) {
struct elf32_sym *sym;
GET_POINTER_SAFE(sym, struct elf32_sym, symtaboff + i);
if((ELF32_ST_TYPE(sym->info) == STT_FUNC) && (sym->name != 0)) {
char *name;
void *target;
name = (char *)elf_data + strtaboff + sym->name;
target = (char *)dest + sym->value;
if(!callback(name, target))
return 0;
}
}
return 1;
}

View File

@ -1,16 +0,0 @@
#ifndef __ELF_LOADER_H
#define __ELF_LOADER_H
struct symbol {
char *name;
void *target;
};
typedef void * (*symbol_resolver)(const char *);
typedef int (*symbol_callback)(const char *, void *);
void *find_symbol(const struct symbol *symbols, const char *name);
/* elf_data must be aligned on a 32-bit boundary */
int load_elf(symbol_resolver resolver, symbol_callback callback, void *elf_data, int elf_length, void *dest, int dest_length);
#endif /* __ELF_LOADER_H */

View File

@ -1,37 +0,0 @@
.global exception_setjmp
.type exception_setjmp, @function
exception_setjmp:
l.sw 0(r3), r1
l.sw 4(r3), r2
l.sw 8(r3), r9
l.sw 12(r3), r10
l.sw 16(r3), r14
l.sw 20(r3), r16
l.sw 24(r3), r18
l.sw 28(r3), r20
l.sw 32(r3), r22
l.sw 36(r3), r24
l.sw 40(r3), r26
l.sw 44(r3), r28
l.sw 48(r3), r30
l.jr r9
l.ori r11, r0, 0
.global exception_longjmp
.type exception_longjmp, @function
exception_longjmp:
l.lwz r1, 0(r3)
l.lwz r2, 4(r3)
l.lwz r9, 8(r3)
l.lwz r10, 12(r3)
l.lwz r14, 16(r3)
l.lwz r16, 20(r3)
l.lwz r18, 24(r3)
l.lwz r20, 28(r3)
l.lwz r22, 32(r3)
l.lwz r24, 36(r3)
l.lwz r26, 40(r3)
l.lwz r28, 44(r3)
l.lwz r30, 48(r3)
l.jr r9
l.ori r11, r0, 1

View File

@ -1,58 +0,0 @@
#include <generated/csr.h>
#include "log.h"
#include "exceptions.h"
#define MAX_EXCEPTION_CONTEXTS 64
struct exception_context {
void *jb[13];
};
static struct exception_context exception_contexts[MAX_EXCEPTION_CONTEXTS];
static int ec_top;
static int stored_id;
static long long int stored_params[3];
void *exception_push(void)
{
if(ec_top >= MAX_EXCEPTION_CONTEXTS)
exception_raise(EID_INTERNAL_ERROR);
return exception_contexts[ec_top++].jb;
}
void exception_pop(int levels)
{
ec_top -= levels;
}
int exception_getid(long long int *eparams)
{
int i;
if(eparams)
for(i=0;i<3;i++)
eparams[i] = stored_params[i];
return stored_id;
}
void exception_raise(int id)
{
exception_raise_params(id, 0, 0, 0);
}
void exception_raise_params(int id,
long long int p0, long long int p1,
long long int p2)
{
if(ec_top > 0) {
stored_id = id;
stored_params[0] = p0;
stored_params[1] = p1;
stored_params[2] = p2;
exception_longjmp(exception_contexts[--ec_top].jb);
} else {
log("ERROR: uncaught exception, ID=%d\n", id);
while(1);
}
}

View File

@ -1,25 +0,0 @@
#ifndef __EXCEPTIONS_H
#define __EXCEPTIONS_H
enum {
EID_NONE = 0,
EID_INTERNAL_ERROR = 1,
EID_RPC_EXCEPTION = 2,
EID_RTIO_UNDERFLOW = 3,
EID_RTIO_SEQUENCE_ERROR = 4,
EID_RTIO_OVERFLOW = 5,
EID_DDS_BATCH_ERROR = 6,
};
int exception_setjmp(void *jb) __attribute__((returns_twice));
void exception_longjmp(void *jb) __attribute__((noreturn));
void *exception_push(void);
void exception_pop(int levels);
int exception_getid(long long int *eparams);
void exception_raise(int id) __attribute__((noreturn));
void exception_raise_params(int id,
long long int p0, long long int p1,
long long int p2) __attribute__((noreturn));
#endif /* __EXCEPTIONS_H */

View File

@ -1,65 +0,0 @@
#!/usr/bin/env python3
import sys
from elftools.elf.elffile import ELFFile
services = [
("syscalls", [
("now_init", "now_init"),
("now_save", "now_save"),
("watchdog_set", "watchdog_set"),
("watchdog_clear", "watchdog_clear"),
("rpc", "rpc"),
("rtio_get_counter", "rtio_get_counter"),
("ttl_set_o", "ttl_set_o"),
("ttl_set_oe", "ttl_set_oe"),
("ttl_set_sensitivity", "ttl_set_sensitivity"),
("ttl_get", "ttl_get"),
("ttl_clock_set", "ttl_clock_set"),
("dds_init", "dds_init"),
("dds_batch_enter", "dds_batch_enter"),
("dds_batch_exit", "dds_batch_exit"),
("dds_set", "dds_set"),
]),
("eh", [
("setjmp", "exception_setjmp"),
("push", "exception_push"),
("pop", "exception_pop"),
("getid", "exception_getid"),
("raise", "exception_raise"),
])
]
def print_service_table(ksupport_elf_filename):
with open(ksupport_elf_filename, "rb") as f:
elf = ELFFile(f)
symtab = elf.get_section_by_name(b".symtab")
symbols = {symbol.name: symbol.entry.st_value
for symbol in symtab.iter_symbols()}
for name, contents in services:
print("static const struct symbol {}[] = {{".format(name))
for name, value in contents:
print(" {{\"{}\", (void *)0x{:08x}}},"
.format(name, symbols[bytes(value, "ascii")]))
print(" {NULL, NULL}")
print("};")
def main():
if len(sys.argv) == 2:
print_service_table(sys.argv[1])
else:
print("Incorrect number of command line arguments")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1,120 +1,82 @@
#include <string.h> #include <string.h>
#include <generated/csr.h> #include <generated/csr.h>
#include <dyld.h>
#include "kloader.h"
#include "log.h" #include "log.h"
#include "flash_storage.h" #include "flash_storage.h"
#include "mailbox.h" #include "mailbox.h"
#include "messages.h" #include "messages.h"
#include "elf_loader.h"
#include "services.h"
#include "kloader.h"
static struct symbol symtab[128]; static void start_kernel_cpu(struct msg_load_request *msg)
static int _symtab_count;
static char _symtab_strings[128*16];
static char *_symtab_strptr;
static void symtab_init(void)
{ {
memset(symtab, 0, sizeof(symtab)); // Stop kernel CPU before messing with its code.
_symtab_count = 0; kernel_cpu_reset_write(1);
_symtab_strptr = _symtab_strings;
// Load kernel support code.
extern void _binary_ksupport_elf_start, _binary_ksupport_elf_end;
memcpy((void *)(KERNELCPU_EXEC_ADDRESS - KSUPPORT_HEADER_SIZE),
&_binary_ksupport_elf_start,
&_binary_ksupport_elf_end - &_binary_ksupport_elf_start);
// Start kernel CPU.
mailbox_send(msg);
kernel_cpu_reset_write(0);
} }
static int symtab_add(const char *name, void *target) void kloader_start_bridge()
{ {
if(_symtab_count >= sizeof(symtab)/sizeof(symtab[0])) { start_kernel_cpu(NULL);
log("Too many provided symbols in object"); }
symtab_init();
return 0;
}
symtab[_symtab_count].name = _symtab_strptr;
symtab[_symtab_count].target = target;
_symtab_count++;
while(1) { static int load_or_start_kernel(void *library, const char *kernel)
if(_symtab_strptr >= &_symtab_strings[sizeof(_symtab_strings)]) { {
log("Provided symbol string table overflow"); static struct dyld_info library_info;
symtab_init(); struct msg_load_request request = {
.library = library,
.library_info = &library_info,
.kernel = kernel,
};
start_kernel_cpu(&request);
struct msg_load_reply *reply = mailbox_wait_and_receive();
if(reply != NULL && reply->type == MESSAGE_TYPE_LOAD_REPLY) {
log("cannot load/run kernel: %s", reply->error);
return 0; return 0;
} }
*_symtab_strptr = *name;
_symtab_strptr++;
if(*name == 0)
break;
name++;
}
return 1; return 1;
} }
int kloader_load(void *buffer, int length) int kloader_load_library(void *library)
{ {
if(!kernel_cpu_reset_read()) { if(!kernel_cpu_reset_read()) {
log("BUG: attempted to load while kernel CPU running"); log("BUG: attempted to load kernel library while kernel CPU is running");
return 0; return 0;
} }
symtab_init();
return load_elf( return load_or_start_kernel(library, NULL);
resolve_service_symbol, symtab_add,
buffer, length, (void *)KERNELCPU_PAYLOAD_ADDRESS, 4*1024*1024);
} }
kernel_function kloader_find(const char *name) int kloader_start_kernel(const char *name)
{ {
return find_symbol(symtab, name); return load_or_start_kernel(NULL, name);
} }
extern char _binary_ksupport_bin_start; int kloader_start_idle_kernel(void)
extern char _binary_ksupport_bin_end;
static void start_kernel_cpu(void *addr)
{ {
memcpy((void *)KERNELCPU_EXEC_ADDRESS, &_binary_ksupport_bin_start,
&_binary_ksupport_bin_end - &_binary_ksupport_bin_start);
mailbox_acknowledge();
mailbox_send(addr);
kernel_cpu_reset_write(0);
}
void kloader_start_bridge(void)
{
start_kernel_cpu(NULL);
}
void kloader_start_user_kernel(kernel_function k)
{
if(!kernel_cpu_reset_read()) {
log("BUG: attempted to start kernel CPU while already running (user kernel)");
return;
}
start_kernel_cpu((void *)k);
}
void kloader_start_idle_kernel(void)
{
char buffer[32*1024];
int len;
kernel_function k;
if(!kernel_cpu_reset_read()) {
log("BUG: attempted to start kernel CPU while already running (idle kernel)");
return;
}
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) #if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
len = fs_read("idle_kernel", buffer, sizeof(buffer), NULL); char buffer[32*1024];
if(len <= 0) int length;
return;
if(!kloader_load(buffer, len)) { length = fs_read("idle_kernel", buffer, sizeof(buffer), NULL);
log("Failed to load ELF binary for idle kernel"); if(length <= 0)
return; return 0;
}
k = kloader_find("run"); return load_or_start_kernel(buffer, "test.__modinit__");
if(!k) { #else
log("Failed to find entry point for ELF kernel"); return 0;
return;
}
start_kernel_cpu((void *)k);
#endif #endif
} }
@ -127,7 +89,7 @@ void kloader_stop(void)
int kloader_validate_kpointer(void *p) int kloader_validate_kpointer(void *p)
{ {
unsigned int v = (unsigned int)p; unsigned int v = (unsigned int)p;
if((v < 0x40400000) || (v > (0x4fffffff - 1024*1024))) { if((v < KERNELCPU_EXEC_ADDRESS) || (v > KERNELCPU_LAST_ADDRESS)) {
log("Received invalid pointer from kernel CPU: 0x%08x", v); log("Received invalid pointer from kernel CPU: 0x%08x", v);
return 0; return 0;
} }

View File

@ -2,18 +2,17 @@
#define __KLOADER_H #define __KLOADER_H
#define KERNELCPU_EXEC_ADDRESS 0x40400000 #define KERNELCPU_EXEC_ADDRESS 0x40400000
#define KERNELCPU_PAYLOAD_ADDRESS 0x40408000 #define KERNELCPU_PAYLOAD_ADDRESS 0x40420000
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
#define KSUPPORT_HEADER_SIZE 0x80
extern long long int now; extern long long int now;
typedef void (*kernel_function)(void); int kloader_load_library(void *code);
int kloader_load(void *buffer, int length);
kernel_function kloader_find(const char *name);
void kloader_start_bridge(void); void kloader_start_bridge(void);
void kloader_start_idle_kernel(void); int kloader_start_idle_kernel(void);
void kloader_start_user_kernel(kernel_function k); int kloader_start_kernel(const char *name);
void kloader_stop(void); void kloader_stop(void);
int kloader_validate_kpointer(void *p); int kloader_validate_kpointer(void *p);

View File

@ -1,67 +1,254 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "exceptions.h" #include <link.h>
#include "bridge.h" #include <dlfcn.h>
#include <dyld.h>
#include <unwind.h>
#include "ksupport.h"
#include "kloader.h"
#include "mailbox.h" #include "mailbox.h"
#include "messages.h" #include "messages.h"
#include "rtio.h" #include "bridge.h"
#include "artiq_personality.h"
#include "ttl.h"
#include "dds.h" #include "dds.h"
#include "rtio.h"
/* for the prototypes for watchdog_set() and watchdog_clear() */ /* compiler-rt symbols */
#include "clock.h" extern void __divsi3, __modsi3, __ledf2, __gedf2, __unorddf2, __eqdf2, __ltdf2,
/* for the prototype for rpc() */ __nedf2, __gtdf2, __negsf2, __negdf2, __addsf3, __subsf3, __mulsf3,
#include "session.h" __divsf3, __lshrdi3, __muldi3, __divdi3, __ashldi3, __ashrdi3,
/* for the prototype for log() */ __udivmoddi4, __floatsisf, __floatunsisf, __fixsfsi, __fixunssfsi,
#include "log.h" __adddf3, __subdf3, __muldf3, __divdf3, __floatsidf, __floatunsidf,
__floatdidf, __fixdfsi, __fixdfdi, __fixunsdfsi, __clzsi2, __ctzsi2,
__udivdi3, __umoddi3, __moddi3;
void exception_handler(unsigned long vect, unsigned long *sp); /* artiq_personality symbols */
void exception_handler(unsigned long vect, unsigned long *sp) extern void __artiq_personality;
struct symbol {
const char *name;
void *addr;
};
static const struct symbol runtime_exports[] = {
/* compiler-rt */
{"divsi3", &__divsi3},
{"modsi3", &__modsi3},
{"ledf2", &__ledf2},
{"gedf2", &__gedf2},
{"unorddf2", &__unorddf2},
{"eqdf2", &__eqdf2},
{"ltdf2", &__ltdf2},
{"nedf2", &__nedf2},
{"gtdf2", &__gtdf2},
{"negsf2", &__negsf2},
{"negdf2", &__negdf2},
{"addsf3", &__addsf3},
{"subsf3", &__subsf3},
{"mulsf3", &__mulsf3},
{"divsf3", &__divsf3},
{"lshrdi3", &__lshrdi3},
{"muldi3", &__muldi3},
{"divdi3", &__divdi3},
{"ashldi3", &__ashldi3},
{"ashrdi3", &__ashrdi3},
{"udivmoddi4", &__udivmoddi4},
{"floatsisf", &__floatsisf},
{"floatunsisf", &__floatunsisf},
{"fixsfsi", &__fixsfsi},
{"fixunssfsi", &__fixunssfsi},
{"adddf3", &__adddf3},
{"subdf3", &__subdf3},
{"muldf3", &__muldf3},
{"divdf3", &__divdf3},
{"floatsidf", &__floatsidf},
{"floatunsidf", &__floatunsidf},
{"floatdidf", &__floatdidf},
{"fixdfsi", &__fixdfsi},
{"fixdfdi", &__fixdfdi},
{"fixunsdfsi", &__fixunsdfsi},
{"clzsi2", &__clzsi2},
{"ctzsi2", &__ctzsi2},
{"udivdi3", &__udivdi3},
{"umoddi3", &__umoddi3},
{"moddi3", &__moddi3},
/* exceptions */
{"_Unwind_Resume", &_Unwind_Resume},
{"__artiq_personality", &__artiq_personality},
{"__artiq_raise", &__artiq_raise},
{"__artiq_reraise", &__artiq_reraise},
/* proxified syscalls */
{"now_init", &now_init},
{"now_save", &now_save},
{"watchdog_set", &watchdog_set},
{"watchdog_clear", &watchdog_clear},
{"log", &log},
{"lognonl", &lognonl},
{"rpc", &rpc},
/* direct syscalls */
{"rtio_get_counter", &rtio_get_counter},
{"ttl_set_o", &ttl_set_o},
{"ttl_set_oe", &ttl_set_oe},
{"ttl_set_sensitivity", &ttl_set_sensitivity},
{"ttl_get", &ttl_get},
{"ttl_clock_set", &ttl_clock_set},
{"dds_init", &dds_init},
{"dds_batch_enter", &dds_batch_enter},
{"dds_batch_exit", &dds_batch_exit},
{"dds_set", &dds_set},
/* end */
{NULL, NULL}
};
/* called by libunwind */
int fprintf(FILE *stream, const char *fmt, ...)
{ {
struct msg_exception msg; struct msg_log request;
msg.type = MESSAGE_TYPE_EXCEPTION; request.type = MESSAGE_TYPE_LOG;
msg.eid = EID_INTERNAL_ERROR; request.fmt = fmt;
msg.eparams[0] = 256; request.no_newline = 1;
msg.eparams[1] = 256; va_start(request.args, fmt);
msg.eparams[2] = 256; mailbox_send_and_wait(&request);
mailbox_send_and_wait(&msg); va_end(request.args);
while(1);
return 0;
} }
typedef void (*kernel_function)(void); /* called by libunwind */
int dladdr (const void *address, Dl_info *info) {
/* we don't try to resolve names */
return 0;
}
/* called by libunwind */
int dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, size_t, void *), void *data) {
Elf32_Ehdr *ehdr;
struct dl_phdr_info phdr_info;
int retval;
ehdr = (Elf32_Ehdr *)(KERNELCPU_EXEC_ADDRESS - KSUPPORT_HEADER_SIZE);
phdr_info = (struct dl_phdr_info){
.dlpi_addr = 0, /* absolutely linked */
.dlpi_name = "<ksupport>",
.dlpi_phdr = (Elf32_Phdr*) ((intptr_t)ehdr + ehdr->e_phoff),
.dlpi_phnum = ehdr->e_phnum,
};
retval = callback(&phdr_info, sizeof(phdr_info), data);
if(retval)
return retval;
ehdr = (Elf32_Ehdr *)KERNELCPU_PAYLOAD_ADDRESS;
phdr_info = (struct dl_phdr_info){
.dlpi_addr = KERNELCPU_PAYLOAD_ADDRESS,
.dlpi_name = "<kernel>",
.dlpi_phdr = (Elf32_Phdr*) ((intptr_t)ehdr + ehdr->e_phoff),
.dlpi_phnum = ehdr->e_phnum,
};
retval = callback(&phdr_info, sizeof(phdr_info), data);
return retval;
}
static Elf32_Addr resolve_runtime_export(const char *name) {
const struct symbol *sym = runtime_exports;
while(sym->name) {
if(!strcmp(sym->name, name))
return (Elf32_Addr)sym->addr;
++sym;
}
return 0;
}
void exception_handler(unsigned long vect, unsigned long *regs,
unsigned long pc, unsigned long ea);
void exception_handler(unsigned long vect, unsigned long *regs,
unsigned long pc, unsigned long ea)
{
artiq_raise_from_c("InternalError",
"Hardware exception {0} at PC {1}, EA {2}",
vect, pc, ea);
}
int main(void); int main(void);
int main(void) int main(void)
{ {
kernel_function k; struct msg_load_request *msg = mailbox_receive();
void *jb;
k = mailbox_receive(); if(msg == NULL) {
if(k == NULL)
bridge_main(); bridge_main();
else { while(1);
jb = exception_push(); }
if(exception_setjmp(jb)) {
struct msg_exception msg; if(msg->library != NULL) {
const char *error;
if(!dyld_load(msg->library, KERNELCPU_PAYLOAD_ADDRESS,
resolve_runtime_export, msg->library_info, &error)) {
struct msg_load_reply msg = {
.type = MESSAGE_TYPE_LOAD_REPLY,
.error = error
};
mailbox_send(&msg);
while(1);
}
}
void (*kernel)(void) = NULL;
if(msg->kernel != NULL) {
kernel = dyld_lookup(msg->kernel, msg->library_info);
if(kernel == NULL) {
char error[256];
snprintf(error, sizeof(error),
"kernel '%s' not found in library", msg->kernel);
struct msg_load_reply msg = {
.type = MESSAGE_TYPE_LOAD_REPLY,
.error = error
};
mailbox_send(&msg);
while(1);
}
}
mailbox_acknowledge();
if(kernel) {
void (*run_closure)(void *) = msg->library_info->init;
run_closure(kernel);
msg.type = MESSAGE_TYPE_EXCEPTION;
msg.eid = exception_getid(msg.eparams);
mailbox_send_and_wait(&msg);
} else {
struct msg_base msg; struct msg_base msg;
k();
exception_pop(1);
msg.type = MESSAGE_TYPE_FINISHED; msg.type = MESSAGE_TYPE_FINISHED;
mailbox_send_and_wait(&msg); mailbox_send_and_wait(&msg);
} }
}
while(1);
}
/* called from __artiq_personality */
void __artiq_terminate(struct artiq_exception *artiq_exn,
struct artiq_backtrace_item *backtrace,
size_t backtrace_size) {
struct msg_exception msg;
msg.type = MESSAGE_TYPE_EXCEPTION;
msg.exception = artiq_exn;
msg.backtrace = backtrace;
msg.backtrace_size = backtrace_size;
mailbox_send(&msg);
while(1); while(1);
} }
long long int now_init(void);
long long int now_init(void) long long int now_init(void)
{ {
struct msg_base request; struct msg_base request;
@ -72,8 +259,10 @@ long long int now_init(void)
mailbox_send_and_wait(&request); mailbox_send_and_wait(&request);
reply = mailbox_wait_and_receive(); reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY) if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY) {
exception_raise_params(EID_INTERNAL_ERROR, 1, 0, 0); log("Malformed MESSAGE_TYPE_NOW_INIT_REQUEST reply type");
while(1);
}
now = reply->now; now = reply->now;
mailbox_acknowledge(); mailbox_acknowledge();
@ -85,7 +274,6 @@ long long int now_init(void)
return now; return now;
} }
void now_save(long long int now);
void now_save(long long int now) void now_save(long long int now)
{ {
struct msg_now_save request; struct msg_now_save request;
@ -106,8 +294,10 @@ int watchdog_set(int ms)
mailbox_send_and_wait(&request); mailbox_send_and_wait(&request);
reply = mailbox_wait_and_receive(); reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY) if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY) {
exception_raise_params(EID_INTERNAL_ERROR, 2, 0, 0); log("Malformed MESSAGE_TYPE_WATCHDOG_SET_REQUEST reply type");
while(1);
}
id = reply->id; id = reply->id;
mailbox_acknowledge(); mailbox_acknowledge();
@ -127,7 +317,6 @@ int rpc(int rpc_num, ...)
{ {
struct msg_rpc_request request; struct msg_rpc_request request;
struct msg_rpc_reply *reply; struct msg_rpc_reply *reply;
int eid, retval;
request.type = MESSAGE_TYPE_RPC_REQUEST; request.type = MESSAGE_TYPE_RPC_REQUEST;
request.rpc_num = rpc_num; request.rpc_num = rpc_num;
@ -136,15 +325,21 @@ int rpc(int rpc_num, ...)
va_end(request.args); va_end(request.args);
reply = mailbox_wait_and_receive(); reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_RPC_REPLY) if(reply->type != MESSAGE_TYPE_RPC_REPLY) {
exception_raise_params(EID_INTERNAL_ERROR, 3, 0, 0); log("Malformed MESSAGE_TYPE_RPC_REPLY reply type");
eid = reply->eid; while(1);
retval = reply->retval; }
mailbox_acknowledge();
if(eid != EID_NONE) if(reply->exception != NULL) {
exception_raise(eid); struct artiq_exception exception;
memcpy(&exception, reply->exception, sizeof(exception));
mailbox_acknowledge();
__artiq_raise(&exception);
} else {
int retval = reply->retval;
mailbox_acknowledge();
return retval; return retval;
}
} }
void lognonl(const char *fmt, ...) void lognonl(const char *fmt, ...)

12
soc/runtime/ksupport.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __KSTARTUP_H
#define __KSTARTUP_H
long long int now_init(void);
void now_save(long long int now);
int watchdog_set(int ms);
void watchdog_clear(int id);
int rpc(int rpc_num, ...);
void lognonl(const char *fmt, ...);
void log(const char *fmt, ...);
#endif /* __KSTARTUP_H */

View File

@ -4,10 +4,10 @@ ENTRY(_start)
INCLUDE generated/regions.ld INCLUDE generated/regions.ld
/* First 4M of main memory are reserved for runtime code/data /* First 4M of main memory are reserved for runtime code/data
* then comes kernel memory. First 32K of kernel memory are for support code. * then comes kernel memory. First 128K of kernel memory are for support code.
*/ */
MEMORY { MEMORY {
ksupport : ORIGIN = 0x40400000, LENGTH = 0x8000 ksupport (RWX) : ORIGIN = 0x40400000, LENGTH = 0x20000
} }
/* On AMP systems, kernel stack is at the end of main RAM, /* On AMP systems, kernel stack is at the end of main RAM,
@ -15,6 +15,13 @@ MEMORY {
*/ */
PROVIDE(_fstack = 0x40000000 + LENGTH(main_ram) - 1024*1024 - 4); PROVIDE(_fstack = 0x40000000 + LENGTH(main_ram) - 1024*1024 - 4);
/* Force ld to make the ELF header as loadable. */
PHDRS
{
text PT_LOAD FILEHDR PHDRS;
eh_frame PT_GNU_EH_FRAME;
}
SECTIONS SECTIONS
{ {
.text : .text :
@ -22,7 +29,7 @@ SECTIONS
_ftext = .; _ftext = .;
*(.text .stub .text.* .gnu.linkonce.t.*) *(.text .stub .text.* .gnu.linkonce.t.*)
_etext = .; _etext = .;
} > ksupport } :text
.rodata : .rodata :
{ {
@ -33,6 +40,16 @@ SECTIONS
_erodata = .; _erodata = .;
} > ksupport } > ksupport
.eh_frame :
{
*(.eh_frame)
} :text
.eh_frame_hdr :
{
*(.eh_frame_hdr)
} :text :eh_frame
.data : .data :
{ {
. = ALIGN(4); . = ALIGN(4);
@ -41,7 +58,7 @@ SECTIONS
*(.data1) *(.data1)
*(.sdata .sdata.* .gnu.linkonce.s.*) *(.sdata .sdata.* .gnu.linkonce.s.*)
_edata = .; _edata = .;
} > ksupport }
.bss : .bss :
{ {
@ -57,5 +74,5 @@ SECTIONS
_ebss = .; _ebss = .;
. = ALIGN(8); . = ALIGN(8);
_heapstart = .; _heapstart = .;
} > ksupport }
} }

View File

@ -2,8 +2,10 @@
#define __MESSAGES_H #define __MESSAGES_H
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h>
enum { enum {
MESSAGE_TYPE_LOAD_REPLY,
MESSAGE_TYPE_NOW_INIT_REQUEST, MESSAGE_TYPE_NOW_INIT_REQUEST,
MESSAGE_TYPE_NOW_INIT_REPLY, MESSAGE_TYPE_NOW_INIT_REPLY,
MESSAGE_TYPE_NOW_SAVE, MESSAGE_TYPE_NOW_SAVE,
@ -34,6 +36,17 @@ struct msg_base {
/* kernel messages */ /* kernel messages */
struct msg_load_request {
void *library;
struct dyld_info *library_info;
const char *kernel;
};
struct msg_load_reply {
int type;
const char *error;
};
struct msg_now_init_reply { struct msg_now_init_reply {
int type; int type;
long long int now; long long int now;
@ -46,8 +59,9 @@ struct msg_now_save {
struct msg_exception { struct msg_exception {
int type; int type;
int eid; struct artiq_exception *exception;
long long int eparams[3]; struct artiq_backtrace_item *backtrace;
size_t backtrace_size;
}; };
struct msg_watchdog_set_request { struct msg_watchdog_set_request {
@ -73,7 +87,7 @@ struct msg_rpc_request {
struct msg_rpc_reply { struct msg_rpc_reply {
int type; int type;
int eid; struct artiq_exception *exception;
int retval; int retval;
}; };

View File

@ -2,7 +2,7 @@
#define __RTIO_H #define __RTIO_H
#include <generated/csr.h> #include <generated/csr.h>
#include "exceptions.h" #include "artiq_personality.h"
#define RTIO_O_STATUS_FULL 1 #define RTIO_O_STATUS_FULL 1
#define RTIO_O_STATUS_UNDERFLOW 2 #define RTIO_O_STATUS_UNDERFLOW 2
@ -24,12 +24,14 @@ static inline void rtio_write_and_process_status(long long int timestamp, int ch
while(rtio_o_status_read() & RTIO_O_STATUS_FULL); while(rtio_o_status_read() & RTIO_O_STATUS_FULL);
if(status & RTIO_O_STATUS_UNDERFLOW) { if(status & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1); rtio_o_underflow_reset_write(1);
exception_raise_params(EID_RTIO_UNDERFLOW, artiq_raise_from_c("RTIOUnderflow",
"RTIO underflow at {0}mu, channel {1}, counter {2}",
timestamp, channel, rtio_get_counter()); timestamp, channel, rtio_get_counter());
} }
if(status & RTIO_O_STATUS_SEQUENCE_ERROR) { if(status & RTIO_O_STATUS_SEQUENCE_ERROR) {
rtio_o_sequence_error_reset_write(1); rtio_o_sequence_error_reset_write(1);
exception_raise_params(EID_RTIO_SEQUENCE_ERROR, artiq_raise_from_c("RTIOSequenceError",
"RTIO sequence error at {0}mu, channel {1}",
timestamp, channel, 0); timestamp, channel, 0);
} }
} }

View File

@ -10,6 +10,13 @@ MEMORY {
runtime : ORIGIN = 0x40000000, LENGTH = 0x400000 /* 4M */ runtime : ORIGIN = 0x40000000, LENGTH = 0x400000 /* 4M */
} }
/* First 4M of main memory are reserved for runtime code/data
* then comes kernel memory. First 32K of kernel memory are for support code.
*/
MEMORY {
kernel : ORIGIN = 0x40400000, LENGTH = 0x8000
}
/* Kernel memory space start right after the runtime, /* Kernel memory space start right after the runtime,
* and ends before the runtime stack. * and ends before the runtime stack.
* Runtime stack is always at the end of main_ram. * Runtime stack is always at the end of main_ram.
@ -17,6 +24,11 @@ MEMORY {
*/ */
PROVIDE(_fstack = 0x40000000 + LENGTH(main_ram) - 4); PROVIDE(_fstack = 0x40000000 + LENGTH(main_ram) - 4);
/* On AMP systems, kernel stack is at the end of main RAM,
* before the runtime stack. Leave 1M for runtime stack.
*/
PROVIDE(_kernel_fstack = 0x40000000 + LENGTH(main_ram) - 1024*1024 - 4);
SECTIONS SECTIONS
{ {
.text : .text :
@ -58,6 +70,12 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
_ebss = .; _ebss = .;
. = ALIGN(8); . = ALIGN(8);
_heapstart = .;
} > runtime } > runtime
/DISCARD/ :
{
*(.eh_frame)
}
_heapstart = .;
} }

View File

@ -1,78 +0,0 @@
#include <string.h>
#include "elf_loader.h"
#include "session.h"
#include "clock.h"
#include "ttl.h"
#include "dds.h"
#include "exceptions.h"
#include "services.h"
#include "service_table.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-int"
extern __divsi3, __modsi3, __ledf2, __gedf2, __unorddf2, __eqdf2, __ltdf2,
__nedf2, __gtdf2, __negsf2, __negdf2, __addsf3, __subsf3, __mulsf3,
__divsf3, __lshrdi3, __muldi3, __divdi3, __ashldi3, __ashrdi3,
__udivmoddi4, __floatsisf, __floatunsisf, __fixsfsi, __fixunssfsi,
__adddf3, __subdf3, __muldf3, __divdf3, __floatsidf, __floatunsidf,
__floatdidf, __fixdfsi, __fixdfdi, __fixunsdfsi, __clzsi2, __ctzsi2,
__udivdi3, __umoddi3, __moddi3;
#pragma GCC diagnostic pop
static const struct symbol compiler_rt[] = {
{"divsi3", &__divsi3},
{"modsi3", &__modsi3},
{"ledf2", &__ledf2},
{"gedf2", &__gedf2},
{"unorddf2", &__unorddf2},
{"eqdf2", &__eqdf2},
{"ltdf2", &__ltdf2},
{"nedf2", &__nedf2},
{"gtdf2", &__gtdf2},
{"negsf2", &__negsf2},
{"negdf2", &__negdf2},
{"addsf3", &__addsf3},
{"subsf3", &__subsf3},
{"mulsf3", &__mulsf3},
{"divsf3", &__divsf3},
{"lshrdi3", &__lshrdi3},
{"muldi3", &__muldi3},
{"divdi3", &__divdi3},
{"ashldi3", &__ashldi3},
{"ashrdi3", &__ashrdi3},
{"udivmoddi4", &__udivmoddi4},
{"floatsisf", &__floatsisf},
{"floatunsisf", &__floatunsisf},
{"fixsfsi", &__fixsfsi},
{"fixunssfsi", &__fixunssfsi},
{"adddf3", &__adddf3},
{"subdf3", &__subdf3},
{"muldf3", &__muldf3},
{"divdf3", &__divdf3},
{"floatsidf", &__floatsidf},
{"floatunsidf", &__floatunsidf},
{"floatdidf", &__floatdidf},
{"fixdfsi", &__fixdfsi},
{"fixdfdi", &__fixdfdi},
{"fixunsdfsi", &__fixunsdfsi},
{"clzsi2", &__clzsi2},
{"ctzsi2", &__ctzsi2},
{"udivdi3", &__udivdi3},
{"umoddi3", &__umoddi3},
{"moddi3", &__moddi3},
{NULL, NULL}
};
void *resolve_service_symbol(const char *name)
{
if(strncmp(name, "__", 2) != 0)
return NULL;
name += 2;
if(strncmp(name, "syscall_", 8) == 0)
return find_symbol(syscalls, name + 8);
if(strncmp(name, "eh_", 3) == 0)
return find_symbol(eh, name + 3);
return find_symbol(compiler_rt, name);
}

View File

@ -1,6 +0,0 @@
#ifndef __SERVICES_H
#define __SERVICES_H
void *resolve_service_symbol(const char *name);
#endif /* __SERVICES_H */

View File

@ -10,7 +10,7 @@
#include "clock.h" #include "clock.h"
#include "log.h" #include "log.h"
#include "kloader.h" #include "kloader.h"
#include "exceptions.h" #include "artiq_personality.h"
#include "flash_storage.h" #include "flash_storage.h"
#include "rtiocrg.h" #include "rtiocrg.h"
#include "session.h" #include "session.h"
@ -86,7 +86,7 @@ enum {
REMOTEMSG_TYPE_IDENT_REQUEST, REMOTEMSG_TYPE_IDENT_REQUEST,
REMOTEMSG_TYPE_SWITCH_CLOCK, REMOTEMSG_TYPE_SWITCH_CLOCK,
REMOTEMSG_TYPE_LOAD_OBJECT, REMOTEMSG_TYPE_LOAD_LIBRARY,
REMOTEMSG_TYPE_RUN_KERNEL, REMOTEMSG_TYPE_RUN_KERNEL,
REMOTEMSG_TYPE_RPC_REPLY, REMOTEMSG_TYPE_RPC_REPLY,
@ -161,23 +161,22 @@ static int process_input(void)
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_FAILED; buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_FAILED;
submit_output(9); submit_output(9);
break; break;
case REMOTEMSG_TYPE_LOAD_OBJECT: case REMOTEMSG_TYPE_LOAD_LIBRARY:
if(user_kernel_state >= USER_KERNEL_RUNNING) { if(user_kernel_state >= USER_KERNEL_RUNNING) {
log("Attempted to load new kernel while already running"); log("Attempted to load new kernel library while already running");
buffer_out[8] = REMOTEMSG_TYPE_LOAD_FAILED; buffer_out[8] = REMOTEMSG_TYPE_LOAD_FAILED;
submit_output(9); submit_output(9);
break; break;
} }
if(kloader_load(&buffer_in[9], get_in_packet_len() - 8)) { if(kloader_load_library(&buffer_in[9])) {
buffer_out[8] = REMOTEMSG_TYPE_LOAD_COMPLETED; buffer_out[8] = REMOTEMSG_TYPE_LOAD_COMPLETED;
user_kernel_state = USER_KERNEL_LOADED; user_kernel_state = USER_KERNEL_LOADED;
} else } else {
buffer_out[8] = REMOTEMSG_TYPE_LOAD_FAILED; buffer_out[8] = REMOTEMSG_TYPE_LOAD_FAILED;
}
submit_output(9); submit_output(9);
break; break;
case REMOTEMSG_TYPE_RUN_KERNEL: { case REMOTEMSG_TYPE_RUN_KERNEL: {
kernel_function k;
if(user_kernel_state != USER_KERNEL_LOADED) { if(user_kernel_state != USER_KERNEL_LOADED) {
log("Attempted to run kernel while not in the LOADED state"); log("Attempted to run kernel while not in the LOADED state");
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED; buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
@ -193,16 +192,14 @@ static int process_input(void)
} }
buffer_in[buffer_in_index] = 0; buffer_in[buffer_in_index] = 0;
k = kloader_find((char *)&buffer_in[9]); watchdog_init();
if(k == NULL) { if(!kloader_start_kernel((char *)&buffer_in[9])) {
log("Failed to find kernel entry point '%s' in object", &buffer_in[9]); log("Failed to find kernel entry point '%s' in object", &buffer_in[9]);
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED; buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
submit_output(9); submit_output(9);
break; break;
} }
watchdog_init();
kloader_start_user_kernel(k);
user_kernel_state = USER_KERNEL_RUNNING; user_kernel_state = USER_KERNEL_RUNNING;
break; break;
} }
@ -215,7 +212,7 @@ static int process_input(void)
} }
reply.type = MESSAGE_TYPE_RPC_REPLY; reply.type = MESSAGE_TYPE_RPC_REPLY;
memcpy(&reply.eid, &buffer_in[9], 4); // FIXME memcpy(&reply.eid, &buffer_in[9], 4);
memcpy(&reply.retval, &buffer_in[13], 4); memcpy(&reply.retval, &buffer_in[13], 4);
mailbox_send_and_wait(&reply); mailbox_send_and_wait(&reply);
user_kernel_state = USER_KERNEL_RUNNING; user_kernel_state = USER_KERNEL_RUNNING;
@ -481,8 +478,8 @@ static int process_kmsg(struct msg_base *umsg)
struct msg_exception *msg = (struct msg_exception *)umsg; struct msg_exception *msg = (struct msg_exception *)umsg;
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_EXCEPTION; buffer_out[8] = REMOTEMSG_TYPE_KERNEL_EXCEPTION;
memcpy(&buffer_out[9], &msg->eid, 4); // memcpy(&buffer_out[9], &msg->eid, 4);
memcpy(&buffer_out[13], msg->eparams, 3*8); // memcpy(&buffer_out[13], msg->eparams, 3*8);
submit_output(9+4+3*8); submit_output(9+4+3*8);
kloader_stop(); kloader_stop();

View File

@ -1,6 +1,6 @@
#include <generated/csr.h> #include <generated/csr.h>
#include "exceptions.h" #include "artiq_personality.h"
#include "rtio.h" #include "rtio.h"
#include "ttl.h" #include "ttl.h"
@ -40,7 +40,8 @@ long long int ttl_get(int channel, long long int time_limit)
while((status = rtio_i_status_read())) { while((status = rtio_i_status_read())) {
if(rtio_i_status_read() & RTIO_I_STATUS_OVERFLOW) { if(rtio_i_status_read() & RTIO_I_STATUS_OVERFLOW) {
rtio_i_overflow_reset_write(1); rtio_i_overflow_reset_write(1);
exception_raise_params(EID_RTIO_OVERFLOW, artiq_raise_from_c("RTIOOverflow",
"RTIO overflow at channel {0}",
channel, 0, 0); channel, 0, 0);
} }
if(rtio_get_counter() >= time_limit) { if(rtio_get_counter() >= time_limit) {