artiq/artiq/firmware/ksupport/glue.c

159 lines
3.4 KiB
C

#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <link.h>
#include <dlfcn.h>
struct slice {
void *ptr;
size_t len;
};
void send_to_core_log(struct slice str);
void send_to_rtio_log(struct slice data);
#define KERNELCPU_EXEC_ADDRESS 0x45000000
#define KERNELCPU_PAYLOAD_ADDRESS 0x45060000
#define KERNELCPU_LAST_ADDRESS 0x4fffffff
#define KSUPPORT_HEADER_SIZE 0x74
FILE *stderr;
/* called by libunwind */
char *getenv(const char *var)
{
return NULL;
}
/* called by libunwind */
int fprintf(FILE *stream, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
size_t size = vsnprintf(NULL, 0, fmt, args);
char *buf = __builtin_alloca(size + 1);
va_end(args);
va_start(args, fmt);
vsnprintf(buf, size + 1, fmt, args);
va_end(args);
struct slice str = { buf, size };
send_to_core_log(str);
return 0;
}
/* called by libunwind */
int fflush(FILE *stream)
{
return 0;
}
/* 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;
}
/* called by kernel */
double round(double x);
double round(double x)
{
union {double f; uint64_t i;} u = {x};
int e = u.i >> 52 & 0x7ff;
double y;
if (e >= 0x3ff+52)
return x;
if (u.i >> 63)
x = -x;
if (e < 0x3ff-1) {
/* we don't do it in ARTIQ */
/* raise inexact if x!=0 */
// FORCE_EVAL(x + 0x1p52);
return 0*u.f;
}
y = (double)(x + 0x1p52) - 0x1p52 - x;
if (y > 0.5)
y = y + x - 1;
else if (y <= -0.5)
y = y + x + 1;
else
y = y + x;
if (u.i >> 63)
y = -y;
return y;
}
/* called by kernel */
int core_log(const char *fmt, ...);
int core_log(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
size_t size = vsnprintf(NULL, 0, fmt, args);
char *buf = __builtin_alloca(size + 1);
va_end(args);
va_start(args, fmt);
vsnprintf(buf, size + 1, fmt, args);
va_end(args);
struct slice str = { buf, size };
send_to_core_log(str);
return 0;
}
/* called by kernel */
void rtio_log(const char *fmt, ...);
void rtio_log(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
size_t size = vsnprintf(NULL, 0, fmt, args);
char *buf = __builtin_alloca(size + 1);
va_end(args);
va_start(args, fmt);
vsnprintf(buf, size + 1, fmt, args);
va_end(args);
struct slice str = { buf, size };
send_to_rtio_log(str);
}