/*
 * hal_kentry.S - Entry points into the kernel (exceptions/interrupts/syscalls)
 *
 * 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 x86_ASM
#include <hal_boot.h>
#include <hal_kentry.h>
#include <hal_apic.h>

#define	TRAPENTRY(a)	\
	pushq	$(a);	\
	jmp	alltraps;

#define	ZTRAPENTRY(a) \
	pushq	$0; \
	TRAPENTRY(a)

	.text
	.globl	hal_exception_entry
	.globl	hal_timer_intr
	.globl	hal_com1_intr
	.globl	hal_keyboard_intr
	.type	hal_exception_entry, @function
	.type	hal_timer_intr, @function
	.type	hal_com1_intr, @function
	.type	hal_keyboard_intr, @function

	/*
	 * General exceptions.
	 */
ASM_ENTRY(x86_trap00)
	ZTRAPENTRY(T_DIVIDE)

ASM_ENTRY(x86_trap01)
	ZTRAPENTRY(T_TRCTRAP)

ASM_ENTRY(x86_trap02)
	ZTRAPENTRY(T_NMI)

ASM_ENTRY(x86_trap03)
	ZTRAPENTRY(T_BPTFLT)

ASM_ENTRY(x86_trap04)
	ZTRAPENTRY(T_OFLOW)

ASM_ENTRY(x86_trap05)
	ZTRAPENTRY(T_BOUND)

ASM_ENTRY(x86_trap06)
	ZTRAPENTRY(T_PRIVINFLT)

ASM_ENTRY(x86_trap07)
	ZTRAPENTRY(T_DNA)

ASM_ENTRY(x86_trap08)
	TRAPENTRY(T_DOUBLEFLT)

ASM_ENTRY(x86_trap09)
	ZTRAPENTRY(T_FPOPFLT)

ASM_ENTRY(x86_trap0a)
	TRAPENTRY(T_TSSFLT)

ASM_ENTRY(x86_trap0b)
	TRAPENTRY(T_SEGNPFLT)

ASM_ENTRY(x86_trap0c)
	TRAPENTRY(T_STKFLT)

ASM_ENTRY(x86_trap0d)
	TRAPENTRY(T_PROTFLT)

ASM_ENTRY(x86_trap0e)
	TRAPENTRY(T_PAGEFLT)

ASM_ENTRY(x86_trap0f)
	ZTRAPENTRY(T_ASTFLT)

ASM_ENTRY(x86_trap10)
	ZTRAPENTRY(T_ARITHTRAP)

ASM_ENTRY(x86_trap11)
	TRAPENTRY(T_ALIGNFLT)

ASM_ENTRY(x86_trap12)
	ZTRAPENTRY(T_MCA)

ASM_ENTRY(x86_trap13)
	ZTRAPENTRY(T_XMM)

ASM_ENTRY(x86_trap14)
ASM_ENTRY(x86_trap15)
ASM_ENTRY(x86_trap16)
ASM_ENTRY(x86_trap17)
ASM_ENTRY(x86_trap18)
ASM_ENTRY(x86_trap19)
ASM_ENTRY(x86_trap1a)
ASM_ENTRY(x86_trap1b)
ASM_ENTRY(x86_trap1c)
ASM_ENTRY(x86_trap1d)
ASM_ENTRY(x86_trap1e)
ASM_ENTRY(x86_trap1f)
ASM_ENTRY(x86_rsvd)
	/* 20 - 31 reserved for future exp */
	ZTRAPENTRY(T_RESERVED)

	/*
	 * APIC interrupts.
	 */
ASM_ENTRY(x86_lapic_spurious)
	ZTRAPENTRY(T_ASTFLT)

ASM_ENTRY(x86_lapic_timer)
	pushq	$0
	pushq	$T_ASTFLT
	INTR_SAVE_REGS

	movq	%rsp,%rdi
	call	hal_timer_intr

	movq	lapic_va(%rip),%rax
	movl	$0,LAPIC_EOI(%rax)

	INTR_RESTORE_REGS
	addq	$16,%rsp
	iretq

