1/**
2 * \file
3 * \brief Standard headers for kernel code.
4 *
5 * All C source in the kernel should include this file first.
6 * This file should contain only definitions and prototypes that are
7 * required for the majority of kernel code.
8 */
9
10/*
11 * Copyright (c) 2007, 2008, 2009, 2010, 2016, ETH Zurich.
12 * All rights reserved.
13 *
14 * This file is distributed under the terms in the attached LICENSE file.
15 * If you do not find this file, copies can be found by writing to:
16 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
17 */
18
19#ifndef __KERNEL_H
20#define __KERNEL_H
21
22#include <assert.h>
23#include <stddef.h>
24#include <stdio.h> // printf for debug
25#include <stdint.h>
26#include <inttypes.h>
27#include <stdbool.h>
28#include <barrelfish_kpi/types.h>
29#include <barrelfish_kpi/cpu.h>
30#include <barrelfish_kpi/registers_arch.h>
31#include <errors/errno.h>
32#include <bitmacros.h>
33#include <debug.h>
34#include <offsets.h> /* XXX */
35#include <schedule.h>
36#include <logging.h>
37
38extern const char *kernel_command_line;
39extern coreid_t my_core_id;
40
41bool arch_core_is_bsp(void);
42
43/*
44 * Utility macros.
45 * FIXME: should we move these elsewhere?
46 */
47
48/** Macro to return the number of entries in a statically-allocated array. */
49#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
50
51/// Round up n to the next multiple of size
52#define ROUND_UP(n, size)           ((((n) + (size) - 1)) & (~((size) - 1)))
53
54#ifndef min
55#define min(a,b) ((a) < (b) ? (a) : (b))
56#endif
57#ifndef max
58#define max(a,b) ((a) > (b) ? (a) : (b))
59#endif
60
61/**
62 * \brief Align block at base_addr with size n to power of two
63 * alignable at its size
64 *
65 * Compute the highest exponent x of n so that 2^x \< n _and_
66 * the base_addr is aligned at its size.
67 * For example: n = 20, base_addr = 4 => size can be 1, 2 or 4.
68 * Biggest possible block is 4 => x = 2
69 *
70 * \param n         Size of the block to split in bytes
71 * \param base_addr Base address of the block to split
72 *
73 * \return Highest exponent (bits) for the blocksize to use next
74 */
75
76/// Computes the floor of log_2 of the given number
77static inline uint8_t log2flr(uintptr_t num)
78{
79    uint8_t l = 0;
80    uintptr_t n;
81    for (n = num; n > 1; n >>= 1, l++);
82    return l;
83}
84
85/// Computes the ceiling of log_2 of the given number
86static inline uint8_t log2cl(uintptr_t num)
87{
88    uint8_t l = log2flr(num);
89    if (num == ((uintptr_t)1) << l) { /* fencepost case */
90        return l;
91    } else {
92        return l + 1;
93    }
94}
95
96static inline int bitaddralign(size_t n, lpaddr_t base_addr)
97{
98    int exponent = sizeof(size_t) * NBBY - 1;
99
100    if(n == 0) {
101        return 0;
102    }
103
104    while ((exponent > 0) && ((base_addr % (1UL << exponent)) != 0)){
105        exponent--;
106    }
107    return((1UL << exponent) > n ? log2flr(n) : exponent);
108}
109
110void wait_cycles(uint64_t duration);
111void kernel_startup_early(void);
112void kernel_startup(void) __attribute__ ((noreturn));
113
114/**
115 * kernel timeslice in system ticks
116 */
117extern systime_t kernel_timeslice;
118
119/**
120 * command-line option for kernel timeslice in milliseconds
121 */
122extern unsigned int config_timeslice;
123
124/**
125 * variable for gating timer interrupts.
126 */
127extern bool kernel_ticks_enabled;
128
129
130extern lvaddr_t kernel_trace_buf;
131
132extern struct capability monitor_ep;
133
134/*
135 * Variant based on Padraig Brady's implementation
136 * http://www.pixelbeat.org/programming/gcc/static_assert.html
137 */
138#define ASSERT_CONCAT_(a, b) a##b
139#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
140
141/* These can't be used after statements in c89. */
142#ifdef __COUNTER__
143  /* Microsoft compiler. */
144  #define STATIC_ASSERT(e,m) \
145    enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
146#else
147  /* This can't be used twice on the same line so ensure if using in headers
148   * that the headers are not included twice (by wrapping in #ifndef...#endif)
149   * Note it doesn't cause an issue when used on same line of separate modules
150   * compiled with gcc -combine -fwhole-program.  */
151  #define STATIC_ASSERT(e,m) \
152    enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
153#endif
154
155#define STATIC_ASSERT_SIZEOF(tname,n)                   \
156    STATIC_ASSERT(sizeof(tname) == n,                   \
157        ASSERT_CONCAT("Size mismatch:", tname)          \
158        )
159
160#define sa_offsetof(x,y) ((size_t)(((void*)&(((x*)0)->y)) - (void*)(x*)0))
161
162#define STATIC_ASSERT_OFFSETOF(tname, field, offset)    \
163    STATIC_ASSERT(sa_offsetof(tname, field) == offset,    \
164        ASSERT_CONCAT("Offset mismatch:", field)        \
165        )
166
167#endif // __KERNEL_H
168