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