/*
 * hal_kentry.h - General values used in the different kernel entries
 *
 * Copyright (c) 2017 Maxime Villard
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#define	T_PRIVINFLT	 0	/* privileged instruction */
#define	T_BPTFLT	 1	/* breakpoint trap */
#define	T_ARITHTRAP	 2	/* arithmetic trap */
#define	T_ASTFLT	 3	/* asynchronous system trap */
#define	T_PROTFLT	 4	/* protection fault */
#define	T_TRCTRAP	 5	/* trace trap */
#define	T_PAGEFLT	 6	/* page fault */
#define	T_ALIGNFLT	 7	/* alignment fault */
#define	T_DIVIDE	 8	/* integer divide fault */
#define	T_NMI		 9	/* non-maskable interrupt */
#define	T_OFLOW		10	/* overflow trap */
#define	T_BOUND		11	/* bounds check fault */
#define	T_DNA		12	/* device not available fault */
#define	T_DOUBLEFLT	13	/* double fault */
#define	T_FPOPFLT	14	/* fp coprocessor operand fetch fault */
#define	T_TSSFLT	15	/* invalid tss fault */
#define	T_SEGNPFLT	16	/* segment not present fault */
#define	T_STKFLT	17	/* stack fault */
#define	T_MCA		18	/* machine check */
#define T_XMM		19	/* SSE FP exception */
#define T_RESERVED	20	/* reserved fault base */

/* Trap's coming from user mode */
#define	T_USER	0x100

#define TLSVAR(off)	%gs:TLS_ ## off

/*
 * Processor Status Longword.
 */
#define	PSL_C		0x00000001	/* carry flag */
#define	PSL_PF		0x00000004	/* parity flag */
#define	PSL_AF		0x00000010	/* auxiliary carry flag */
#define	PSL_Z		0x00000040	/* zero flag */
#define	PSL_N		0x00000080	/* sign flag */
#define	PSL_T		0x00000100	/* trap flag */
#define	PSL_I		0x00000200	/* interrupt enable flag */
#define	PSL_D		0x00000400	/* direction flag */
#define	PSL_V		0x00000800	/* overflow flag */
#define	PSL_IOPL	0x00003000	/* i/o privilege level */
#define	PSL_NT		0x00004000	/* nested task */
#define	PSL_RF		0x00010000	/* resume flag */
#define	PSL_VM		0x00020000	/* virtual 8086 mode */
#define	PSL_AC		0x00040000	/* alignment check flag */
#define	PSL_VIF		0x00080000	/* virtual interrupt enable flag */
#define	PSL_VIP		0x00100000	/* virtual interrupt pending flag */
#define	PSL_ID		0x00200000	/* identification flag */

#define	PSL_MBO		0x00000002	/* must be one bits */
#define	PSL_MBZ		0xffc08028	/* must be zero bits */

#define	PSL_USERSET	(PSL_MBO | PSL_I)

/*
 * Trap frame
 */

#define TF_REGSIZE	(19 * 8)

#define INTR_SAVE_REGS	\
	subq	$TF_REGSIZE,%rsp	; \
	movq	%rax,TF_RAX(%rsp)	; \
	movq	%rbx,TF_RBX(%rsp)	; \
	movq	%rcx,TF_RCX(%rsp)	; \
	movq	%rdx,TF_RDX(%rsp)	; \
	movq	%rbp,TF_RBP(%rsp)	; \
	movq	%rdi,TF_RDI(%rsp)	; \
	movq	%rsi,TF_RSI(%rsp)	; \
	movq	%r8,TF_R8(%rsp)		; \
	movq	%r9,TF_R9(%rsp)		; \
	movq	%r10,TF_R10(%rsp)	; \
	movq	%r11,TF_R11(%rsp)	; \
	movq	%r12,TF_R12(%rsp)	; \
	movq	%r13,TF_R13(%rsp)	; \
	movq	%r14,TF_R14(%rsp)	; \
	movq	%r15,TF_R15(%rsp)	; \
	/* movw	%gs,TF_GS(%rsp) */	; \
	movw	%fs,TF_FS(%rsp)		; \
	movw	%es,TF_ES(%rsp)		; \
	movw	%ds,TF_DS(%rsp)		; \
	cld

#define INTR_RESTORE_REGS	\
	movq	TF_RAX(%rsp),%rax	; \
	movq	TF_RBX(%rsp),%rbx	; \
	movq	TF_RCX(%rsp),%rcx	; \
	movq	TF_RDX(%rsp),%rdx	; \
	movq	TF_RBP(%rsp),%rbp	; \
	movq	TF_RDI(%rsp),%rdi	; \
	movq	TF_RSI(%rsp),%rsi	; \
	movq	TF_R8(%rsp),%r8		; \
	movq	TF_R9(%rsp),%r9		; \
	movq	TF_R10(%rsp),%r10	; \
	movq	TF_R11(%rsp),%r11	; \
	movq	TF_R12(%rsp),%r12	; \
	movq	TF_R13(%rsp),%r13	; \
	movq	TF_R14(%rsp),%r14	; \
	movq	TF_R15(%rsp),%r15	; \
	/* movw	TF_GS(%rsp),%gs */	; \
	movw	TF_FS(%rsp),%fs		; \
	movw	TF_ES(%rsp),%es		; \
	movw	TF_DS(%rsp),%ds		; \
	addq	$TF_REGSIZE,%rsp	; \
	cld

#ifndef x86_ASM

/*
 * The x86_64 CPU trap frame. !!WARNING!! The size of this structure must be
 * exactly TF_SIZE.
 */
typedef struct hal_trapframe_s {
	/* Pushed by INTR_SAVE_REGS */
	uint64_t tf_rax;
	uint64_t tf_rbx;
	uint64_t tf_rcx;
	uint64_t tf_rdx;
	uint64_t tf_rdi;
	uint64_t tf_rsi;
	uint64_t tf_rbp;
	uint64_t tf_r8;
	uint64_t tf_r9;
	uint64_t tf_r10;
	uint64_t tf_r11;
	uint64_t tf_r12;
	uint64_t tf_r13;
	uint64_t tf_r14;
	uint64_t tf_r15;
	uint64_t tf_gs;
	uint64_t tf_fs;
	uint64_t tf_es;
	uint64_t tf_ds;

	/* Pushed by the ISR */
	uint64_t tf_trapno;

	/* Pushed by the hardware if exception */
	uint64_t tf_err;	/* in fact, this one may not... */
	uint64_t tf_rip;
	uint64_t tf_cs;
	uint64_t tf_rflags;

	/* Always pushed by the hardware */
	uint64_t tf_rsp;
	uint64_t tf_ss;
} hal_trapframe_t;

typedef struct hal_cpu_context_s {
	uint64_t ctx_rsp0;
	uint64_t ctx_tf;
	hal_trapframe_t ctx_hidden_tf;
} hal_cpu_context_t;

#else

/* Offsets in the trapframe structure */
#define TF_RAX	0
#define TF_RBX	8
#define TF_RCX	16
#define TF_RDX	24
#define TF_RDI	32
#define TF_RSI	40
#define TF_RBP	48
#define TF_R8	56
#define TF_R9	64
#define TF_R10	72
#define TF_R11	80
#define TF_R12	88
#define TF_R13	96
#define TF_R14	104
#define TF_R15	112
#define TF_GS	120
#define TF_FS	128
#define TF_ES	136
#define TF_DS	144

/* Size of the trapframe structure */
#define TF_SIZE	208

/* Offsets in the context structure */
#define CTX_RSP0  0
#define CTX_TF    8

#endif