ASM_ENTRY(x86_ioapic_com1)
	pushq	$0
	pushq	$T_ASTFLT
	INTR_SAVE_REGS

	movq	%rsp,%rdi
	call	hal_com1_intr

	movq	lapic_va(%rip),%rax
	movl	$0,LAPIC_EOI(%rax)

	INTR_RESTORE_REGS
	addq	$16,%rsp
	iretq

ASM_ENTRY(x86_ioapic_keyboard)
	pushq	$0
	pushq	$T_ASTFLT
	INTR_SAVE_REGS

	movq	%rsp,%rdi
	call	hal_keyboard_intr

	movq	lapic_va(%rip),%rax
	movl	$0,LAPIC_EOI(%rax)

	INTR_RESTORE_REGS
	addq	$16,%rsp
	iretq

	/*
	 * The XCU interrupt entries.
	 */

#define XCU_WTI_ENTRY(n) 		\
ASM_ENTRY(x86_xcu_wti_ ## n)		\
	pushq	$0		;	\
	pushq	$T_ASTFLT	;	\
	INTR_SAVE_REGS		;	\
				;	\
	call	hal_do_interrupt;	\
				;	\
	INTR_RESTORE_REGS	;	\
	addq	$16,%rsp	;	\
	iretq

#define XCU_HWI_ENTRY(n) 		\
ASM_ENTRY(x86_xcu_hwi_ ## n)		\
	pushq	$0		;	\
	pushq	$T_ASTFLT	;	\
	INTR_SAVE_REGS		;	\
				;	\
	call	hal_do_interrupt;	\
				;	\
	INTR_RESTORE_REGS	;	\
	addq	$16,%rsp	;	\
	iretq

#define XCU_PTI_ENTRY(n) 		\
ASM_ENTRY(x86_xcu_pti_ ## n)		\
	pushq	$0		;	\
	pushq	$T_ASTFLT	;	\
	INTR_SAVE_REGS		;	\
				;	\
	call	hal_do_interrupt;	\
				;	\
	INTR_RESTORE_REGS	;	\
	addq	$16,%rsp	;	\
	iretq

XCU_WTI_ENTRY(0)
XCU_HWI_ENTRY(0)
XCU_PTI_ENTRY(0)

/*
 * Arguments pushed on the stack:
 *  tf_trapno
 *  tf_err: Dummy inserted if not defined
 *  tf_rip
 *  tf_cs
 *  tf_rflags
 *  tf_rsp
 *  tf_ss
 */
alltraps:
	movq	%rsp,%rdi
	call	hal_exception_entry
	/* NOTREACHED */

	.data
	.globl	x86_traps
	.globl	x86_intrs
	.type	x86_traps, @object
	.type	x86_intrs, @object

	.align	64
x86_traps:
	.quad	x86_trap00, x86_trap01
	.quad	x86_trap02, x86_trap03
	.quad	x86_trap04, x86_trap05
	.quad	x86_trap06, x86_trap07
	.quad	x86_trap08, x86_trap09
	.quad	x86_trap0a, x86_trap0b
	.quad	x86_trap0c, x86_trap0d
	.quad	x86_trap0e, x86_trap0f
	.quad	x86_trap10, x86_trap11
	.quad	x86_trap12, x86_trap13
	.quad	x86_trap14, x86_trap15
	.quad	x86_trap16, x86_trap17
	.quad	x86_trap18, x86_trap19
	.quad	x86_trap1a, x86_trap1b
	.quad	x86_trap1c, x86_trap1d
	.quad	x86_trap1e, x86_trap1f

x86_intrs:
	.quad	x86_lapic_spurious
	.quad	x86_xcu_wti_0
	.quad	x86_xcu_hwi_0
	.quad	x86_xcu_pti_0

	.quad	x86_lapic_timer
	.quad	x86_ioapic_com1
	.quad	x86_ioapic_keyboard

