1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6
7 #include <arch/ops.h>
8 #include <fbl/atomic.h>
9 #include <hypervisor/cpu.h>
10 #include <kernel/cpu.h>
11 #include <kernel/mp.h>
12 #include <kernel/thread.h>
13
14 namespace {
15
16 struct percpu_state {
17 fbl::atomic<cpu_mask_t> cpu_mask;
18 hypervisor::percpu_task_t task;
19 void* context;
20
percpu_state__anon974e60840111::percpu_state21 percpu_state(hypervisor::percpu_task_t _task, void* _context)
22 : cpu_mask(0), task(_task), context(_context) {}
23 };
24
25 } // namespace
26
27 namespace hypervisor {
28
percpu_task(void * arg)29 static void percpu_task(void* arg) {
30 auto state = static_cast<percpu_state*>(arg);
31 cpu_num_t cpu_num = arch_curr_cpu_num();
32 zx_status_t status = state->task(state->context, cpu_num);
33 if (status == ZX_OK)
34 state->cpu_mask.fetch_or(cpu_num_to_mask(cpu_num));
35 }
36
percpu_exec(percpu_task_t task,void * context)37 cpu_mask_t percpu_exec(percpu_task_t task, void* context) {
38 percpu_state state(task, context);
39 mp_sync_exec(MP_IPI_TARGET_ALL, 0, percpu_task, &state);
40 return state.cpu_mask.load();
41 }
42
cpu_of(uint16_t vpid)43 cpu_num_t cpu_of(uint16_t vpid) {
44 return (vpid - 1) % arch_max_num_cpus();
45 }
46
pin_thread(uint16_t vpid)47 thread_t* pin_thread(uint16_t vpid) {
48 thread_t* thread = get_current_thread();
49 thread_set_cpu_affinity(thread, cpu_num_to_mask(cpu_of(vpid)));
50 return thread;
51 }
52
check_pinned_cpu_invariant(uint16_t vpid,const thread_t * thread)53 bool check_pinned_cpu_invariant(uint16_t vpid, const thread_t* thread) {
54 cpu_num_t cpu = cpu_of(vpid);
55 return thread == get_current_thread() &&
56 thread->cpu_affinity & cpu_num_to_mask(cpu) &&
57 arch_curr_cpu_num() == cpu;
58 }
59
60 } // namespace hypervisor
61