270 lines
5.6 KiB
C
270 lines
5.6 KiB
C
/* ap.c COPYRIGHT FUJITSU LIMITED 2015 */
|
|
/**
|
|
* \file ap.c
|
|
* Licence details are found in the file LICENSE.
|
|
*
|
|
* \brief
|
|
* Initiallization code for CPU cores other than the boot core.
|
|
*
|
|
* \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
|
|
*
|
|
*
|
|
* HISTORY:
|
|
* 2012/10/10: bgerofi - enable syscall channels for all MIC cores
|
|
*
|
|
*/
|
|
#include <types.h>
|
|
#include <kmsg.h>
|
|
#include <ihk/cpu.h>
|
|
#include <ihk/mm.h>
|
|
#include <ihk/debug.h>
|
|
#include <process.h>
|
|
#include <init.h>
|
|
#include <march.h>
|
|
#include <cls.h>
|
|
#include <time.h>
|
|
#include <syscall.h>
|
|
#include <rusage_private.h>
|
|
|
|
//#define DEBUG_PRINT_AP
|
|
|
|
#ifdef DEBUG_PRINT_AP
|
|
#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
|
|
|
|
int num_processors = 1;
|
|
static volatile int ap_stop = 1;
|
|
|
|
mcs_lock_node_t ap_syscall_semaphore;
|
|
|
|
static void ap_wait(void)
|
|
{
|
|
init_tick();
|
|
while (ap_stop) {
|
|
barrier();
|
|
cpu_pause();
|
|
}
|
|
sync_tick();
|
|
|
|
kmalloc_init();
|
|
sched_init();
|
|
arch_start_pvclock();
|
|
|
|
if (find_command_line("hidos")) {
|
|
mcs_lock_node_t mcs_node;
|
|
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__);
|
|
}
|
|
mcs_lock_lock_noirq(&ap_syscall_semaphore, &mcs_node);
|
|
init_host_ikc2mckernel();
|
|
init_host_ikc2linux(ikc_cpu);
|
|
mcs_lock_unlock_noirq(&ap_syscall_semaphore, &mcs_node);
|
|
|
|
{
|
|
extern void hfi1_kmalloc_cache_prealloc(void);
|
|
hfi1_kmalloc_cache_prealloc();
|
|
}
|
|
}
|
|
|
|
/* one of them listens */
|
|
mc_ikc_test_init();
|
|
|
|
schedule();
|
|
}
|
|
|
|
void ap_start(void)
|
|
{
|
|
init_tick();
|
|
mcs_lock_init(&ap_syscall_semaphore);
|
|
ap_stop = 0;
|
|
sync_tick();
|
|
}
|
|
|
|
void ap_init(void)
|
|
{
|
|
struct ihk_mc_cpu_info *cpu_info;
|
|
int i;
|
|
int bsp_hw_id, bsp_cpu_id;
|
|
|
|
ihk_mc_init_ap();
|
|
init_delay();
|
|
|
|
cpu_info = ihk_mc_get_cpu_info();
|
|
bsp_hw_id = ihk_mc_get_hardware_processor_id();
|
|
|
|
/* If no information exists, UP mode */
|
|
if (!cpu_info) {
|
|
return;
|
|
}
|
|
|
|
bsp_cpu_id = 0;
|
|
for (i = 0; i < cpu_info->ncpus; ++i) {
|
|
if (cpu_info->hw_ids[i] == bsp_hw_id) {
|
|
bsp_cpu_id = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
kprintf("BSP: %d (HW ID: %d @ NUMA %d)\n", bsp_cpu_id,
|
|
bsp_hw_id, cpu_info->nodes[0]);
|
|
|
|
for (i = 0; i < cpu_info->ncpus; i++) {
|
|
if (cpu_info->hw_ids[i] == bsp_hw_id) {
|
|
continue;
|
|
}
|
|
dkprintf("AP Booting: %d (HW ID: %d @ NUMA %d)\n", i,
|
|
cpu_info->hw_ids[i], cpu_info->nodes[i]);
|
|
ihk_mc_boot_cpu(cpu_info->hw_ids[i], (unsigned long)ap_wait);
|
|
|
|
num_processors++;
|
|
}
|
|
kprintf("BSP: booted %d AP CPUs\n", cpu_info->ncpus - 1);
|
|
}
|
|
|
|
#include <sysfs.h>
|
|
#include <kmalloc.h>
|
|
#include <string.h>
|
|
#include <vsprintf.h>
|
|
|
|
static ssize_t
|
|
show_int(struct sysfs_ops *ops, void *instance, void *buf, size_t size)
|
|
{
|
|
int *p = instance;
|
|
|
|
return snprintf(buf, size, "%d\n", *p);
|
|
}/* show_int() */
|
|
|
|
struct sysfs_ops show_int_ops = {
|
|
.show = &show_int,
|
|
};
|
|
|
|
struct fake_cpu_info {
|
|
int online;
|
|
};
|
|
|
|
static struct fake_cpu_info *fake_cpu_infos = NULL;
|
|
|
|
enum fake_cpu_info_member {
|
|
ONLINE,
|
|
};
|
|
|
|
struct fake_cpu_info_ops {
|
|
enum fake_cpu_info_member member;
|
|
struct sysfs_ops ops;
|
|
};
|
|
|
|
static ssize_t
|
|
show_fake_cpu_info(struct sysfs_ops *ops0, void *instance, void *buf,
|
|
size_t size)
|
|
{
|
|
struct fake_cpu_info_ops *ops
|
|
= container_of(ops0, struct fake_cpu_info_ops, ops);
|
|
struct fake_cpu_info *info = instance;
|
|
ssize_t n;
|
|
|
|
switch (ops->member) {
|
|
case ONLINE:
|
|
n = snprintf(buf, size, "%d\n", info->online);
|
|
break;
|
|
default:
|
|
n = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
if (n >= size) {
|
|
n = -ENOSPC;
|
|
}
|
|
|
|
return n;
|
|
} /* show_fake_cpu_info() */
|
|
|
|
static ssize_t
|
|
store_fake_cpu_info(struct sysfs_ops *ops0, void *instance, void *buf,
|
|
size_t size)
|
|
{
|
|
struct fake_cpu_info_ops *ops
|
|
= container_of(ops0, struct fake_cpu_info_ops, ops);
|
|
struct fake_cpu_info *info = instance;
|
|
ssize_t n;
|
|
|
|
switch (ops->member) {
|
|
case ONLINE:
|
|
kprintf("NYI:store_fake_cpu_info(%p,%p,%p,%ld): "
|
|
"online %d --> \"%.*s\"\n",
|
|
ops0, instance, buf, size, info->online,
|
|
(int)size, buf);
|
|
n = size;
|
|
break;
|
|
default:
|
|
n = -EIO;
|
|
break;
|
|
}
|
|
|
|
return n;
|
|
} /* store_fake_cpu_info() */
|
|
|
|
static struct fake_cpu_info_ops show_fci_online = {
|
|
.member = ONLINE,
|
|
.ops.show = &show_fake_cpu_info,
|
|
.ops.store = &store_fake_cpu_info,
|
|
};
|
|
|
|
void
|
|
cpu_sysfs_setup(void)
|
|
{
|
|
int error;
|
|
int cpu;
|
|
sysfs_handle_t targeth;
|
|
struct fake_cpu_info *info;
|
|
|
|
/* sample of simple variable **********************************/
|
|
error = sysfs_createf(&show_int_ops, &num_processors, 0444,
|
|
"/sys/devices/system/cpu/num_processors");
|
|
if (error) {
|
|
panic("cpu_sysfs_setup:sysfs_createf(num_processors) failed\n");
|
|
}
|
|
|
|
/* sample of more complex variable ****************************/
|
|
/* setup table */
|
|
info = kmalloc(sizeof(*info) * num_processors, IHK_MC_AP_CRITICAL);
|
|
for (cpu = 0; cpu < num_processors; ++cpu) {
|
|
info[cpu].online = 1;
|
|
}
|
|
fake_cpu_infos = info;
|
|
|
|
/* setup sysfs tree */
|
|
for (cpu = 0; cpu < num_processors; ++cpu) {
|
|
/* online */
|
|
error = sysfs_createf(&show_fci_online.ops,
|
|
&fake_cpu_infos[cpu], 0644,
|
|
"/sys/devices/system/cpu/cpu%d/online", cpu);
|
|
if (error) {
|
|
panic("cpu_sysfs_setup:sysfs_createf failed\n");
|
|
}
|
|
|
|
/* link to cpu%d */
|
|
error = sysfs_lookupf(&targeth,
|
|
"/sys/devices/system/cpu/cpu%d", cpu);
|
|
if (error) {
|
|
panic("cpu_sysfs_setup:sysfs_lookupf failed\n");
|
|
}
|
|
|
|
error = sysfs_symlinkf(targeth, "/sys/bus/cpu/devices/cpu%d",
|
|
cpu);
|
|
if (error) {
|
|
panic("cpu_sysfs_setup:sysfs_symlinkf failed\n");
|
|
}
|
|
}
|
|
|
|
return;
|
|
} /* cpu_sysfs_setup() */
|