diff --git a/repos/base-hw/src/core/include/kernel/pd.h b/repos/base-hw/src/core/include/kernel/pd.h index e5445432e..7ac8517a8 100644 --- a/repos/base-hw/src/core/include/kernel/pd.h +++ b/repos/base-hw/src/core/include/kernel/pd.h @@ -210,7 +210,7 @@ class Kernel::Mode_transition_control enum { SIZE_LOG2 = Genode::Translation_table::MIN_PAGE_SIZE_LOG2, SIZE = 1 << SIZE_LOG2, - VIRT_BASE = Processor::EXCEPTION_ENTRY, + VIRT_BASE = Processor::exception_entry, ALIGN_LOG2 = Genode::Translation_table::ALIGNM_LOG2, ALIGN = 1 << ALIGN_LOG2, }; diff --git a/repos/base-hw/src/core/include/kernel/processor_pool.h b/repos/base-hw/src/core/include/kernel/processor_pool.h index 61180d0fa..4eef15379 100644 --- a/repos/base-hw/src/core/include/kernel/processor_pool.h +++ b/repos/base-hw/src/core/include/kernel/processor_pool.h @@ -46,7 +46,7 @@ class Kernel::Idle_thread : public Thread enum { STACK_SIZE = sizeof(addr_t) * 32, - STACK_ALIGNM = Cpu::DATA_ACCESS_ALIGNM, + STACK_ALIGNM = Cpu::data_access_align, }; char _stack[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM))); diff --git a/repos/base-hw/src/core/include/spec/arm/cpu_support.h b/repos/base-hw/src/core/include/spec/arm/cpu_support.h index 8c5076640..83ec7ed61 100644 --- a/repos/base-hw/src/core/include/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm/cpu_support.h @@ -35,26 +35,20 @@ class Genode::Arm { public: - enum { - TTBCR_N = 0, - EXCEPTION_ENTRY = 0xffff0000, - DATA_ACCESS_ALIGNM = 4, - }; + static constexpr addr_t exception_entry = 0xffff0000; + static constexpr addr_t data_access_align = 4; /** * Multiprocessor affinity register */ struct Mpidr : Register<32> { - struct Aff_0 : Bitfield<0, 8> { }; + struct Aff_0 : Bitfield<0, 8> { }; /* affinity value 0 */ - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c0, c0, 5" : [v] "=r" (v) ::); + asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (v) :: ); return v; } }; @@ -64,13 +58,10 @@ class Genode::Arm */ struct Ctr : Register<32> { - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c0, c0, 1" : [v]"=r"(v) :: ); + asm volatile ("mrc p15, 0, %0, c0, c0, 1" : "=r" (v) :: ); return v; } }; @@ -85,9 +76,6 @@ class Genode::Arm struct I : Bitfield<12,1> { }; /* enable instruction caches */ struct V : Bitfield<13,1> { }; /* select exception entry */ - /** - * Read register value - */ static access_t read() { access_t v; @@ -95,14 +83,11 @@ class Genode::Arm return v; } - /** - * Write register value - */ static void write(access_t const v) { asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r" (v) : ); } /** - * Initialization that is common + * Do initialization that is common on value 'v' */ static void init_common(access_t & v) { @@ -112,7 +97,7 @@ class Genode::Arm } /** - * Initialization for virtual kernel stage + * Do initialization for virtual mode in kernel on value 'v' */ static void init_virt_kernel(access_t & v) { M::set(v, 1); } }; @@ -122,28 +107,15 @@ class Genode::Arm */ struct Ttbcr : Register<32> { - struct N : Bitfield<0, 3> { }; /* base address width */ - - /** - * Write register, only in privileged CPU mode - */ static void write(access_t const v) { - asm volatile ("mcr p15, 0, %[v], c2, c0, 2" :: [v]"r"(v) : ); } + asm volatile ("mcr p15, 0, %0, c2, c0, 2" :: "r" (v) : ); } - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c2, c0, 2" : [v]"=r"(v) :: ); + asm volatile ("mrc p15, 0, %0, c2, c0, 2" : "=r" (v) :: ); return v; } - - /** - * Value for the switch to virtual mode in kernel - */ - static access_t init_virt_kernel() { return N::bits(TTBCR_N); } }; /** @@ -151,21 +123,15 @@ class Genode::Arm */ struct Ttbr0 : Register<32> { - struct Ba : Bitfield<14-TTBCR_N, 18+TTBCR_N> { }; + struct Ba : Bitfield<14, 18> { }; /* base */ - /** - * Write register, only in privileged CPU mode - */ static void write(access_t const v) { - asm volatile ("mcr p15, 0, %[v], c2, c0, 0" :: [v]"r"(v) : ); } + asm volatile ("mcr p15, 0, %0, c2, c0, 0" :: "r" (v) : ); } - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c2, c0, 0" : [v]"=r"(v) :: ); + asm volatile ("mrc p15, 0, %0, c2, c0, 0" : "=r" (v) :: ); return v; } }; @@ -175,48 +141,15 @@ class Genode::Arm */ struct Dacr : Register<32> { - enum Dx_values { NO_ACCESS = 0, CLIENT = 1 }; + struct D0 : Bitfield<0,2> { }; /* access mode for domain 0 */ - /** - * Access values for the 16 available domains - */ - struct D0 : Bitfield<0,2> { }; - struct D1 : Bitfield<2,2> { }; - struct D2 : Bitfield<4,2> { }; - struct D3 : Bitfield<6,2> { }; - struct D4 : Bitfield<8,2> { }; - struct D5 : Bitfield<10,2> { }; - struct D6 : Bitfield<12,2> { }; - struct D7 : Bitfield<14,2> { }; - struct D8 : Bitfield<16,2> { }; - struct D9 : Bitfield<18,2> { }; - struct D10 : Bitfield<20,2> { }; - struct D11 : Bitfield<22,2> { }; - struct D12 : Bitfield<24,2> { }; - struct D13 : Bitfield<26,2> { }; - struct D14 : Bitfield<28,2> { }; - struct D15 : Bitfield<30,2> { }; - - /** - * Write register, only in privileged CPU mode - */ static void write(access_t const v) { - asm volatile ("mcr p15, 0, %[v], c3, c0, 0" :: [v]"r"(v) : ); } + asm volatile ("mcr p15, 0, %0, c3, c0, 0" :: "r" (v) : ); } /** - * Initialize for Genodes operational mode + * Return value initialized for virtual mode in kernel */ - static access_t init_virt_kernel() - { - return D0::bits(CLIENT) | D1::bits(NO_ACCESS) | - D2::bits(NO_ACCESS) | D3::bits(NO_ACCESS) | - D4::bits(NO_ACCESS) | D5::bits(NO_ACCESS) | - D6::bits(NO_ACCESS) | D7::bits(NO_ACCESS) | - D8::bits(NO_ACCESS) | D9::bits(NO_ACCESS) | - D10::bits(NO_ACCESS) | D11::bits(NO_ACCESS) | - D12::bits(NO_ACCESS) | D13::bits(NO_ACCESS) | - D14::bits(NO_ACCESS) | D15::bits(NO_ACCESS); - } + static access_t init_virt_kernel() { return D0::bits(1); } }; /** @@ -224,14 +157,8 @@ class Genode::Arm */ struct Icimvau : Register<32> { - /** - * Write register value - */ - static void write(access_t const v) - { - asm volatile ( - "mcr p15, 0, %[v], c7, c5, 1\n" :: [v] "r" (v) : ); - } + static void write(access_t const v) { + asm volatile ("mcr p15, 0, %0, c7, c5, 1" :: "r" (v) : ); } }; /** @@ -239,14 +166,8 @@ class Genode::Arm */ struct Dccmvac : Register<32> { - /** - * Write register value - */ - static void write(access_t const v) - { - asm volatile ( - "mcr p15, 0, %[v], c7, c10, 1\n" :: [v] "r" (v) : ); - } + static void write(access_t const v) { + asm volatile ("mcr p15, 0, %0, c7, c10, 1" :: "r" (v) : ); } }; /** @@ -254,21 +175,13 @@ class Genode::Arm */ struct Cidr : Register<32> { - /** - * Write register value - */ - static void write(access_t const v) - { - asm volatile ("mcr p15, 0, %[v], c13, c0, 1" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile ("mcr p15, 0, %0, c13, c0, 1" :: "r" (v) : ); } - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c13, c0, 1" : [v]"=r"(v) :: ); + asm volatile ("mrc p15, 0, %0, c13, c0, 1" : "=r" (v) :: ); return v; } }; @@ -278,81 +191,59 @@ class Genode::Arm */ struct Psr : Register<32> { - struct M : Bitfield<0,5> /* processor mode */ - { - enum { USER = 0b10000, SUPERVISOR = 0b10011 }; - }; - - struct T : Bitfield<5,1> /* instruction state */ - { - enum { ARM = 0 }; - }; + static constexpr access_t usr = 16; + static constexpr access_t svc = 19; + struct M : Bitfield<0,5> { }; /* CPU mode */ struct F : Bitfield<6,1> { }; /* FIQ disable */ struct I : Bitfield<7,1> { }; /* IRQ disable */ - struct A : Bitfield<8,1> { }; /* asynchronous abort disable */ + struct A : Bitfield<8,1> { }; /* async. abort disable */ - struct E : Bitfield<9,1> /* load/store endianess */ - { - enum { LITTLE = 0 }; - }; - - struct J : Bitfield<24,1> /* instruction state */ - { - enum { ARM = 0 }; - }; - - /** - * Read register - */ static access_t read() { access_t v; - asm volatile ("mrs %[v], cpsr" : [v] "=r" (v) : : ); + asm volatile ("mrs %0, cpsr" : "=r" (v) :: ); return v; } - /** - * Write register - */ static void write(access_t const v) { - asm volatile ("msr cpsr, %[v]" : : [v] "r" (v) : ); } + asm volatile ("msr cpsr, %0" :: "r" (v) : ); } /** - * Initial value for a user execution context with trustzone - * - * FIXME: This function should not be declared in 'Arm' but in - * 'Arm_v7', but for now the declaration is necessary - * because of 'User_context::User_context()'. + * Return value initialized for user execution with trustzone */ inline static access_t init_user_with_trustzone(); /** - * Initial value for an userland execution context + * Do common initialization on register value 'v' */ - static access_t init_user() + static void init_common(access_t & v) { - return M::bits(M::USER) | - T::bits(T::ARM) | - F::bits(1) | - I::bits(0) | - A::bits(1) | - E::bits(E::LITTLE) | - J::bits(J::ARM); + F::set(v, 1); + A::set(v, 1); } /** - * Initial value for the kernel execution context + * Return initial value for user execution + */ + static access_t init_user() + { + access_t v = 0; + init_common(v); + M::set(v, usr); + return v; + } + + /** + * Return initial value for the kernel */ static access_t init_kernel() { - return M::bits(M::SUPERVISOR) | - T::bits(T::ARM) | - F::bits(1) | - I::bits(1) | - A::bits(1) | - E::bits(E::LITTLE) | - J::bits(J::ARM); + access_t v = 0; + init_common(v); + M::set(v, svc); + I::set(v, 1); + return v; } }; @@ -361,17 +252,12 @@ class Genode::Arm */ struct Fsr : Register<32> { - /** - * Fault status encoding - */ - enum Fault_status - { - SECTION_TRANSLATION = 5, - PAGE_TRANSLATION = 7, - }; + static constexpr access_t section = 5; + static constexpr access_t page = 7; - struct Fs_3_0 : Bitfield<0, 4> { }; /* fault status */ - struct Fs_4 : Bitfield<10, 1> { }; /* fault status */ + struct Fs_0 : Bitfield<0, 4> { }; /* fault status */ + struct Fs_1 : Bitfield<10, 1> { }; /* fault status */ + struct Fs : Bitset_2 { }; /* fault status */ }; /** @@ -379,25 +265,12 @@ class Genode::Arm */ struct Ifsr : Fsr { - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c5, c0, 1" : [v]"=r"(v) :: ); + asm volatile ("mrc p15, 0, %0, c5, c0, 1" : "=r" (v) :: ); return v; } - - /** - * Read fault status - */ - static Fault_status fault_status() - { - access_t const v = read(); - return (Fault_status)(Fs_3_0::get(v) | - (Fs_4::get(v) << Fs_3_0::WIDTH)); - } }; /** @@ -407,24 +280,12 @@ class Genode::Arm { struct Wnr : Bitfield<11, 1> { }; /* write not read bit */ - /** - * Read register value - */ static access_t read() { access_t v; - asm volatile ("mrc p15, 0, %[v], c5, c0, 0" : [v]"=r"(v) :: ); + asm volatile ("mrc p15, 0, %0, c5, c0, 0" : "=r" (v) :: ); return v; } - - /** - * Read fault status - */ - static Fault_status fault_status() { - access_t const v = read(); - return (Fault_status)(Fs_3_0::get(v) | - (Fs_4::get(v) << Fs_3_0::WIDTH)); - } }; /** @@ -432,10 +293,8 @@ class Genode::Arm */ struct Dfar : Register<32> { - /** - * Read register value - */ - static access_t read() { + static access_t read() + { access_t v; asm volatile ("mrc p15, 0, %[v], c6, c0, 0" : [v]"=r"(v) :: ); return v; @@ -477,10 +336,9 @@ class Genode::Arm */ User_context(); - /*************************************************** - ** Communication between user and context holder ** - ***************************************************/ - + /** + * Support for kernel calls + */ void user_arg_0(unsigned const arg) { r0 = arg; } void user_arg_1(unsigned const arg) { r1 = arg; } void user_arg_2(unsigned const arg) { r2 = arg; } @@ -511,62 +369,52 @@ class Genode::Arm } /** - * Return if the context is in a page fault due to a translation miss + * Return if the context is in a page fault due to translation miss * * \param va holds the virtual fault-address if call returns 1 * \param w holds wether it's a write fault if call returns 1 */ bool in_fault(addr_t & va, addr_t & w) const { - /* determine fault type */ switch (cpu_exception) { case PREFETCH_ABORT: { /* check if fault was caused by a translation miss */ - Ifsr::Fault_status const fs = Ifsr::fault_status(); - if (fs == Ifsr::SECTION_TRANSLATION || - fs == Ifsr::PAGE_TRANSLATION) - { - /* fetch fault data */ - w = 0; - va = ip; - return 1; - } - return 0; } + Ifsr::access_t const fs = Ifsr::Fs::get(Ifsr::read()); + if (fs != Ifsr::section && fs != Ifsr::page) { return 0; } + + /* fetch fault data */ + w = 0; + va = ip; + return 1; } case DATA_ABORT: { /* check if fault was caused by translation miss */ - Dfsr::Fault_status const fs = Dfsr::fault_status(); - if(fs == Dfsr::SECTION_TRANSLATION || - fs == Dfsr::PAGE_TRANSLATION) - { - /* fetch fault data */ - Dfsr::access_t const dfsr = Dfsr::read(); - w = Dfsr::Wnr::get(dfsr); - va = Dfar::read(); - return 1; - } - return 0; } + Dfsr::access_t const fs = Dfsr::Fs::get(Dfsr::read()); + if (fs != Dfsr::section && fs != Dfsr::page) { return 0; } - default: return 0; - } + /* fetch fault data */ + Dfsr::access_t const dfsr = Dfsr::read(); + w = Dfsr::Wnr::get(dfsr); + va = Dfar::read(); + return 1; } + + default: return 0; } } }; /** * Returns true if current execution context is running in user mode */ - inline static bool is_user() { - return Psr::M::get(Psr::read()) == Psr::M::USER; } + static bool is_user() { return Psr::M::get(Psr::read()) == Psr::usr; } /** * Invalidate all entries of all instruction caches */ - __attribute__((always_inline)) - static void invalidate_instr_caches() { - asm volatile ("mcr p15, 0, %[rd], c7, c5, 0" :: [rd]"r"(0) : ); } + __attribute__((always_inline)) static void invalidate_instr_caches() { + asm volatile ("mcr p15, 0, %0, c7, c5, 0" :: "r" (0) : ); } /** * Flush all entries of all data caches @@ -588,14 +436,12 @@ class Genode::Arm } /** - * Invalidate all TLB entries of one address space - * - * \param pid ID of the targeted address space + * Invalidate all TLB entries of the address space named 'pid' */ static void flush_tlb_by_pid(unsigned const pid) { flush_caches(); - asm volatile ("mcr p15, 0, %[pid], c8, c7, 2" :: [pid]"r"(pid) : ); + asm volatile ("mcr p15, 0, %0, c8, c7, 2" :: "r" (pid) : ); } /** @@ -604,41 +450,36 @@ class Genode::Arm static void flush_tlb() { flush_caches(); - asm volatile ("mcr p15, 0, %[rd], c8, c7, 0" :: [rd]"r"(0) : ); + asm volatile ("mcr p15, 0, %0, c8, c7, 0" :: "r" (0) : ); } + static constexpr addr_t line_size = 1 << Board::CACHE_LINE_SIZE_LOG2; + static constexpr addr_t line_align_mask = ~(line_size - 1); + /** - * Clean every data-cache entry within a virtual region + * Flush data-cache entries for virtual region ['base', 'base + size') */ static void flush_data_caches_by_virt_region(addr_t base, size_t const size) { - enum { - LINE_SIZE = 1 << Board::CACHE_LINE_SIZE_LOG2, - LINE_ALIGNM_MASK = ~(LINE_SIZE - 1), - }; addr_t const top = base + size; - base = base & LINE_ALIGNM_MASK; - for (; base < top; base += LINE_SIZE) { Dccmvac::write(base); } + base &= line_align_mask; + for (; base < top; base += line_size) { Dccmvac::write(base); } } /** - * Invalidate every instruction-cache entry within a virtual region + * Bin instr.-cache entries for virtual region ['base', 'base + size') */ static void invalidate_instr_caches_by_virt_region(addr_t base, size_t const size) { - enum { - LINE_SIZE = 1 << Board::CACHE_LINE_SIZE_LOG2, - LINE_ALIGNM_MASK = ~(LINE_SIZE - 1), - }; addr_t const top = base + size; - base = base & LINE_ALIGNM_MASK; - for (; base < top; base += LINE_SIZE) { Icimvau::write(base); } + base &= line_align_mask; + for (; base < top; base += line_size) { Icimvau::write(base); } } /** - * Return true if the processor support multiple cores + * Return true if the CPU supports multiple cores */ static bool is_smp() { return PROCESSORS > 1; } }; diff --git a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h index 1b3befe26..eb62ddca2 100644 --- a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h @@ -29,11 +29,14 @@ namespace Genode { /** - * Memory region attributes for the translation descriptor 'T' + * Commons for all translations */ - template - static typename T::access_t - arm_memory_region_attr(Page_flags const & flags); + class Translation; + + /** + * Second level translation table + */ + class Page_table; /** * First level translation table @@ -41,276 +44,245 @@ namespace Genode class Translation_table; } -class Genode::Translation_table +class Genode::Translation { private: /** - * Return permission configuration according to given mapping flags - * - * \param T targeted translation-table-descriptor type - * \param flags mapping flags - * - * \return descriptor value with AP and XN set and the rest left zero + * Return TEX value for device-memory translations */ - template - static typename T::access_t - access_permission_bits(Page_flags const & flags) + static constexpr unsigned _device_tex(); + + protected: + + /** + * Return translation according to flags 'f' and phys. address 'pa' + */ + template static typename T::access_t + _create(Page_flags const & f, addr_t const pa) { - typedef typename T::Xn Xn; - typedef typename T::Ap Ap; - typedef typename T::access_t access_t; - bool const w = flags.writeable; - bool const p = flags.privileged; - access_t ap; - if (w) { if (p) { ap = Ap::bits(0b001); } - else { ap = Ap::bits(0b011); } - } else { if (p) { ap = Ap::bits(0b101); } - else { ap = Ap::bits(0b010); } + typename T::access_t v = T::Pa::masked(pa); + T::S::set(v, Cpu::is_smp()); + T::Ng::set(v, !f.global); + T::Xn::set(v, !f.executable); + if (f.device) { T::Tex::set(v, _device_tex()); } + else { + switch (f.cacheable) { + case CACHED: T::Tex::set(v, 5); + case WRITE_COMBINED: T::B::set(v, 1); break; + case UNCACHED: T::Tex::set(v, 1); break; } } + if (f.writeable) if (f.privileged) T::Ap::set(v, 1); + else T::Ap::set(v, 3); + else if (f.privileged) T::Ap::set(v, 5); + else T::Ap::set(v, 2); + return v; + } +}; + +class Genode::Page_table +{ + public: + + enum { + SIZE_LOG2 = 10, + SIZE = 1 << SIZE_LOG2, + ALIGNM_LOG2 = SIZE_LOG2, + }; + + /** + * Common descriptor structure + */ + struct Descriptor : Register<32>, Translation + { + enum Type { FAULT, SMALL_PAGE }; + + enum { + VIRT_SIZE_LOG2 = 12, + VIRT_SIZE = 1 << VIRT_SIZE_LOG2, + VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1, + VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK), + }; + + struct Type_0 : Bitfield<0, 2> { }; + struct Type_1 : Bitfield<1, 1> { }; + + /** + * Get descriptor type of 'v' + */ + static Type type(access_t const v) + { + access_t const t0 = Type_0::get(v); + if (t0 == 0) { return FAULT; } + access_t const t1 = Type_1::get(v); + if (t1 == 1) { return SMALL_PAGE; } + return FAULT; } - return Xn::bits(!flags.executable) | ap; + + /** + * At descriptor value 'v' set type to 't' + */ + static void type(access_t & v, Type const t) + { + switch (t) { + case FAULT: Type_0::set(v, 0); return; + case SMALL_PAGE: Type_1::set(v, 1); return; } + } + + static void invalidate(access_t & v) { type(v, FAULT); } + + static bool valid(access_t & v) { return type(v) != FAULT; } + }; + + /** + * Small page descriptor structure + */ + struct Small_page : Descriptor + { + struct Xn : Bitfield<0, 1> { }; /* execute never */ + struct B : Bitfield<2, 1> { }; /* mem region attr. */ + struct Ap_0 : Bitfield<4, 2> { }; /* access permission */ + struct Tex : Bitfield<6, 3> { }; /* mem region attr. */ + struct Ap_1 : Bitfield<9, 1> { }; /* access permission */ + struct S : Bitfield<10, 1> { }; /* shareable bit */ + struct Ng : Bitfield<11, 1> { }; /* not global bit */ + struct Pa : Bitfield<12, 20> { }; /* physical base */ + struct Ap : Bitset_2 { }; /* access permission */ + + /** + * Return page descriptor for physical address 'pa' and 'flags' + */ + static access_t create(Page_flags const & flags, addr_t const pa) + { + access_t v = _create(flags, pa); + Descriptor::type(v, Descriptor::SMALL_PAGE); + return v; + } + }; + + private: + + /* table payload that must be the only member of this class */ + Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)]; + + enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 }; + + /** + * Get entry index by virtual offset + * + * \param i is overridden with the index if call returns 0 + * \param vo virtual offset relative to the virtual table base + * + * \retval 0 on success + * \retval <0 translation failed + */ + bool _index_by_vo (unsigned & i, addr_t const vo) const + { + if (vo > max_virt_offset()) return false; + i = vo >> Descriptor::VIRT_SIZE_LOG2; + return true; + } + + public: + + /** + * Constructor + */ + Page_table() + { + assert(aligned(this, ALIGNM_LOG2)); + memset(&_entries, 0, sizeof(_entries)); } /** - * Second level translation table + * Maximum virtual offset that can be translated by this table */ - class Page_table + static addr_t max_virt_offset() { - public: + return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2) + + (Descriptor::VIRT_SIZE - 1); + } - enum { - SIZE_LOG2 = 10, - SIZE = 1 << SIZE_LOG2, - ALIGNM_LOG2 = SIZE_LOG2, - }; + /** + * Insert one atomic translation into this table + * + * \param vo offset of the virtual region represented + * by the translation within the virtual + * region represented by this table + * \param pa base of the physical backing store + * \param size size of the translated region + * \param flags mapping flags + */ + void insert_translation(addr_t vo, + addr_t pa, + size_t size, + Page_flags const & flags) + { + constexpr size_t sz = Descriptor::VIRT_SIZE; - /** - * Common descriptor structure - */ - struct Descriptor : Register<32> - { - /** - * Descriptor types - */ - enum Type { FAULT, SMALL_PAGE }; + for (unsigned i; (size > 0) && _index_by_vo(i, vo); + size = (size < sz) ? 0 : size - sz, + vo += sz, pa += sz) + { - enum { - VIRT_SIZE_LOG2 = 12, - VIRT_SIZE = 1 << VIRT_SIZE_LOG2, - VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1, - VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK), - }; + /* compose new descriptor value */ + Small_page::access_t const e = + Small_page::create(flags, pa); - struct Type_0 : Bitfield<0, 2> { }; - struct Type_1 : Bitfield<1, 1> { }; + /* check if it is a good idea to override the entry */ + assert(!Descriptor::valid(_entries[i]) || + _entries[i] == e); - /** - * Get descriptor type of 'v' - */ - static Type type(access_t const v) - { - access_t const t0 = Type_0::get(v); - if (t0 == 0) { return FAULT; } - access_t const t1 = Type_1::get(v); - if (t1 == 1) return SMALL_PAGE; - return FAULT; - } + /* override entry */ + _entries[i] = e; - /** - * Set descriptor type of 'v' - */ - static void type(access_t & v, Type const t) - { - switch (t) { - case FAULT: - Type_0::set(v, 0); - return; - case SMALL_PAGE: - Type_1::set(v, 1); - return; - } - } + /* some CPUs need to act on changed translations */ + Cpu::translation_added((addr_t)&_entries[i], + sizeof(Descriptor::access_t)); + } + } - /** - * Invalidate descriptor 'v' - */ - static void invalidate(access_t & v) { type(v, FAULT); } + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + */ + void remove_translation(addr_t vo, size_t size) + { + constexpr size_t sz = Descriptor::VIRT_SIZE; - /** - * Return if descriptor 'v' is valid - */ - static bool valid(access_t & v) { - return type(v) != FAULT; } - }; - - /** - * Small page descriptor structure - */ - struct Small_page : Descriptor - { - struct Xn : Bitfield<0, 1> { }; /* execute never */ - struct B : Bitfield<2, 1> { }; /* mem region attr. */ - struct C : Bitfield<3, 1> { }; /* mem region attr. */ - struct Ap_0 : Bitfield<4, 2> { }; /* access permission */ - struct Tex : Bitfield<6, 3> { }; /* mem region attr. */ - struct Ap_1 : Bitfield<9, 1> { }; /* access permission */ - struct S : Bitfield<10, 1> { }; /* shareable bit */ - struct Ng : Bitfield<11, 1> { }; /* not global bit */ - struct Pa : Bitfield<12, 20> { }; /* physical base */ - - struct Ap : Bitset_2 { }; /* access permission */ - - /** - * Compose descriptor value - */ - static access_t create(Page_flags const & flags, - addr_t const pa) - { - access_t v = access_permission_bits(flags); - v |= arm_memory_region_attr(flags); - v |= Ng::bits(!flags.global); - v |= S::bits(Cpu::is_smp()); - v |= Pa::masked(pa); - Descriptor::type(v, Descriptor::SMALL_PAGE); - return v; - } - }; - - private: - - /* - * Table payload - * - * Must be the only member of this class - */ - Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)]; - - enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 }; - - /** - * Get entry index by virtual offset - * - * \param i is overridden with the index if call returns 0 - * \param vo virtual offset relative to the virtual table base - * - * \retval 0 on success - * \retval <0 translation failed - */ - bool _index_by_vo (unsigned & i, addr_t const vo) const - { - if (vo > max_virt_offset()) return false; - i = vo >> Descriptor::VIRT_SIZE_LOG2; - return true; + for (unsigned i; (size > 0) && _index_by_vo(i, vo); + size = (size < sz) ? 0 : size - sz, vo += sz) + { + switch (Descriptor::type(_entries[i])) { + case Descriptor::SMALL_PAGE: + Descriptor::invalidate(_entries[i]); + default: ; } + } + } - public: + /** + * Does this table solely contain invalid entries + */ + bool empty() + { + for (unsigned i = 0; i <= MAX_INDEX; i++) { + if (Descriptor::valid(_entries[i])) return false; } + return true; + } - /** - * Constructor - */ - Page_table() - { - assert(aligned(this, ALIGNM_LOG2)); - memset(&_entries, 0, sizeof(_entries)); - } - - /** - * Maximum virtual offset that can be translated by this table - */ - static addr_t max_virt_offset() - { - return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2) - + (Descriptor::VIRT_SIZE - 1); - } - - /** - * Insert one atomic translation into this table - * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - */ - void insert_translation(addr_t vo, - addr_t pa, - size_t size, - Page_flags const & flags) - { - constexpr size_t sz = Descriptor::VIRT_SIZE; - - for (unsigned i; (size > 0) && _index_by_vo(i, vo); - size = (size < sz) ? 0 : size - sz, - vo += sz, pa += sz) - { - - /* compose new descriptor value */ - Small_page::access_t const e = - Small_page::create(flags, pa); - - /* check if it is a good idea to override the entry */ - assert(!Descriptor::valid(_entries[i]) || - _entries[i] == e); - - /* override entry */ - _entries[i] = e; - - /* some CPUs need to act on changed translations */ - Cpu::translation_added((addr_t)&_entries[i], - sizeof(Descriptor::access_t)); - } - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - */ - void remove_translation(addr_t vo, size_t size) - { - constexpr size_t sz = Descriptor::VIRT_SIZE; - - for (unsigned i; (size > 0) && _index_by_vo(i, vo); - size = (size < sz) ? 0 : size - sz, vo += sz) { - - switch (Descriptor::type(_entries[i])) { - - case Descriptor::SMALL_PAGE: - { - Descriptor::invalidate(_entries[i]); - } - - default: ; - } - } - } - - /** - * Does this table solely contain invalid entries - */ - bool empty() - { - for (unsigned i = 0; i <= MAX_INDEX; i++) - if (Descriptor::valid(_entries[i])) return false; - return true; - } - - } __attribute__((aligned(1< + struct Descriptor : Register<32>, Translation { - /** - * Descriptor types - */ enum Type { FAULT, PAGE_TABLE, SECTION }; enum { @@ -344,13 +313,9 @@ class Genode::Translation_table { switch (Type_0::get(v)) { case 0: return FAULT; - case 1: return PAGE_TABLE; - } - - switch (Type_1::get(v)) { - case 1: return SECTION; - } + case 1: return PAGE_TABLE; } + if (Type_1::get(v) == 1) { return SECTION; } return FAULT; } @@ -360,26 +325,13 @@ class Genode::Translation_table static void type(access_t & v, Type const t) { switch (t) { - case FAULT: - Type_0::set(v, 0); - return; - case PAGE_TABLE: - Type_0::set(v, 1); - return; - case SECTION: - Type_1::set(v, 1); - return; - } + case FAULT: Type_0::set(v, 0); return; + case PAGE_TABLE: Type_0::set(v, 1); return; + case SECTION: Type_1::set(v, 1); return; } } - /** - * Invalidate descriptor 'v' - */ static void invalidate(access_t & v) { type(v, FAULT); } - /** - * Return if descriptor 'v' is valid - */ static bool valid(access_t & v) { return type(v) != FAULT; } static inline Type align(addr_t vo, addr_t pa, size_t size) @@ -398,14 +350,13 @@ class Genode::Translation_table struct Pa : Bitfield<10, 22> { }; /* physical base */ /** - * Compose descriptor value + * Return descriptor value for page table 'pt */ static access_t create(Page_table * const pt) { - access_t v = Domain::bits(DOMAIN) | - Pa::masked((addr_t)pt); - Descriptor::type(v, Descriptor::PAGE_TABLE); - return v; + access_t v = Pa::masked((addr_t)pt); + Descriptor::type(v, Descriptor::PAGE_TABLE); + return v; } }; @@ -414,30 +365,22 @@ class Genode::Translation_table */ struct Section : Descriptor { - struct B : Bitfield<2, 1> { }; /* mem. region attr. */ - struct C : Bitfield<3, 1> { }; /* mem. region attr. */ - struct Xn : Bitfield<4, 1> { }; /* execute never bit */ - struct Domain : Bitfield<5, 4> { }; /* domain */ - struct Ap_0 : Bitfield<10, 2> { }; /* access permission */ - struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */ - struct Ap_1 : Bitfield<15, 1> { }; /* access permission */ - struct S : Bitfield<16, 1> { }; /* shared */ - struct Ng : Bitfield<17, 1> { }; /* not global */ - struct Pa : Bitfield<20, 12> { }; /* physical base */ - struct Ap : Bitset_2 { }; /* access permission */ + struct B : Bitfield<2, 1> { }; /* mem. region attr. */ + struct Xn : Bitfield<4, 1> { }; /* execute never bit */ + struct Ap_0 : Bitfield<10, 2> { }; /* access permission */ + struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */ + struct Ap_1 : Bitfield<15, 1> { }; /* access permission */ + struct S : Bitfield<16, 1> { }; /* shared */ + struct Ng : Bitfield<17, 1> { }; /* not global */ + struct Pa : Bitfield<20, 12> { }; /* physical base */ + struct Ap : Bitset_2 { }; /* access permission */ /** - * Compose descriptor value + * Return section descriptor for physical address 'pa' and 'flags' */ - static access_t create(Page_flags const & flags, - addr_t const pa) + static access_t create(Page_flags const & flags, addr_t const pa) { - access_t v = access_permission_bits
(flags); - v |= arm_memory_region_attr
(flags); - v |= Domain::bits(DOMAIN); - v |= S::bits(Cpu::is_smp()); - v |= Ng::bits(!flags.global); - v |= Pa::masked(pa); + access_t v = _create
(flags, pa); Descriptor::type(v, Descriptor::SECTION); return v; } @@ -451,15 +394,9 @@ class Genode::Translation_table enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 }; /** - * Get entry index by virtual offset + * Try to get entry index in 'i' for virtual offset 'vo! * - * \param i is overridden with the resulting index - * \param vo offset within the virtual region represented - * by this table - * - * \retval 0 on success - * \retval <0 if virtual offset couldn't be resolved, - * in this case 'i' reside invalid + * \return wether it was successful */ bool _index_by_vo(unsigned & i, addr_t const vo) const { @@ -478,12 +415,9 @@ class Genode::Translation_table * \param flags mapping flags * \param slab second level page slab allocator */ - void _insert_second_level(unsigned i, - addr_t const vo, - addr_t const pa, - size_t const size, - Page_flags const & flags, - Page_slab * slab) + void _insert_second_level(unsigned i, addr_t const vo, addr_t const pa, + size_t const size, Page_flags const & flags, + Page_slab * const slab) { Page_table * pt = 0; switch (Descriptor::type(_entries[i])) { @@ -499,13 +433,13 @@ class Genode::Translation_table _entries[i] = Page_table_descriptor::create(pt_phys); /* some processors need to act on changed translations */ - Cpu::translation_added((addr_t)&_entries[i], - sizeof(Descriptor::access_t)); + size_t const dsize = sizeof(Descriptor::access_t); + Cpu::translation_added((addr_t)&_entries[i], dsize); } case Descriptor::PAGE_TABLE: { - /* use allocator to retrieve virtual address of page table */ + /* use allocator to retrieve virtual addr. of page table */ void * pt_phys = (void*) Page_table_descriptor::Pa::masked(_entries[i]); pt = (Page_table *) slab->virt_addr(pt_phys); @@ -514,11 +448,11 @@ class Genode::Translation_table } default: assert(0); - }; + } /* insert translation */ - pt->insert_translation(vo - Section::Pa::masked(vo), - pa, size, flags); + addr_t const pt_vo = vo - Section::Pa::masked(vo); + pt->insert_translation(pt_vo, pa, size, flags); } public: @@ -542,26 +476,21 @@ class Genode::Translation_table */ static addr_t max_virt_offset() { - return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2) - + (Descriptor::VIRT_SIZE - 1); + constexpr addr_t base = MAX_INDEX << Descriptor::VIRT_SIZE_LOG2; + return base + (Descriptor::VIRT_SIZE - 1); } /** * Insert translations into this table * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - * \param slab second level page slab allocator + * \param vo offset of virt. transl. region in virt. table region + * \param pa base of physical backing store + * \param size size of translated region + * \param f mapping flags + * \param s second level page slab allocator */ - void insert_translation(addr_t vo, - addr_t pa, - size_t size, - Page_flags const & flags, - Page_slab * slab) + void insert_translation(addr_t vo, addr_t pa, size_t size, + Page_flags const & f, Page_slab * const s) { /* check sanity */ assert(!(vo & Page_table::Descriptor::VIRT_OFFSET_MASK) && @@ -569,8 +498,8 @@ class Genode::Translation_table for (unsigned i; (size > 0) && _index_by_vo (i, vo);) { - addr_t end = (vo + Descriptor::VIRT_SIZE) - & Descriptor::VIRT_BASE_MASK; + addr_t const ve = (vo + Descriptor::VIRT_SIZE); + addr_t const end = ve & Descriptor::VIRT_BASE_MASK; /* decide granularity of entry that can be inserted */ switch (Descriptor::align(vo, pa, size)) { @@ -578,29 +507,25 @@ class Genode::Translation_table case Descriptor::SECTION: { /* compose new entry */ - Section::access_t const e = Section::create(flags, pa); - - /* check if it is a good idea to override the entry */ - assert(!Descriptor::valid(_entries[i]) || - _entries[i] == e); + Section::access_t const e = Section::create(f, pa); /* override entry */ + if (_entries[i] == e) { break; } + assert(!Descriptor::valid(_entries[i])); _entries[i] = e; /* some CPUs need to act on changed translations */ - Cpu::translation_added((addr_t)&_entries[i], - sizeof(Descriptor::access_t)); + constexpr size_t ds = sizeof(Descriptor::access_t); + Cpu::translation_added((addr_t)&_entries[i], ds); break; } default: - { - _insert_second_level(i, vo, pa, min(size, end-vo), flags, slab); - } + _insert_second_level(i, vo, pa, min(size, end - vo), f, s); }; /* check whether we wrap */ - if (end < vo) return; + if (end < vo) { return; } size_t sz = end - vo; size = (size > sz) ? size - sz : 0; @@ -623,8 +548,8 @@ class Genode::Translation_table for (unsigned i; (size > 0) && _index_by_vo(i, vo);) { - addr_t end = (vo + Descriptor::VIRT_SIZE) - & Descriptor::VIRT_BASE_MASK; + constexpr addr_t dbm = Descriptor::VIRT_BASE_MASK; + addr_t const end = (vo + Descriptor::VIRT_SIZE) & dbm; switch (Descriptor::type(_entries[i])) { @@ -647,11 +572,7 @@ class Genode::Translation_table break; } - default: - { - Descriptor::invalidate(_entries[i]); - } - } + default: Descriptor::invalidate(_entries[i]); } /* check whether we wrap */ if (end < vo) return; diff --git a/repos/base-hw/src/core/include/spec/arm_gic/pic_support.h b/repos/base-hw/src/core/include/spec/arm_gic/pic_support.h index 578c8f26e..f0421cee1 100644 --- a/repos/base-hw/src/core/include/spec/arm_gic/pic_support.h +++ b/repos/base-hw/src/core/include/spec/arm_gic/pic_support.h @@ -39,79 +39,55 @@ class Genode::Arm_gic_distributor : public Mmio { public: - enum { NR_OF_IRQ = 1024 }; - - /** - * Constructor - */ - Arm_gic_distributor(addr_t const base) : Mmio(base) { } + static constexpr unsigned nr_of_irq = 1024; /** * Control register */ - struct Ctlr : Register<0x000, 32> - { - struct Enable : Bitfield<0,1> { }; - }; + struct Ctlr : Register<0x000, 32> { + struct Enable : Bitfield<0,1> { }; }; /** * Controller type register */ - struct Typer : Register<0x004, 32> - { - struct It_lines_number : Bitfield<0,5> { }; - struct Cpu_number : Bitfield<5,3> { }; - }; + struct Typer : Register<0x004, 32> { + struct It_lines_number : Bitfield<0,5> { }; }; /** * Interrupt group register */ - struct Igroupr : Register_array<0x80, 32, NR_OF_IRQ, 1> - { - struct Group_status : Bitfield<0, 1> { }; - }; + struct Igroupr : Register_array<0x80, 32, nr_of_irq, 1> { + struct Group_status : Bitfield<0, 1> { }; }; /** * Interrupt set enable registers */ - struct Isenabler : Register_array<0x100, 32, NR_OF_IRQ, 1, true> - { - struct Set_enable : Bitfield<0, 1> { }; - }; + struct Isenabler : Register_array<0x100, 32, nr_of_irq, 1, true> { + struct Set_enable : Bitfield<0, 1> { }; }; /** * Interrupt clear enable registers */ - struct Icenabler : Register_array<0x180, 32, NR_OF_IRQ, 1, true> - { - struct Clear_enable : Bitfield<0, 1> { }; - }; + struct Icenabler : Register_array<0x180, 32, nr_of_irq, 1, true> { + struct Clear_enable : Bitfield<0, 1> { }; }; /** * Interrupt priority level registers */ - struct Ipriorityr : Register_array<0x400, 32, NR_OF_IRQ, 8> - { - enum { GET_MIN = 0xff }; - - struct Priority : Bitfield<0, 8> { }; - }; + struct Ipriorityr : Register_array<0x400, 32, nr_of_irq, 8> { + struct Priority : Bitfield<0, 8> { }; }; /** * Interrupt processor target registers */ - struct Itargetsr : Register_array<0x800, 32, NR_OF_IRQ, 8> - { - struct Cpu_targets : Bitfield<0, 8> { }; - }; + struct Itargetsr : Register_array<0x800, 32, nr_of_irq, 8> { + struct Cpu_targets : Bitfield<0, 8> { }; }; /** * Interrupt configuration registers */ - struct Icfgr : Register_array<0xc00, 32, NR_OF_IRQ, 2> - { - struct Edge_triggered : Bitfield<1, 1> { }; - }; + struct Icfgr : Register_array<0xc00, 32, nr_of_irq, 2> { + struct Edge_triggered : Bitfield<1, 1> { }; }; /** * Software generated interrupt register @@ -123,27 +99,27 @@ class Genode::Arm_gic_distributor : public Mmio }; /** - * Minimum supported interrupt priority + * Constructor */ - Ipriorityr::access_t min_priority() + Arm_gic_distributor(addr_t const base) : Mmio(base) { } + + /** + * Return minimum IRQ priority + */ + unsigned min_priority() { - write(Ipriorityr::GET_MIN, 0); + write(~0, 0); return read(0); } /** - * Maximum supported interrupt priority + * Return highest IRQ number */ - Ipriorityr::access_t max_priority() { return 0; } - - /** - * ID of the maximum supported interrupt - */ - Typer::access_t max_interrupt() + unsigned max_irq() { - enum { LINE_WIDTH_LOG2 = 5 }; - Typer::access_t lnr = read(); - return ((lnr + 1) << LINE_WIDTH_LOG2) - 1; + constexpr unsigned line_width_log2 = 5; + Typer::access_t const lnr = read(); + return ((lnr + 1) << line_width_log2) - 1; } }; @@ -151,20 +127,12 @@ class Genode::Arm_gic_cpu_interface : public Mmio { public: - /** - * Constructor - */ - Arm_gic_cpu_interface(addr_t const base) : Mmio(base) { } - /** * Control register */ struct Ctlr : Register<0x00, 32> { - /* Without security extension */ - struct Enable : Bitfield<0,1> { }; - - /* In a secure world */ + struct Enable : Bitfield<0,1> { }; struct Enable_grp0 : Bitfield<0,1> { }; struct Enable_grp1 : Bitfield<1,1> { }; struct Fiq_en : Bitfield<3,1> { }; @@ -173,74 +141,66 @@ class Genode::Arm_gic_cpu_interface : public Mmio /** * Priority mask register */ - struct Pmr : Register<0x04, 32> - { - struct Priority : Bitfield<0,8> { }; - }; + struct Pmr : Register<0x04, 32> { + struct Priority : Bitfield<0,8> { }; }; /** * Binary point register */ - struct Bpr : Register<0x08, 32> - { - enum { NO_PREEMPTION = 7 }; - - struct Binary_point : Bitfield<0,3> { }; - }; + struct Bpr : Register<0x08, 32> { + struct Binary_point : Bitfield<0,3> { }; }; /** * Interrupt acknowledge register */ - struct Iar : Register<0x0c, 32, true> - { - struct Irq_id : Bitfield<0,10> { }; - }; + struct Iar : Register<0x0c, 32, true> { + struct Irq_id : Bitfield<0,10> { }; }; /** * End of interrupt register */ - struct Eoir : Register<0x10, 32, true> - { - struct Irq_id : Bitfield<0,10> { }; - struct Cpu_id : Bitfield<10,3> { }; - }; + struct Eoir : Register<0x10, 32, true> { + struct Irq_id : Bitfield<0,10> { }; }; + + /** + * Constructor + */ + Arm_gic_cpu_interface(addr_t const base) : Mmio(base) { } }; class Genode::Arm_gic { protected: - enum { - MIN_SPI = 32, - SPURIOUS_ID = 1023, - }; - typedef Arm_gic_cpu_interface Cpui; typedef Arm_gic_distributor Distr; + static constexpr unsigned min_spi = 32; + static constexpr unsigned spurious_id = 1023; + Distr _distr; Cpui _cpui; - unsigned const _max_interrupt; + unsigned const _max_irq; unsigned _last_request; /** - * Return inter-processor interrupt of a specific processor - * - * \param processor_id kernel name of targeted processor + * Return inter-processor IRQ of the CPU with kernel name 'cpu_id' */ - unsigned _ip_interrupt(unsigned const processor_id) const - { - return processor_id + 1; - } + unsigned _ipi(unsigned const cpu_id) const { return cpu_id + 1; } /** * Platform specific initialization */ void _init(); + /** + * Return wether kernel name 'irq_id' addresses a valid IRQ + */ + bool _valid(unsigned const irq_id) const { return irq_id <= _max_irq; } + public: - enum { NR_OF_IRQ = Distr::NR_OF_IRQ }; + enum { NR_OF_IRQ = Distr::nr_of_irq }; /** * Constructor @@ -248,124 +208,83 @@ class Genode::Arm_gic Arm_gic(addr_t const distr_base, addr_t const cpu_base) : _distr(distr_base), _cpui(cpu_base), - _max_interrupt(_distr.max_interrupt()), - _last_request(SPURIOUS_ID) - { - _init(); - } + _max_irq(_distr.max_irq()), + _last_request(spurious_id) { _init(); } /** - * Initialize processor local interface of the controller + * Initialize CPU local interface of the controller */ void init_processor_local() { /* disable the priority filter */ _cpui.write(_distr.min_priority()); - /* disable preemption of interrupt handling by interrupts */ - _cpui.write(Cpui::Bpr::NO_PREEMPTION); + /* disable preemption of IRQ handling by other IRQs */ + _cpui.write(~0); /* enable device */ _cpui.write(1); } /** - * Get the ID of the last interrupt request + * Try to take an IRQ and return wether it was successful * - * \return True if the request with ID 'i' is treated as accepted - * by the CPU and awaits an subsequently 'finish_request' - * call. Otherwise this returns false and the value of 'i' - * remains useless. + * \param irq_id contains kernel name of taken IRQ on success */ - bool take_request(unsigned & i) + bool take_request(unsigned & irq_id) { _last_request = _cpui.read(); - i = _last_request; - return valid(i); + irq_id = _last_request; + return _valid(irq_id); } /** - * Complete the last request that was taken via 'take_request' + * End the last taken IRQ */ void finish_request() { - if (!valid(_last_request)) return; - _cpui.write(Cpui::Eoir::Irq_id::bits(_last_request) | - Cpui::Eoir::Cpu_id::bits(0) ); - _last_request = SPURIOUS_ID; + if (!_valid(_last_request)) { return; } + _cpui.write(_last_request); + _last_request = spurious_id; } /** - * Check if 'i' is a valid interrupt request ID at the device - */ - bool valid(unsigned const i) const { return i <= _max_interrupt; } - - /** - * Unmask all interrupts - */ - void unmask() - { - for (unsigned i=0; i <= _max_interrupt; i++) { - _distr.write(1, i); - } - } - - /** - * Unmask interrupt and assign it to a specific processor + * Unmask IRQ and assign it to one CPU * - * \param interrupt_id kernel name of targeted interrupt - * \param processor_id kernel name of targeted processor + * \param irq_id kernel name of targeted IRQ + * \param cpu_id kernel name of targeted CPU */ - void unmask(unsigned const interrupt_id, unsigned const processor_id) + void unmask(unsigned const irq_id, unsigned const cpu_id) { - unsigned const targets = 1 << processor_id; - _distr.write(targets, interrupt_id); - _distr.write(1, interrupt_id); + unsigned const targets = 1 << cpu_id; + _distr.write(targets, irq_id); + _distr.write(1, irq_id); } /** - * Mask all interrupts + * Mask IRQ with kernel name 'irq_id' */ - void mask() - { - for (unsigned i=0; i <= _max_interrupt; i++) { - _distr.write(1, i); - } - } + void mask(unsigned const irq_id) { + _distr.write(1, irq_id); } /** - * Mask specific interrupt + * Return wether an IRQ is inter-processor IRQ of a CPU * - * \param interrupt_id kernel name of targeted interrupt + * \param irq_id kernel name of the IRQ + * \param cpu_id kernel name of the CPU */ - void mask(unsigned const interrupt_id) - { - _distr.write(1, interrupt_id); - } + bool is_ip_interrupt(unsigned const irq_id, unsigned const cpu_id) { + return irq_id == _ipi(cpu_id); } /** - * Wether an interrupt is inter-processor interrupt of a processor - * - * \param interrupt_id kernel name of the interrupt - * \param processor_id kernel name of the processor + * Raise inter-processor IRQ of the CPU with kernel name 'cpu_id' */ - bool is_ip_interrupt(unsigned const interrupt_id, - unsigned const processor_id) - { - return interrupt_id == _ip_interrupt(processor_id); - } - - /** - * Trigger the inter-processor interrupt of a processor - * - * \param processor_id kernel name of the processor - */ - void trigger_ip_interrupt(unsigned const processor_id) + void trigger_ip_interrupt(unsigned const cpu_id) { typedef Distr::Sgir Sgir; Sgir::access_t sgir = 0; - Sgir::Sgi_int_id::set(sgir, _ip_interrupt(processor_id)); - Sgir::Cpu_target_list::set(sgir, 1 << processor_id); + Sgir::Sgi_int_id::set(sgir, _ipi(cpu_id)); + Sgir::Cpu_target_list::set(sgir, 1 << cpu_id); _distr.write(sgir); } }; diff --git a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h index 60368131a..152a14555 100644 --- a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h +++ b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h @@ -146,7 +146,7 @@ class Genode::Cpu : public Arm Cidr::write(process_id); Dacr::write(Dacr::init_virt_kernel()); Ttbr0::write(Ttbr0::init(table)); - Ttbcr::write(Ttbcr::init_virt_kernel()); + Ttbcr::write(0); Sctlr::write(Sctlr::init_virt_kernel()); } diff --git a/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h b/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h index 93ff844ee..ea1c3bc26 100644 --- a/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h @@ -18,21 +18,6 @@ /* core includes */ #include -template -static typename T::access_t -Genode::arm_memory_region_attr(Page_flags const & flags) -{ - typedef typename T::Tex Tex; - typedef typename T::C C; - typedef typename T::B B; - if (flags.device) { return 0; } - - switch (flags.cacheable) { - case CACHED: return Tex::bits(5) | B::bits(1); - case WRITE_COMBINED: return B::bits(1); - case UNCACHED: return Tex::bits(1); - } - return 0; -} +constexpr unsigned Genode::Translation::_device_tex() { return 0; } #endif /* _TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h index 0704103c3..b4c559bf1 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h @@ -166,33 +166,10 @@ class Genode::Arm_v7 : public Arm */ struct Nsacr : Register<32> { - /************************************************ - ** Coprocessor 0-13 non-secure acccess enable ** - ************************************************/ - struct Cpnsae10 : Bitfield<10, 1> { }; struct Cpnsae11 : Bitfield<11, 1> { }; }; - /** - * Translation table base control register - */ - struct Ttbcr : Arm::Ttbcr - { - struct Pd0 : Bitfield<4,1> { }; /* disable walk for TTBR0 */ - struct Pd1 : Bitfield<5,1> { }; /* disable walk for TTBR1 */ - - /** - * Value for the switch to virtual mode in kernel - */ - static access_t init_virt_kernel() - { - return Arm::Ttbcr::init_virt_kernel() | - Pd0::bits(0) | - Pd1::bits(0); - } - }; - /** * System control register */ @@ -252,9 +229,7 @@ class Genode::Arm_v7 : public Arm struct Irgn : Bitset_2 { }; /* inner cache attr */ /** - * Return initialized value - * - * \param table base of targeted translation table + * Return value initialized with translation table 'table' */ static access_t init(addr_t const table) { @@ -283,7 +258,7 @@ class Genode::Arm_v7 : public Arm Cidr::write(process_id); Dacr::write(Dacr::init_virt_kernel()); Ttbr0::write(Ttbr0::init(table)); - Ttbcr::write(Ttbcr::init_virt_kernel()); + Ttbcr::write(0); Sctlr::write(Sctlr::init_virt_kernel()); inval_branch_predicts(); } @@ -317,32 +292,20 @@ class Genode::Arm_v7 : public Arm ******************************/ /** - * Set the exception-vector's base-address for the monitor mode - * software stack. - * - * \param addr address of the exception vector's base + * Set exception-vector's address for monitor mode to 'a' */ - static inline void mon_exception_entry_at(addr_t const addr) - { - asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (addr)); - } + static void mon_exception_entry_at(addr_t const a) { + asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (a)); } /** * Enable access of co-processors cp10 and cp11 from non-secure mode. */ static inline void allow_coprocessor_nonsecure() { - Nsacr::access_t rd = Nsacr::Cpnsae10::bits(1) | - Nsacr::Cpnsae11::bits(1); - asm volatile ("mcr p15, 0, %[rd], c1, c1, 2" : : [rd] "r" (rd)); - } - - /** - * Invalidate all predictions about the future control-flow - */ - static void invalidate_control_flow_predictions() - { - asm volatile ("mcr p15, 0, r0, c7, c5, 6"); + Nsacr::access_t v = 0; + Nsacr::Cpnsae10::set(v, 1); + Nsacr::Cpnsae11::set(v, 1); + asm volatile ("mcr p15, 0, %[v], c1, c1, 2" : : [v] "r" (v)); } /** @@ -351,17 +314,14 @@ class Genode::Arm_v7 : public Arm static void data_synchronization_barrier() { asm volatile ("dsb"); } /** - * Enable secondary processors that loop on wait-for-event - * - * \param ip initial instruction pointer for secondary processors + * Enable secondary processors with instr. pointer 'ip' */ static void start_secondary_processors(void * const ip) { - if (is_smp()) { - Board::secondary_processors_ip(ip); - data_synchronization_barrier(); - asm volatile ("sev\n"); - } + if (!is_smp()) { return; } + Board::secondary_processors_ip(ip); + data_synchronization_barrier(); + asm volatile ("sev\n"); } /** @@ -391,18 +351,13 @@ void Genode::Arm::invalidate_data_caches() } -Genode::Arm::Psr::access_t -Genode::Arm::Psr::init_user_with_trustzone() +Genode::Arm::Psr::access_t Genode::Arm::Psr::init_user_with_trustzone() { - return M::bits(M::USER) | - T::bits(T::ARM) | - F::bits(0) | - I::bits(1) | - A::bits(1) | - E::bits(E::LITTLE) | - J::bits(J::ARM); + access_t v = 0; + M::set(v, usr); + I::set(v, 1); + A::set(v, 1); + return v; } - #endif /* _SPEC__ARM_V7__CPU_SUPPORT_H_ */ - diff --git a/repos/base-hw/src/core/include/spec/arm_v7/translation_table.h b/repos/base-hw/src/core/include/spec/arm_v7/translation_table.h index 679287638..677096c9f 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/translation_table.h @@ -18,21 +18,6 @@ /* core includes */ #include -template -static typename T::access_t -Genode::arm_memory_region_attr(Page_flags const & flags) -{ - typedef typename T::Tex Tex; - typedef typename T::C C; - typedef typename T::B B; - if (flags.device) { return Tex::bits(2); } - - switch (flags.cacheable) { - case CACHED: return Tex::bits(5) | B::bits(1); - case WRITE_COMBINED: return B::bits(1); - case UNCACHED: return Tex::bits(1); - } - return 0; -} +constexpr unsigned Genode::Translation::_device_tex() { return 2; } #endif /* _TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx31/pic.h b/repos/base-hw/src/core/include/spec/imx31/pic.h index 82805adc4..b62477b0b 100644 --- a/repos/base-hw/src/core/include/spec/imx31/pic.h +++ b/repos/base-hw/src/core/include/spec/imx31/pic.h @@ -24,189 +24,90 @@ namespace Genode class Genode::Pic : public Mmio { - /** - * Interrupt control register - */ - struct Intcntl : Register<0x0, 32> - { - struct Nm : Bitfield<18,1> /* IRQ mode */ + private: + + struct Intcntl : Register<0x0, 32> { }; /* IRQ control register */ + struct Nimask : Register<0x4, 32> { }; /* normal IRQ mask reg. */ + struct Intennum : Register<0x8, 32> { }; /* IRQ enable nr. reg. */ + struct Intdisnum : Register<0xc, 32> { }; /* IRQ disable nr. reg. */ + struct Intenableh : Register<0x10, 32> { }; /* IRQ enable register */ + struct Intenablel : Register<0x14, 32> { }; /* IRQ enable register */ + struct Inttypeh : Register<0x18, 32> { }; /* IRQ type register */ + struct Inttypel : Register<0x1c, 32> { }; /* IRQ type register */ + struct Intsrch : Register<0x48, 32> { }; /* IRQ source register */ + struct Intsrcl : Register<0x4c, 32> { }; /* IRQ source register */ + struct Nipndh : Register<0x58, 32> { }; /* normal IRQ pending */ + struct Nipndl : Register<0x5c, 32> { }; /* normal IRQ pending */ + + /** + * Normal interrupt priority registers + */ + struct Nipriority : Register_array<0x20, 32, 8, 32> { }; + + /** + * Normal interrupt vector and status register + */ + struct Nivecsr : Register<0x40, 32> { - enum { SW_CONTROL = 0 }; + struct Nvector : Bitfield<16, 16> { }; }; - struct Fiad : Bitfield<19,1> { }; /* FIQ rises prio in arbiter */ - struct Niad : Bitfield<20,1> { }; /* IRQ rises prio in arbiter */ - struct Fidis : Bitfield<21,1> { }; /* FIQ disable */ - struct Nidis : Bitfield<22,1> { }; /* IRQ disable */ - struct Abfen : Bitfield<24,1> { }; /* if ABFLAG is sticky */ - struct Abflag : Bitfield<25,1> { }; /* rise prio in bus arbiter */ - - static access_t init_value() - { - return Nm::bits(Nm::SW_CONTROL) | - Fiad::bits(0) | - Niad::bits(0) | - Fidis::bits(0) | - Nidis::bits(0) | - Abfen::bits(0) | - Abflag::bits(0); - } - }; - - /** - * Normal interrupt mask register - */ - struct Nimask : Register<0x4, 32> - { - enum { NONE_MASKED = ~0 }; - }; - - /** - * Interrupt enable number register - */ - struct Intennum : Register<0x8, 32> - { - struct Enable : Bitfield<0,6> { }; - }; - - /** - * Interrupt disable number register - */ - struct Intdisnum : Register<0xc, 32> - { - struct Disable : Bitfield<0,6> { }; - }; - - /** - * Interrupt enable register - */ - struct Intenableh : Register<0x10, 32> { }; - struct Intenablel : Register<0x14, 32> { }; - - /** - * Interrupt type register - */ - struct Inttype { enum { ALL_IRQS = 0 }; }; - struct Inttypeh : Register<0x18, 32> { }; - struct Inttypel : Register<0x1c, 32> { }; - - /** - * Normal interrupt priority registers - */ - struct Nipriority : Register_array<0x20, 32, 8, 32> - { - enum { ALL_LOWEST = 0 }; - }; - - /** - * Interrupt source registers - */ - struct Intsrch : Register<0x48, 32> { }; - struct Intsrcl : Register<0x4c, 32> { }; - - /** - * Normal interrupt pending registers - */ - struct Nipndh : Register<0x58, 32> { }; - struct Nipndl : Register<0x5c, 32> { }; - - /** - * Normal interrupt vector and status register - */ - struct Nivecsr : Register<0x40, 32> - { - struct Nvector : Bitfield<16, 16> { }; - }; + /** + * Validate request number 'i' + */ + bool _valid(unsigned const i) const { return i < NR_OF_IRQ; } public: enum { NR_OF_IRQ = 64 }; /** - * Constructor, enables all interrupts + * Constructor */ Pic() : Mmio(Board::AVIC_MMIO_BASE) { - mask(); - write(Nimask::NONE_MASKED); - write(Intcntl::init_value()); - write(Inttype::ALL_IRQS); - write(Inttype::ALL_IRQS); - for (unsigned i = 0; i < Nipriority::ITEMS; i++) - write(Nipriority::ALL_LOWEST, i); + write(0); + write(0); + write(~0); + write(0); + write(0); + write(0); + for (unsigned i = 0; i < Nipriority::ITEMS; i++) { + write(0, i); } } /** - * Initialize processor local interface of the controller - */ - void init_processor_local() { } - - /** - * Receive a pending request number 'i' + * Try to receive an IRQ in 'i' and return wether it was successful */ bool take_request(unsigned & i) { i = read(); - return valid(i) ? true : false; + return _valid(i); } /** - * Finish the last taken request + * Unmask IRQ 'i' */ - void finish_request() { - /* requests disappear by source retraction or masking */ } + void unmask(unsigned const i, unsigned) { + if (_valid(i)) { write(i); } } /** - * Validate request number 'i' + * Mask IRQ 'i' */ - bool valid(unsigned const i) const { - return i < NR_OF_IRQ; } + void mask(unsigned const i) { if (i < NR_OF_IRQ) write(i); } /** - * Mask all interrupts + * Return wether IRQ 'irq_id' is inter-processor IRQ of CPU 'cpu_id' */ - void mask() - { - write(0); - write(0); - } + bool is_ip_interrupt(unsigned, unsigned) { return false; } - /** - * Unmask interrupt - * - * \param interrupt_id kernel name of targeted interrupt - */ - void unmask(unsigned const interrupt_id, unsigned) - { - if (interrupt_id < NR_OF_IRQ) { - write(interrupt_id); - } - } + /************* + ** Dummies ** + *************/ - /** - * Mask interrupt 'i' - */ - void mask(unsigned const i) { - if (i < NR_OF_IRQ) write(i); } - - /** - * Wether an interrupt is inter-processor interrupt of a processor - * - * \param interrupt_id kernel name of the interrupt - * \param processor_id kernel name of the processor - */ - bool is_ip_interrupt(unsigned const interrupt_id, - unsigned const processor_id) - { - return false; - } - - /** - * Trigger the inter-processor interrupt of a processor - * - * \param processor_id kernel name of the processor - */ - void trigger_ip_interrupt(unsigned const processor_id) { } + void init_processor_local() { } + void trigger_ip_interrupt(unsigned) { } + void finish_request() { /* done by source retraction or masking */ } }; namespace Kernel { class Pic : public Genode::Pic { }; } diff --git a/repos/base-hw/src/core/include/spec/imx53/pic.h b/repos/base-hw/src/core/include/spec/imx53/pic.h index 893897511..6392f2c6d 100644 --- a/repos/base-hw/src/core/include/spec/imx53/pic.h +++ b/repos/base-hw/src/core/include/spec/imx53/pic.h @@ -46,73 +46,40 @@ class Genode::Pic : public Mmio struct Nsen_mask : Bitfield<31,1> { }; }; - struct Priomask : Register<0xc, 32> - { - struct Mask : Bitfield<0,8> { }; - }; - - struct Syncctrl : Register<0x10, 32> - { - struct Syncmode : Bitfield<0,2> { }; - }; - - struct Dsmint : Register<0x14, 32> - { - struct Dsm : Bitfield<0,1> { }; - }; + /** + * Priority mask register + */ + struct Priomask : Register<0xc, 32> { + struct Mask : Bitfield<0,8> { }; }; /** * Interrupt security registers */ - struct Intsec : Register_array<0x80, 32, NR_OF_IRQ, 1> - { - struct Nonsecure : Bitfield<0, 1> { }; - }; + struct Intsec : Register_array<0x80, 32, NR_OF_IRQ, 1> { + struct Nonsecure : Bitfield<0, 1> { }; }; /** * Interrupt set enable registers */ - struct Enset : Register_array<0x100, 32, NR_OF_IRQ, 1, true> - { - struct Set_enable : Bitfield<0, 1> { }; - }; + struct Enset : Register_array<0x100, 32, NR_OF_IRQ, 1, true> { + struct Set_enable : Bitfield<0, 1> { }; }; /** * Interrupt clear enable registers */ - struct Enclear : Register_array<0x180, 32, NR_OF_IRQ, 1, true> - { - struct Clear_enable : Bitfield<0, 1> { }; - }; + struct Enclear : Register_array<0x180, 32, NR_OF_IRQ, 1, true> { + struct Clear_enable : Bitfield<0, 1> { }; }; /** * Interrupt priority level registers */ - struct Priority : Register_array<0x400, 32, NR_OF_IRQ, 8> - { - enum { MIN_PRIO = 0xff }; - }; - - /** - * Pending registers - */ - struct Pndr : Register_array<0xd00, 32, NR_OF_IRQ, 1> - { - struct Pending : Bitfield<0, 1> { }; - }; + struct Priority : Register_array<0x400, 32, NR_OF_IRQ, 8> { }; /** * Highest interrupt pending registers */ - struct Hipndr : Register_array<0xd80, 32, NR_OF_IRQ, 1, true> - { - struct Pending : Bitfield<0, 1> { }; - }; - - /** - * Maximum supported interrupt priority - */ - unsigned _max_priority() { return 255; } + struct Hipndr : Register_array<0xd80, 32, NR_OF_IRQ, 1, true> { + struct Pending : Bitfield<0, 1> { }; }; /** * Initializes security extension if needed @@ -131,104 +98,66 @@ class Genode::Pic : public Mmio write(1, i); } write(0x1f); - write(Intctrl::Enable::bits(1) | - Intctrl::Nsen::bits(1) | - Intctrl::Nsen_mask::bits(1)); + Intctrl::access_t v = 0; + Intctrl::Enable::set(v, 1); + Intctrl::Nsen::set(v, 1); + Intctrl::Nsen_mask::set(v, 1); + write(v); _init_security_ext(); } /** - * Mark interrupt unsecure - * - * \param i targeted interrupt + * Mark interrupt 'i' unsecure */ void unsecure(unsigned const i); /** - * Mark interrupt secure - * - * \param i targeted interrupt + * Mark interrupt 'i' secure */ void secure(unsigned const i); - /** - * Initialize processor local interface of the controller - */ - void init_processor_local() { } - /** * Receive a pending request number 'i' */ bool take_request(unsigned & i) { for (unsigned j = 0; j < NR_OF_IRQ; j++) { - if (read(j)) { - i = j; - return true; - } + if (!read(j)) { continue; } + i = j; + return true; } return false; } - /** - * Finish the last taken request - */ - void finish_request() { } - /** * Validate request number 'i' */ - bool valid(unsigned const i) const { - return i < NR_OF_IRQ; } + bool valid(unsigned const i) const { return i < NR_OF_IRQ; } /** - * Mask all interrupts + * Unmask interrupt 'i' */ - void mask() - { - for (unsigned i=0; i < NR_OF_IRQ; i++) - write(1, i); - } - - /** - * Unmask interrupt - * - * \param interrupt_id kernel name of targeted interrupt - */ - void unmask(unsigned const interrupt_id, unsigned) - { - if (interrupt_id < NR_OF_IRQ) { - write(1, interrupt_id); - } - } + void unmask(unsigned const i, unsigned) { + if (valid(i)) { write(1, i); } } /** * Mask interrupt 'i' */ - void mask(unsigned const i) - { - if (i < NR_OF_IRQ) - write(1, i); - } + void mask(unsigned const i) { + if (valid(i)) { write(1, i); } } /** * Wether an interrupt is inter-processor interrupt of a processor - * - * \param interrupt_id kernel name of the interrupt - * \param processor_id kernel name of the processor */ - bool is_ip_interrupt(unsigned const interrupt_id, - unsigned const processor_id) - { - return false; - } + bool is_ip_interrupt(unsigned, unsigned) { return false; } - /** - * Trigger the inter-processor interrupt of a processor - * - * \param processor_id kernel name of the processor - */ - void trigger_ip_interrupt(unsigned const processor_id) { } + /************* + ** Dummies ** + *************/ + + void trigger_ip_interrupt(unsigned) { } + void init_processor_local() { } + void finish_request() { } }; namespace Kernel { class Pic : public Genode::Pic { }; } diff --git a/repos/base-hw/src/core/include/spec/panda/board.h b/repos/base-hw/src/core/include/spec/panda/board.h index 7b141bda3..494f4a6d1 100644 --- a/repos/base-hw/src/core/include/spec/panda/board.h +++ b/repos/base-hw/src/core/include/spec/panda/board.h @@ -50,29 +50,29 @@ namespace Genode struct Aux : Register<0x104, 32> { - struct Associativity : Bitfield<16,1> { - enum { WAY_8, WAY_16 }; }; - struct Way_size : Bitfield<17,3> { - enum { SZ_64KB = 0x3 }; }; - struct Share_override : Bitfield<22,1> {}; - struct Reserved : Bitfield<25,1> {}; - struct Ns_lockdown : Bitfield<26,1> {}; - struct Ns_irq_ctrl : Bitfield<27,1> {}; - struct Data_prefetch : Bitfield<28,1> {}; - struct Inst_prefetch : Bitfield<29,1> {}; - struct Early_bresp : Bitfield<30,1> {}; + struct Associativity : Bitfield<16,1> { }; + struct Way_size : Bitfield<17,3> { }; + struct Share_override : Bitfield<22,1> { }; + struct Reserved : Bitfield<25,1> { }; + struct Ns_lockdown : Bitfield<26,1> { }; + struct Ns_irq_ctrl : Bitfield<27,1> { }; + struct Data_prefetch : Bitfield<28,1> { }; + struct Inst_prefetch : Bitfield<29,1> { }; + struct Early_bresp : Bitfield<30,1> { }; static access_t init_value() { - return Associativity::bits(Associativity::WAY_16) | - Way_size::bits(Way_size::SZ_64KB) | - Share_override::bits(1) | - Reserved::bits(1) | - Ns_lockdown::bits(1) | - Ns_irq_ctrl::bits(1) | - Data_prefetch::bits(1) | - Inst_prefetch::bits(1) | - Early_bresp::bits(1); + access_t v = 0; + Associativity::set(v, 1); + Way_size::set(v, 3); + Share_override::set(v, 1); + Reserved::set(v, 1); + Ns_lockdown::set(v, 1); + Ns_irq_ctrl::set(v, 1); + Data_prefetch::set(v, 1); + Inst_prefetch::set(v, 1); + Early_bresp::set(v, 1); + return v; } }; diff --git a/repos/base-hw/src/core/include/spec/vea9x4/trustzone/pic.h b/repos/base-hw/src/core/include/spec/vea9x4/trustzone/pic.h index d529d57d6..caea8d1ca 100644 --- a/repos/base-hw/src/core/include/spec/vea9x4/trustzone/pic.h +++ b/repos/base-hw/src/core/include/spec/vea9x4/trustzone/pic.h @@ -38,7 +38,7 @@ class Genode::Pic : public Arm_gic Cpu::PL390_CPU_MMIO_BASE) { /* configure every shared peripheral interrupt */ - for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) { + for (unsigned i = min_spi; i <= _max_interrupt; i++) { _distr.write(0, i); _distr.write(0, i); _distr.write(0xff, i); @@ -55,7 +55,7 @@ class Genode::Pic : public Arm_gic _cpui.write(ctlr); /* use whole band of prios */ - _cpui.write(Cpui::Bpr::NO_PREEMPTION); + _cpui.write(~0); /* enable device */ _distr.write(Distr::Ctlr::Enable::bits(1)); diff --git a/repos/base-hw/src/core/kernel/kernel.cc b/repos/base-hw/src/core/kernel/kernel.cc index f0af51ccd..e5af77e94 100644 --- a/repos/base-hw/src/core/kernel/kernel.cc +++ b/repos/base-hw/src/core/kernel/kernel.cc @@ -246,7 +246,6 @@ extern "C" void init_kernel_multiprocessor() /* synchronize data view of all processors */ Processor::invalidate_data_caches(); Processor::invalidate_instr_caches(); - Processor::invalidate_control_flow_predictions(); Processor::data_synchronization_barrier(); /* initialize processor in physical mode */ diff --git a/repos/base-hw/src/core/spec/arm_gic/pic.cc b/repos/base-hw/src/core/spec/arm_gic/pic.cc index ba1acf5d8..f10dc2ab3 100644 --- a/repos/base-hw/src/core/spec/arm_gic/pic.cc +++ b/repos/base-hw/src/core/spec/arm_gic/pic.cc @@ -22,10 +22,9 @@ void Arm_gic::_init() _distr.write(0); /* configure every shared peripheral interrupt */ - for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) - { + for (unsigned i = min_spi; i <= _max_irq; i++) { _distr.write(0, i); - _distr.write(_distr.max_priority(), i); + _distr.write(0, i); } /* enable device */ _distr.write(1); diff --git a/repos/base-hw/src/core/spec/arm_v6/perf_counter.cc b/repos/base-hw/src/core/spec/arm_v6/perf_counter.cc index 436bc5fe7..308f1f563 100644 --- a/repos/base-hw/src/core/spec/arm_v6/perf_counter.cc +++ b/repos/base-hw/src/core/spec/arm_v6/perf_counter.cc @@ -33,9 +33,11 @@ struct Pmcr : Register<32> static access_t enable_and_reset() { - return E::bits(1) | - P::bits(1) | - C::bits(1); + access_t v = 0; + E::set(v, 1); + P::set(v, 1); + C::set(v, 1); + return v; } static access_t read() @@ -45,10 +47,8 @@ struct Pmcr : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %[v], c15, c12, 0" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %[v], c15, c12, 0" :: [v]"r"(v) : ); } }; @@ -57,12 +57,7 @@ struct Pmcr : Register<32> */ struct Sysvalcntrr : Register<32> { - struct Resetcntr : Bitfield<0,1> { }; /* reset all counter */ - - static access_t reset_counter() - { - return Resetcntr::bits(0); - } + static access_t reset_counter() { return 0; } static access_t read() { @@ -71,10 +66,8 @@ struct Sysvalcntrr : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %[v], c15, c12, 1" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %[v], c15, c12, 1" :: [v]"r"(v) : ); } }; @@ -85,10 +78,7 @@ struct Accvalctlr : Register<32> { struct V : Bitfield<0,1> { }; /* enable access in user-mode */ - static access_t enable_user_access() - { - return V::bits(1); - } + static access_t enable_user_access() { return V::bits(1); } static access_t read() { @@ -97,18 +87,16 @@ struct Accvalctlr : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %[v], c15, c9, 0" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %[v], c15, c9, 0" :: [v]"r"(v) : ); } }; void Kernel::Perf_counter::enable() { /* enable counters and disable overflow interrupt. */ - Pmcr::access_t v = Pmcr::enable_and_reset() | - Pmcr::D::bits(1); /* count every 64 cycles */ + Pmcr::access_t v = Pmcr::enable_and_reset(); + Pmcr::D::set(v, 1); /* count every 64 cycles */ Pmcr::write(v); Sysvalcntrr::write(Sysvalcntrr::reset_counter()); diff --git a/repos/base-hw/src/core/spec/arm_v7/perf_counter.cc b/repos/base-hw/src/core/spec/arm_v7/perf_counter.cc index 26dffeb71..daed56c68 100644 --- a/repos/base-hw/src/core/spec/arm_v7/perf_counter.cc +++ b/repos/base-hw/src/core/spec/arm_v7/perf_counter.cc @@ -33,9 +33,11 @@ struct Pmcr : Register<32> static access_t enable_and_reset() { - return E::bits(1) | - P::bits(1) | - C::bits(1); + access_t v = 0; + E::set(v, 1); + P::set(v, 1); + C::set(v, 1); + return v; } static access_t read() @@ -45,10 +47,8 @@ struct Pmcr : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %[v], c9, c12, 0" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %[v], c9, c12, 0" :: [v]"r"(v) : ); } }; @@ -57,15 +57,17 @@ struct Pmcr : Register<32> */ struct Pmintenclr : Register<32> { - struct C : Bitfield<31,1> { }; /* disable cycle counter overflow interrupt request */ - struct P0 : Bitfield<0,1> { }; /* disable pmc0 overflow interrupt request */ - struct P1 : Bitfield<1,1> { }; /* disable pmc1 overflow interrupt reuqest */ + struct C : Bitfield<31,1> { }; /* disable cycle counter overflow IRQ */ + struct P0 : Bitfield<0,1> { }; /* disable pmc0 overflow IRQ */ + struct P1 : Bitfield<1,1> { }; /* disable pmc1 overflow IRQ */ static access_t disable_overflow_intr() { - return C::bits(1) | - P0::bits(1) | - P1::bits(1); + access_t v = 0; + C::set(v, 1) ; + P0::set(v, 1); + P1::set(v, 1); + return v; } static access_t read() @@ -75,10 +77,8 @@ struct Pmintenclr : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %[v], c9, c14, 2" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %[v], c9, c14, 2" :: [v]"r"(v) : ); } }; @@ -95,11 +95,13 @@ struct Pmcntenset : Register<32> static access_t enable_counter() { - return C::bits(1) | - P0::bits(1) | - P1::bits(1) | - P2::bits(1) | - P3::bits(1); + access_t v = 0; + C::set(v, 1); + P0::set(v, 1); + P1::set(v, 1); + P2::set(v, 1); + P3::set(v, 1); + return v; } static access_t read() @@ -109,10 +111,8 @@ struct Pmcntenset : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %0, c9, c12, 1" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %0, c9, c12, 1" :: [v]"r"(v) : ); } }; @@ -127,9 +127,11 @@ struct Pmovsr : Register<32> static access_t clear_overflow_flags() { - return C::bits(1) | - P0::bits(1) | - P1::bits(1); + access_t v = 0; + C::set(v, 1); + P0::set(v, 1); + P1::set(v, 1); + return v; } static access_t read() @@ -139,10 +141,8 @@ struct Pmovsr : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %0, c9, c12, 3" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %0, c9, c12, 3" :: [v]"r"(v) : ); } }; @@ -151,12 +151,9 @@ struct Pmovsr : Register<32> */ struct Pmuseren : Register<32> { - struct En : Bitfield<0,1> { }; /* enable user mode access */ + struct En : Bitfield<0,1> { }; /* enable user mode access */ - static access_t enable() - { - return En::bits(1); - } + static access_t enable() { return En::bits(1); } static access_t read() { @@ -165,10 +162,8 @@ struct Pmuseren : Register<32> return v; } - static void write(access_t const v) - { - asm volatile("mcr p15, 0, %0, c9, c14, 0" :: [v]"r"(v) : ); - } + static void write(access_t const v) { + asm volatile("mcr p15, 0, %0, c9, c14, 0" :: [v]"r"(v) : ); } }; diff --git a/repos/base-hw/src/core/spec/vea9x4/trustzone/pic.cc b/repos/base-hw/src/core/spec/vea9x4/trustzone/pic.cc index 0e7af5103..721d9f32a 100644 --- a/repos/base-hw/src/core/spec/vea9x4/trustzone/pic.cc +++ b/repos/base-hw/src/core/spec/vea9x4/trustzone/pic.cc @@ -1,6 +1,7 @@ /* * \brief Programmable interrupt controller for core - * \author Martin stein + * \author Stefan Kalkowski + * \author Martin Stein * \date 2011-10-26 */ @@ -19,22 +20,25 @@ using namespace Genode; void Arm_gic::_init() { /* configure every shared peripheral interrupt */ - for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) { + for (unsigned i = min_spi; i <= _max_irq; i++) { _distr.write(0, i); _distr.write(0, i); - _distr.write(0xff, i); + _distr.write(~0, i); } /* disable the priority filter */ - _cpui.write(0xff); + _cpui.write(~0); /* signal secure IRQ via FIQ interface */ - _cpui.write(Cpui::Ctlr::Enable_grp0::bits(1) | - Cpui::Ctlr::Enable_grp1::bits(1) | - Cpui::Ctlr::Fiq_en::bits(1)); + typedef Cpui::Ctlr Ctlr; + Ctlr::access_t v = 0; + Ctlr::Enable_grp0::set(v, 1); + Ctlr::Enable_grp1::set(v, 1); + Ctlr::Fiq_en::set(v, 1); + _cpui.write(v); /* use whole band of prios */ - _cpui.write(Cpui::Bpr::NO_PREEMPTION); + _cpui.write(~0); /* enable device */ _distr.write(Distr::Ctlr::Enable::bits(1));