mirror of https://github.com/m-labs/artiq.git
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:
parent
6db93b34e8
commit
62fdc75d2d
|
@ -16,7 +16,7 @@ class _H2DMsgType(Enum):
|
|||
IDENT_REQUEST = 2
|
||||
SWITCH_CLOCK = 3
|
||||
|
||||
LOAD_OBJECT = 4
|
||||
LOAD_LIBRARY = 4
|
||||
RUN_KERNEL = 5
|
||||
|
||||
RPC_REPLY = 6
|
||||
|
@ -124,7 +124,7 @@ class CommGeneric:
|
|||
raise IOError("Incorrect reply from device: {}".format(ty))
|
||||
|
||||
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)
|
||||
_, ty = self._read_header()
|
||||
if ty != _D2HMsgType.LOAD_COMPLETED:
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
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_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o ttl.o dds.o
|
||||
OBJECTS := isr.o clock.o rtiocrg.o flash_storage.o mailbox.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
|
||||
|
||||
|
@ -19,7 +25,7 @@ all: runtime.bin runtime.fbi
|
|||
|
||||
runtime.elf: $(OBJECTS) libs
|
||||
$(LD) $(LDFLAGS) \
|
||||
-T linker.ld \
|
||||
-T runtime.ld \
|
||||
-N -o $@ \
|
||||
$(MSCDIR)/software/libbase/crt0-$(CPU).o \
|
||||
$(OBJECTS) \
|
||||
|
@ -29,24 +35,23 @@ runtime.elf: $(OBJECTS) libs
|
|||
-lbase -lcompiler-rt -llwip
|
||||
@chmod -x $@
|
||||
|
||||
ksupport.elf: $(OBJECTS_KSUPPORT)
|
||||
ksupport.elf: $(OBJECTS_KSUPPORT) libs
|
||||
$(LD) $(LDFLAGS) \
|
||||
--eh-frame-hdr \
|
||||
-T ksupport.ld \
|
||||
-N -o $@ \
|
||||
$(MSCDIR)/software/libbase/crt0-$(CPU).o \
|
||||
$^ \
|
||||
$(OBJECTS_KSUPPORT) \
|
||||
-L$(MSCDIR)/software/libbase \
|
||||
-L$(MSCDIR)/software/libcompiler-rt \
|
||||
-lcompiler-rt
|
||||
-L$(MSCDIR)/software/libunwind \
|
||||
-L$(MSCDIR)/software/libdyld \
|
||||
-lbase -lcompiler-rt -lunwind -ldyld
|
||||
@chmod -x $@
|
||||
|
||||
ksupport_data.o: ksupport.bin
|
||||
ksupport_data.o: ksupport.elf
|
||||
$(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
|
||||
$(compile-dep)
|
||||
|
||||
|
@ -58,13 +63,15 @@ main.o: main.c
|
|||
|
||||
libs:
|
||||
$(MAKE) -C $(MSCDIR)/software/libcompiler-rt
|
||||
$(MAKE) -C $(MSCDIR)/software/libunwind
|
||||
$(MAKE) -C $(MSCDIR)/software/libbase
|
||||
$(MAKE) -C $(MSCDIR)/software/libdyld
|
||||
$(MAKE) -C liblwip
|
||||
|
||||
clean:
|
||||
$(MAKE) -C liblwip clean
|
||||
$(RM) $(OBJECTS) $(OBJECTS:.o=.d) $(OBJECTS_KSUPPORT) $(OBJECTS_KSUPPORT:.o=.d)
|
||||
$(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
|
||||
|
|
|
@ -246,7 +246,9 @@ struct artiq_raised_exception {
|
|||
static struct artiq_raised_exception inflight;
|
||||
|
||||
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));
|
||||
inflight.unwind.exception_class = ARTIQ_EXCEPTION_CLASS;
|
||||
|
|
|
@ -32,7 +32,7 @@ static void send_ready(void)
|
|||
struct msg_base msg;
|
||||
|
||||
msg.type = MESSAGE_TYPE_BRG_READY;
|
||||
mailbox_send_and_wait(&msg);
|
||||
mailbox_send_and_wait(&msg);
|
||||
}
|
||||
|
||||
void bridge_main(void)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <generated/csr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "exceptions.h"
|
||||
#include "artiq_personality.h"
|
||||
#include "rtio.h"
|
||||
#include "log.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)
|
||||
{
|
||||
if(batch_mode)
|
||||
exception_raise(EID_DDS_BATCH_ERROR);
|
||||
artiq_raise_from_c("DDSBatchError", "DDS batch error", 0, 0, 0);
|
||||
batch_mode = 1;
|
||||
batch_count = 0;
|
||||
batch_ref_time = timestamp;
|
||||
|
@ -191,7 +191,7 @@ void dds_batch_exit(void)
|
|||
int i;
|
||||
|
||||
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);
|
||||
/* + FUD time */
|
||||
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_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) */
|
||||
batch[batch_count].channel = channel;
|
||||
batch[batch_count].ftw = ftw;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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()
|
|
@ -1,120 +1,82 @@
|
|||
#include <string.h>
|
||||
#include <generated/csr.h>
|
||||
|
||||
#include <dyld.h>
|
||||
|
||||
#include "kloader.h"
|
||||
#include "log.h"
|
||||
#include "flash_storage.h"
|
||||
#include "mailbox.h"
|
||||
#include "messages.h"
|
||||
#include "elf_loader.h"
|
||||
#include "services.h"
|
||||
#include "kloader.h"
|
||||
|
||||
static struct symbol symtab[128];
|
||||
static int _symtab_count;
|
||||
static char _symtab_strings[128*16];
|
||||
static char *_symtab_strptr;
|
||||
|
||||
static void symtab_init(void)
|
||||
static void start_kernel_cpu(struct msg_load_request *msg)
|
||||
{
|
||||
memset(symtab, 0, sizeof(symtab));
|
||||
_symtab_count = 0;
|
||||
_symtab_strptr = _symtab_strings;
|
||||
// Stop kernel CPU before messing with its code.
|
||||
kernel_cpu_reset_write(1);
|
||||
|
||||
// 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])) {
|
||||
log("Too many provided symbols in object");
|
||||
symtab_init();
|
||||
return 0;
|
||||
}
|
||||
symtab[_symtab_count].name = _symtab_strptr;
|
||||
symtab[_symtab_count].target = target;
|
||||
_symtab_count++;
|
||||
start_kernel_cpu(NULL);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
if(_symtab_strptr >= &_symtab_strings[sizeof(_symtab_strings)]) {
|
||||
log("Provided symbol string table overflow");
|
||||
symtab_init();
|
||||
return 0;
|
||||
}
|
||||
*_symtab_strptr = *name;
|
||||
_symtab_strptr++;
|
||||
if(*name == 0)
|
||||
break;
|
||||
name++;
|
||||
static int load_or_start_kernel(void *library, const char *kernel)
|
||||
{
|
||||
static struct dyld_info library_info;
|
||||
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 1;
|
||||
}
|
||||
|
||||
int kloader_load(void *buffer, int length)
|
||||
int kloader_load_library(void *library)
|
||||
{
|
||||
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;
|
||||
}
|
||||
symtab_init();
|
||||
return load_elf(
|
||||
resolve_service_symbol, symtab_add,
|
||||
buffer, length, (void *)KERNELCPU_PAYLOAD_ADDRESS, 4*1024*1024);
|
||||
|
||||
return load_or_start_kernel(library, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
extern char _binary_ksupport_bin_end;
|
||||
|
||||
static void start_kernel_cpu(void *addr)
|
||||
int kloader_start_idle_kernel(void)
|
||||
{
|
||||
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)
|
||||
len = fs_read("idle_kernel", buffer, sizeof(buffer), NULL);
|
||||
if(len <= 0)
|
||||
return;
|
||||
if(!kloader_load(buffer, len)) {
|
||||
log("Failed to load ELF binary for idle kernel");
|
||||
return;
|
||||
}
|
||||
k = kloader_find("run");
|
||||
if(!k) {
|
||||
log("Failed to find entry point for ELF kernel");
|
||||
return;
|
||||
}
|
||||
start_kernel_cpu((void *)k);
|
||||
char buffer[32*1024];
|
||||
int length;
|
||||
|
||||
length = fs_read("idle_kernel", buffer, sizeof(buffer), NULL);
|
||||
if(length <= 0)
|
||||
return 0;
|
||||
|
||||
return load_or_start_kernel(buffer, "test.__modinit__");
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -127,7 +89,7 @@ void kloader_stop(void)
|
|||
int kloader_validate_kpointer(void *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);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
#ifndef __KLOADER_H
|
||||
#define __KLOADER_H
|
||||
|
||||
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
||||
#define KERNELCPU_PAYLOAD_ADDRESS 0x40408000
|
||||
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
||||
#define KERNELCPU_PAYLOAD_ADDRESS 0x40420000
|
||||
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
|
||||
#define KSUPPORT_HEADER_SIZE 0x80
|
||||
|
||||
extern long long int now;
|
||||
|
||||
typedef void (*kernel_function)(void);
|
||||
|
||||
int kloader_load(void *buffer, int length);
|
||||
kernel_function kloader_find(const char *name);
|
||||
int kloader_load_library(void *code);
|
||||
|
||||
void kloader_start_bridge(void);
|
||||
void kloader_start_idle_kernel(void);
|
||||
void kloader_start_user_kernel(kernel_function k);
|
||||
int kloader_start_idle_kernel(void);
|
||||
int kloader_start_kernel(const char *name);
|
||||
void kloader_stop(void);
|
||||
|
||||
int kloader_validate_kpointer(void *p);
|
||||
|
|
|
@ -1,67 +1,254 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "exceptions.h"
|
||||
#include "bridge.h"
|
||||
#include <link.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dyld.h>
|
||||
#include <unwind.h>
|
||||
|
||||
#include "ksupport.h"
|
||||
#include "kloader.h"
|
||||
#include "mailbox.h"
|
||||
#include "messages.h"
|
||||
#include "rtio.h"
|
||||
#include "bridge.h"
|
||||
#include "artiq_personality.h"
|
||||
#include "ttl.h"
|
||||
#include "dds.h"
|
||||
#include "rtio.h"
|
||||
|
||||
/* for the prototypes for watchdog_set() and watchdog_clear() */
|
||||
#include "clock.h"
|
||||
/* for the prototype for rpc() */
|
||||
#include "session.h"
|
||||
/* for the prototype for log() */
|
||||
#include "log.h"
|
||||
/* compiler-rt symbols */
|
||||
extern void __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;
|
||||
|
||||
void exception_handler(unsigned long vect, unsigned long *sp);
|
||||
void exception_handler(unsigned long vect, unsigned long *sp)
|
||||
/* artiq_personality symbols */
|
||||
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;
|
||||
msg.eid = EID_INTERNAL_ERROR;
|
||||
msg.eparams[0] = 256;
|
||||
msg.eparams[1] = 256;
|
||||
msg.eparams[2] = 256;
|
||||
mailbox_send_and_wait(&msg);
|
||||
while(1);
|
||||
request.type = MESSAGE_TYPE_LOG;
|
||||
request.fmt = fmt;
|
||||
request.no_newline = 1;
|
||||
va_start(request.args, fmt);
|
||||
mailbox_send_and_wait(&request);
|
||||
va_end(request.args);
|
||||
|
||||
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)
|
||||
{
|
||||
kernel_function k;
|
||||
void *jb;
|
||||
struct msg_load_request *msg = mailbox_receive();
|
||||
|
||||
k = mailbox_receive();
|
||||
|
||||
if(k == NULL)
|
||||
if(msg == NULL) {
|
||||
bridge_main();
|
||||
else {
|
||||
jb = exception_push();
|
||||
if(exception_setjmp(jb)) {
|
||||
struct msg_exception msg;
|
||||
while(1);
|
||||
}
|
||||
|
||||
msg.type = MESSAGE_TYPE_EXCEPTION;
|
||||
msg.eid = exception_getid(msg.eparams);
|
||||
mailbox_send_and_wait(&msg);
|
||||
} else {
|
||||
struct msg_base msg;
|
||||
|
||||
k();
|
||||
exception_pop(1);
|
||||
|
||||
msg.type = MESSAGE_TYPE_FINISHED;
|
||||
mailbox_send_and_wait(&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);
|
||||
|
||||
struct msg_base msg;
|
||||
msg.type = MESSAGE_TYPE_FINISHED;
|
||||
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);
|
||||
}
|
||||
|
||||
long long int now_init(void);
|
||||
long long int now_init(void)
|
||||
{
|
||||
struct msg_base request;
|
||||
|
@ -72,8 +259,10 @@ long long int now_init(void)
|
|||
mailbox_send_and_wait(&request);
|
||||
|
||||
reply = mailbox_wait_and_receive();
|
||||
if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY)
|
||||
exception_raise_params(EID_INTERNAL_ERROR, 1, 0, 0);
|
||||
if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY) {
|
||||
log("Malformed MESSAGE_TYPE_NOW_INIT_REQUEST reply type");
|
||||
while(1);
|
||||
}
|
||||
now = reply->now;
|
||||
mailbox_acknowledge();
|
||||
|
||||
|
@ -85,7 +274,6 @@ long long int now_init(void)
|
|||
return now;
|
||||
}
|
||||
|
||||
void now_save(long long int now);
|
||||
void now_save(long long int now)
|
||||
{
|
||||
struct msg_now_save request;
|
||||
|
@ -106,8 +294,10 @@ int watchdog_set(int ms)
|
|||
mailbox_send_and_wait(&request);
|
||||
|
||||
reply = mailbox_wait_and_receive();
|
||||
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY)
|
||||
exception_raise_params(EID_INTERNAL_ERROR, 2, 0, 0);
|
||||
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY) {
|
||||
log("Malformed MESSAGE_TYPE_WATCHDOG_SET_REQUEST reply type");
|
||||
while(1);
|
||||
}
|
||||
id = reply->id;
|
||||
mailbox_acknowledge();
|
||||
|
||||
|
@ -127,7 +317,6 @@ int rpc(int rpc_num, ...)
|
|||
{
|
||||
struct msg_rpc_request request;
|
||||
struct msg_rpc_reply *reply;
|
||||
int eid, retval;
|
||||
|
||||
request.type = MESSAGE_TYPE_RPC_REQUEST;
|
||||
request.rpc_num = rpc_num;
|
||||
|
@ -136,15 +325,21 @@ int rpc(int rpc_num, ...)
|
|||
va_end(request.args);
|
||||
|
||||
reply = mailbox_wait_and_receive();
|
||||
if(reply->type != MESSAGE_TYPE_RPC_REPLY)
|
||||
exception_raise_params(EID_INTERNAL_ERROR, 3, 0, 0);
|
||||
eid = reply->eid;
|
||||
retval = reply->retval;
|
||||
mailbox_acknowledge();
|
||||
if(reply->type != MESSAGE_TYPE_RPC_REPLY) {
|
||||
log("Malformed MESSAGE_TYPE_RPC_REPLY reply type");
|
||||
while(1);
|
||||
}
|
||||
|
||||
if(eid != EID_NONE)
|
||||
exception_raise(eid);
|
||||
return retval;
|
||||
if(reply->exception != NULL) {
|
||||
struct artiq_exception exception;
|
||||
memcpy(&exception, reply->exception, sizeof(exception));
|
||||
mailbox_acknowledge();
|
||||
__artiq_raise(&exception);
|
||||
} else {
|
||||
int retval = reply->retval;
|
||||
mailbox_acknowledge();
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void lognonl(const char *fmt, ...)
|
||||
|
|
|
@ -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 */
|
|
@ -4,10 +4,10 @@ ENTRY(_start)
|
|||
INCLUDE generated/regions.ld
|
||||
|
||||
/* 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 {
|
||||
ksupport : ORIGIN = 0x40400000, LENGTH = 0x8000
|
||||
ksupport (RWX) : ORIGIN = 0x40400000, LENGTH = 0x20000
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Force ld to make the ELF header as loadable. */
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FILEHDR PHDRS;
|
||||
eh_frame PT_GNU_EH_FRAME;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
|
@ -22,7 +29,7 @@ SECTIONS
|
|||
_ftext = .;
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
_etext = .;
|
||||
} > ksupport
|
||||
} :text
|
||||
|
||||
.rodata :
|
||||
{
|
||||
|
@ -33,6 +40,16 @@ SECTIONS
|
|||
_erodata = .;
|
||||
} > ksupport
|
||||
|
||||
.eh_frame :
|
||||
{
|
||||
*(.eh_frame)
|
||||
} :text
|
||||
|
||||
.eh_frame_hdr :
|
||||
{
|
||||
*(.eh_frame_hdr)
|
||||
} :text :eh_frame
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
@ -41,7 +58,7 @@ SECTIONS
|
|||
*(.data1)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
_edata = .;
|
||||
} > ksupport
|
||||
}
|
||||
|
||||
.bss :
|
||||
{
|
||||
|
@ -57,5 +74,5 @@ SECTIONS
|
|||
_ebss = .;
|
||||
. = ALIGN(8);
|
||||
_heapstart = .;
|
||||
} > ksupport
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define __MESSAGES_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum {
|
||||
MESSAGE_TYPE_LOAD_REPLY,
|
||||
MESSAGE_TYPE_NOW_INIT_REQUEST,
|
||||
MESSAGE_TYPE_NOW_INIT_REPLY,
|
||||
MESSAGE_TYPE_NOW_SAVE,
|
||||
|
@ -34,6 +36,17 @@ struct msg_base {
|
|||
|
||||
/* 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 {
|
||||
int type;
|
||||
long long int now;
|
||||
|
@ -46,8 +59,9 @@ struct msg_now_save {
|
|||
|
||||
struct msg_exception {
|
||||
int type;
|
||||
int eid;
|
||||
long long int eparams[3];
|
||||
struct artiq_exception *exception;
|
||||
struct artiq_backtrace_item *backtrace;
|
||||
size_t backtrace_size;
|
||||
};
|
||||
|
||||
struct msg_watchdog_set_request {
|
||||
|
@ -73,7 +87,7 @@ struct msg_rpc_request {
|
|||
|
||||
struct msg_rpc_reply {
|
||||
int type;
|
||||
int eid;
|
||||
struct artiq_exception *exception;
|
||||
int retval;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define __RTIO_H
|
||||
|
||||
#include <generated/csr.h>
|
||||
#include "exceptions.h"
|
||||
#include "artiq_personality.h"
|
||||
|
||||
#define RTIO_O_STATUS_FULL 1
|
||||
#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);
|
||||
if(status & RTIO_O_STATUS_UNDERFLOW) {
|
||||
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());
|
||||
}
|
||||
if(status & RTIO_O_STATUS_SEQUENCE_ERROR) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@ MEMORY {
|
|||
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,
|
||||
* and ends before the runtime stack.
|
||||
* Runtime stack is always at the end of main_ram.
|
||||
|
@ -17,6 +24,11 @@ MEMORY {
|
|||
*/
|
||||
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
|
||||
{
|
||||
.text :
|
||||
|
@ -58,6 +70,12 @@ SECTIONS
|
|||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
. = ALIGN(8);
|
||||
_heapstart = .;
|
||||
} > runtime
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.eh_frame)
|
||||
}
|
||||
|
||||
_heapstart = .;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __SERVICES_H
|
||||
#define __SERVICES_H
|
||||
|
||||
void *resolve_service_symbol(const char *name);
|
||||
|
||||
#endif /* __SERVICES_H */
|
|
@ -10,7 +10,7 @@
|
|||
#include "clock.h"
|
||||
#include "log.h"
|
||||
#include "kloader.h"
|
||||
#include "exceptions.h"
|
||||
#include "artiq_personality.h"
|
||||
#include "flash_storage.h"
|
||||
#include "rtiocrg.h"
|
||||
#include "session.h"
|
||||
|
@ -19,7 +19,7 @@
|
|||
#define BUFFER_OUT_SIZE (1024*1024)
|
||||
|
||||
static int buffer_in_index;
|
||||
/* The 9th byte (right after the header) of buffer_in must be aligned
|
||||
/* The 9th byte (right after the header) of buffer_in must be aligned
|
||||
* to a 32-bit boundary for elf_loader to work.
|
||||
*/
|
||||
static struct {
|
||||
|
@ -85,8 +85,8 @@ enum {
|
|||
REMOTEMSG_TYPE_LOG_REQUEST = 1,
|
||||
REMOTEMSG_TYPE_IDENT_REQUEST,
|
||||
REMOTEMSG_TYPE_SWITCH_CLOCK,
|
||||
|
||||
REMOTEMSG_TYPE_LOAD_OBJECT,
|
||||
|
||||
REMOTEMSG_TYPE_LOAD_LIBRARY,
|
||||
REMOTEMSG_TYPE_RUN_KERNEL,
|
||||
|
||||
REMOTEMSG_TYPE_RPC_REPLY,
|
||||
|
@ -161,23 +161,22 @@ static int process_input(void)
|
|||
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_FAILED;
|
||||
submit_output(9);
|
||||
break;
|
||||
case REMOTEMSG_TYPE_LOAD_OBJECT:
|
||||
case REMOTEMSG_TYPE_LOAD_LIBRARY:
|
||||
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;
|
||||
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;
|
||||
user_kernel_state = USER_KERNEL_LOADED;
|
||||
} else
|
||||
} else {
|
||||
buffer_out[8] = REMOTEMSG_TYPE_LOAD_FAILED;
|
||||
}
|
||||
submit_output(9);
|
||||
break;
|
||||
case REMOTEMSG_TYPE_RUN_KERNEL: {
|
||||
kernel_function k;
|
||||
|
||||
if(user_kernel_state != USER_KERNEL_LOADED) {
|
||||
log("Attempted to run kernel while not in the LOADED state");
|
||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
|
||||
|
@ -193,16 +192,14 @@ static int process_input(void)
|
|||
}
|
||||
buffer_in[buffer_in_index] = 0;
|
||||
|
||||
k = kloader_find((char *)&buffer_in[9]);
|
||||
if(k == NULL) {
|
||||
watchdog_init();
|
||||
if(!kloader_start_kernel((char *)&buffer_in[9])) {
|
||||
log("Failed to find kernel entry point '%s' in object", &buffer_in[9]);
|
||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_STARTUP_FAILED;
|
||||
submit_output(9);
|
||||
break;
|
||||
}
|
||||
|
||||
watchdog_init();
|
||||
kloader_start_user_kernel(k);
|
||||
user_kernel_state = USER_KERNEL_RUNNING;
|
||||
break;
|
||||
}
|
||||
|
@ -215,7 +212,7 @@ static int process_input(void)
|
|||
}
|
||||
|
||||
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);
|
||||
mailbox_send_and_wait(&reply);
|
||||
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;
|
||||
|
||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_EXCEPTION;
|
||||
memcpy(&buffer_out[9], &msg->eid, 4);
|
||||
memcpy(&buffer_out[13], msg->eparams, 3*8);
|
||||
// memcpy(&buffer_out[9], &msg->eid, 4);
|
||||
// memcpy(&buffer_out[13], msg->eparams, 3*8);
|
||||
submit_output(9+4+3*8);
|
||||
|
||||
kloader_stop();
|
||||
|
@ -545,7 +542,7 @@ void session_poll(void **data, int *len)
|
|||
|
||||
l = get_out_packet_len();
|
||||
|
||||
/* If the output buffer is available,
|
||||
/* If the output buffer is available,
|
||||
* check if the kernel CPU has something to transmit.
|
||||
*/
|
||||
if(l == 0) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <generated/csr.h>
|
||||
|
||||
#include "exceptions.h"
|
||||
#include "artiq_personality.h"
|
||||
#include "rtio.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())) {
|
||||
if(rtio_i_status_read() & RTIO_I_STATUS_OVERFLOW) {
|
||||
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);
|
||||
}
|
||||
if(rtio_get_counter() >= time_limit) {
|
||||
|
|
Loading…
Reference in New Issue