/** * \file * \brief Standard headers for kernel code. * * All C source in the kernel should include this file first. * This file should contain only definitions and prototypes that are * required for the majority of kernel code. */ /* * Copyright (c) 2007, 2008, 2009, 2010, 2016, ETH Zurich. * All rights reserved. * * This file is distributed under the terms in the attached LICENSE file. * If you do not find this file, copies can be found by writing to: * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ #ifndef __KERNEL_H #define __KERNEL_H #include #include #include // printf for debug #include #include #include #include #include #include #include #include #include #include /* XXX */ #include #include extern const char *kernel_command_line; extern coreid_t my_core_id; bool arch_core_is_bsp(void); /* * Utility macros. * FIXME: should we move these elsewhere? */ /** Macro to return the number of entries in a statically-allocated array. */ #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) /// Round up n to the next multiple of size #define ROUND_UP(n, size) ((((n) + (size) - 1)) & (~((size) - 1))) #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) #endif /** * \brief Align block at base_addr with size n to power of two * alignable at its size * * Compute the highest exponent x of n so that 2^x \< n _and_ * the base_addr is aligned at its size. * For example: n = 20, base_addr = 4 => size can be 1, 2 or 4. * Biggest possible block is 4 => x = 2 * * \param n Size of the block to split in bytes * \param base_addr Base address of the block to split * * \return Highest exponent (bits) for the blocksize to use next */ /// Computes the floor of log_2 of the given number static inline uint8_t log2flr(uintptr_t num) { uint8_t l = 0; uintptr_t n; for (n = num; n > 1; n >>= 1, l++); return l; } /// Computes the ceiling of log_2 of the given number static inline uint8_t log2cl(uintptr_t num) { uint8_t l = log2flr(num); if (num == ((uintptr_t)1) << l) { /* fencepost case */ return l; } else { return l + 1; } } static inline int bitaddralign(size_t n, lpaddr_t base_addr) { int exponent = sizeof(size_t) * NBBY - 1; if(n == 0) { return 0; } while ((exponent > 0) && ((base_addr % (1UL << exponent)) != 0)){ exponent--; } return((1UL << exponent) > n ? log2flr(n) : exponent); } void wait_cycles(uint64_t duration); void kernel_startup_early(void); void kernel_startup(void) __attribute__ ((noreturn)); /** * kernel timeslice in system ticks */ extern systime_t kernel_timeslice; /** * command-line option for kernel timeslice in milliseconds */ extern unsigned int config_timeslice; /** * variable for gating timer interrupts. */ extern bool kernel_ticks_enabled; extern lvaddr_t kernel_trace_buf; extern struct capability monitor_ep; #ifndef STATIC_ASSERT /* * Variant based on Padraig Brady's implementation * http://www.pixelbeat.org/programming/gcc/static_assert.html */ #define ASSERT_CONCAT_(a, b) a##b #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) /* These can't be used after statements in c89. */ #ifdef __COUNTER__ /* Microsoft compiler. */ #define STATIC_ASSERT(e,m) \ enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) } #else /* This can't be used twice on the same line so ensure if using in headers * that the headers are not included twice (by wrapping in #ifndef...#endif) * Note it doesn't cause an issue when used on same line of separate modules * compiled with gcc -combine -fwhole-program. */ #define STATIC_ASSERT(e,m) \ enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) } #endif #define STATIC_ASSERT_SIZEOF(tname,n) \ STATIC_ASSERT(sizeof(tname) == n, \ ASSERT_CONCAT("Size mismatch:", tname) \ ) #define sa_offsetof(x,y) ((size_t)(((void*)&(((x*)0)->y)) - (void*)(x*)0)) #define STATIC_ASSERT_OFFSETOF(tname, field, offset) \ STATIC_ASSERT(sa_offsetof(tname, field) == offset, \ ASSERT_CONCAT("Offset mismatch:", field) \ ) #endif #endif // __KERNEL_H