runtime: eliminate struct dyld_info from kernel interface.

This commit is contained in:
whitequark 2016-09-30 01:25:46 +00:00
parent c6a57d2043
commit 7cfa667d98
4 changed files with 51 additions and 56 deletions

View File

@ -1,8 +1,6 @@
#include <string.h> #include <string.h>
#include <generated/csr.h> #include <generated/csr.h>
#include <dyld.h>
#include "kloader.h" #include "kloader.h"
#include "log.h" #include "log.h"
#include "clock.h" #include "clock.h"
@ -10,8 +8,13 @@
#include "mailbox.h" #include "mailbox.h"
#include "messages.h" #include "messages.h"
static void start_kernel_cpu(struct msg_load_request *msg) int kloader_load_library(const void *library)
{ {
if(!kernel_cpu_reset_read()) {
core_log("BUG: attempted to load kernel library while kernel CPU is running\n");
return 0;
}
// Stop kernel CPU before messing with its code. // Stop kernel CPU before messing with its code.
kernel_cpu_reset_write(1); kernel_cpu_reset_write(1);
@ -22,22 +25,15 @@ static void start_kernel_cpu(struct msg_load_request *msg)
&_binary_ksupport_elf_end - &_binary_ksupport_elf_start); &_binary_ksupport_elf_end - &_binary_ksupport_elf_start);
// Start kernel CPU. // Start kernel CPU.
mailbox_send(msg);
kernel_cpu_reset_write(0); kernel_cpu_reset_write(0);
}
static int load_or_start_kernel(const void *library, int run_kernel)
{
static struct dyld_info library_info;
struct msg_load_request request = { struct msg_load_request request = {
.library = library, .type = MESSAGE_TYPE_LOAD_REQUEST,
.library_info = &library_info, .library = library,
.run_kernel = run_kernel,
}; };
start_kernel_cpu(&request); mailbox_send(&request);
struct msg_load_reply *reply = mailbox_wait_and_receive(); struct msg_load_reply *reply = mailbox_wait_and_receive();
mailbox_acknowledge();
if(reply->type != MESSAGE_TYPE_LOAD_REPLY) { if(reply->type != MESSAGE_TYPE_LOAD_REPLY) {
core_log("BUG: unexpected reply to load/run request\n"); core_log("BUG: unexpected reply to load/run request\n");
@ -52,14 +48,14 @@ static int load_or_start_kernel(const void *library, int run_kernel)
return 1; return 1;
} }
int kloader_load_library(const void *library) void kloader_start_kernel()
{ {
if(!kernel_cpu_reset_read()) { if(kernel_cpu_reset_read()) {
core_log("BUG: attempted to load kernel library while kernel CPU is running\n"); core_log("BUG: attempted to load kernel library while kernel CPU is stopped\n");
return 0; return;
} }
return load_or_start_kernel(library, 0); mailbox_acknowledge();
} }
void kloader_filter_backtrace(struct artiq_backtrace_item *backtrace, void kloader_filter_backtrace(struct artiq_backtrace_item *backtrace,
@ -78,11 +74,6 @@ void kloader_filter_backtrace(struct artiq_backtrace_item *backtrace,
*backtrace_size = cursor - backtrace; *backtrace_size = cursor - backtrace;
} }
void kloader_start_kernel()
{
load_or_start_kernel(NULL, 1);
}
static int kloader_start_flash_kernel(char *key) static int kloader_start_flash_kernel(char *key)
{ {
#if (defined CSR_SPIFLASH_BASE && defined CONFIG_SPIFLASH_PAGE_SIZE) #if (defined CSR_SPIFLASH_BASE && defined CONFIG_SPIFLASH_PAGE_SIZE)
@ -98,7 +89,10 @@ static int kloader_start_flash_kernel(char *key)
return 0; return 0;
} }
return load_or_start_kernel(buffer, 1); if(!kloader_load_library(buffer))
return 0;
kloader_start_kernel();
return 1;
#else #else
return 0; return 0;
#endif #endif

View File

@ -370,44 +370,40 @@ static void now_save(void)
int main(void); int main(void);
int main(void) int main(void)
{ {
struct msg_load_request *request = mailbox_receive(); static struct dyld_info library_info;
struct msg_load_request *request = mailbox_wait_and_receive();
struct msg_load_reply load_reply = { struct msg_load_reply load_reply = {
.type = MESSAGE_TYPE_LOAD_REPLY, .type = MESSAGE_TYPE_LOAD_REPLY,
.error = NULL .error = NULL
}; };
if(request->library != NULL) { if(!dyld_load(request->library, KERNELCPU_PAYLOAD_ADDRESS,
if(!dyld_load(request->library, KERNELCPU_PAYLOAD_ADDRESS, resolve_runtime_export, &library_info,
resolve_runtime_export, request->library_info, &load_reply.error)) {
&load_reply.error)) {
mailbox_send(&load_reply);
while(1);
}
void *__bss_start = dyld_lookup("__bss_start", request->library_info);
void *_end = dyld_lookup("_end", request->library_info);
memset(__bss_start, 0, _end - __bss_start);
}
if(request->run_kernel) {
void (*kernel_run)() = request->library_info->init;
void *typeinfo = dyld_lookup("typeinfo", request->library_info);
mailbox_send_and_wait(&load_reply);
now_init();
kernel_run();
now_save();
attribute_writeback(typeinfo);
struct msg_base finished_reply;
finished_reply.type = MESSAGE_TYPE_FINISHED;
mailbox_send_and_wait(&finished_reply);
} else {
mailbox_send(&load_reply); mailbox_send(&load_reply);
while(1);
} }
void *__bss_start = dyld_lookup("__bss_start", &library_info);
void *_end = dyld_lookup("_end", &library_info);
memset(__bss_start, 0, _end - __bss_start);
void (*kernel_run)() = library_info.init;
void *typeinfo = dyld_lookup("typeinfo", &library_info);
mailbox_send_and_wait(&load_reply);
now_init();
kernel_run();
now_save();
attribute_writeback(typeinfo);
struct msg_base finished_reply;
finished_reply.type = MESSAGE_TYPE_FINISHED;
mailbox_send_and_wait(&finished_reply);
while(1); while(1);
} }

View File

@ -6,6 +6,7 @@
#include <stdint.h> #include <stdint.h>
enum { enum {
MESSAGE_TYPE_LOAD_REQUEST,
MESSAGE_TYPE_LOAD_REPLY, MESSAGE_TYPE_LOAD_REPLY,
MESSAGE_TYPE_NOW_INIT_REQUEST, MESSAGE_TYPE_NOW_INIT_REQUEST,
MESSAGE_TYPE_NOW_INIT_REPLY, MESSAGE_TYPE_NOW_INIT_REPLY,
@ -33,9 +34,8 @@ struct msg_base {
/* kernel messages */ /* kernel messages */
struct msg_load_request { struct msg_load_request {
int type;
const void *library; const void *library;
struct dyld_info *library_info;
int run_kernel;
}; };
struct msg_load_reply { struct msg_load_reply {

View File

@ -929,6 +929,11 @@ static int process_kmsg(struct msg_base *umsg)
return 0; return 0;
if(kloader_is_essential_kmsg(umsg->type)) if(kloader_is_essential_kmsg(umsg->type))
return 1; /* handled elsewhere */ return 1; /* handled elsewhere */
if(user_kernel_state == USER_KERNEL_LOADED &&
umsg->type == MESSAGE_TYPE_LOAD_REPLY) {
// Kernel standing by.
return 1;
}
if(user_kernel_state == USER_KERNEL_WAIT_RPC && if(user_kernel_state == USER_KERNEL_WAIT_RPC &&
umsg->type == MESSAGE_TYPE_RPC_RECV_REQUEST) { umsg->type == MESSAGE_TYPE_RPC_RECV_REQUEST) {
// Handled and acknowledged when we receive // Handled and acknowledged when we receive