/*
 * hal_special.c - implementation of TLS API for x86_64
 *
 * 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
 */

#include <hal_types.h>
#include <hal_apic.h>
#include <hal_special.h>
#include <hal_register.h>
#include <hal_internal.h>
#include <hal_segmentation.h>

#include <core.h>
#include <thread.h>

struct thread_s;

tls_t *curtls()
{
	tls_t *cputls;

	__asm volatile("movq %%gs:%1, %0" :
	    "=r" (cputls) :
	    "m"
	    (*(tls_t * const *)offsetof(tls_t, tls_self)));
	return cputls;
}

gid_t hal_get_gid()
{
	return curtls()->tls_gid;
}

cycle_t hal_time_stamp()
{
	return rdtsc();
}

inline reg_t hal_get_sr()
{
	return 0;
}

uint64_t hal_get_cycles()
{
	uint64_t cycles;
	core_t *core = CURRENT_THREAD->core;

	/*
	 * Put the value of the TSC everywhere
	 */
	cycles = rdtsc();
	core->time_stamp = cycles;
	core->cycles = cycles;

	return cycles;
}

struct thread_s *hal_get_current_thread()
{
	return curtls()->tls_thr;
}

void hal_set_current_thread( struct thread_s * thread )
{
	curtls()->tls_thr = thread;
}

/* -------------------------------------------------------------------------- */

void hal_fpu_enable()
{
	/* FPU not implemented yet */
	return;
	clts();
}

void hal_fpu_disable()
{
	/* FPU not implemented yet */
	return;
	stts();
}

uint32_t hal_get_stack()
{
	x86_panic((char *)__func__);
	return 0;
}

uint32_t hal_set_stack( void * new_val )
{
	x86_panic((char *)__func__);
	return 0;
}

uint32_t hal_get_bad_vaddr()
{
	x86_panic((char *)__func__);
	return 0;
}

uint32_t hal_uncached_read( uint32_t * ptr )
{
	x86_panic((char *)__func__);
	return 0;
}

void hal_invalid_dcache_line( void * ptr )
{
	x86_panic((char *)__func__);
}

void hal_fence()
{
	mfence();
}

void hal_rdbar()
{
	x86_panic((char *)__func__);
}

void hal_core_sleep()
{
	x86_panic((char *)__func__);
}

void hal_fixed_delay( uint32_t delay )
{
	x86_panic((char *)__func__);
}

void hal_get_mmu_excp(intptr_t *mmu_ins_excp_code, intptr_t *mmu_ins_bad_vaddr,
    intptr_t *mmu_dat_excp_code, intptr_t *mmu_dat_bad_vaddr)
{
	x86_panic((char *)__func__);
}

