diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h index 9218d99393..1692e5aa84 100644 --- a/repos/base-nova/include/nova/syscall-generic.h +++ b/repos/base-nova/include/nova/syscall-generic.h @@ -242,6 +242,14 @@ namespace Nova { EC_DONATE_SC = 2U, EC_RESCHEDULE = 3U, EC_MIGRATE = 4U, + EC_TIME = 5U, + }; + + enum Sc_op { + SC_TIME_IDLE = 0, + SC_TIME_CROSS = 1, + SC_TIME_KILLED = 2, + SC_EC_TIME = 3, }; /** diff --git a/repos/base-nova/include/spec/32bit/nova/syscalls.h b/repos/base-nova/include/spec/32bit/nova/syscalls.h index 919214fc70..e52c61d334 100644 --- a/repos/base-nova/include/spec/32bit/nova/syscalls.h +++ b/repos/base-nova/include/spec/32bit/nova/syscalls.h @@ -182,6 +182,40 @@ namespace Nova { return (uint8_t)status; } + + ALWAYS_INLINE + inline uint8_t syscall_6(Syscall s, uint8_t flags, unsigned sel, + mword_t &p1, mword_t &p2, mword_t &p3, + mword_t &p4) + { + mword_t status = eax(s, flags, sel); + + asm volatile (" push %%ebp;" + " push %%ebx;" + + " mov %%ecx, %%ebx;" + " mov %%esp, %%ecx;" + " mov %%edx, %%ebp;" + + " call 0f;" + "0:" + " addl $(1f-0b), (%%esp);" + " mov (%%esp), %%edx;" + "sysenter;" + "1:" + + " mov %%ebp, %%edx;" + " mov %%ebx, %%ecx;" + " pop %%ebx;" + " pop %%ebp;" + : "+a" (status), "+D" (p1), "+S" (p2), "+c" (p3), + "+d" (p4) + : + : "memory"); + return (uint8_t)status; + } + + ALWAYS_INLINE inline uint8_t call(unsigned pt) { @@ -239,14 +273,51 @@ namespace Nova { } + ALWAYS_INLINE + inline uint8_t util_time(Syscall const syscall, mword_t const cap, + uint8_t const op, unsigned long long &time) + { + mword_t time_h = 0, time_l = 0; + uint8_t res = syscall_5(syscall, op, cap, time_h, time_l); + time = (uint64_t(time_h) << 32ULL) | uint64_t(time_l); + return res; + } + + + ALWAYS_INLINE + inline uint8_t sc_ec_time(mword_t const cap_sc, mword_t const cap_ec, + unsigned long long &time_sc, + unsigned long long &time_ec) + { + mword_t time_h_sc = cap_ec, time_l_sc = 0; + mword_t time_h_ec = 0, time_l_ec = 0; + uint8_t res = syscall_6(NOVA_SC_CTRL, Sc_op::SC_EC_TIME, cap_sc, + time_h_sc, time_l_sc, time_h_ec, + time_l_ec); + time_sc = (uint64_t(time_h_sc) << 32ULL) | uint64_t(time_l_sc); + time_ec = (uint64_t(time_h_ec) << 32ULL) | uint64_t(time_l_ec); + return res; + } + + ALWAYS_INLINE inline uint8_t ec_ctrl(Ec_op op, mword_t ec = ~0UL, mword_t para = ~0UL, Crd crd = 0) { + if (op == EC_TIME) + return NOVA_INV_HYPERCALL; + return syscall_2(NOVA_EC_CTRL, op, ec, para, crd.value()); } + ALWAYS_INLINE + inline uint8_t ec_time(mword_t const ec, unsigned long long &time) + { + return util_time(NOVA_EC_CTRL, ec, Ec_op::EC_TIME, time); + } + + ALWAYS_INLINE inline uint8_t create_sc(unsigned sc, unsigned pd, unsigned ec, Qpd qpd) { @@ -396,13 +467,9 @@ namespace Nova { ALWAYS_INLINE - inline uint8_t sc_ctrl(unsigned sc, unsigned long long &time, uint8_t op = 0) + inline uint8_t sc_ctrl(unsigned const sc, unsigned long long &time, uint8_t op = 0) { - mword_t time_h = 0, time_l = 0; - uint8_t res = syscall_5(NOVA_SC_CTRL, op, sc, time_h, time_l); - time = time_h; - time = (time << 32ULL) | time_l; - return res; + return util_time(NOVA_SC_CTRL, sc, op, time); } } #endif /* _INCLUDE__SPEC__32BIT__NOVA__SYSCALLS_H_ */ diff --git a/repos/base-nova/include/spec/64bit/nova/syscalls.h b/repos/base-nova/include/spec/64bit/nova/syscalls.h index 5576fb8d4a..3ab7e887ed 100644 --- a/repos/base-nova/include/spec/64bit/nova/syscalls.h +++ b/repos/base-nova/include/spec/64bit/nova/syscalls.h @@ -132,6 +132,24 @@ namespace Nova { return (uint8_t)status; } + ALWAYS_INLINE + inline uint8_t syscall_6(Syscall s, uint8_t flags, mword_t sel, + mword_t &p1, mword_t &p2, mword_t &p3, + mword_t &p4) + { + mword_t status = rdi(s, flags, sel); + + register mword_t r8 asm ("r8") = p4; + + asm volatile ("syscall" + : "+D" (status), "+S"(p1), "+d"(p2), "+a"(p3), "+r"(r8) + : + : "rcx", "r11", "memory"); + + p4 = r8; + + return (uint8_t)status; + } ALWAYS_INLINE inline uint8_t call(mword_t pt) @@ -191,14 +209,51 @@ namespace Nova { } + ALWAYS_INLINE + inline uint8_t util_time(Syscall const syscall, mword_t const cap, + uint8_t const op, unsigned long long &time) + { + mword_t time_h = 0, time_l = 0; + uint8_t res = syscall_5(syscall, op, cap, time_h, time_l); + time = (time_h << 32ULL) | (time_l & 0xFFFFFFFFULL); + return res; + } + + + ALWAYS_INLINE + inline uint8_t sc_ec_time(mword_t const cap_sc, mword_t const cap_ec, + unsigned long long &time_sc, + unsigned long long &time_ec) + { + mword_t time_h_sc = cap_ec, time_l_sc = 0; + mword_t time_h_ec = 0, time_l_ec = 0; + uint8_t res = syscall_6(NOVA_SC_CTRL, Sc_op::SC_EC_TIME, cap_sc, + time_h_sc, time_l_sc, time_h_ec, + time_l_ec); + time_sc = (time_h_sc << 32ULL) | (time_l_sc & 0xFFFFFFFFULL); + time_ec = (time_h_ec << 32ULL) | (time_l_ec & 0xFFFFFFFFULL); + return res; + } + + ALWAYS_INLINE inline uint8_t ec_ctrl(Ec_op op, mword_t ec = ~0UL, mword_t para = ~0UL, Crd crd = 0) { + if (op == EC_TIME) + return NOVA_INV_HYPERCALL; + return syscall_2(NOVA_EC_CTRL, op, ec, para, crd.value()); } + ALWAYS_INLINE + inline uint8_t ec_time(mword_t const ec, unsigned long long &time) + { + return util_time(NOVA_EC_CTRL, ec, Ec_op::EC_TIME, time); + } + + ALWAYS_INLINE inline uint8_t create_sc(mword_t sc, mword_t pd, mword_t ec, Qpd qpd) { @@ -316,13 +371,10 @@ namespace Nova { ALWAYS_INLINE - inline uint8_t sc_ctrl(mword_t sm, unsigned long long &time, uint8_t op = 0) + inline uint8_t sc_ctrl(mword_t const sc, unsigned long long &time, + Sc_op const op) { - mword_t time_h = 0, time_l = 0; - uint8_t res = syscall_5(NOVA_SC_CTRL, op, sm, time_h, time_l); - time = time_h; - time = (time << 32ULL) | (time_l & 0xFFFFFFFFULL); - return res; + return util_time(NOVA_SC_CTRL, sc, op, time); } diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash index edf4c29f5a..bf8d5f7d78 100644 --- a/repos/base-nova/ports/nova.hash +++ b/repos/base-nova/ports/nova.hash @@ -1 +1 @@ -6a1f0e6e6386e60748607c3c460c51a36a162307 +33a2fa953ec52b0f63b921f4d33d68891c0aada0 diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port index 804413f12b..90f33a67b9 100644 --- a/repos/base-nova/ports/nova.port +++ b/repos/base-nova/ports/nova.port @@ -4,7 +4,7 @@ DOWNLOADS := nova.git # r10 branch URL(nova) := https://github.com/alex-ab/NOVA.git -REV(nova) := 7e3b5d3916825fb32e011cff4ee9b09ecdcb8d05 +REV(nova) := 00dc49bc18e7f72a9c85487e8f94fd859511d89d DIR(nova) := src/kernel/nova PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch)) diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc index 6b8354e2fd..bb887537f9 100644 --- a/repos/base-nova/src/core/platform.cc +++ b/repos/base-nova/src/core/platform.cc @@ -391,23 +391,6 @@ Platform::Platform() Obj_crd(sc_idle_base, log2cpu), true)) nova_die(); - /* test reading out idle SCs */ - bool sc_init = true; - for (unsigned i = 0; i < hip.cpu_max(); i++) { - - if (!hip.is_cpu_enabled(i)) - continue; - - uint64_t n_time; - uint8_t res = Nova::sc_ctrl(sc_idle_base + i, n_time); - if (res != Nova::NOVA_OK) { - sc_init = false; - error(i, " ", res, " ", n_time, " - failed"); - } - } - if (!sc_init) - nova_die(); - /* configure virtual address spaces */ #ifdef __x86_64__ _vm_size = 0x7fffc0000000UL - _vm_base; @@ -865,19 +848,30 @@ Platform::Platform() Info trace_source_info() const override { uint64_t sc_time = 0; + uint64_t ec_time = 0; + uint8_t res = 0; - enum SYSCALL_OP { IDLE_SC = 0, CROSS_SC = 1, - KILLED_SC = 2 }; - uint8_t syscall_op = (name == "cross") ? CROSS_SC : - ((name == "killed") ? KILLED_SC : IDLE_SC); + if (name == "killed") { + res = Nova::sc_ec_time(sc_sel, sc_sel, + sc_time, ec_time); + } else { + auto syscall_op = (name == "cross") + ? Sc_op::SC_TIME_CROSS + : Sc_op::SC_TIME_IDLE; + + res = Nova::sc_ctrl(sc_sel, sc_time, + syscall_op); + + if (syscall_op == Sc_op::SC_TIME_IDLE) + ec_time = sc_time; + } - uint8_t res = Nova::sc_ctrl(sc_sel, sc_time, syscall_op); if (res != Nova::NOVA_OK) - warning("sc_ctrl on idle SC cap, op=", syscall_op, + warning("sc_ctrl on ", name, " failed" ", res=", res); return { Session_label("kernel"), Trace::Thread_name(name), - Trace::Execution_time(sc_time, sc_time), affinity }; + Trace::Execution_time(ec_time, sc_time), affinity }; } Trace_source(Trace::Source_registry ®istry, @@ -920,16 +914,26 @@ Platform::Platform() */ Info trace_source_info() const override { + uint64_t ec_time = 0; uint64_t sc_time = 0; if (name == "root") { - uint8_t res = Nova::sc_ctrl(ec_sc_sel + 1, sc_time); + uint8_t res = Nova::sc_ec_time(ec_sc_sel + 1, + ec_sc_sel, + sc_time, + ec_time); if (res != Nova::NOVA_OK) - warning("sc_ctrl for ", name, " thread failed res=", res); + warning("sc_ec_time for root failed " + "res=", res); + } else { + uint8_t res = Nova::ec_time(ec_sc_sel, ec_time); + if (res != Nova::NOVA_OK) + warning("ec_time for", name, " thread " + "failed res=", res); } return { Session_label("core"), name, - Trace::Execution_time(sc_time, sc_time), location }; + Trace::Execution_time(ec_time, sc_time), location }; } Core_trace_source(Trace::Source_registry ®istry, diff --git a/repos/base-nova/src/core/platform_thread.cc b/repos/base-nova/src/core/platform_thread.cc index 10b89ab62f..dede726d2e 100644 --- a/repos/base-nova/src/core/platform_thread.cc +++ b/repos/base-nova/src/core/platform_thread.cc @@ -314,17 +314,22 @@ const char * Platform_thread::pd_name() const { Trace::Execution_time Platform_thread::execution_time() const { - unsigned long long time = 0; + uint64_t sc_time = 0; + uint64_t ec_time = 0; - /* for ECs without a SC we simply return 0 */ - if (!sc_created()) - return { time, time, Nova::Qpd::DEFAULT_QUANTUM, _priority }; + if (!sc_created()) { + /* time executed by EC (on whatever SC) */ + uint8_t res = Nova::ec_time(_sel_ec(), ec_time); + if (res != Nova::NOVA_OK) + warning("ec_time failed res=", res); + return { ec_time, sc_time, Nova::Qpd::DEFAULT_QUANTUM, _priority }; + } - uint8_t res = Nova::sc_ctrl(_sel_sc(), time); + uint8_t res = Nova::sc_ec_time(_sel_sc(), _sel_ec(), sc_time, ec_time); if (res != Nova::NOVA_OK) warning("sc_ctrl failed res=", res); - return { time, time, Nova::Qpd::DEFAULT_QUANTUM, _priority }; + return { ec_time, sc_time, Nova::Qpd::DEFAULT_QUANTUM, _priority }; } diff --git a/repos/base-nova/src/core/thread_start.cc b/repos/base-nova/src/core/thread_start.cc index 7dc4024bbf..e600464c91 100644 --- a/repos/base-nova/src/core/thread_start.cc +++ b/repos/base-nova/src/core/thread_start.cc @@ -127,10 +127,14 @@ void Thread::start() */ Info trace_source_info() const override { - uint64_t sc_time = 0; + uint64_t ec_time = 0; + + uint8_t res = Nova::ec_time(thread.native_thread().ec_sel, ec_time); + if (res != Nova::NOVA_OK) + warning("ec_time for core thread failed res=", res); return { Session_label("core"), thread.name(), - Trace::Execution_time(sc_time, sc_time), thread._affinity }; + Trace::Execution_time(ec_time, 0), thread._affinity }; } Core_trace_source(Trace::Source_registry ®istry, Thread &t) diff --git a/repos/base-nova/src/core/vm_session_component.cc b/repos/base-nova/src/core/vm_session_component.cc index 32195e4fc3..7d3d72c3e1 100644 --- a/repos/base-nova/src/core/vm_session_component.cc +++ b/repos/base-nova/src/core/vm_session_component.cc @@ -85,14 +85,15 @@ static uint8_t _with_kernel_quota_upgrade(addr_t const pd_target, Trace::Source::Info Vm_session_component::Vcpu::trace_source_info() const { + uint64_t ec_time = 0; uint64_t sc_time = 0; - uint8_t res = Nova::sc_ctrl(sc_sel(), sc_time); + uint8_t res = Nova::sc_ec_time(sc_sel(), ec_sel(), sc_time, ec_time); if (res != Nova::NOVA_OK) - warning("sc_ctrl failed res=", res); + warning("vCPU sc_ec_time failed res=", res); return { _label, String<5>("vCPU"), - Trace::Execution_time(sc_time, sc_time, + Trace::Execution_time(ec_time, sc_time, Nova::Qpd::DEFAULT_QUANTUM, _priority), _location }; }