diff --git a/src/emu/CMakeLists.txt b/src/emu/CMakeLists.txt index 8352a24..a992629 100644 --- a/src/emu/CMakeLists.txt +++ b/src/emu/CMakeLists.txt @@ -49,6 +49,8 @@ add_library(emu STATIC nosv/event.c nodes/setup.c nodes/event.c + kernel/setup.c + kernel/event.c ) add_executable(ovniemu ovniemu.c) diff --git a/src/emu/emu.c b/src/emu/emu.c index cf3528b..254d41f 100644 --- a/src/emu/emu.c +++ b/src/emu/emu.c @@ -46,7 +46,7 @@ emu_init(struct emu *emu, int argc, char *argv[]) } if (player_init(&emu->player, &emu->trace) != 0) { - err("emu_init: cannot init player for trace '%s'\n", + err("cannot init player for trace '%s'\n", emu->args.tracedir); return -1; } @@ -54,7 +54,10 @@ emu_init(struct emu *emu, int argc, char *argv[]) model_init(&emu->model); /* Register all the models */ - models_register(&emu->model); + if (models_register(&emu->model) != 0) { + err("failed to register models"); + return -1; + } if (model_probe(&emu->model, emu) != 0) { err("model_probe failed"); diff --git a/src/emu/kernel.c b/src/emu/kernel.c deleted file mode 100644 index 532279a..0000000 --- a/src/emu/kernel.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (c) 2021 Barcelona Supercomputing Center (BSC) - * SPDX-License-Identifier: GPL-3.0-or-later */ - -#include "uthash.h" - -#include "chan.h" -#include "emu.h" -#include "ovni.h" -#include "prv.h" -#include "trace.h" - -/* --------------------------- init ------------------------------- */ - -void -hook_init_kernel(struct ovni_emu *emu) -{ - int64_t *clock = &emu->delta_time; - FILE *prv_th = emu->prv_thread; - FILE *prv_cpu = emu->prv_cpu; - - /* Init the channels in all threads */ - for (size_t i = 0; i < emu->total_nthreads; i++) { - struct ovni_ethread *th = emu->global_thread[i]; - int row = th->gindex + 1; - struct ovni_chan **uth = &emu->th_chan; - - chan_th_init(th, uth, CHAN_KERNEL_CS, CHAN_TRACK_NONE, 0, 1, 1, row, prv_th, clock); - } - - /* Init the channels in all cpus */ - for (size_t i = 0; i < emu->total_ncpus; i++) { - struct ovni_cpu *cpu = emu->global_cpu[i]; - int row = cpu->gindex + 1; - struct ovni_chan **ucpu = &emu->cpu_chan; - - chan_cpu_init(cpu, ucpu, CHAN_KERNEL_CS, CHAN_TRACK_TH_ACTIVE, 0, 0, 1, row, prv_cpu, clock); - } -} - -/* --------------------------- pre ------------------------------- */ - -static void -context_switch(struct ovni_emu *emu) -{ - struct ovni_ethread *th = emu->cur_thread; - struct ovni_chan *chan = &th->chan[CHAN_KERNEL_CS]; - - switch (emu->cur_ev->header.value) { - case 'O': - chan_push(chan, ST_KERNEL_CSOUT); - break; - case 'I': - chan_pop(chan, ST_KERNEL_CSOUT); - break; - default: - edie(emu, "unexpected value '%c' (expecting 'O' or 'I')\n", - emu->cur_ev->header.value); - } -} - -void -hook_pre_kernel(struct ovni_emu *emu) -{ - if (emu->cur_ev->header.model != 'K') - edie(emu, "hook_pre_kernel: unexpected event with model %c\n", - emu->cur_ev->header.model); - - switch (emu->cur_ev->header.category) { - case 'C': - context_switch(emu); - break; - default: - edie(emu, "hook_pre_kernel: unexpected event with category %c\n", - emu->cur_ev->header.category); - } -} diff --git a/src/emu/kernel/event.c b/src/emu/kernel/event.c new file mode 100644 index 0000000..ddced5f --- /dev/null +++ b/src/emu/kernel/event.c @@ -0,0 +1,68 @@ +#include "kernel_priv.h" + +enum { PUSH = 1, POP = 2, IGN = 3 }; + +static const int ss_table[256][256][3] = { + ['C'] = { + ['O'] = { CH_CS, PUSH, ST_CSOUT }, + ['I'] = { CH_CS, POP, ST_CSOUT }, + }, +}; + +static int +simple(struct emu *emu) +{ + const int *entry = ss_table[emu->ev->c][emu->ev->v]; + int chind = entry[0]; + int action = entry[1]; + int st = entry[2]; + + struct kernel_thread *th = EXT(emu->thread, 'K'); + struct chan *ch = &th->m.ch[chind]; + + if (action == PUSH) { + return chan_push(ch, value_int64(st)); + } else if (action == POP) { + return chan_pop(ch, value_int64(st)); + } else if (action == IGN) { + return 0; /* do nothing */ + } else { + err("unknown event"); + return -1; + } + + return 0; +} + +static int +process_ev(struct emu *emu) +{ + switch (emu->ev->c) { + case 'C': + return simple(emu); + default: + err("unknown Kernel event category"); + return -1; + } + + /* Not reached */ + return 0; +} + +int +kernel_event(struct emu *emu) +{ + dbg("in kernel_event"); + if (emu->ev->m != 'K') { + err("unexpected event model %c\n", emu->ev->m); + return -1; + } + + dbg("got kernel event %s", emu->ev->mcv); + if (process_ev(emu) != 0) { + err("error processing Kernel event"); + return -1; + } + + return 0; +} diff --git a/src/emu/kernel/kernel_priv.h b/src/emu/kernel/kernel_priv.h new file mode 100644 index 0000000..940477f --- /dev/null +++ b/src/emu/kernel/kernel_priv.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef KERNEL_PRIV_H +#define KERNEL_PRIV_H + +#include "emu.h" +#include "model_cpu.h" +#include "model_thread.h" + +/* Private enums */ + +enum kernel_chan { + CH_CS = 0, + CH_MAX, +}; + +enum kernel_cs_state { + ST_CSOUT = 3, +}; + +struct kernel_thread { + struct model_thread m; +}; + +struct kernel_cpu { + struct model_cpu m; +}; + +int kernel_probe(struct emu *emu); +int kernel_create(struct emu *emu); +int kernel_connect(struct emu *emu); +int kernel_event(struct emu *emu); +int kernel_finish(struct emu *emu); + +#endif /* KERNEL_PRIV_H */ diff --git a/src/emu/kernel/setup.c b/src/emu/kernel/setup.c new file mode 100644 index 0000000..0b318cb --- /dev/null +++ b/src/emu/kernel/setup.c @@ -0,0 +1,135 @@ +#include "kernel_priv.h" + +static const char model_name[] = "kernel"; +static const int model_id = 'K'; + +struct model_spec model_kernel = { + .name = model_name, + .model = model_id, + .create = kernel_create, + .connect = kernel_connect, + .event = kernel_event, + .probe = kernel_probe, +}; + +/* ----------------- channels ------------------ */ + +static const char *chan_name[CH_MAX] = { + [CH_CS] = "subsystem", +}; + +static const int chan_stack[CH_MAX] = { + [CH_CS] = 1, +}; + +/* ----------------- pvt ------------------ */ + +static const int pvt_type[] = { + [CH_CS] = 45, +}; + +static const char *pcf_prefix[CH_MAX] = { + [CH_CS] = "Kernel subsystem", +}; + +static const struct pcf_value_label kernel_cs_values[] = { + { ST_CSOUT, "Context switch: Out of the CPU" }, + { -1, NULL }, +}; + +static const struct pcf_value_label (*pcf_labels[CH_MAX])[] = { + [CH_CS] = &kernel_cs_values, +}; + +static const struct model_pvt_spec pvt_spec = { + .type = pvt_type, + .prefix = pcf_prefix, + .label = pcf_labels, +}; + +/* ----------------- tracking ------------------ */ + +static const int th_track[CH_MAX] = { + [CH_CS] = TRACK_TH_ANY, +}; + +static const int cpu_track[CH_MAX] = { + [CH_CS] = TRACK_TH_RUN, /* FIXME: Why active */ +}; + +/* ----------------- chan_spec ------------------ */ + +static const struct model_chan_spec th_chan = { + .nch = CH_MAX, + .prefix = model_name, + .ch_names = chan_name, + .ch_stack = chan_stack, + .pvt = &pvt_spec, + .track = th_track, +}; + +static const struct model_chan_spec cpu_chan = { + .nch = CH_MAX, + .prefix = model_name, + .ch_names = chan_name, + .ch_stack = chan_stack, + .pvt = &pvt_spec, + .track = cpu_track, +}; + +/* ----------------- models ------------------ */ + +static const struct model_cpu_spec cpu_spec = { + .size = sizeof(struct kernel_cpu), + .chan = &cpu_chan, + .model = &model_kernel, +}; + +static const struct model_thread_spec th_spec = { + .size = sizeof(struct kernel_thread), + .chan = &th_chan, + .model = &model_kernel, +}; + +/* ----------------------------------------------------- */ + +int +kernel_probe(struct emu *emu) +{ + if (emu->system.nthreads == 0) + return 1; + + return 0; +} + +int +kernel_create(struct emu *emu) +{ + if (model_thread_create(emu, &th_spec) != 0) { + err("model_thread_init failed"); + return -1; + } + + if (model_cpu_create(emu, &cpu_spec) != 0) { + err("model_cpu_init failed"); + return -1; + } + + return 0; +} + +int +kernel_connect(struct emu *emu) +{ + if (model_thread_connect(emu, &th_spec) != 0) { + err("model_thread_connect failed"); + return -1; + } + + if (model_cpu_connect(emu, &cpu_spec) != 0) { + err("model_cpu_connect failed"); + return -1; + } + + return 0; +} diff --git a/src/emu/model.c b/src/emu/model.c index 625234d..4c2e87e 100644 --- a/src/emu/model.c +++ b/src/emu/model.c @@ -14,14 +14,21 @@ model_init(struct model *model) memset(model, 0, sizeof(struct model)); } -void +int model_register(struct model *model, struct model_spec *spec) { int i = spec->model; + + if (model->registered[i]) { + err("model %c already registered", i); + return -1; + } + model->spec[i] = spec; model->registered[i] = 1; dbg("registered model %c", (char) i); + return 0; } int diff --git a/src/emu/model.h b/src/emu/model.h index 8fa6f79..5d59fc2 100644 --- a/src/emu/model.h +++ b/src/emu/model.h @@ -26,7 +26,7 @@ struct model { }; void model_init(struct model *model); -void model_register(struct model *model, struct model_spec *spec); +int model_register(struct model *model, struct model_spec *spec); int model_probe(struct model *model, struct emu *emu); int model_create(struct model *model, struct emu *emu); diff --git a/src/emu/models.c b/src/emu/models.c index c778be9..ffd639e 100644 --- a/src/emu/models.c +++ b/src/emu/models.c @@ -3,25 +3,33 @@ #include "models.h" +#include "common.h" #include extern struct model_spec model_ovni; extern struct model_spec model_nanos6; extern struct model_spec model_nosv; extern struct model_spec model_nodes; +extern struct model_spec model_kernel; static struct model_spec *models[] = { &model_ovni, &model_nanos6, &model_nosv, &model_nodes, + &model_kernel, NULL }; -void +int models_register(struct model *model) { for (int i = 0; models[i] != NULL; i++) { - model_register(model, models[i]); + if (model_register(model, models[i]) != 0) { + err("model_register failed"); + return -1; + } } + + return 0; } diff --git a/src/emu/models.h b/src/emu/models.h index cca0e0c..d999243 100644 --- a/src/emu/models.h +++ b/src/emu/models.h @@ -6,7 +6,7 @@ #include "model.h" -void +int models_register(struct model *model); #endif /* MODELS_H */