1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2014 Travis Geiselbrecht
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7 
8 #pragma once
9 
10 #define CURRENT_PERCPU_PTR_OFFSET 16
11 
12 #ifndef __ASSEMBLER__
13 
14 #include <assert.h>
15 #include <arch/arm64/registers.h>
16 #include <stddef.h>
17 #include <sys/types.h>
18 #include <zircon/compiler.h>
19 #include <zircon/tls.h>
20 
21 __BEGIN_CDECLS
22 
23 struct fpstate {
24     uint32_t fpcr;
25     uint32_t fpsr;
26     uint64_t regs[64];
27 };
28 
29 struct arm64_percpu;
30 
31 struct arch_thread {
32     // The compiler (when it's Clang with -mcmodel=kernel) knows
33     // the position of these two fields relative to TPIDR_EL1,
34     // which is what __builtin_thread_pointer() returns.  TPIDR_EL1
35     // points just past these, i.e. to &abi[1].
36     uintptr_t stack_guard;
37     vaddr_t unsafe_sp;
38     union {
39         char thread_pointer_location;
40         vaddr_t sp;
41     };
42 
43     // Debugger access to userspace general regs while suspended or stopped
44     // in an exception.
45     // The regs are saved on the stack and then a pointer is stored here.
46     // NULL if not suspended or stopped in an exception.
47     struct arm64_iframe_long* suspended_general_regs;
48 
49     // Point to the current cpu pointer when the thread is running, used to
50     // restore x18 on exception entry. Swapped on context switch.
51     struct arm64_percpu* current_percpu_ptr;
52 
53     // if non-NULL, address to return to on data fault
54     void* data_fault_resume;
55 
56     // saved fpu state
57     struct fpstate fpstate;
58 
59     // |track_debug_state| tells whether the kernel should keep track of the whole debug state for
60     // this thread. Normally this is set explicitly by an user that wants to make use of HW
61     // breakpoints or watchpoints.
62     // Userspace can still read the complete |debug_state| even if |track_debug_state| is false.
63     bool track_debug_state;
64     arm64_debug_state_t debug_state;
65 };
66 
67 #define thread_pointer_offsetof(field)          \
68     ((int)offsetof(struct arch_thread, field) - \
69      (int)offsetof(struct arch_thread, thread_pointer_location))
70 
71 static_assert(
72     thread_pointer_offsetof(stack_guard) == ZX_TLS_STACK_GUARD_OFFSET,
73     "stack_guard field in wrong place");
74 static_assert(
75     thread_pointer_offsetof(unsafe_sp) == ZX_TLS_UNSAFE_SP_OFFSET,
76     "unsafe_sp field in wrong place");
77 static_assert(
78     thread_pointer_offsetof(current_percpu_ptr) == CURRENT_PERCPU_PTR_OFFSET,
79     "per cpu ptr offset in wrong place");
80 
81 __END_CDECLS
82 
83 #endif // __ASSEMBLER__
84