the 'num_processors' symbol is also used by linux, so trying to load all symbols from linux and mckernel at the same time renders either symbol inaccessible (the first to be seen is kept by default). This provides an alternate name for the mckernel symbol, thus letting us access both more easily if required. Change-Id: I8074d4f9f9ac45717df9a8df16be710ff762e161
437 lines
9.4 KiB
C
437 lines
9.4 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>
|
|
#include <debug.h>
|
|
|
|
//#define IOCTL_FUNC_EXTENSION
|
|
#ifdef IOCTL_FUNC_EXTENSION
|
|
#include <ioctl.h>
|
|
#endif
|
|
|
|
//#define DEBUG_PRINT_INIT
|
|
|
|
#ifdef DEBUG_PRINT_INIT
|
|
#undef DDEBUG_DEFAULT
|
|
#define DDEBUG_DEFAULT DDEBUG_PRINT
|
|
#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);
|
|
}
|
|
|
|
|
|
/* Symbols with name conflict with the linux kernel
|
|
* Give the possibility to load all symbols at the same time
|
|
*/
|
|
int *mck_num_processors = &num_processors;
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
extern int safe_kernel_map;
|
|
|
|
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);
|
|
|
|
ptr = find_command_line("safe_kernel_map");
|
|
if (ptr) {
|
|
safe_kernel_map = 1;
|
|
}
|
|
|
|
/* idle_halt option */
|
|
ptr = find_command_line("idle_halt");
|
|
if (ptr) {
|
|
idle_halt = 1;
|
|
}
|
|
|
|
/* allow_oversubscribe option */
|
|
ptr = find_command_line("allow_oversubscribe");
|
|
if (ptr) {
|
|
allow_oversubscribe = 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 uti_init()
|
|
{
|
|
ihk_set_mckernel_do_futex((unsigned long)do_futex);
|
|
}
|
|
|
|
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();
|
|
uti_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();
|
|
dynamic_debug_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;
|
|
}
|