/*
 * Copyright (c) 2010-2015 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Thread support primitives
 *
 * This module provides core thread related primitives for the IA-32
 * processor architecture.
 */

#include <kernel.h>
#include <ksched.h>
#include <arch/x86/mmustructs.h>

/* forward declaration */

/* Initial thread stack frame, such that everything is laid out as expected
 * for when z_swap() switches to it for the first time.
 */
struct _x86_initial_frame {
	u32_t swap_retval;
	u32_t ebp;
	u32_t ebx;
	u32_t esi;
	u32_t edi;
	void *thread_entry;
	u32_t eflags;
	k_thread_entry_t entry;
	void *p1;
	void *p2;
	void *p3;
};

#ifdef CONFIG_X86_USERSPACE
/* Nothing to do here if KPTI is enabled. We are in supervisor mode, so the
 * active PDPT is the kernel's page tables. If the incoming thread is in user
 * mode we are going to switch CR3 to the thread- specific tables when we go
 * through z_x86_trampoline_to_user.
 *
 * We don't need to update _main_tss either, privilege elevation always lands
 * on the trampoline stack and the irq/sycall code has to manually transition
 * off of it to the thread's kernel stack after switching page tables.
 */
#ifndef CONFIG_X86_KPTI
/* Change to new set of page tables. ONLY intended for use from
 * z_x88_swap_update_page_tables(). This changes CR3, no memory access
 * afterwards is legal unless it is known for sure that the relevant
 * mappings are identical wrt supervisor mode until we iret out.
 */
static inline void page_tables_set(struct x86_page_tables *ptables)
{
	__asm__ volatile("movl %0, %%cr3\n\t" : : "r" (ptables) : "memory");
}

/* Update the to the incoming thread's page table, and update the location
 * of the privilege elevation stack.
 *
 * May be called ONLY during context switch and when supervisor
 * threads drop synchronously to user mode. Hot code path!
 */
void z_x86_swap_update_page_tables(struct k_thread *incoming)
{
	struct x86_page_tables *ptables;

	/* If we're a user thread, we want the active page tables to
	 * be the per-thread instance.
	 *
	 * However, if we're a supervisor thread, use the master
	 * kernel page tables instead.
	 */
	if ((incoming->base.user_options & K_USER) != 0) {
		ptables = z_x86_thread_page_tables_get(incoming);

		/* In case of privilege elevation, use the incoming
		 * thread's kernel stack. This area starts immediately
		 * before the PDPT.
		 */
		_main_tss.esp0 = (uintptr_t)ptables;
	} else {
		ptables = &z_x86_kernel_ptables;
	}

	/* Check first that we actually need to do this, since setting
	 * CR3 involves an expensive full TLB flush.
	 */
	if (ptables != z_x86_page_tables_get()) {
		page_tables_set(ptables);
	}
}
#endif /* CONFIG_X86_KPTI */

static FUNC_NORETURN void drop_to_user(k_thread_entry_t user_entry,
				       void *p1, void *p2, void *p3)
{
	u32_t stack_end;

	/* Transition will reset stack pointer to initial, discarding
	 * any old context since this is a one-way operation
	 */
	stack_end = STACK_ROUND_DOWN(_current->stack_info.start +
				     _current->stack_info.size);

	z_x86_userspace_enter(user_entry, p1, p2, p3, stack_end,
			      _current->stack_info.start);
	CODE_UNREACHABLE;
}

FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
					void *p1, void *p2, void *p3)
{
	struct z_x86_thread_stack_header *header =
		(struct z_x86_thread_stack_header *)_current->stack_obj;

	/* Set up the kernel stack used during privilege elevation */
	z_x86_mmu_set_flags(&z_x86_kernel_ptables, &header->privilege_stack,
			    MMU_PAGE_SIZE, MMU_ENTRY_WRITE, Z_X86_MMU_RW,
			    true);

	/* Initialize per-thread page tables, since that wasn't done when
	 * the thread was initialized (K_USER was not set at creation time)
	 */
	z_x86_thread_pt_init(_current);

	/* Apply memory domain configuration, if assigned */
	if (_current->mem_domain_info.mem_domain != NULL) {
		z_x86_apply_mem_domain(z_x86_thread_page_tables_get(_current),
				       _current->mem_domain_info.mem_domain);
	}

#ifndef CONFIG_X86_KPTI
	/* We're synchronously dropping into user mode from a thread that
	 * used to be in supervisor mode. K_USER flag has now been set, but
	 * Need to swap from the kernel's page tables to the per-thread page
	 * tables.
	 *
	 * Safe to update page tables from here, all tables are identity-
	 * mapped and memory areas used before the ring 3 transition all
	 * have the same attributes wrt supervisor mode access.
	 */
	z_x86_swap_update_page_tables(_current);
#endif

	drop_to_user(user_entry, p1, p2, p3);
}

