412 lines
9.0 KiB
C
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, ¶m, 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, ¶m, 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;
|
|
}
|