zephyr/arch/x86_64/core/xuk.h

172 lines
5.4 KiB
C

/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _XUK_H
#define _XUK_H
#include <xuk-switch.h>
#include "shared-page.h"
/*
* APIs exposed by the xuk layer to OS integration:
*/
/* Set a single CPU-specific pointer which can be retrieved (on that
* CPU!) with get_f_ptr()
*/
static inline void xuk_set_f_ptr(int cpu, void *p)
{
_shared.fs_ptrs[cpu] = (long)p;
}
/* Likewise, but "G" */
static inline void xuk_set_g_ptr(int cpu, void *p)
{
_shared.gs_ptrs[cpu] = (long)p;
}
/* Retrieves the pointer set by set_f_ptr() for the current CPU */
static inline void *xuk_get_f_ptr()
{
long long ret, off = 0;
__asm__("movq %%fs:(%1), %0" : "=r"(ret) : "r"(off));
return (void *)(long)ret;
}
/* Retrieves the pointer set by set_g_ptr() for the current CPU */
static inline void *xuk_get_g_ptr()
{
long long ret, off = 0;
__asm__("movq %%gs:(%1), %0" : "=r"(ret) : "r"(off));
return (void *)(long)ret;
}
/**
* @brief Sets a global handler for the specified interrupt.
*
* Interrupt numbers live in a partitioned space:
*
* + Values from 0 - 0xff are mapped to INTIx interrupts in the global
* index of IO-APIC inputs, which on many systems correspond to
* legacy IRQ0-IRQ15 interrupts at the bottom of the interrupt
* range. These handlers are not passed a meaningful value in their
* first argument, though the function pointer type declares one.
*
* + Values from 0x100 to 0x1ff are mapped to raw vectors 0x00-0xff
* and can be used for handling exceptions, for INT instructions, or
* for MSI- or IPI-directed interrupts that specifiy specific
* vectors.
*
* + Values outside this range may be exposed symbolically for other
* interrupts sources, for example local APIC LVT interrupts.
*
* If there is a pre-existing handler specified for a specified raw
* vector, this function will replace it.
*
* @param interrupt Interrupt number. See above for interpretation.
* @param priority Integer in the range 2-15. Higher-valued interrupts
* can interrupt lower ones. Ignored for raw vector
* numbers, as their priority is encoded in the top
* four bits of the vector number. A priority of zero
* is treated as "don't care" and the interrupt will
* be assigned the lowest available vector.
* @param handler Function pointer to invoke on interrupt receipt. It
* will be passed the specified argument as the first
* argument and the x86 exception error code (if any)
* in the second.
* @param arg Opaque value to pass to the handler when invoked.
*
*/
void xuk_set_isr(int interrupt, int priority,
void (*handler)(void *, int), void *arg);
#define INT_APIC_LVT_TIMER 0x200
#define XUK_INT_RAW_VECTOR(vector) ((vector)+0x100)
void xuk_set_isr_mask(int interrupt, int masked);
/* Stack frame on interrupt entry. Obviously they get pushed onto the
* stack in the opposite order than they appear here; the last few
* entries are the hardware frame. Note that not all registers are
* present, the ABI caller-save registers don't get pushed until after
* the handler as an optimization.
*/
struct xuk_entry_frame {
unsigned long long r11;
unsigned long long r10;
unsigned long long r9;
unsigned long long r8;
unsigned long long rsi;
unsigned long long rcx;
unsigned long long rax;
unsigned long long rdx;
unsigned long long rdi;
unsigned long long rip;
unsigned long long cs;
unsigned long long rflags;
unsigned long long rsp;
unsigned long long ss;
};
/* Full stack frame, i.e. the one used as the handles in xuk_switch().
* Once more, the registers declared here are NOT POPULATED during the
* execution of an interrupt service routine.
*/
struct xuk_stack_frame {
unsigned long long r15;
unsigned long long r14;
unsigned long long r13;
unsigned long long r12;
unsigned long long rbp;
unsigned long long rbx;
struct xuk_entry_frame entry;
};
/* Sets up a new stack. The sp argument should point to the quadword
* above (!) the allocated stack area (i.e. the frame will be pushed
* below it). The frame will be set up to enter the function in the
* specified code segment with the specified flags register. An array
* of up to 6 function arguments may also be provided. Returns a
* handle suitable for passing to switch() or for returning from
* isr_exit_restore_stack().
*/
long xuk_setup_stack(long sp, void *fn, unsigned int eflags,
long *args, int nargs);
/*
* OS-defined utilities required by the xuk layer:
*/
/* Returns the address of a stack pointer in 32 bit memory to be used
* by AP processor bootstraping and startup.
*/
unsigned int _init_cpu_stack(int cpu);
/* OS CPU startup entry point, running on the stack returned by
* init_cpu_stack()
*/
void _cpu_start(int cpu);
/* Called on receipt of an unregistered interrupt/exception. Passes
* the vector number and the CPU error code, if any.
*/
void _unhandled_vector(int vector, int err, struct xuk_entry_frame *f);
/* Called on ISR entry before nested interrupts are enabled so the OS
* can arrange bookeeping. Really should be exposed as an inline and
* not a function call; cycles on interrupt entry are precious.
*/
void _isr_entry(void);
/* Called on ISR exit to choose a next thread to run. The argument is
* a context pointer to the thread that was interrupted.
*/
void *_isr_exit_restore_stack(void *interrupted);
#endif /* _XUK_H */