/* Implemented in userspace.S */
extern void z_x86_syscall_entry_stub(void);

/* Syscalls invoked by 'int 0x80'. Installed in the IDT at DPL=3 so that
 * userspace can invoke it.
 */
NANO_CPU_INT_REGISTER(z_x86_syscall_entry_stub, -1, -1, 0x80, 3);

#endif /* CONFIG_X86_USERSPACE */

#if defined(CONFIG_FLOAT) && defined(CONFIG_FP_SHARING)

extern int z_float_disable(struct k_thread *thread);

int arch_float_disable(struct k_thread *thread)
{
#if defined(CONFIG_LAZY_FP_SHARING)
	return z_float_disable(thread);
#else
	return -ENOSYS;
#endif /* CONFIG_LAZY_FP_SHARING */
}
#endif /* CONFIG_FLOAT && CONFIG_FP_SHARING */

void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
		     size_t stack_size, k_thread_entry_t entry,
		     void *parameter1, void *parameter2, void *parameter3,
		     int priority, unsigned int options)
{
	char *stack_buf;
	char *stack_high;
	struct _x86_initial_frame *initial_frame;
#if defined(CONFIG_X86_USERSPACE) || defined(CONFIG_X86_STACK_PROTECTION)
	struct z_x86_thread_stack_header *header =
		(struct z_x86_thread_stack_header *)stack;
#endif

	Z_ASSERT_VALID_PRIO(priority, entry);
	stack_buf = Z_THREAD_STACK_BUFFER(stack);
	z_new_thread_init(thread, stack_buf, stack_size, priority, options);

#ifdef CONFIG_X86_USERSPACE
	/* Set MMU properties for the privilege mode elevation stack.
	 * If we're not starting in user mode, this functions as a guard
	 * area.
	 */
	z_x86_mmu_set_flags(&z_x86_kernel_ptables, &header->privilege_stack,
		MMU_PAGE_SIZE,
		((options & K_USER) == 0U) ? MMU_ENTRY_READ : MMU_ENTRY_WRITE,
		Z_X86_MMU_RW, true);
#endif /* CONFIG_X86_USERSPACE */

#if CONFIG_X86_STACK_PROTECTION
	/* Set guard area to read-only to catch stack overflows */
	z_x86_mmu_set_flags(&z_x86_kernel_ptables, &header->guard_page,
			    MMU_PAGE_SIZE, MMU_ENTRY_READ, Z_X86_MMU_RW,
			    true);
#endif

	stack_high = (char *)STACK_ROUND_DOWN(stack_buf + stack_size);

	/* Create an initial context on the stack expected by z_swap() */
	initial_frame = (struct _x86_initial_frame *)
		(stack_high - sizeof(struct _x86_initial_frame));
	/* z_thread_entry() arguments */
	initial_frame->entry = entry;
	initial_frame->p1 = parameter1;
	initial_frame->p2 = parameter2;
	initial_frame->p3 = parameter3;
	initial_frame->eflags = EFLAGS_INITIAL;
#ifdef CONFIG_X86_USERSPACE
	if ((options & K_USER) != 0U) {
		z_x86_thread_pt_init(thread);
#ifdef _THREAD_WRAPPER_REQUIRED
		initial_frame->edi = (u32_t)drop_to_user;
		initial_frame->thread_entry = z_x86_thread_entry_wrapper;
#else
		initial_frame->thread_entry = drop_to_user;
#endif /* _THREAD_WRAPPER_REQUIRED */
	} else
#endif /* CONFIG_X86_USERSPACE */
	{
#ifdef _THREAD_WRAPPER_REQUIRED
		initial_frame->edi = (u32_t)z_thread_entry;
		initial_frame->thread_entry = z_x86_thread_entry_wrapper;
#else
		initial_frame->thread_entry = z_thread_entry;
#endif
	}
	/* Remaining _x86_initial_frame members can be garbage, z_thread_entry()
	 * doesn't care about their state when execution begins
	 */
	thread->callee_saved.esp = (unsigned long)initial_frame;

#if defined(CONFIG_LAZY_FP_SHARING)
	thread->arch.excNestCount = 0;
#endif /* CONFIG_LAZY_FP_SHARING */

	thread->arch.flags = 0;
}
