akaros/kern/include/smp.h
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2009 The Regents of the University of California
   3 * Barret Rhoden <brho@cs.berkeley.edu>
   4 * See LICENSE for details.
   5 */
   6
   7#pragma once
   8
   9/* SMP related functions */
  10
  11#include <arch/smp.h>
  12#include <ros/common.h>
  13#include <sys/queue.h>
  14#include <trap.h>
  15#include <atomic.h>
  16#include <process.h>
  17#include <syscall.h>
  18#include <alarm.h>
  19#include <trace.h>
  20#include <core_set.h>
  21
  22#define CPU_STATE_IRQ                   0
  23#define CPU_STATE_KERNEL                1
  24#define CPU_STATE_USER                  2
  25#define CPU_STATE_IDLE                  3
  26#define NR_CPU_STATES                   4
  27
  28static char *cpu_state_names[NR_CPU_STATES] =
  29{
  30        "irq",
  31        "kern",
  32        "user",
  33        "idle",
  34};
  35
  36struct per_cpu_info {
  37#ifdef CONFIG_X86
  38        uintptr_t stacktop;             /* must be first */
  39        int coreid;                     /* must be second */
  40        int nmi_status;
  41        uintptr_t nmi_worker_stacktop;
  42        int vmx_enabled;
  43        int guest_pcoreid;
  44#endif
  45        spinlock_t lock;
  46        /* Process management */
  47        // cur_proc should be valid on all cores that are not management cores.
  48        struct proc *cur_proc;          /* which process context is loaded */
  49        struct proc *owning_proc;       /* proc owning the core / cur_ctx */
  50        uint32_t owning_vcoreid;        /* of owning proc, if applicable */
  51        struct user_context *cur_ctx;   /* user ctx we came in on (can be 0) */
  52        struct user_context actual_ctx; /* storage for cur_ctx */
  53        uint32_t __ctx_depth;           /* don't access directly.  see trap.h.*/
  54        int __lock_checking_enabled;/* == 1, enables spinlock depth checking */
  55        struct kthread *cur_kthread;/* tracks the running kernel context */
  56        struct kthread *spare;          /* useful when restarting */
  57        struct timer_chain tchain;      /* for the per-core alarm */
  58        unsigned int lock_depth;
  59        struct trace_ring traces;
  60        int cpu_state;
  61        uint64_t last_tick_cnt;
  62        uint64_t state_ticks[NR_CPU_STATES];
  63        /* TODO: 64b (not sure if we'll need these at all */
  64#ifdef CONFIG_X86
  65        taskstate_t *tss;
  66        segdesc_t *gdt;
  67#endif
  68        /* KMSGs */
  69        spinlock_t immed_amsg_lock;
  70        struct kernel_msg_list immed_amsgs;
  71        spinlock_t routine_amsg_lock;
  72        struct kernel_msg_list routine_amsgs;
  73        /* profiling -- opaque to all but the profiling code. */
  74        void *profiling;
  75}__attribute__((aligned(ARCH_CL_SIZE)));
  76
  77typedef struct per_cpu_info  per_cpu_info_t;
  78extern per_cpu_info_t per_cpu_info[MAX_NUM_CORES];
  79
  80#define for_each_core(i) for (int (i) = 0; (i) < num_cores; (i)++)
  81
  82#define pcpui_ptr(i) &per_cpu_info[(i)]
  83#define pcpui_var(i, var) per_cpu_info[(i)].var
  84#define this_pcpui_ptr() pcpui_ptr(core_id())
  85#define this_pcpui_var(var) pcpui_var(core_id(), var)
  86
  87/* Allows the kernel to figure out what process is running on this core.  Can be
  88 * used just like a pointer to a struct proc. */
  89#define current this_pcpui_var(cur_proc)
  90/* Allows the kernel to figure out what *user* ctx is on this core's stack.  Can
  91 * be used just like a pointer to a struct user_context.  Note the distinction
  92 * between kernel and user contexts.  The kernel always returns to its nested,
  93 * interrupted contexts via iret/etc.  We never do that for user contexts. */
  94#define current_ctx this_pcpui_var(cur_ctx)
  95
  96#define current_kthread this_pcpui_var(cur_kthread)
  97
  98/* SMP bootup functions */
  99void smp_boot(void);
 100void smp_idle(void) __attribute__((noreturn));
 101void smp_percpu_init(void); // this must be called by each core individually
 102void __arch_pcpu_init(uint32_t coreid); /* each arch has one of these */
 103
 104void __set_cpu_state(struct per_cpu_info *pcpui, int state);
 105void reset_cpu_state_ticks(int coreid);
 106
 107/* SMP utility functions */
 108int smp_call_function_self(isr_t handler, void *data,
 109                           handler_wrapper_t **wait_wrapper);
 110int smp_call_function_all(isr_t handler, void *data,
 111                          handler_wrapper_t **wait_wrapper);
 112int smp_call_function_single(uint32_t dest, isr_t handler, void *data,
 113                             handler_wrapper_t **wait_wrapper);
 114int smp_call_wait(handler_wrapper_t *wrapper);
 115
 116/* PCPUI Trace Rings: */
 117struct pcpu_trace_event {
 118        int                             type;
 119        int                             arg0;
 120        uint64_t                        arg1;
 121};
 122
 123/* If you want to add a type, use the next available number, increment NR_TYPES,
 124 * use your own macro, and provide a handler.  Add your handler to
 125 * pcpui_tr_handlers in smp.c. */
 126#define PCPUI_TR_TYPE_NULL              0
 127#define PCPUI_TR_TYPE_KMSG              1
 128#define PCPUI_TR_TYPE_LOCKS             2
 129#define PCPUI_NR_TYPES                  3
 130
 131#ifdef CONFIG_TRACE_KMSGS
 132
 133# define pcpui_trace_kmsg(pcpui, pc)                                           \
 134{                                                                              \
 135        struct pcpu_trace_event *e = get_trace_slot_racy(&pcpui->traces);      \
 136        if (e) {                                                               \
 137                e->type = PCPUI_TR_TYPE_KMSG;                                  \
 138                e->arg1 = pc;                                                  \
 139        }                                                                      \
 140}
 141
 142#else
 143
 144# define pcpui_trace_kmsg(pcpui, pc)
 145
 146#endif /* CONFIG_TRACE_KMSGS */
 147
 148
 149#ifdef CONFIG_TRACE_LOCKS
 150
 151# define pcpui_trace_locks(pcpui, lock)                                        \
 152{                                                                              \
 153        struct pcpu_trace_event *e = get_trace_slot_overwrite(&pcpui->traces); \
 154        if (e) {                                                               \
 155                e->type = PCPUI_TR_TYPE_LOCKS;                                 \
 156                e->arg0 = (int)tsc2usec(read_tsc());                           \
 157                e->arg1 = (uintptr_t)lock;                                     \
 158        }                                                                      \
 159}
 160
 161#else
 162
 163# define pcpui_trace_locks(pcpui, lock)
 164
 165#endif /* CONFIG_TRACE_LOCKS */
 166
 167void smp_do_in_cores(const struct core_set *cset, void (*func)(void *),
 168                     void *opaque);
 169
 170/* Run the handlers for all events in a pcpui ring.  Can run on all cores, or
 171 * just one core.  'type' selects which event type is handled (0 for all). */
 172void pcpui_tr_foreach(int coreid, int type);
 173void pcpui_tr_foreach_all(int type);
 174void pcpui_tr_reset_all(void);
 175void pcpui_tr_reset_and_clear_all(void);
 176