@@ -252,4 +252,24 @@ void *lkl_tls_get(struct lkl_tls_key *key);
*/
void lkl_print(const char *str, int len);
+/**
+ * lkl_panic - called during a kernel panic
+ *
+ */
+void lkl_panic(void);
+
+/**
+ * lkl_start_kernel() - registers the host operations and starts the kernel
+ *
+ * @ops: pointer to host operations
+ * @fmt: format for command line string that is going to be used to
+ * generate the Linux kernel command line
+ *
+ * Return: 0 if there is no error; otherwise non-zero value returns.
+ *
+ * The function returns only after the kernel is shutdown with lkl_sys_halt.
+ */
+int lkl_start_kernel(struct lkl_host_operations *ops,
+ const char *fmt, ...);
+
#endif
new file mode 100644
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/binfmts.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/personality.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/start_kernel.h>
+#include <linux/fdtable.h>
+#include <linux/tick.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <asm/host_ops.h>
+#include <asm/irq.h>
+#include <asm/unistd.h>
+#include <asm/syscalls.h>
+#include <asm/cpu.h>
+#include <os.h>
+#include <as-layout.h>
+
+
+static void *init_sem;
+static int is_running;
+
+
+struct lkl_host_operations *lkl_ops;
+
+long lkl_panic_blink(int state)
+{
+ lkl_panic();
+ return 0;
+}
+
+static void __init *lkl_run_kernel(void *arg)
+{
+
+ panic_blink = lkl_panic_blink;
+
+ threads_init();
+ lkl_cpu_get();
+ start_kernel();
+
+ return NULL;
+}
+
+int __init lkl_start_kernel(struct lkl_host_operations *ops,
+ const char *fmt, ...)
+{
+ int ret;
+
+ lkl_ops = ops;
+
+ init_sem = lkl_sem_alloc(0);
+ if (!init_sem)
+ return -ENOMEM;
+
+ ret = lkl_cpu_init();
+ if (ret)
+ goto out_free_init_sem;
+
+ ret = lkl_thread_create(lkl_run_kernel, NULL);
+ if (!ret) {
+ ret = -ENOMEM;
+ goto out_free_init_sem;
+ }
+
+ lkl_sem_down(init_sem);
+ lkl_sem_free(init_sem);
+ current_thread_info()->task->thread.arch.tid = lkl_thread_self();
+ lkl_cpu_change_owner(current_thread_info()->task->thread.arch.tid);
+
+ lkl_cpu_put();
+ is_running = 1;
+
+ return 0;
+
+out_free_init_sem:
+ lkl_sem_free(init_sem);
+
+ return ret;
+}
+
+int lkl_is_running(void)
+{
+ return is_running;
+}
+
+
+long lkl_sys_halt(void)
+{
+ long err;
+ long params[6] = {LINUX_REBOOT_MAGIC1,
+ LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, };
+
+ err = lkl_syscall(__NR_reboot, params);
+ if (err < 0)
+ return err;
+
+ is_running = false;
+
+ lkl_cpu_wait_shutdown();
+
+ syscalls_cleanup();
+ threads_cleanup();
+ /* Shutdown the clockevents source. */
+ tick_suspend_local();
+ free_mem();
+ lkl_thread_join(current_thread_info()->task->thread.arch.tid);
+
+ return 0;
+}
+
+
+static int lkl_run_init(struct linux_binprm *bprm);
+
+static struct linux_binfmt lkl_run_init_binfmt = {
+ .module = THIS_MODULE,
+ .load_binary = lkl_run_init,
+};
+
+static int lkl_run_init(struct linux_binprm *bprm)
+{
+ int ret;
+
+ if (strcmp("/init", bprm->filename) != 0)
+ return -EINVAL;
+
+ ret = begin_new_exec(bprm);
+ if (ret)
+ return ret;
+ set_personality(PER_LINUX);
+ setup_new_exec(bprm);
+
+ set_binfmt(&lkl_run_init_binfmt);
+
+ init_pid_ns.child_reaper = 0;
+
+ syscalls_init();
+
+ lkl_sem_up(init_sem);
+ lkl_thread_exit();
+
+ return 0;
+}
+
+
+/* skip mounting the "real" rootfs. ramfs is good enough. */
+static int __init fs_setup(void)
+{
+ int fd, flags = 0;
+
+ if (force_o_largefile())
+ flags |= O_LARGEFILE;
+ fd = do_sys_open(AT_FDCWD, "/init", O_CREAT | flags, 0700);
+ WARN_ON(fd < 0);
+ close_fd(fd);
+
+ register_binfmt(&lkl_run_init_binfmt);
+
+ return 0;
+}
+late_initcall(fs_setup);
@@ -114,6 +114,8 @@ void os_kill_process(int pid, int reap_child)
void os_kill_ptraced_process(int pid, int reap_child)
{
+ if (pid == 0)
+ return;
kill(pid, SIGKILL);
ptrace(PTRACE_KILL, pid);
ptrace(PTRACE_CONT, pid);