1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #ifndef X86_CPU_USER_REGS_H
3 #define X86_CPU_USER_REGS_H
4
5 #include <xen/stdint.h>
6
7 /*
8 * cpu_user_regs represents the interrupted GPR state at the point of an
9 * interrupt, exception or syscall. The layout is dictated by the hardware
10 * format for the event frame, with software filling in the rest.
11 */
12 struct cpu_user_regs
13 {
14 union { uint64_t r15; uint32_t r15d; uint16_t r15w; uint8_t r15b; };
15 union { uint64_t r14; uint32_t r14d; uint16_t r14w; uint8_t r14b; };
16 union { uint64_t r13; uint32_t r13d; uint16_t r13w; uint8_t r13b; };
17 union { uint64_t r12; uint32_t r12d; uint16_t r12w; uint8_t r12b; };
18 union { uint64_t rbp; uint32_t ebp; uint16_t bp; uint8_t bpl; };
19 union { uint64_t rbx; uint32_t ebx; uint16_t bx; struct { uint8_t bl, bh; }; };
20 union { uint64_t r11; uint32_t r11d; uint16_t r11w; uint8_t r11b; };
21 union { uint64_t r10; uint32_t r10d; uint16_t r10w; uint8_t r10b; };
22 union { uint64_t r9; uint32_t r9d; uint16_t r9w; uint8_t r9b; };
23 union { uint64_t r8; uint32_t r8d; uint16_t r8w; uint8_t r8b; };
24 union { uint64_t rax; uint32_t eax; uint16_t ax; struct { uint8_t al, ah; }; };
25 union { uint64_t rcx; uint32_t ecx; uint16_t cx; struct { uint8_t cl, ch; }; };
26 union { uint64_t rdx; uint32_t edx; uint16_t dx; struct { uint8_t dl, dh; }; };
27 union { uint64_t rsi; uint32_t esi; uint16_t si; uint8_t sil; };
28 union { uint64_t rdi; uint32_t edi; uint16_t di; uint8_t dil; };
29
30 /*
31 * During IDT delivery for exceptions with an error code, hardware pushes
32 * to this point. Entry_vector is filled in by software.
33 */
34
35 uint32_t error_code;
36 uint32_t entry_vector;
37
38 /*
39 * During IDT delivery for interrupts or exceptions without an error code,
40 * hardware pushes to this point. Both error_code and entry_vector are
41 * filled in by software.
42 */
43
44 union { uint64_t rip; uint32_t eip; uint16_t ip; };
45 uint16_t cs, _pad0[1];
46 uint8_t saved_upcall_mask; /* PV (v)rflags.IF == !saved_upcall_mask */
47 uint8_t _pad1[3];
48 union { uint64_t rflags; uint32_t eflags; uint16_t flags; };
49 union { uint64_t rsp; uint32_t esp; uint16_t sp; uint8_t spl; };
50 uint16_t ss, _pad2[3];
51
52 /*
53 * For IDT delivery, tss->rsp0 points to this boundary as embedded within
54 * struct cpu_info. It must be 16-byte aligned.
55 */
56 };
57
msr_fold(const struct cpu_user_regs * regs)58 static inline uint64_t msr_fold(const struct cpu_user_regs *regs)
59 {
60 return (regs->rdx << 32) | regs->eax;
61 }
62
msr_split(struct cpu_user_regs * regs,uint64_t val)63 static inline void msr_split(struct cpu_user_regs *regs, uint64_t val)
64 {
65 regs->rdx = val >> 32;
66 regs->rax = (uint32_t)val;
67 }
68
69 #endif /* X86_CPU_USER_REGS_H */
70