/* * \brief CPU driver for core * \author Sebastian Sumpf * \date 2015-06-02 */ /* * Copyright (C) 2015-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _CORE__SPEC__RISCV__CPU_H_ #define _CORE__SPEC__RISCV__CPU_H_ /* Genode includes */ #include #include #include namespace Genode { /** * CPU driver for core */ class Cpu; typedef __uint128_t sizet_arithm_t; } namespace Kernel { class Pd; } class Genode::Cpu { public: static constexpr addr_t mtc_size = 0x1000; static constexpr addr_t exception_entry = (~0ULL) & ~(0xfff); /** * Extend basic CPU state by members relevant for 'base-hw' only */ struct Context : Cpu_state { struct Sptbr : Register<64> { struct Ppn : Bitfield<0, 38> { }; struct Asid : Bitfield<38, 26> { }; }; Sptbr::access_t sptbr; /** * Return base of assigned translation table */ addr_t translation_table() const { return Sptbr::Ppn::get(sptbr) << 12; } /** * Assign translation-table base 'table' */ void translation_table(addr_t const table) { Sptbr::Ppn::set(sptbr, table >> 12); } /** * Assign protection domain */ void protection_domain(Genode::uint8_t const id) { Sptbr::Asid::set(sptbr, id); } }; struct Pd { Genode::uint8_t asid; /* address space id */ Pd(Genode::uint8_t id) : asid(id) {} }; /** * A usermode execution state */ struct User_context : Context { /** * Constructor */ User_context(); /** * Support for kernel calls */ void user_arg_0(unsigned const arg) { a0 = arg; } void user_arg_1(unsigned const arg) { a1 = arg; } void user_arg_2(unsigned const arg) { a2 = arg; } void user_arg_3(unsigned const arg) { a3 = arg; } void user_arg_4(unsigned const arg) { a4 = arg; } addr_t user_arg_0() const { return a0; } addr_t user_arg_1() const { return a1; } addr_t user_arg_2() const { return a2; } addr_t user_arg_3() const { return a3; } addr_t user_arg_4() const { return a4; } /** * Initialize thread context * * \param table physical base of appropriate translation table * \param pd_id kernel name of appropriate protection domain */ void init_thread(addr_t const table, unsigned const pd_id) { protection_domain(pd_id); translation_table(table); } }; static void wait_for_interrupt() { asm volatile ("wfi"); }; /** * From the manual * * The behavior of SFENCE.VM depends on the current value of the sasid * register. If sasid is nonzero, SFENCE.VM takes effect only for address * translations in the current address space. If sasid is zero, SFENCE.VM * affects address translations for all address spaces. In this case, it * also affects global mappings, which are described in Section 4.5.1. * * Right no we will flush anything */ static void sfence() { /* * Note: In core the address space id must be zero */ asm volatile ("sfence.vm\n"); } /** * Post processing after a translation was added to a translation table * * \param addr virtual address of the translation * \param size size of the translation */ static void translation_added(addr_t const addr, size_t const size); static void invalidate_tlb_by_pid(unsigned const pid) { sfence(); } /** * Return kernel name of the executing CPU */ static unsigned executing_id() { return primary_id(); } /** * Return kernel name of the primary CPU */ static unsigned primary_id() { return 0; } static addr_t sbadaddr() { addr_t addr; asm volatile ("csrr %0, sbadaddr\n" : "=r"(addr)); return addr; } /************* ** Dummies ** *************/ void switch_to(User_context&) { } }; #endif /* _CORE__SPEC__RISCV__CPU_H_ */