Files
mckernel/kernel/init.c
2018-02-06 10:40:12 +09:00

412 lines
9.0 KiB
C

/**
* \file kernel/init.c
* License details are found in the file LICENSE.
* \brief
* main function and initializer
* \author Taku Shimosawa <shimosawa@is.s.u-tokyo.ac.jp> \par
* Copyright (C) 2011 - 2012 Taku Shimosawa
* \author Balazs Gerofi <bgerofi@riken.jp> \par
* Copyright (C) 2012 RIKEN AICS
* \author Tomoki Shirasawa <tomoki.shirasawa.kk@hitachi-solutions.com> \par
* Copyright (C) 2012 - 2013 Hitachi, Ltd.
* \author Balazs Gerofi <bgerofi@is.s.u-tokyo.ac.jp> \par
* Copyright (C) 2013 The University of Tokyo
*/
/*
* HISTORY:
* 2013/09/02 shirasawa add terminate thread
* 2013/06/02 balazs resolved merge conflicts with futex code
* 2013/05/20 simin exchange the dcfa stuff init/exit order in mcexec
*/
#include <types.h>
#include <kmsg.h>
#include <kmalloc.h>
#include <ihk/cpu.h>
#include <ihk/mm.h>
#include <ihk/debug.h>
#include <ihk/dma.h>
#include <ihk/perfctr.h>
#include <process.h>
#include <init.h>
#include <cls.h>
#include <syscall.h>
#include <sysfs.h>
#include <ihk/monitor.h>
//#define IOCTL_FUNC_EXTENSION
#ifdef IOCTL_FUNC_EXTENSION
#include <ioctl.h>
#endif
//#define DEBUG_PRINT_INIT
#ifdef DEBUG_PRINT_INIT
#define dkprintf(...) do { kprintf(__VA_ARGS__); } while (0)
#define ekprintf(...) do { kprintf(__VA_ARGS__); } while (0)
#else
#define dkprintf(...) do { } while (0)
#define ekprintf(...) do { kprintf(__VA_ARGS__); } while (0)
#endif
#define DUMP_LEVEL_USER_UNUSED_EXCLUDE 24
extern unsigned long ihk_mc_get_ns_per_tsc(void);
extern long syscall(int, ihk_mc_user_context_t *);
struct ihk_os_monitor *monitor;
struct rusage_global *rusage;
static void handler_init(void)
{
ihk_mc_set_syscall_handler(syscall);
}
unsigned long data[1024] __attribute__((aligned(64)));
#ifdef USE_DMA
static void dma_test(void)
{
struct ihk_dma_request req;
unsigned long fin = 0;
int i, j;
for (j = 0; j < 2; ++j) {
fin = 0;
memset(data, 0, 1024 * sizeof(unsigned long));
for (i = 0; i < 8; i++) {
data[i] = i;
}
kprintf("DMA Test Started.\n");
memset(&req, 0, sizeof(req));
req.src_os = IHK_THIS_OS;
req.src_phys = virt_to_phys(data);
req.dest_os = IHK_THIS_OS;
req.dest_phys = virt_to_phys(&data[256]);
req.size = 64;
req.notify = (void *)virt_to_phys(&fin);
req.notify_os = IHK_THIS_OS;
req.priv = (void *)0x2984;
kprintf("VtoP : %p, %lx\n", data, virt_to_phys(data));
kprintf("notify : %p, %lx (%lx)\n", &fin, virt_to_phys(&fin),
sizeof(req));
if (ihk_mc_dma_request(0, &req) != 0) {
kprintf("Failed to request DMA!\n");
}
kprintf("DMA Test Wait.\n");
while (!fin) {
barrier();
}
kprintf("DMA Test End.\n");
for (i = 0; i < 8; i++) {
if (data[i] != data[256 + i]) {
kprintf("DMA result is inconsistent!\n");
panic("");
}
}
}
}
#endif
extern char *ihk_get_kargs(void);
char *find_command_line(char *name)
{
char *cmdline = ihk_get_kargs();
if (!cmdline) {
return NULL;
}
return strstr(cmdline, name);
}
static void parse_kargs(void)
{
char *ptr;
char *key_dump_level = "dump_level=";
unsigned int dump_level = DUMP_LEVEL_USER_UNUSED_EXCLUDE;
kprintf("KCommand Line: %s\n", ihk_get_kargs());
/* parse dump_level option */
ptr = find_command_line(key_dump_level);
if (ptr) {
ptr += strlen(key_dump_level);
dump_level = 0;
while (('0' <= *ptr) && (*ptr <= '9')) {
dump_level *= 10;
dump_level += *ptr++ - '0';
}
}
ihk_mc_set_dump_level(dump_level);
/* idle_halt option */
ptr = find_command_line("idle_halt");
if (ptr) {
idle_halt = 1;
}
}
extern void ihk_mc_get_boot_time(unsigned long *tv_sec, unsigned long *tv_nsec);
extern unsigned long ihk_mc_get_ns_per_tsc(void);
static void time_init(void)
{
unsigned long tv_sec, tv_nsec;
unsigned long ns_per_kclock;
unsigned long tsc;
ihk_mc_get_boot_time(&tv_sec, &tv_nsec);
ns_per_kclock = ihk_mc_get_ns_per_tsc();
tod_data.origin.tv_sec = tv_sec;
tod_data.origin.tv_nsec = tv_nsec;
if (ns_per_kclock) {
tod_data.clocks_per_sec = (1000L * NS_PER_SEC) / ns_per_kclock;
tsc = rdtsc();
tod_data.origin.tv_sec -= tsc / tod_data.clocks_per_sec;
tod_data.origin.tv_nsec -= NS_PER_SEC * (tsc % tod_data.clocks_per_sec)
/ tod_data.clocks_per_sec;
if (tod_data.origin.tv_nsec < 0) {
--tod_data.origin.tv_sec;
tod_data.origin.tv_nsec += NS_PER_SEC;
}
}
if (!ns_per_kclock) {
gettime_local_support = 0;
}
if (gettime_local_support) {
tod_data.do_local = 1;
}
return;
}
#ifdef POSTK_DEBUG_TEMP_FIX_73 /* NULL access for *monitor fix */
void monitor_init(void)
#else /* POSTK_DEBUG_TEMP_FIX_73 */
static void monitor_init()
#endif /* POSTK_DEBUG_TEMP_FIX_73 */
{
int z;
unsigned long phys;
#ifdef POSTK_DEBUG_TEMP_FIX_73 /* NULL access for *monitor fix */
const struct ihk_mc_cpu_info *cpu_info = ihk_mc_get_cpu_info();
if (!cpu_info) {
panic("PANIC: in monitor_init() ihk_mc_cpu_info is NULL.");
return;
}
z = sizeof(struct ihk_os_monitor) +
sizeof(struct ihk_os_cpu_monitor) * (cpu_info->ncpus - 1);
z = (z + PAGE_SIZE -1) >> PAGE_SHIFT;
monitor = ihk_mc_alloc_pages(z, IHK_MC_AP_CRITICAL);
memset(monitor, 0, z * PAGE_SIZE);
monitor->num_processors = (cpu_info->ncpus - 1);
phys = virt_to_phys(monitor);
ihk_set_monitor(phys, sizeof(struct ihk_os_monitor) +
sizeof(struct ihk_os_cpu_monitor) * (cpu_info->ncpus - 1));
return;
#else /* POSTK_DEBUG_TEMP_FIX_73 */
z = sizeof(struct ihk_os_monitor) +
sizeof(struct ihk_os_cpu_monitor) * num_processors;
z = (z + PAGE_SIZE -1) >> PAGE_SHIFT;
monitor = ihk_mc_alloc_pages(z, IHK_MC_AP_CRITICAL);
memset(monitor, 0, z * PAGE_SIZE);
monitor->num_processors = num_processors;
phys = virt_to_phys(monitor);
ihk_set_monitor(phys, sizeof(struct ihk_os_monitor) +
sizeof(struct ihk_os_cpu_monitor) * num_processors);
#endif /* POSTK_DEBUG_TEMP_FIX_73 */
}
int nmi_mode;
static void nmi_init()
{
unsigned long phys;
phys = virt_to_phys(&nmi_mode);
ihk_set_nmi_mode_addr(phys);
}
static void rest_init(void)
{
handler_init();
#ifdef USE_DMA
ihk_mc_dma_init();
dma_test();
#endif
ap_init();
#ifndef POSTK_DEBUG_TEMP_FIX_73 /* NULL access for *monitor fix */
monitor_init();
#endif /* !POSTK_DEBUG_TEMP_FIX_73 */
cpu_local_var_init();
nmi_init();
time_init();
kmalloc_init();
ihk_ikc_master_init();
proc_init();
sched_init();
}
static void setup_remote_snooping_samples(void)
{
static long lvalue = 0xf123456789abcde0;
static char *svalue = "string(remote)";
int error;
struct sysfs_bitmap_param param;
error = sysfs_createf(SYSFS_SNOOPING_OPS_d32, &lvalue, 0444, "/sys/test/remote/d32");
if (error) {
panic("setup_remote_snooping_samples: d32");
}
error = sysfs_createf(SYSFS_SNOOPING_OPS_d64, &lvalue, 0444, "/sys/test/remote/d64");
if (error) {
panic("setup_remote_snooping_samples: d64");
}
error = sysfs_createf(SYSFS_SNOOPING_OPS_u32, &lvalue, 0444, "/sys/test/remote/u32");
if (error) {
panic("setup_remote_snooping_samples: u32");
}
error = sysfs_createf(SYSFS_SNOOPING_OPS_u64, &lvalue, 0444, "/sys/test/remote/u64");
if (error) {
panic("setup_remote_snooping_samples: u64");
}
error = sysfs_createf(SYSFS_SNOOPING_OPS_s, svalue, 0444, "/sys/test/remote/s");
if (error) {
panic("setup_remote_snooping_samples: s");
}
param.nbits = 40;
param.ptr = &lvalue;
error = sysfs_createf(SYSFS_SNOOPING_OPS_pbl, &param, 0444, "/sys/test/remote/pbl");
if (error) {
panic("setup_remote_snooping_samples: pbl");
}
param.nbits = 40;
param.ptr = &lvalue;
error = sysfs_createf(SYSFS_SNOOPING_OPS_pb, &param, 0444, "/sys/test/remote/pb");
if (error) {
panic("setup_remote_snooping_samples: pb");
}
error = sysfs_createf(SYSFS_SNOOPING_OPS_u32K, &lvalue, 0444, "/sys/test/remote/u32K");
if (error) {
panic("setup_remote_snooping_samples: u32K");
}
return;
} /* setup_remote_snooping_samples() */
static void populate_sysfs(void)
{
cpu_sysfs_setup();
numa_sysfs_setup();
//setup_remote_snooping_samples();
} /* populate_sysfs() */
int host_ikc_inited = 0;
extern int num_processors;
static void post_init(void)
{
cpu_enable_interrupt();
while (!host_ikc_inited) {
barrier();
cpu_pause();
}
if (find_command_line("hidos")) {
int ikc_cpu = ihk_mc_get_ikc_cpu(ihk_mc_get_processor_id());
if(ikc_cpu < 0) {
ekprintf("%s,ihk_mc_get_ikc_cpu failed\n", __FUNCTION__);
}
init_host_ikc2mckernel();
init_host_ikc2linux(ikc_cpu);
}
arch_setup_vdso();
arch_start_pvclock();
ap_start();
sysfs_init();
populate_sysfs();
}
#ifdef DCFA_RUN
extern void user_main();
#endif
#ifdef DCFA_KMOD
extern int mc_cmd_client_init(void);
extern void ibmic_cmd_init(void);
#endif
int main(void)
{
arch_init();
/*
* In attached-mic,
* bootparam is not mapped until arch_init() is finished.
* In builtin-mic and builtin-x86,
* virtual address of bootparam is changed in arch_init().
*/
parse_kargs();
mem_init();
rest_init();
arch_ready();
post_init();
futex_init();
done_init();
kputs("IHK/McKernel booted.\n");
#ifdef DCFA_KMOD
mc_cmd_client_init();
#ifdef CMD_DCFA
ibmic_cmd_init();
#endif
#endif
#ifdef DCFA_RUN
kputs("DCFA begin\n");
user_main();
kputs("DCFA end\n");
#else
schedule();
#endif
return 0;
}