Adding support for Xen for x86 (32bit and 64bit)

This commit is contained in:
Sahoo 2025-12-30 16:07:27 +05:30
parent 14b30f209f
commit dd83fb7347
21 changed files with 6421 additions and 0 deletions

View file

@ -0,0 +1,128 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
.extern ulTopOfSystemStack
.extern ulInterruptNesting
/*-----------------------------------------------------------*/
.macro portFREERTOS_INTERRUPT_ENTRY
/* Save general purpose registers. */
pusha
/* If ulInterruptNesting is zero the rest of the task context will need
saving and a stack switch might be required. */
movl ulInterruptNesting, %eax
test %eax, %eax
jne 2f
/* Interrupts are not nested, so save the rest of the task context. */
.if configSUPPORT_FPU == 1
/* If the task has a buffer allocated to save the FPU context then
save the FPU context now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
fwait
1:
/* Save the address of the FPU context, if any. */
push pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl %esp, (%eax)
/* Switch stacks. */
movl ulTopOfSystemStack, %esp
movl %esp, %ebp
2:
/* Increment nesting count. */
add $1, ulInterruptNesting
.endm
/*-----------------------------------------------------------*/
.macro portINTERRUPT_EPILOGUE
cli
sub $1, ulInterruptNesting
/* If the nesting has unwound to zero. */
movl ulInterruptNesting, %eax
test %eax, %eax
jne 2f
/* If a yield was requested then select a new TCB now. */
movl ulPortYieldPending, %eax
test %eax, %eax
je 1f
movl $0, ulPortYieldPending
call vTaskSwitchContext
1:
/* Stack location is first item in the TCB. */
movl pxCurrentTCB, %eax
movl (%eax), %esp
.if configSUPPORT_FPU == 1
/* Restore address of task's FPU context buffer. */
pop pucPortTaskFPUContextBuffer
/* If the task has a buffer allocated in which its FPU context is saved,
then restore it now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
frstor ( %eax )
1:
.endif
2:
popa
.endm
/*-----------------------------------------------------------*/
.macro portFREERTOS_INTERRUPT_EXIT
portINTERRUPT_EPILOGUE
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endm

View file

@ -0,0 +1,2 @@
# Description
This folder contain source for FreeRTOS port for x86_32.

View file

@ -0,0 +1,627 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <limits.h>
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "io.h"
#include "ioapic.h"
#include "stdio.h"
#include "IRQ.h"
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
/* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#if ( ( configMAX_API_CALL_INTERRUPT_PRIORITY > portMAX_PRIORITY ) || ( configMAX_API_CALL_INTERRUPT_PRIORITY < 2 ) )
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be between 2 and 15
#endif
#if ( ( configSUPPORT_FPU == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
#error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port with an FPU
#endif
/* A critical section is exited when the critical section nesting count reaches
* this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU
* context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Only the IF bit is set so tasks start with interrupts enabled. */
#define portINITIAL_EFLAGS ( 0x200UL )
/* Error interrupts are at the highest priority vectors. */
#define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
#define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
#define portAPIC_DEBUG_SERIAL_INT_VECTOR ( 0x24 )
/* EFLAGS bits. */
#define portEFLAGS_IF ( 0x200UL )
/* FPU context size if FSAVE is used. */
#define portFPU_CONTEXT_SIZE_BYTES 108
/* The expected size of each entry in the IDT. Used to check structure packing
* is set correctly. */
#define portEXPECTED_IDT_ENTRY_SIZE 8
/* Default flags setting for entries in the IDT. */
#define portIDT_FLAGS ( 0x8E )
/* This is the lowest possible ISR vector available to application code. */
#define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
/* If configASSERT() is defined then the system stack is filled with this value
* to allow for a crude stack overflow check. */
#define portSTACK_WORD ( 0xecececec )
/*-----------------------------------------------------------*/
/*
* Starts the first task executing.
*/
extern void vPortStartFirstTask( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*
* Complete one descriptor in the IDT.
*/
static void prvSetInterruptGate( uint8_t ucNumber,
ISR_Handler_t pxHandlerFunction,
uint8_t ucFlags );
/*
* The default handler installed in each IDT position.
*/
extern void vPortCentralInterruptWrapper( void );
/*
* Handler for portYIELD().
*/
extern void vPortYieldCall( void );
/*
* Configure the APIC to generate the RTOS tick.
*/
static void prvSetupLAPIC( void );
/*
* Tick interrupt handler.
*/
extern void vPortTimerHandler( void );
extern void vPortIRQHandler( void );
extern void vHypervisorCallback( void );
extern void vSCIHandler( void );
extern void vTestInterruptHandler( void );
void enable_sci(void);
void init_time(void);
/*
* Check an interrupt vector is not too high, too low, in use by FreeRTOS, or
* already in use by the application.
*/
static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber );
/*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This
* variable must be initialised to a non zero value to ensure interrupts don't
* inadvertently become unmasked before the scheduler starts. It is set to zero
* before the first task starts executing. */
volatile uint32_t ulCriticalNesting = 9999UL;
/* A structure used to map the various fields of an IDT entry into separate
* structure members. */
struct IDTEntry
{
uint16_t usISRLow; /* Low 16 bits of handler address. */
uint16_t usSegmentSelector; /* Flat model means this is not changed. */
uint8_t ucZero; /* Must be set to zero. */
uint8_t ucFlags; /* Flags for this entry. */
uint16_t usISRHigh; /* High 16 bits of handler address. */
}
__attribute__( ( packed ) );
typedef struct IDTEntry IDTEntry_t;
/* Use to pass the location of the IDT to the CPU. */
struct IDTPointer
{
uint16_t usTableLimit;
uint32_t ulTableBase; /* The address of the first entry in xInterruptDescriptorTable. */
}
__attribute__( ( __packed__ ) );
typedef struct IDTPointer IDTPointer_t;
/* The IDT itself. */
static __attribute__( ( aligned( 32 ) ) ) IDTEntry_t xInterruptDescriptorTable[ portNUM_VECTORS ];
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
/* A table in which application defined interrupt handlers are stored. These
* are called by the central interrupt handler if a common interrupt entry
* point it used. */
static ISR_Handler_t xInterruptHandlerTable[ portNUM_VECTORS ] = { NULL };
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
#if ( configSUPPORT_FPU == 1 )
/* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
* then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
* not NULL then it points to a buffer into which the FPU context can be saved. */
uint8_t * pucPortTaskFPUContextBuffer __attribute__( ( used ) ) = pdFALSE;
#endif /* configSUPPORT_FPU */
/* The stack used by interrupt handlers. */
static uint32_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__( ( used ) ) = { 0 };
/* Don't use the very top of the system stack so the return address
* appears as 0 if the debugger tries to unwind the stack. */
volatile uint32_t ulTopOfSystemStack __attribute__( ( used ) ) = ( uint32_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
/* If a yield is requested from an interrupt or from a critical section then
* the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
* instead to indicate the yield should be performed at the end of the interrupt
* when the critical section is exited. */
volatile uint32_t ulPortYieldPending __attribute__( ( used ) ) = pdFALSE;
volatile uint32_t schedStart __attribute__( ( used ) ) = pdFALSE;
/* Counts the interrupt nesting depth. Used to know when to switch to the
* interrupt/system stack and when to save/restore a complete context. */
volatile uint32_t ulInterruptNesting __attribute__( ( used ) ) = 0;
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t * pxPortInitialiseStack( StackType_t *pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{
uint32_t ulCodeSegment;
/* Setup the initial stack as expected by the portFREERTOS_INTERRUPT_EXIT macro. */
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = 0x00;
pxTopOfStack--;
/* Parameters first. */
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
/* There is nothing to return to so assert if attempting to use the return
* address. */
*pxTopOfStack = ( StackType_t ) prvTaskExitError;
pxTopOfStack--;
/* iret used to start the task pops up to here. */
*pxTopOfStack = portINITIAL_EFLAGS;
pxTopOfStack--;
/* CS */
__asm volatile ( "movl %%cs, %0" : "=r" ( ulCodeSegment ) );
*pxTopOfStack = ulCodeSegment;
pxTopOfStack--;
/* First instruction in the task. */
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* General purpose registers as expected by a POPA instruction. */
*pxTopOfStack = 0xEA;
pxTopOfStack--;
*pxTopOfStack = 0xEC;
pxTopOfStack--;
*pxTopOfStack = 0xED1; /* EDX */
pxTopOfStack--;
*pxTopOfStack = 0xEB1; /* EBX */
pxTopOfStack--;
/* Hole for ESP. */
pxTopOfStack--;
*pxTopOfStack = 0x00; /* EBP */
pxTopOfStack--;
*pxTopOfStack = 0xE5; /* ESI */
pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee; /* EDI */
#if ( configSUPPORT_FPU == 1 )
{
pxTopOfStack--;
/* Buffer for FPU context, which is initialised to NULL as tasks are not
* created with an FPU context. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
}
#endif /* configSUPPORT_FPU */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvSetInterruptGate( uint8_t ucNumber,
ISR_Handler_t pxHandlerFunction,
uint8_t ucFlags )
{
uint16_t usCodeSegment;
uint32_t ulBase = ( uint32_t ) pxHandlerFunction;
xInterruptDescriptorTable[ ucNumber ].usISRLow = ( uint16_t ) ( ulBase & USHRT_MAX );
xInterruptDescriptorTable[ ucNumber ].usISRHigh = ( uint16_t ) ( ( ulBase >> 16UL ) & USHRT_MAX );
/* When the flat model is used the CS will never change. */
__asm volatile ( "mov %%cs, %0" : "=r" ( usCodeSegment ) );
xInterruptDescriptorTable[ ucNumber ].usSegmentSelector = usCodeSegment;
xInterruptDescriptorTable[ ucNumber ].ucZero = 0;
xInterruptDescriptorTable[ ucNumber ].ucFlags = ucFlags | 0x60;
}
/*-----------------------------------------------------------*/
#define PIC1 0x20
#define PIC2 0xA0
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
void vPortSetupIDT( void )
{
extern void vPortAPICErrorHandlerWrapper( void );
extern void vPortAPICSpuriousHandler( void );
// Disable interrupts from 8259
outb(PIC1_COMMAND, 0x21);
outb(PIC1_DATA, 0xFF);
outb(PIC1_COMMAND, 0x22);
outb(PIC1_DATA, 0xFF);
uint32_t ulNum;
IDTPointer_t xIDT;
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
{
for( ulNum = 0; ulNum < portNUM_VECTORS; ulNum++ )
{
/* If a handler has not already been installed on this vector. */
if( ( xInterruptDescriptorTable[ ulNum ].usISRLow == 0x00 ) && ( xInterruptDescriptorTable[ ulNum ].usISRHigh == 0x00 ) )
{
prvSetInterruptGate( ( uint8_t ) ulNum, vPortCentralInterruptWrapper, portIDT_FLAGS );
}
}
}
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/* Install APIC timer ISR vector. */
prvSetInterruptGate( ( uint8_t ) 50, vPortTimerHandler, portIDT_FLAGS );
/* Install API error handler. */
prvSetInterruptGate( ( uint8_t ) portAPIC_LVT_ERROR_VECTOR, vPortAPICErrorHandlerWrapper, portIDT_FLAGS );
/* Install Yield handler. */
prvSetInterruptGate( ( uint8_t ) portAPIC_YIELD_INT_VECTOR, vPortYieldCall, portIDT_FLAGS );
/* Install spurious interrupt vector. */
prvSetInterruptGate( ( uint8_t ) portAPIC_SPURIOUS_INT_VECTOR, vPortAPICSpuriousHandler, portIDT_FLAGS );
/* Install Vector for Debug Serial Port */
prvSetInterruptGate( ( uint8_t ) portAPIC_DEBUG_SERIAL_INT_VECTOR, vPortIRQHandler, portIDT_FLAGS );
prvSetInterruptGate( ( uint8_t ) 37, vHypervisorCallback, portIDT_FLAGS );
prvSetInterruptGate( ( uint8_t ) 41, vSCIHandler, portIDT_FLAGS );
prvSetInterruptGate( ( uint8_t ) 96, vTestInterruptHandler, portIDT_FLAGS );
/* Set IDT address. */
xIDT.ulTableBase = ( uint32_t ) xInterruptDescriptorTable;
xIDT.usTableLimit = sizeof( xInterruptDescriptorTable ) - 1;
/* Set IDT in CPU. */
__asm volatile ( "lidt %0" ::"m" ( xIDT ) );
//__asm volatile ("ltr %w0" :: "rm" (7 * 8));
prvSetupLAPIC();
set_ioapic_irq_mask(portAPIC_DEBUG_SERIAL_INT_VECTOR-0x20,0);
set_ioapic_irq_mask(portAPIC_TIMER_INT_VECTOR-0x20,0);
enable_sci();
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */
configASSERT( ulCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ; ; )
{
}
}
/*-----------------------------------------------------------*/
static void prvSetupLAPIC( void )
{
extern void vPortAPICErrorHandlerWrapper( void );
extern void vPortAPICSpuriousHandler( void );
/* Initialise LAPIC to a well known state. */
portAPIC_LDR = 0xFFFFFFFF;
portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
portAPIC_LVT_TIMER = portAPIC_DISABLE;
portAPIC_LVT_PERF = portAPIC_NMI;
portAPIC_LVT_LINT0 = portAPIC_DISABLE;
portAPIC_LVT_LINT1 = portAPIC_DISABLE;
portAPIC_TASK_PRIORITY = 0;
/* Enable the APIC, mapping the spurious interrupt at the same time. */
portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
/* Set timer error vector. */
portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
BaseType_t xWord;
/* Some versions of GCC require the -mno-ms-bitfields command line option
* for packing to work. */
configASSERT( sizeof( struct IDTEntry ) == portEXPECTED_IDT_ENTRY_SIZE );
/* Fill part of the system stack with a known value to help detect stack
* overflow. A few zeros are left so GDB doesn't get confused unwinding
* the stack. */
for( xWord = 0; xWord < configISR_STACK_SIZE - 20; xWord++ )
{
ulSystemStack[ xWord ] = portSTACK_WORD;
}
/* Initialise Interrupt Descriptor Table (IDT). */
vPortSetupIDT();
init_time();
/* Make sure the stack used by interrupts is aligned. */
ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
ulCriticalNesting = 0;
/* Should not return from the following function as the scheduler will then
* be executing the tasks. */
vPortStartFirstTask();
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
if( ulCriticalNesting == 0 )
{
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
__asm volatile ( "cli" );
}
#else
{
portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
}
#endif
}
/* Now that interrupts are disabled, ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{
/* Decrement the nesting count as the critical section is being
* exited. */
ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
/* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
__asm volatile ( "sti" );
}
#else
{
portAPIC_TASK_PRIORITY = 0;
}
#endif
/* If a yield was pended from within the critical section then
* perform the yield now. */
if( ulPortYieldPending != pdFALSE )
{
ulPortYieldPending = pdFALSE;
__asm volatile ( portYIELD_INTERRUPT );
}
}
}
}
/*-----------------------------------------------------------*/
uint32_t ulPortSetInterruptMask( void )
{
volatile uint32_t ulOriginalMask;
/* Set mask to max syscall priority. */
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
/* Return whether interrupts were already enabled or not. Pop adjusts
* the stack first. */
__asm volatile ( "pushf \t\n"
"pop %0 \t\n"
"cli "
: "=rm" ( ulOriginalMask )::"memory" );
ulOriginalMask &= portEFLAGS_IF;
}
#else
{
/* Return original mask. */
ulOriginalMask = portAPIC_TASK_PRIORITY;
portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
}
#endif /* if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY ) */
return ulOriginalMask;
}
/*-----------------------------------------------------------*/
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
if( ulNewMaskValue != pdFALSE )
{
__asm volatile ( "sti" );
}
}
#else
{
portAPIC_TASK_PRIORITY = ulNewMaskValue;
configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
}
#endif /* if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY ) */
}
/*-----------------------------------------------------------*/
#if ( configSUPPORT_FPU == 1 )
void vPortTaskUsesFPU( void )
{
/* A task is registering the fact that it needs an FPU context. Allocate a
* buffer into which the context can be saved. */
pucPortTaskFPUContextBuffer = ( uint8_t * ) pvPortMalloc( portFPU_CONTEXT_SIZE_BYTES );
configASSERT( pucPortTaskFPUContextBuffer );
/* Initialise the floating point registers. */
__asm volatile ( "fninit" );
}
#endif /* configSUPPORT_FPU */
void (*test_irq_handler)(void) = NULL;
void process_test_interrupt() {
if (test_irq_handler) test_irq_handler();
}
/*-----------------------------------------------------------*/
void vPortAPICErrorHandler( void )
{
/* Variable to hold the APIC error status for viewing in the debugger. */
volatile uint32_t ulErrorStatus = 0;
portAPIC_ERROR_STATUS = 0;
ulErrorStatus = portAPIC_ERROR_STATUS;
( void ) ulErrorStatus;
/* Force an assert. */
configASSERT( ulCriticalNesting == ~0UL );
}
/*-----------------------------------------------------------*/
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
void vPortCentralInterruptHandler( uint32_t ulVector )
{
if( ulVector < portNUM_VECTORS )
{
uint32_t irq = ulVector - 0x20;
INT_HANDLER irq_handler = get_int_handler(irq);
if (irq_handler != NULL) {
irq_handler();
}
}
/* Check for a system stack overflow. */
configASSERT( ulSystemStack[ 10 ] == portSTACK_WORD );
configASSERT( ulSystemStack[ 12 ] == portSTACK_WORD );
configASSERT( ulSystemStack[ 14 ] == portSTACK_WORD );
}
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/*-----------------------------------------------------------*/
void vGenerateYieldInterrupt( void )
{
__asm volatile ( portYIELD_INTERRUPT );
}
/*-----------------------------------------------------------*/
int vHaltCPU(void)
{
__asm volatile ("hlt");
return 1;
}

View file

@ -0,0 +1,351 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
.file "portASM.S"
#include "FreeRTOSConfig.h"
#include "ISR_Support.h"
.extern pxCurrentTCB
.extern vTaskSwitchContext
.extern vPortCentralInterruptHandler
.extern xTaskIncrementTick
.extern vPortAPICErrorHandler
.extern pucPortTaskFPUContextBuffer
.extern ulPortYieldPending
.extern process_sci
.global vPortStartFirstTask
.global vPortCentralInterruptWrapper
.global vPortAPICErrorHandlerWrapper
.global vPortTimerHandler
.global vPortYieldCall
.global vPortIRQHandler
.global vHypervisorCallback
.global vSCIHandler
.global vTestInterruptHandler
.global vPortAPICSpuriousHandler
.text
/*-----------------------------------------------------------*/
.align 4
.func vPortYieldCall
vPortYieldCall:
/* Save general purpose registers. */
pusha
.if configSUPPORT_FPU == 1
/* If the task has a buffer allocated to save the FPU context then save
the FPU context now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
fnsave ( %eax )
fwait
1:
/* Save the address of the FPU context, if any. */
push pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl %esp, (%eax)
call vTaskSwitchContext
/* Find the location of pxCurrentTCB again - a callee saved register could
be used in place of eax to prevent this second load, but that then relies
on the compiler and other asm code. */
movl pxCurrentTCB, %eax
movl (%eax), %esp
.if configSUPPORT_FPU == 1
/* Restore address of task's FPU context buffer. */
pop pucPortTaskFPUContextBuffer
/* If the task has a buffer allocated in which its FPU context is saved,
then restore it now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
frstor ( %eax )
1:
.endif
popa
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortStartFirstTask
vPortStartFirstTask:
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl (%eax), %esp
/* Restore FPU context flag. */
.if configSUPPORT_FPU == 1
pop pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Restore general purpose registers. */
popa
movl $0x1, schedStart
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortAPICErrorHandlerWrapper
vPortAPICErrorHandlerWrapper:
pusha
call vPortAPICErrorHandler
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortIRQHandler
vPortIRQHandler:
/* Save general purpose registers. */
pusha
call send_char_to_cli
mov $0x20, %eax
mov $0x20, %edx
outb %al, %dx
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
.align 4
.func vHypervisorCallback
vHypervisorCallback:
/* Save general purpose registers. */
pusha
call do_hypervisor_callback
mov $0x20, %eax
mov $0x20, %edx
outb %al, %dx
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
.align 4
.func vSCIHandler
vSCIHandler:
/* Save general purpose registers. */
pusha
call process_sci
mov $0x20, %eax
mov $0x20, %edx
outb %al, %dx
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
.align 4
.func vTestInterruptHandler
vTestInterruptHandler:
/* Save general purpose registers. */
pusha
call process_test_interrupt
mov $0x20, %eax
mov $0x20, %edx
outb %al, %dx
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortTimerHandler
vPortTimerHandler:
/* Save general purpose registers. */
pusha
movl schedStart, %eax
test %eax, %eax
je end_tmr
/* Interrupts are not nested, so save the rest of the task context. */
.if configSUPPORT_FPU == 1
/* If the task has a buffer allocated to save the FPU context then save the
FPU context now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
fwait
1:
/* Save the address of the FPU context, if any. */
push pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl %esp, (%eax)
/* Switch stacks. */
movl ulTopOfSystemStack, %esp
movl %esp, %ebp
/* Increment nesting count. */
add $1, ulInterruptNesting
call xTaskIncrementTick
sti
/* Is a switch to another task required? */
test %eax, %eax
je _skip_context_switch
cli
call vTaskSwitchContext
_skip_context_switch:
cli
/* Decrement the variable used to determine if a switch to a system
stack is necessary. */
sub $1, ulInterruptNesting
/* Stack location is first item in the TCB. */
movl pxCurrentTCB, %eax
movl (%eax), %esp
.if configSUPPORT_FPU == 1
/* Restore address of task's FPU context buffer. */
pop pucPortTaskFPUContextBuffer
/* If the task has a buffer allocated in which its FPU context is saved,
then restore it now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
frstor ( %eax )
1:
.endif
end_tmr:
mov $0x20, %eax
mov $0x20, %edx
outb %al, %dx
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
/*-----------------------------------------------------------*/
.if configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1
.align 4
.func vPortCentralInterruptWrapper
vPortCentralInterruptWrapper:
portFREERTOS_INTERRUPT_ENTRY
movl $0xFEE00170, %eax /* Highest In Service Register (ISR) long word. */
movl $8, %ecx /* Loop counter. */
next_isr_long_word:
test %ecx, %ecx /* Loop counter reached 0? */
je wrapper_epilogue /* Looked at all ISR registers without finding a bit set. */
sub $1, %ecx /* Sub 1 from loop counter. */
movl (%eax), %ebx /* Load next ISR long word. */
sub $0x10, %eax /* Point to next ISR long word in case no bits are set in the current long word. */
test %ebx, %ebx /* Are there any bits set? */
je next_isr_long_word /* Look at next ISR long word if no bits were set. */
sti
bsr %ebx, %ebx /* A bit was set, which one? */
movl $32, %eax /* Destination operand for following multiplication. */
mul %ecx /* Calculate base vector for current register, 32 vectors per register. */
add %ebx, %eax /* Add bit offset into register to get final vector number. */
push %eax /* Vector number is function parameter. */
call vPortCentralInterruptHandler
pop %eax /* Remove parameter. */
wrapper_epilogue:
portFREERTOS_INTERRUPT_EXIT
.endfunc
.endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/*-----------------------------------------------------------*/
.align 4
.func vPortAPISpuriousHandler
vPortAPICSpuriousHandler:
iret
.endfunc
.end

View file

@ -0,0 +1,277 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
#include "FreeRTOSConfig.h"
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t;
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffUL )
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 32
/*-----------------------------------------------------------*/
/* Task utilities. */
/* The interrupt priority (for vectors 16 to 255) is determined using vector/16.
* The quotient is rounded to the nearest integer with 1 being the lowest priority
* and 15 is the highest. Therefore the following two interrupts are at the lowest
* priority. *NOTE 1* If the yield vector is changed then it must also be changed
* in the portYIELD_INTERRUPT definition immediately below. */
#define portAPIC_YIELD_INT_VECTOR ( 0x21 )
#define portAPIC_TIMER_INT_VECTOR ( 0x22 )
/* Build yield interrupt instruction. */
#define portYIELD_INTERRUPT "int $0x21"
/* APIC register addresses. */
#define portAPIC_EOI ( *( ( volatile uint32_t * ) 0xFEE000B0UL ) )
/* APIC bit definitions. */
#define portAPIC_ENABLE_BIT ( 1UL << 8UL )
#define portAPIC_TIMER_PERIODIC ( 1UL << 17UL )
#define portAPIC_DISABLE ( 1UL << 16UL )
#define portAPIC_NMI ( 4 << 8 )
#define portAPIC_DIV_16 ( 0x03 )
/* Define local API register addresses. */
#define portAPIC_ID_REGISTER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x20UL ) ) )
#define portAPIC_SPURIOUS_INT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xF0UL ) ) )
#define portAPIC_LVT_TIMER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x320UL ) ) )
#define portAPIC_TIMER_INITIAL_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x380UL ) ) )
#define portAPIC_TIMER_CURRENT_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x390UL ) ) )
#define portAPIC_TASK_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x80UL ) ) )
#define portAPIC_LVT_ERROR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x370UL ) ) )
#define portAPIC_ERROR_STATUS ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x280UL ) ) )
#define portAPIC_LDR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xD0UL ) ) )
#define portAPIC_TMRDIV ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x3E0UL ) ) )
#define portAPIC_LVT_PERF ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x340UL ) ) )
#define portAPIC_LVT_LINT0 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x350UL ) ) )
#define portAPIC_LVT_LINT1 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x360UL ) ) )
extern int vHaltCPU(void);
/* Don't yield if inside a critical section - instead hold the yield pending
* so it is performed when the critical section is exited. */
#define portYIELD() \
{ \
extern volatile uint32_t ulCriticalNesting; \
extern volatile uint32_t ulPortYieldPending; \
if( ulCriticalNesting != 0 ) \
{ \
ulPortYieldPending = pdTRUE; \
} \
else \
{ \
__asm volatile ( portYIELD_INTERRUPT ); \
} \
}
/* Called at the end of an ISR that can cause a context switch - pend a yield if
* xSwitchRequired is not false. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \
extern volatile uint32_t ulPortYieldPending; \
if( xSwitchRequired != pdFALSE ) \
{ \
ulPortYieldPending = 1; \
} \
}
/* Same as portEND_SWITCHING_ISR() - take your pick which name to use. */
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------
* Critical section control
*----------------------------------------------------------*/
/* Critical sections for use in interrupts. */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
/* These macros do not globally disable/enable interrupts. They do mask off
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() __asm volatile ( "cli" )
#define portENABLE_INTERRUPTS() __asm volatile ( "sti" )
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these
* macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
__asm volatile ( "bsr %1, %0\n\t" \
: "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" )
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#define portNOP() __asm volatile ( "NOP" )
/*-----------------------------------------------------------
* Misc
*----------------------------------------------------------*/
#define portNUM_VECTORS 256
#define portMAX_PRIORITY 15
typedef void ( * ISR_Handler_t ) ( void );
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
* before any floating point instructions are executed. */
#ifndef configSUPPORT_FPU
#define configSUPPORT_FPU 0
#endif
#if configSUPPORT_FPU == 1
void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#endif
#ifndef configAPIC_BASE
/* configAPIC_BASE_ADDRESS sets the base address of the local APIC. It can
* be overridden in FreeRTOSConfig.h should it not be constant. */
#define configAPIC_BASE 0xFEE00000UL
#endif
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
/* The FreeRTOS scheduling algorithm selects the task that will enter the
* Running state. configUSE_PORT_OPTIMISED_TASK_SELECTION is used to set how
* that is done.
*
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 0 then the task to
* enter the Running state is selected using a portable algorithm written in
* C. This is the slowest method, but the algorithm does not restrict the
* maximum number of unique RTOS task priorities that are available.
*
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 1 then the task to
* enter the Running state is selected using a single assembly instruction.
* This is the fastest method, but restricts the maximum number of unique RTOS
* task priorities to 32 (the same task priority can be assigned to any number
* of RTOS tasks). */
#warning configUSE_PORT_OPTIMISED_TASK_SELECTION was not defined in FreeRTOSConfig.h and has been defaulted to 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#ifndef configISR_STACK_SIZE
/* Interrupt entry code will switch the stack in use to a dedicated system
* stack.
*
* configISR_STACK_SIZE defines the number of 32-bit values that can be stored
* on the system stack, and must be large enough to hold a potentially nested
* interrupt stack frame. */
#error configISR_STACK_SIZE was not defined in FreeRTOSConfig.h.
#endif
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
/* Interrupt safe FreeRTOS functions (those that end in "FromISR" must not
* be called from an interrupt that has a priority above that set by
* configMAX_API_CALL_INTERRUPT_PRIORITY. */
#warning configMAX_API_CALL_INTERRUPT_PRIORITY was not defined in FreeRTOSConfig.h and has been defaulted to 10
#define configMAX_API_CALL_INTERRUPT_PRIORITY 10
#endif
#ifndef configSUPPORT_FPU
#warning configSUPPORT_FPU was not defined in FreeRTOSConfig.h and has been defaulted to 0
#define configSUPPORT_FPU 0
#endif
/* The value written to the task priority register to raise the interrupt mask
* to the maximum from which FreeRTOS API calls can be made. */
#define portAPIC_PRIORITY_SHIFT ( 4UL )
#define portAPIC_MAX_SUB_PRIORITY ( 0x0fUL )
#define portMAX_API_CALL_PRIORITY ( ( configMAX_API_CALL_INTERRUPT_PRIORITY << portAPIC_PRIORITY_SHIFT ) | portAPIC_MAX_SUB_PRIORITY )
/* Asserts if interrupt safe FreeRTOS functions are called from a priority
* above the max system call interrupt priority. */
#define portAPIC_PROCESSOR_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) )
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) )
/* Restricted User Mode Tasks Not Supported on 32-bit */
#define portPRIVILEGE_BIT 0x0UL
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -0,0 +1,257 @@
/*
* FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Set to 1 to enable functionality */
#define __SHOW_KERNEL_PARAMS__ 0
/* Local definitions boot loader */
#define MULTIBOOT_SIGNATURE 0x2BADB002
#define MULTIBOOT_BOOTINFO_MMAP 0x00000040
/* Local definitions for GD table */
#define GDT_ENTRIES 8
#define GDT_ENTRY_SIZE 8
#define GDT_BYTES (GDT_ENTRIES * GDT_ENTRY_SIZE)
/* Globals and externs */
.global _mboot_hdr
.global _start
.global _restart
.extern bootsign
.extern bootinfo
.extern __text_start
.extern __text_end
.extern __data_vma
.extern __data_lma
.extern __data_start
.extern __data_end
.extern __bss_start
.extern __bss_end
.extern __stack_for_main
.global __text_start
.global __text_end
.global __data_vma
.global __data_lma
.global __data_start
.global __data_end
.global __bss_start
.global __bss_end
.globl shared_info, hypercall_page
.global grant_table
.global argo_ring
.global rdtsc_low
.global rdtsc_high
.extern setsegs
.extern kernel_load_check
.extern main
.extern init_serial
/* Local constants for multiboot section */
.set ALIGN, 1<<0 /* align loaded modules on page boundaries */
.set MEMINFO, 1<<1 /* provide memory map */
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
.set FLAGS, ALIGN|MEMINFO /* this is the multiboot 'flag' field */
.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above */
/* Set-up GDT */
.section .data
.align 16
.globl gdt
gdt: .space GDT_BYTES
gdtr: .word (GDT_BYTES-1) /* sizeof _gdt -1 (in bytes) */
.long gdt /* global pointer to the gdt */
/* Start of application text */
.section .text.entry
/* Skip mb header */
jmp _start
.align 4
/* Multiboot header */
_mboot_hdr:
.long MAGIC /* offset = 0 */
.long FLAGS /* offset = 4 */
.long CHECKSUM /* offset = 8 */
.long _mboot_hdr /* should be header address - offset = 12 */
.long __text_start /* load address (start of text) - offset = 16 */
.long __bss_start /* load end address (end of data) - offset = 20*/
.long __bss_end /* bss end address - offset = 24*/
.long _start /* entry_addr - offset = 28*/
#define ELFNOTE(name, type, desc) \
.pushsection .note.name ; \
.align 4 ; \
.long 2f - 1f /* namesz */ ; \
.long 4f - 3f /* descsz */ ; \
.long type /* type */ ; \
1:.asciz #name /* name */ ; \
2:.align 4 ; \
3:desc /* desc */ ; \
4:.align 4 ; \
.popsection
#define XEN_ELFNOTE_PHYS32_ENTRY 18
ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long _start)
/* Unpleasant -- the PTE that maps this page is actually overwritten */
/* to map the real shared-info page! :-) */
.align 4096
shared_info:
.fill 4096,1,0
hypercall_page:
.fill 4096,1,0
grant_table:
.fill 4096*2,1,0
argo_ring:
.fill 4096*5,1,0
rdtsc_low:
.fill 4,1,0
rdtsc_high:
.fill 4,1,0
/* Start of executable code */
_start:
_restart:
/* Initialise the stack pointer */
movl $__stack_for_main, %esp
/* Reset EFLAGS. */
pushl $0
popf
rdtsc # Reads TSC -> %edx:%eax
movl %eax, rdtsc_low # Store lower 32 bits
movl %edx, rdtsc_high # Store upper 32 bits
/* Set up the global descriptor table */
call setsegs
lgdt gdtr
ljmp $0x8, $gdt1 /* CS descriptor 1 */
gdt1:
movl $0x10, %eax /* DS descriptor 2 */
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movl $0x18, %eax /* SS descriptor 3 */
movw %ax, %ss
/* Clear interrupt flag */
cli
/* Initialise platform */
/* Show kernel parameters and call main, or just call main */
#if (__SHOW_KERNEL_PARAMS__ == 1)
/*---------------------------------------------------------------------
On successful OS load EAX should contain 0x2BADB002
EBX should contain the physical address of multiboot info structure
Push the pointers to the multiboot information structure
and the magic number on the stack and check values returned
----------------------------------------------------------------------*/
movl bootsign, %eax
movl bootinfo, %ebx
pushl %ebx /* Multiboot information */
pushl %eax /* Magic number */
call show_kernel_parameters
#else
/*---------------------------------------------------------------------
Call main() routine
----------------------------------------------------------------------*/
call init_serial
pushl %ebx /* Multiboot information */
call main
#endif
/* Should not get here, but just in case - loop forever */
cli
_local_loop:
hlt
jmp _local_loop
/*-------------------------------------------------------------------------
GLOBAL ASSEMBLY LANGUAGE ROUTINES
--------------------------------------------------------------------------*/
/* halt */
.globl halt
halt:
jmp halt
ret
/* inb */
.globl inb
inb: movl 4(%esp), %edx
xorl %eax, %eax # clr eax
inb %dx, %al
ret
/* inw */
.globl inw
inw: movl 4(%esp), %edx
xorl %eax, %eax # clr eax
inw %dx, %ax
ret
/* inl */
.globl inl
inl: movl 4(%esp), %edx
xorl %eax, %eax
inl %dx, %eax
ret
/* outb */
.globl outb
outb: movl 4(%esp), %edx
movl 8(%esp), %eax
outb %al, %dx
ret
/* outw */
.globl outw
outw: movl 4(%esp), %edx
movl 8(%esp), %eax
outw %ax, %dx
ret
/* outl */
.globl outl
outl: movl 4(%esp), %edx
movl 8(%esp), %eax
outl %eax, %dx
ret
.end

View file

@ -0,0 +1,53 @@
; header
;
; Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
;
; SPDX-License-Identifier: MIT
;
; Permission is hereby granted, free of charge, to any person obtaining a copy of
; this software and associated documentation files (the "Software"), to deal in
; the Software without restriction, including without limitation the rights to
; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; the Software, and to permit persons to whom the Software is furnished to do so,
; subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;
MB2_ARCH EQU 0 ; 0 = x86/x86-64
MB2_LEN EQU (mbend-mbhead)
MB2_MAGIC EQU 0xe85250d6
section .multiboot_header align=4096
mbhead:
dd MB2_MAGIC ; Multiboot2 magic number
dd MB2_ARCH ; Architecture
dd MB2_LEN ; Multiboot header length
dd 0x100000000 - MB2_LEN - MB2_ARCH - MB2_MAGIC
; Checksum
mb2_tag_info_start:
dw 1 ; multiboot information request
dw 0
dd mb2_tag_info_end - mb2_tag_info_start
dd 1
dd 2
dd 6
mb2_tag_info_end:
align 8
mb2_tag_end_start:
dw 0 ; last tag
dw 0
dd mb2_tag_end_end - mb2_tag_end_start
mb2_tag_end_end:
mbend:

View file

@ -0,0 +1,367 @@
; idt
;
; Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
;
; SPDX-License-Identifier: MIT
;
; Permission is hereby granted, free of charge, to any person obtaining a copy of
; this software and associated documentation files (the "Software"), to deal in
; the Software without restriction, including without limitation the rights to
; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; the Software, and to permit persons to whom the Software is furnished to do so,
; subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;
section .text
extern vHandler
global sysint
global read_isr
global load_idt
global load_cr3
global starttask
global read_cr2
global InterruptReturn
Interrupt:
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi,rsp
call vHandler
InterruptReturn:
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
add rsp,16
iretq
%macro VECTOR_1 1
global vector%1
vector%1:
cli
push byte %1
jmp Interrupt
%endmacro
%macro VECTOR_2 1
global vector%1
vector%1:
cli
push 0
push %1
jmp Interrupt
%endmacro
VECTOR_2 0
VECTOR_2 1
VECTOR_2 2
VECTOR_2 3
VECTOR_2 4
VECTOR_2 5
VECTOR_2 6
VECTOR_2 7
; Error code is pushed by CPU for the following vectors
; So we dont push error code in these vectors
VECTOR_1 8
VECTOR_1 10
VECTOR_1 11
VECTOR_1 12
VECTOR_1 13
VECTOR_1 14
VECTOR_2 16
VECTOR_1 17
VECTOR_2 18
VECTOR_2 19
VECTOR_2 32
VECTOR_2 33
VECTOR_2 34
VECTOR_2 35
VECTOR_2 36
VECTOR_2 37
VECTOR_2 38
VECTOR_2 39
VECTOR_2 40
VECTOR_2 41
VECTOR_2 42
VECTOR_2 43
VECTOR_2 44
VECTOR_2 45
VECTOR_2 46
VECTOR_2 47
VECTOR_2 48
VECTOR_2 49
VECTOR_2 50
VECTOR_2 51
VECTOR_2 52
VECTOR_2 53
VECTOR_2 54
VECTOR_2 55
VECTOR_2 56
VECTOR_2 57
VECTOR_2 58
VECTOR_2 59
VECTOR_2 60
VECTOR_2 61
VECTOR_2 62
VECTOR_2 63
VECTOR_2 64
VECTOR_2 65
VECTOR_2 66
VECTOR_2 67
VECTOR_2 68
VECTOR_2 69
VECTOR_2 70
VECTOR_2 71
VECTOR_2 72
VECTOR_2 73
VECTOR_2 74
VECTOR_2 75
VECTOR_2 76
VECTOR_2 77
VECTOR_2 78
VECTOR_2 79
VECTOR_2 80
VECTOR_2 81
VECTOR_2 82
VECTOR_2 83
VECTOR_2 84
VECTOR_2 85
VECTOR_2 86
VECTOR_2 87
VECTOR_2 88
VECTOR_2 89
VECTOR_2 90
VECTOR_2 91
VECTOR_2 92
VECTOR_2 93
VECTOR_2 94
VECTOR_2 95
VECTOR_2 96
VECTOR_2 97
VECTOR_2 98
VECTOR_2 99
VECTOR_2 100
VECTOR_2 101
VECTOR_2 102
VECTOR_2 103
VECTOR_2 104
VECTOR_2 105
VECTOR_2 106
VECTOR_2 107
VECTOR_2 108
VECTOR_2 109
VECTOR_2 110
VECTOR_2 111
VECTOR_2 112
VECTOR_2 113
VECTOR_2 114
VECTOR_2 115
VECTOR_2 116
VECTOR_2 117
VECTOR_2 118
VECTOR_2 119
VECTOR_2 120
VECTOR_2 121
VECTOR_2 122
VECTOR_2 123
VECTOR_2 124
VECTOR_2 125
VECTOR_2 126
VECTOR_2 127
; 128 is used by system calls
VECTOR_2 129
VECTOR_2 130
VECTOR_2 131
VECTOR_2 132
VECTOR_2 133
VECTOR_2 134
VECTOR_2 135
VECTOR_2 136
VECTOR_2 137
VECTOR_2 138
VECTOR_2 139
VECTOR_2 140
VECTOR_2 141
VECTOR_2 142
VECTOR_2 143
VECTOR_2 144
VECTOR_2 145
VECTOR_2 146
VECTOR_2 147
VECTOR_2 148
VECTOR_2 149
VECTOR_2 150
VECTOR_2 151
VECTOR_2 152
VECTOR_2 153
VECTOR_2 154
VECTOR_2 155
VECTOR_2 156
VECTOR_2 157
VECTOR_2 158
VECTOR_2 159
VECTOR_2 160
VECTOR_2 161
VECTOR_2 162
VECTOR_2 163
VECTOR_2 164
VECTOR_2 165
VECTOR_2 166
VECTOR_2 167
VECTOR_2 168
VECTOR_2 169
VECTOR_2 170
VECTOR_2 171
VECTOR_2 172
VECTOR_2 173
VECTOR_2 174
VECTOR_2 175
VECTOR_2 176
VECTOR_2 177
VECTOR_2 178
VECTOR_2 179
VECTOR_2 180
VECTOR_2 181
VECTOR_2 182
VECTOR_2 183
VECTOR_2 184
VECTOR_2 185
VECTOR_2 186
VECTOR_2 187
VECTOR_2 188
VECTOR_2 189
VECTOR_2 190
VECTOR_2 191
VECTOR_2 192
VECTOR_2 193
VECTOR_2 194
VECTOR_2 195
VECTOR_2 196
VECTOR_2 197
VECTOR_2 198
VECTOR_2 199
VECTOR_2 200
VECTOR_2 201
VECTOR_2 202
VECTOR_2 203
VECTOR_2 204
VECTOR_2 205
VECTOR_2 206
VECTOR_2 207
VECTOR_2 208
VECTOR_2 209
VECTOR_2 210
VECTOR_2 211
VECTOR_2 212
VECTOR_2 213
VECTOR_2 214
VECTOR_2 215
VECTOR_2 216
VECTOR_2 217
VECTOR_2 218
VECTOR_2 219
VECTOR_2 220
VECTOR_2 221
VECTOR_2 222
VECTOR_2 223
VECTOR_2 224
VECTOR_2 225
VECTOR_2 226
VECTOR_2 227
VECTOR_2 228
VECTOR_2 229
VECTOR_2 230
VECTOR_2 231
VECTOR_2 232
VECTOR_2 233
VECTOR_2 234
VECTOR_2 235
VECTOR_2 236
VECTOR_2 237
VECTOR_2 238
VECTOR_2 239
VECTOR_2 240
VECTOR_2 241
VECTOR_2 242
VECTOR_2 243
VECTOR_2 244
VECTOR_2 245
VECTOR_2 246
VECTOR_2 247
VECTOR_2 248
VECTOR_2 249
VECTOR_2 250
VECTOR_2 251
VECTOR_2 252
VECTOR_2 253
VECTOR_2 254
VECTOR_2 255
sysint:
push 0
push 0x80
jmp Interrupt
read_isr:
mov al,11
out 0x20,al
in al,0x20
ret
load_idt:
lidt [rdi]
ret
load_cr3:
mov rax,rdi
mov cr3,rax
ret
read_cr2:
mov rax,cr2
ret
starttask:
mov rsp,rdi
jmp InterruptReturn

View file

@ -0,0 +1,240 @@
; main
;
; Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
;
; SPDX-License-Identifier: MIT
;
; Permission is hereby granted, free of charge, to any person obtaining a copy of
; this software and associated documentation files (the "Software"), to deal in
; the Software without restriction, including without limitation the rights to
; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; the Software, and to permit persons to whom the Software is furnished to do so,
; subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;
global start
global mboot_info
global pml4
global pud
global wakeup
global hypercall_page
global shared_info
extern long_mode_start
global grant_table
global argo_ring
global rdtsc_low
global rdtsc_high
section .text
bits 32
start:
mov esp, stack_top
rdtsc
mov [rdtsc_low], eax
mov [rdtsc_high], edx
mov [mboot_info], ebx
call setup_page_tables
call enable_paging
lgdt [Gdt64KernelPtr]
jmp 8:long_mode_start
hlt
setup_page_tables:
lea eax, [pud] ; Load the address of pud into eax
mov edx, 0x0 ; Upper 32-bits of the address (since we're in 32-bit mode, this is 0)
or eax, 0x3 ; OR the lower 32-bits of the address with 0x3
mov [pml4], eax ; Store the lower 32-bits in pml4[0] (low)
mov [pml4+4], edx ; Store the upper 32-bits in pml4[0] (high, which is 0)
; Set pud[0] = 0x0000000083 (64-bit value, split into two 32-bit parts)
mov eax, 0x83 ; Load the lower 32-bits of 0x0000000083 into eax
mov edx, 0x0 ; Upper 32-bits of the value (0x00000000)
mov [pud], eax ; Store the lower 32-bits in pud[0] (low)
mov [pud+4], edx ; Store the upper 32-bits in pud[0] (high)
ret
enable_paging:
; pass page table location to cpu
mov eax, pml4
mov cr3, eax
; enable PAE
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; enable long mode
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; enable paging
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
mov eax, cr0
ret
section .bss
align 4096
hypercall_page:
resb 4096
shared_info:
resb 4096
grant_table:
resb 4096 * 2
argo_ring:
resb 4096 * 5
section .bss
align 4096
pml4:
resb 4096
pud:
resb 4096*512
stack_bottom:
resb 16384 * 4
stack_top:
section .rodata
Gdt64Kernel:
dq 0
dq 0x0020980000000000
Gdt64KernelLen: equ $-Gdt64Kernel
Gdt64KernelPtr: dw Gdt64KernelLen-1
dd Gdt64Kernel
extern main
extern serial_send
extern init_serial
extern mboot_info
section .data
mboot_info:
dd 0
rdtsc_low:
dd 0
rdtsc_high:
dd 0
global Tss
Gdt64:
dq 0
dq 0x0020980000000000
dq 0x0020920000000000
dq 0x0020f80000000000
dq 0x0000f20000000000
TssDesc:
dw TssLen-1
dw 0
db 0
db 0x89
db 0
db 0
dq 0
Gdt64Len: equ $-Gdt64
Gdt64Ptr: dw Gdt64Len-1
dq Gdt64
Tss:
dd 0
dq 0xffff800000190000
times 88 db 0
dd TssLen
TssLen: equ $-Tss
section .text
bits 64
long_mode_start:
; Load 64-bit GDT Descriptor in Global Descriptor Table Register
mov rax,Gdt64Ptr
lgdt [rax]
; Load TSS address into Tss Descriptor
mov rax,Tss
mov rdi,TssDesc
mov [rdi+2],ax
shr rax,16
mov [rdi+4],al
shr rax,8
mov [rdi+7],al
shr rax,8
mov [rdi+8],eax
mov ax,0x28
; activate Tss
ltr ax
; enable SSE instructions
mov rax, cr0
bts rax, 1
btr rax, 2
mov cr0, rax
mov rax, cr4
bts rax, 9
bts rax, 10
mov cr4, rax
finit
; enable avx if available
mov eax, 1
cpuid
bt ecx, 28
jnc avx_not_supported
avx_supported:
mov rax, cr4
bts rax, 18
mov cr4, rax
xor ecx, ecx
xgetbv
bts rax, 0
bts rax, 1
bts rax, 2
xsetbv
avx_not_supported:
; load null into all data segment registers
mov ax, 0x10
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call init_serial
cmp word[mboot_info], 0
je err
; load mboot_info in parameter (rdi)
; and call main
mov rdi, 0
mov edi, [mboot_info]
call main
hlt
err:
hlt
jmp err

View file

@ -0,0 +1,298 @@
; syscall
;
; Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
;
; SPDX-License-Identifier: MIT
;
; Permission is hereby granted, free of charge, to any person obtaining a copy of
; this software and associated documentation files (the "Software"), to deal in
; the Software without restriction, including without limitation the rights to
; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; the Software, and to permit persons to whom the Software is furnished to do so,
; subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;
section freertos_system_calls
%define SYSCALL_NUM_writec 0
%define SYSCALL_NUM_xTaskGetTickCount 1
%define SYSCALL_NUM_xTaskDelayUntil 2
%define SYSCALL_NUM_xQueueGenericSend 3
%define SYSCALL_NUM_xQueueReceive 4
%define SYSCALL_NUM_xTimerGenericCommandFromTask 5
%define SYSCALL_NUM_eTaskGetState 6
%define SYSCALL_NUM_pcQueueGetName 7
%define SYSCALL_NUM_pcTimerGetName 8
%define SYSCALL_NUM_pvTimerGetTimerID 9
%define SYSCALL_NUM_ulTaskGenericNotifyTake 10
%define SYSCALL_NUM_ulTaskGenericNotifyValueClear 11
%define SYSCALL_NUM_uxQueueMessagesWaiting 12
%define SYSCALL_NUM_uxQueueSpacesAvailable 13
%define SYSCALL_NUM_uxTaskGetNumberOfTasks 14
%define SYSCALL_NUM_uxTaskGetSystemState 15
%define SYSCALL_NUM_uxTaskPriorityGet 16
%define SYSCALL_NUM_uxTimerGetReloadMode 17
%define SYSCALL_NUM_vQueueAddToRegistry 18
%define SYSCALL_NUM_vQueueUnregisterQueue 19
%define SYSCALL_NUM_vTaskDelay 20
%define SYSCALL_NUM_vTaskGetInfo 21
%define SYSCALL_NUM_vTaskResume 22
%define SYSCALL_NUM_vTaskSetTimeOutState 23
%define SYSCALL_NUM_vTaskSuspend 24
%define SYSCALL_NUM_vTaskSuspendAll 25
%define SYSCALL_NUM_vTimerSetReloadMode 26
%define SYSCALL_NUM_vTimerSetTimerID 27
%define SYSCALL_NUM_xQueueAddToSet 28
%define SYSCALL_NUM_xQueueGiveMutexRecursive 29
%define SYSCALL_NUM_xQueuePeek 30
%define SYSCALL_NUM_xQueueRemoveFromSet 31
%define SYSCALL_NUM_xQueueSelectFromSet 32
%define SYSCALL_NUM_xQueueSemaphoreTake 33
%define SYSCALL_NUM_xQueueTakeMutexRecursive 34
%define SYSCALL_NUM_xTaskCheckForTimeOut 35
%define SYSCALL_NUM_xTaskGenericNotify 36
%define SYSCALL_NUM_xTaskGenericNotifyStateClear 37
%define SYSCALL_NUM_xTaskGenericNotifyWait 38
%define SYSCALL_NUM_xTaskGetCurrentTaskHandle 39
%define SYSCALL_NUM_xTaskGetSchedulerState 40
%define SYSCALL_NUM_xTimerGetExpiryTime 41
%define SYSCALL_NUM_xTimerGetPeriod 42
%define SYSCALL_NUM_xTimerGetTimerDaemonTaskHandle 43
%define SYSCALL_NUM_xTimerIsTimerActive 44
%define SYSCALL_NUM_xTaskAbortDelay 45
%define SYSCALL_NUM_xTaskGetHandle 46
%define SYSCALL_NUM_xEventGroupCreate 47
%define SYSCALL_NUM_xEventGroupWaitBits 48
%define SYSCALL_NUM_vEventGroupDelete 49
%define SYSCALL_NUM_xStreamBufferGenericCreate 50
%define SYSCALL_NUM_xStreamBufferReceive 51
%define SYSCALL_NUM_vStreamBufferDelete 52
%define SYSCALL_NUM_xQueueGetMutexHolder 53
%define SYSCALL_NUM_xEventGroupSync 54
%define SYSCALL_NUM_xEventGroupSetBits 55
%define SYSCALL_NUM_xEventGroupClearBits 56
%define SYSCALL_NUM_xStreamBufferSend 57
%define SYSCALL_NUM_xStreamBufferIsEmpty 58
%define SYSCALL_NUM_xStreamBufferNextMessageLengthBytes 59
%define SYSCALL_NUM_xStreamBufferIsFull 60
%define SYSCALL_NUM_xStreamBufferSpacesAvailable 61
%define SYSCALL_NUM_xStreamBufferReset 62
%define SYSCALL_NUM_xStreamBufferBytesAvailable 64
%macro SYSCALL_0 2
global %1
%1:
mov eax,%2
mov rdi,0
mov rsi,rsp
int 0x80
ret
%endmacro
%macro SYSCALL_1 2
global %1
%1:
sub rsp,8
mov eax, %2
mov [rsp],rdi
mov rdi,1
mov rsi,rsp
int 0x80
add rsp,8
ret
%endmacro
%macro SYSCALL_2 2
global %1
%1:
sub rsp,16
mov eax, %2
mov [rsp],rdi
mov [rsp+8],rsi
mov rdi,2
mov rsi,rsp
int 0x80
add rsp,16
ret
%endmacro
%macro SYSCALL_3 2
global %1
%1:
sub rsp,24
mov eax, %2
mov [rsp],rdi
mov [rsp+8],rsi
mov [rsp+16],rdx
mov rdi,3
mov rsi,rsp
int 0x80
add rsp,24
ret
%endmacro
%macro SYSCALL_4 2
global %1
%1:
sub rsp, 32
mov eax, %2
mov [rsp],rdi
mov [rsp+8],rsi
mov [rsp+16],rdx
mov [rsp+24],rcx
mov rdi,4
mov rsi,rsp
int 0x80
add rsp,32
ret
%endmacro
%macro SYSCALL_5 2
global %1
%1:
sub rsp, 40
mov eax, %2
mov [rsp],rdi
mov [rsp+8],rsi
mov [rsp+16],rdx
mov [rsp+24],rcx
mov [rsp+32],r8
mov rdi,5
mov rsi,rsp
int 0x80
add rsp,40
ret
%endmacro
%macro SYSCALL_6 2
global %1
%1:
sub rsp, 48
mov eax, %2
mov [rsp],rdi
mov [rsp+8],rsi
mov [rsp+16],rdx
mov [rsp+24],rcx
mov [rsp+32],r8
mov [rsp+40],r9
mov rdi,6
mov rsi,rsp
int 0x80
add rsp,48
ret
%endmacro
%macro SYSCALL_7 2
global %1
%1:
sub rsp, 56
mov eax, %7
mov [rsp],rdi
mov [rsp+8],rsi
mov [rsp+16],rdx
mov [rsp+24],rcx
mov [rsp+32],r8
mov [rsp+40],r9
mov rdi,6
mov rsi,rsp
int 0x80
add rsp,56
ret
%endmacro
SYSCALL_1 syscall_writec, SYSCALL_NUM_writec
SYSCALL_0 syscall_xTaskGetTickCount, SYSCALL_NUM_xTaskGetTickCount
SYSCALL_2 syscall_xTaskDelayUntil, SYSCALL_NUM_xTaskDelayUntil
SYSCALL_4 syscall_xQueueGenericSend, SYSCALL_NUM_xQueueGenericSend
SYSCALL_3 syscall_xQueueReceive, SYSCALL_NUM_xQueueReceive
SYSCALL_5 syscall_xTimerGenericCommandFromTask, SYSCALL_NUM_xQueueGenericSend
SYSCALL_1 syscall_eTaskGetState, SYSCALL_NUM_eTaskGetState
SYSCALL_1 syscall_pcQueueGetName, SYSCALL_NUM_pcQueueGetName
SYSCALL_1 syscall_pcTimerGetName, SYSCALL_NUM_pcTimerGetName
SYSCALL_1 syscall_pvTimerGetTimerID, SYSCALL_NUM_pvTimerGetTimerID
SYSCALL_3 syscall_ulTaskGenericNotifyTake, SYSCALL_NUM_ulTaskGenericNotifyTake
SYSCALL_3 syscall_ulTaskGenericNotifyValueClear, SYSCALL_NUM_ulTaskGenericNotifyValueClear
SYSCALL_1 syscall_uxQueueMessagesWaiting, SYSCALL_NUM_uxQueueMessagesWaiting
SYSCALL_1 syscall_uxQueueSpacesAvailable, SYSCALL_NUM_uxQueueSpacesAvailable
SYSCALL_0 syscall_uxTaskGetNumberOfTasks, SYSCALL_NUM_uxTaskGetNumberOfTasks
SYSCALL_3 syscall_uxTaskGetSystemState, SYSCALL_NUM_uxTaskGetSystemState
SYSCALL_1 syscall_uxTaskPriorityGet, SYSCALL_NUM_uxTaskPriorityGet
SYSCALL_1 syscall_uxTimerGetReloadMode, SYSCALL_NUM_uxTimerGetReloadMode
SYSCALL_2 syscall_vQueueAddToRegistry, SYSCALL_NUM_vQueueAddToRegistry
SYSCALL_1 syscall_vQueueUnregisterQueue, SYSCALL_NUM_vQueueUnregisterQueue
SYSCALL_1 syscall_vTaskDelay, SYSCALL_NUM_vTaskDelay
SYSCALL_4 syscall_vTaskGetInfo, SYSCALL_NUM_vTaskGetInfo
SYSCALL_1 syscall_vTaskResume, SYSCALL_NUM_vTaskResume
SYSCALL_1 syscall_vTaskSetTimeOutState, SYSCALL_NUM_vTaskSetTimeOutState
SYSCALL_1 syscall_vTaskSuspend, SYSCALL_NUM_vTaskSuspend
SYSCALL_0 syscall_vTaskSuspendAll, SYSCALL_NUM_vTaskSuspendAll
SYSCALL_2 syscall_vTimerSetReloadMode, SYSCALL_NUM_vTimerSetReloadMode
SYSCALL_2 syscall_vTimerSetTimerID, SYSCALL_NUM_vTimerSetTimerID
SYSCALL_2 syscall_xQueueAddToSet, SYSCALL_NUM_xQueueAddToSet
SYSCALL_1 syscall_xQueueGiveMutexRecursive, SYSCALL_NUM_xQueueGiveMutexRecursive
SYSCALL_3 syscall_xQueuePeek, SYSCALL_NUM_xQueuePeek
SYSCALL_2 syscall_xQueueRemoveFromSet, SYSCALL_NUM_xQueueRemoveFromSet
SYSCALL_2 syscall_xQueueSelectFromSet, SYSCALL_NUM_xQueueSelectFromSet
SYSCALL_2 syscall_xQueueSemaphoreTake, SYSCALL_NUM_xQueueSemaphoreTake
SYSCALL_2 syscall_xQueueTakeMutexRecursive, SYSCALL_NUM_xQueueTakeMutexRecursive
SYSCALL_2 syscall_xTaskCheckForTimeOut, SYSCALL_NUM_xTaskCheckForTimeOut
SYSCALL_5 syscall_xTaskGenericNotify, SYSCALL_NUM_xTaskGenericNotify
SYSCALL_2 syscall_xTaskGenericNotifyStateClear, SYSCALL_NUM_xTaskGenericNotifyStateClear
SYSCALL_5 syscall_xTaskGenericNotifyWait, SYSCALL_NUM_xTaskGenericNotifyWait
SYSCALL_0 syscall_xTaskGetCurrentTaskHandle, SYSCALL_NUM_xTaskGetCurrentTaskHandle
SYSCALL_0 syscall_xTaskGetSchedulerState, SYSCALL_NUM_xTaskGetSchedulerState
SYSCALL_1 syscall_xTimerGetExpiryTime, SYSCALL_NUM_xTimerGetExpiryTime
SYSCALL_1 syscall_xTimerGetPeriod, SYSCALL_NUM_xTimerGetPeriod
SYSCALL_0 syscall_xTimerGetTimerDaemonTaskHandle, SYSCALL_NUM_xTimerGetTimerDaemonTaskHandle
SYSCALL_1 syscall_xTimerIsTimerActive, SYSCALL_NUM_xTimerIsTimerActive
SYSCALL_1 syscall_xTaskAbortDelay, SYSCALL_NUM_xTaskAbortDelay
SYSCALL_1 syscall_xTaskGetHandle, SYSCALL_NUM_xTaskGetHandle
SYSCALL_0 syscall_xEventGroupCreate, SYSCALL_NUM_xEventGroupCreate
SYSCALL_5 syscall_xEventGroupWaitBits, SYSCALL_NUM_xEventGroupWaitBits
SYSCALL_1 syscall_vEventGroupDelete, SYSCALL_NUM_vEventGroupDelete
SYSCALL_5 syscall_xStreamBufferGenericCreate, SYSCALL_NUM_xStreamBufferGenericCreate
SYSCALL_4 syscall_xStreamBufferReceive, SYSCALL_NUM_xStreamBufferReceive
SYSCALL_1 syscall_vStreamBufferDelete, SYSCALL_NUM_vStreamBufferDelete
SYSCALL_1 syscall_xQueueGetMutexHolder, SYSCALL_NUM_xQueueGetMutexHolder
SYSCALL_4 syscall_xEventGroupSync, SYSCALL_NUM_xEventGroupSync
SYSCALL_2 syscall_xEventGroupSetBits, SYSCALL_NUM_xEventGroupSetBits
SYSCALL_2 syscall_xEventGroupClearBits, SYSCALL_NUM_xEventGroupClearBits
SYSCALL_2 syscall_xStreamBufferSend, SYSCALL_NUM_xStreamBufferSend
SYSCALL_1 syscall_xStreamBufferIsEmpty, SYSCALL_NUM_xStreamBufferIsEmpty
SYSCALL_1 syscall_xStreamBufferNextMessageLengthBytes, SYSCALL_NUM_xStreamBufferNextMessageLengthBytes
SYSCALL_1 syscall_xStreamBufferIsFull, SYSCALL_NUM_xStreamBufferIsFull
SYSCALL_1 syscall_xStreamBufferSpacesAvailable, SYSCALL_NUM_xStreamBufferSpacesAvailable
SYSCALL_1 syscall_xStreamBufferReset, SYSCALL_NUM_xStreamBufferReset
SYSCALL_1 syscall_xStreamBufferBytesAvailable, SYSCALL_NUM_xStreamBufferBytesAvailable

View file

@ -0,0 +1,40 @@
# xennote
#
# Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
.extern start
#define ELFNOTE(name, type, desc) \
.pushsection .note.name ; \
.align 4 ; \
.long 2f - 1f /* namesz */ ; \
.long 4f - 3f /* descsz */ ; \
.long type /* type */ ; \
1:.asciz #name /* name */ ; \
2:.align 4 ; \
3:desc /* desc */ ; \
4:.align 4 ; \
.popsection
#define XEN_ELFNOTE_PHYS32_ENTRY 18
ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long start)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
/* page_allocate
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#include "stdint.h"
#include "x86_64.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <memory.h>
void vAlignedFree(void *aligned_ptr) ;
void vFreeAllPages(uint64_t *pgd) ;
uint64_t *pMallocPageTable(void) ;
void vMapPages(uint64_t start_addr,uint64_t end_addr, uint64_t *pgd, uint32_t mode) ;
void vAlignedFree(void *aligned_ptr) {
if (aligned_ptr != NULL) {
void *original_ptr = ((void **)aligned_ptr)[-1];
vPortFree(original_ptr);
}
}
void vFreeAllPages(uint64_t *pgd) {
if (pgd !=NULL) {
for (int pgd_index=256;pgd_index<512;pgd_index++) {
uint64_t *pud = (uint64_t *)(pgd[pgd_index]&0xfffffffff000ULL);
if (pud !=NULL) {
for (int pud_index=0;pud_index<512;pud_index++) {
uint64_t *pmd = (uint64_t *)(pud[pud_index]&0xfffffffff000ULL);
if (pmd !=NULL) {
for (int pmd_index=0;pmd_index<512;pmd_index++) {
uint64_t *pt = (uint64_t *)(pmd[pmd_index]&0xfffffffff000ULL);
if (pt!=NULL) {
vAlignedFree(pt);
}
}
vAlignedFree(pmd);
}
}
vAlignedFree(pud);
}
}
vAlignedFree(pgd);
}
}
uint64_t *pMallocPageTable(void) {
uint64_t *page_table=(uint64_t *)pvAlignedMalloc((uint64_t)512 * sizeof(uint64_t),4096);
memset(page_table,0,(uint64_t)512*sizeof(uint64_t));
return page_table;
}
void vMapPages(uint64_t start_addr,uint64_t end_addr, uint64_t *pgd, uint32_t mode) {
uint32_t pgd_index = 0;
uint32_t pud_index = 0;
uint32_t pmd_index = 0;
uint32_t pt_index = 0;
uint64_t addr = start_addr;
uint64_t target_address = USER_VA_START + start_addr;
while (addr < end_addr) {
pgd_index = PGD_INDEX(target_address);
pud_index = PUD_INDEX(target_address);
pmd_index = PMD_INDEX(target_address);
pt_index = PT_INDEX(target_address);
uint64_t *pud = (uint64_t *)(pgd[pgd_index]&0xfffffffff000ULL);
if (pud == (void *)0) {
pud = pMallocPageTable();
pgd[pgd_index] = (uint64_t) pud;
pgd[pgd_index] |= 0x07;
}
uint64_t *pmd = (uint64_t *)(pud[pud_index]&0xfffffffff000ULL);
if (pmd == (void *)0) {
pmd = pMallocPageTable();
pud[pud_index] = (uint64_t) pmd;
pud[pud_index] |= 0x07;
}
uint64_t *pt = (uint64_t *)(pmd[pmd_index]&0xfffffffff000ULL);
if (pt == (void *)0) {
pt = pMallocPageTable();
pmd[pmd_index] = (uint64_t) pt;
pmd[pmd_index] |= 0x07;
}
pt[pt_index] = addr | (uint64_t)0x07;
if (mode != REGION_RW)
pt[pt_index] &= ~0x2;
addr += PAGE_SIZE_4K;
target_address += PAGE_SIZE_4K;
}
}

View file

@ -0,0 +1,402 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <limits.h>
#include <stdint.h>
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "trap.h"
#include "x86_64.h"
#include "sectionapi.h"
#include "ioapic.h"
#include "io.h"
#include "stdio.h"
#include "string.h"
/* A critical section is exited when the critical section nesting count reaches
* this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* This is the lowest possible ISR vector available to application code. */
#define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
/* EFLAGS bits. */
#define portEFLAGS_IF ( 0x200UL )
/* If configASSERT() is defined then the system stack is filled with this value
* to allow for a crude stack overflow check. */
#define portSTACK_WORD ( 0xecececec )
/*-----------------------------------------------------------*/
/*
* Starts the first task executing.
*/
void vPortStartFirstTask( void );
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
configSTACK_DEPTH_TYPE uxStackDepth );
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged,
xMPU_SETTINGS * xMPUSettings);
void vPortTaskUsesFPU( void );
static void prvSetupLAPIC( void );
void vPortSetupIDT( void );
BaseType_t xPortStartScheduler( void );
void vPortEndScheduler( void );
void vPortEnterCritical( void );
void vPortExitCritical( void );
uint32_t ulPortSetInterruptMask( void );
void vPortClearInterruptMask( uint32_t ulNewMaskValue );
void enable_sci(void);
void init_time(void);
extern struct TSS Tss;
/* A variable is used to keep track of the critical section nesting. This
* variable must be initialised to a non zero value to ensure interrupts don't
* inadvertently become unmasked before the scheduler starts. It is set to zero
* before the first task starts executing. */
volatile uint32_t ulCriticalNesting = 9999UL;
/* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
* then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
* not NULL then it points to a buffer into which the FPU context can be saved. */
#define portFPU_CONTEXT_SIZE_BYTES 512
uint8_t pucPortTaskFPUContextBuffer [portFPU_CONTEXT_SIZE_BYTES] __attribute__((aligned(16)));
uint32_t xTaskUsesFPU = pdFALSE;
/* The stack used by interrupt handlers. */
static uint64_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__( ( used ) ) = { 0 };
/* Don't use the very top of the system stack so the return address
* appears as 0 if the debugger tries to unwind the stack. */
volatile uint64_t ulTopOfSystemStack __attribute__( ( used ) ) = ( uint64_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
/* If a yield is requested from an interrupt or from a critical section then
* the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
* instead to indicate the yield should be performed at the end of the interrupt
* when the critical section is exited. */
volatile uint32_t ulPortYieldPending __attribute__( ( used ) ) = pdFALSE;
volatile uint32_t schedStart __attribute__( ( used ) ) = pdFALSE;
/* Counts the interrupt nesting depth. Used to know when to switch to the
* interrupt/system stack and when to save/restore a complete context. */
volatile uint32_t ulInterruptNesting __attribute__( ( used ) ) = 0;
/*-----------------------------------------------------------*/
int vHaltCPU(void) ;
int vHaltCPU(void) {
__asm__ volatile("hlt");
return 1;
}
extern StackType_t *pxCurrentTCB;
void vPortStartFirstTask() {
schedStart = pdTRUE;
struct TrapFrame* tf = (struct TrapFrame*) *pxCurrentTCB;
xMPU_SETTINGS * xMPUSettings = (xMPU_SETTINGS*) (pxCurrentTCB+1);
load_cr3(xMPUSettings->pgd);
Tss.rsp0 = (uint64_t) xMPUSettings->kernel_stack;
starttask((void*)*pxCurrentTCB);
}
/*
* This method is called by FreeRTOS to store
*/
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
configSTACK_DEPTH_TYPE uxStackDepth )
{
extern uint64_t pml4;
if (uxStackDepth > 0 ) {
xMPUSettings->kernel_stack = &ulSystemStack[configMINIMAL_STACK_SIZE-1];
if (xRegions != NULL) {
// Allocate page table
uint64_t *pgd = pMallocPageTable();
for (int region_index = 0; region_index < portNUM_CONFIGURABLE_REGIONS; region_index++) {
if (xRegions[region_index].pvBaseAddress == 0) {
// last defined index
break;
}
vMapPages((uint64_t) xRegions[region_index].pvBaseAddress, ((uint64_t)xRegions[region_index].pvBaseAddress) + xRegions[region_index].ulLengthInBytes, pgd, xRegions[region_index].ulParameters);
// Copy half page tables address from kernel
(void) memcpy(pgd, &pml4, PAGE_TABLE_SIZE/2*sizeof(uint64_t));
}
xMPUSettings->pgd = (uint64_t) pgd;
} else {
xMPUSettings->pgd = (uint64_t) &pml4;
}
}
}
/*
* See header file for description.
*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged,
xMPU_SETTINGS * xMPUSettings)
{
uint32_t ulCodeSegment;
pxTopOfStack = (StackType_t *)(pxTopOfStack - sizeof(struct TrapFrame));
struct TrapFrame* tf = (struct TrapFrame *)pxTopOfStack;
tf->rdi = (uint64_t) pvParameters;
tf->cs = 0x8;
tf->rip = (uint64_t) pxCode;
tf->ss = 0x10;
tf->rsp = (uint64_t) pxTopOfStack;
tf->rflags = 0x202;
int param = 0;
if (xRunPrivileged == 0) {
Tss.rsp0 = (uint64_t) xMPUSettings->kernel_stack;
tf->cs = (int64_t)((int64_t)0x18|(int64_t)0x3);
tf->ss = (int64_t)((int64_t)0x20|(int64_t)0x3);
tf->rip = USER_VA_START+(uint64_t)pxCode;
}
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
#if defined( configSUPPORT_FPU )
#if ( configSUPPORT_FPU == 1 )
void vPortTaskUsesFPU( void )
{
/* A task is registering the fact that it needs an FPU context. Allocate a
* buffer into which the context can be saved. */
xTaskUsesFPU = pdTRUE;
/* Initialise the floating point registers. */
__asm volatile ( "fninit" );
}
#endif /* configSUPPORT_FPU */
#endif
/*-----------------------------------------------------------*/
#define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
#define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
//#define configCPU_CLOCK_HZ ( 2994354000UL )
#define configCPU_CLOCK_HZ ( 400000000UL )
static void prvSetupLAPIC( void )
{
/* Initialise LAPIC to a well known state. */
portAPIC_LDR = 0xFFFFFFFF;
portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
portAPIC_LVT_TIMER = portAPIC_DISABLE;
portAPIC_LVT_PERF = portAPIC_NMI;
portAPIC_LVT_LINT0 = portAPIC_DISABLE;
portAPIC_LVT_LINT1 = portAPIC_DISABLE;
portAPIC_TASK_PRIORITY = 0;
/* Enable the APIC, mapping the spurious interrupt at the same time. */
portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
/* Set timer error vector. */
portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
}
/*-----------------------------------------------------------*/
#define PIC1 0x20
#define PIC2 0xA0
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
void vPortSetupIDT( void )
{
// Disable interrupts from 8259
outb(PIC1_COMMAND, 0x21);
outb(PIC1_DATA, 0xFF);
outb(PIC1_COMMAND, 0x22);
outb(PIC1_DATA, 0xFF);
vIDTInit();
prvSetupLAPIC();
set_ioapic_irq_mask(portAPIC_TIMER_INT_VECTOR-0x20, 0);
enable_sci();
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
/* Initialise Interrupt Descriptor Table (IDT). */
vPortSetupIDT();
init_time();
/* Make sure the stack used by interrupts is aligned. */
ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
ulCriticalNesting = 0;
/* Enable LAPIC Counter.*/
// portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR;
/* Sometimes needed. */
// portAPIC_TMRDIV = portAPIC_DIV_16;
/* Should not return from the following function as the scheduler will then
* be executing the tasks. */
vPortStartFirstTask();
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
if( ulCriticalNesting == 0UL )
{
__asm volatile ( "cli" );
}
/* Now that interrupts are disabled, ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
if( ulCriticalNesting > 0UL )
{
/* Decrement the nesting count as the critical section is being
* exited. */
ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
__asm volatile ( "sti" );
/* If a yield was pended from within the critical section then
* perform the yield now. */
if( ulPortYieldPending != pdFALSE )
{
ulPortYieldPending = pdFALSE;
__asm volatile ( portYIELD_INTERRUPT );
}
}
}
}
/*-----------------------------------------------------------*/
uint32_t ulPortSetInterruptMask( void )
{
volatile uint64_t ulOriginalMask;
/* Set mask to max syscall priority. */
#if defined (configMAX_API_CALL_INTERRUPT_PRIORITY)
#if defined (portMAX_PRIORITY)
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
/* Return whether interrupts were already enabled or not. Pop adjusts
* the stack first. */
__asm__ volatile (
"pushfq \n\t"
"popq %%rax \n\t"
"cli \n\t"
"movq %%rax, %0 \n\t"
: "=r" (ulOriginalMask)
:
: "rax", "memory"
);
ulOriginalMask &= portEFLAGS_IF;
}
#else
{
/* Return original mask. */
ulOriginalMask = portAPIC_TASK_PRIORITY;
portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
}
#endif /* if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY ) */
#endif
#endif
return ulOriginalMask;
}
/*-----------------------------------------------------------*/
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{
#if defined (configMAX_API_CALL_INTERRUPT_PRIORITY)
#if defined (portMAX_PRIORITY)
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
if( ulNewMaskValue != pdFALSE )
{
__asm volatile ( "sti" );
}
}
#else
{
portAPIC_TASK_PRIORITY = ulNewMaskValue;
configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
}
#endif /* if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY ) */
#endif
#endif
}
/*-----------------------------------------------------------*/
FREERTOS_SYSTEM_CALL int vPortIsPrivileged(void) {
unsigned short cs =(unsigned short)0;
// Read the Code Segment (CS) register
__asm__ __volatile__("mov %%cs, %0" : "=r"(cs));
// Check if the Current Privilege Level (CPL) is 0 (Ring 0)
if ((cs & (unsigned short)0x3) ==(unsigned short) 0) {
return 1; // In Ring 0
} else {
return 0; // Not in Ring 0
}
}

View file

@ -0,0 +1,253 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint64_t
#define portBASE_TYPE long
#define portPOINTER_SIZE_TYPE uint64_t
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef BaseType_t TickType_t;
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffUL )
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 32
/*-----------------------------------------------------------*/
/* Task utilities. */
/* The interrupt priority (for vectors 16 to 255) is determined using vector/16.
* The quotient is rounded to the nearest integer with 1 being the lowest priority
* and 15 is the highest. Therefore the following two interrupts are at the lowest
* priority. *NOTE 1* If the yield vector is changed then it must also be changed
* in the portYIELD_INTERRUPT definition immediately below. */
#define portAPIC_TIMER_INT_VECTOR ( 0x20 )
#define portAPIC_DEBUG_SERIAL_INT_VECTOR ( 0x24 )
#define portAPIC_YIELD_INT_VECTOR ( 0x21 )
/* Build yield interrupt instruction. */
#define portYIELD_INTERRUPT "int $0x21"
/* APIC register addresses. */
#define portAPIC_EOI ( *( ( volatile uint32_t * ) 0xFEE000B0UL ) )
/* APIC bit definitions. */
#define portAPIC_ENABLE_BIT ( 1UL << 8UL )
#define portAPIC_TIMER_PERIODIC ( 1UL << 17UL )
#define portAPIC_DISABLE ( 1UL << 16UL )
#define portAPIC_NMI ( 4 << 8 )
#define portAPIC_DIV_16 ( 0x03 )
/* Define local APIC register addresses. */
#define configAPIC_BASE 0xFEE00000UL
#define portAPIC_ID_REGISTER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x20UL ) ) )
#define portAPIC_SPURIOUS_INT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xF0UL ) ) )
#define portAPIC_LVT_TIMER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x320UL ) ) )
#define portAPIC_TIMER_INITIAL_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x380UL ) ) )
#define portAPIC_TIMER_CURRENT_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x390UL ) ) )
#define portAPIC_TASK_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x80UL ) ) )
#define portAPIC_LVT_ERROR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x370UL ) ) )
#define portAPIC_ERROR_STATUS ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x280UL ) ) )
#define portAPIC_LDR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xD0UL ) ) )
#define portAPIC_TMRDIV ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x3E0UL ) ) )
#define portAPIC_LVT_PERF ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x340UL ) ) )
#define portAPIC_LVT_LINT0 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x350UL ) ) )
#define portAPIC_LVT_LINT1 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x360UL ) ) )
/* Don't yield if inside a critical section - instead hold the yield pending
* so it is performed when the critical section is exited. */
#define portYIELD() \
{ \
extern volatile uint32_t ulCriticalNesting; \
extern volatile uint32_t ulPortYieldPending; \
if( ulCriticalNesting != 0 ) \
{ \
ulPortYieldPending = pdTRUE; \
} \
else \
{ \
__asm volatile ( portYIELD_INTERRUPT ); \
} \
};
/* Called at the end of an ISR that can cause a context switch - pend a yield if
* xSwitchRequired is not false. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \
extern volatile uint32_t ulPortYieldPending; \
if( xSwitchRequired != pdFALSE ) \
{ \
ulPortYieldPending = 1; \
} \
}
/* Same as portEND_SWITCHING_ISR() - take your pick which name to use. */
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------
* Critical section control
*----------------------------------------------------------*/
/* Critical sections for use in interrupts. */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
extern int vPortIsPrivileged(void);
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
/* These macros do not globally disable/enable interrupts. They do mask off
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() __asm volatile ( "cli" )
#define portENABLE_INTERRUPTS() __asm volatile ( "sti" )
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these
* macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
__asm volatile ( "bsr %1, %0\n\t" \
: "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" )
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#define portNOP() __asm volatile ( "NOP" )
/*-----------------------------------------------------------
* Misc
*----------------------------------------------------------*/
#define portNUM_VECTORS 256
#define portMAX_PRIORITY 15
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
/* The FreeRTOS scheduling algorithm selects the task that will enter the
* Running state. configUSE_PORT_OPTIMISED_TASK_SELECTION is used to set how
* that is done.
*
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 0 then the task to
* enter the Running state is selected using a portable algorithm written in
* C. This is the slowest method, but the algorithm does not restrict the
* maximum number of unique RTOS task priorities that are available.
*
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 1 then the task to
* enter the Running state is selected using a single assembly instruction.
* This is the fastest method, but restricts the maximum number of unique RTOS
* task priorities to 32 (the same task priority can be assigned to any number
* of RTOS tasks). */
#warning configUSE_PORT_OPTIMISED_TASK_SELECTION was not defined in FreeRTOSConfig.h and has been defaulted to 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
/* The value written to the task priority register to raise the interrupt mask
* to the maximum from which FreeRTOS API calls can be made. */
#define portAPIC_PRIORITY_SHIFT ( 4UL )
#define portAPIC_MAX_SUB_PRIORITY ( 0x0fUL )
#define portMAX_API_CALL_PRIORITY ( ( configMAX_API_CALL_INTERRUPT_PRIORITY << portAPIC_PRIORITY_SHIFT ) | portAPIC_MAX_SUB_PRIORITY )
/* Asserts if interrupt safe FreeRTOS functions are called from a priority
* above the max system call interrupt priority. */
#define portAPIC_PROCESSOR_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) )
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) )
/* Support for Restricted Tasks */
#define portUSING_MPU_WRAPPERS 1
/*
* The following two setting are saved for each task
* FreeRTOS saves this information in Task Control Block
* and these are used during context switch.
*/
typedef struct {
uint64_t pgd;
StackType_t *kernel_stack;
} xMPU_SETTINGS;
/* Allow upto 16 memory regions to be defined.*/
#define portNUM_CONFIGURABLE_REGIONS 16
#define portPRIVILEGE_BIT 0x80000000UL
#define portIS_PRIVILEGED() vPortIsPrivileged()
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -0,0 +1,579 @@
/* syscall
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "FreeRTOS.h"
#include "syscall.h"
#include "task.h"
#include "queue.h"
#include "trap.h"
#include "timers.h"
#include "x86_64.h"
#include "freertos_serial.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#define MAX_SYSCALLS 128
/* Alse file syscall.asm these constants are also defined there */
#define SYSCALL_NUM_writec 0
#define SYSCALL_NUM_xTaskGetTickCount 1
#define SYSCALL_NUM_xTaskDelayUntil 2
#define SYSCALL_NUM_xQueueGenericSend 3
#define SYSCALL_NUM_xQueueReceive 4
#define SYSCALL_NUM_xTimerGenericCommandFromTask 5
#define SYSCALL_NUM_eTaskGetState 6
#define SYSCALL_NUM_pcQueueGetName 7
#define SYSCALL_NUM_pcTimerGetName 8
#define SYSCALL_NUM_pvTimerGetTimerID 9
#define SYSCALL_NUM_ulTaskGenericNotifyTake 10
#define SYSCALL_NUM_ulTaskGenericNotifyValueClear 11
#define SYSCALL_NUM_uxQueueMessagesWaiting 12
#define SYSCALL_NUM_uxQueueSpacesAvailable 13
#define SYSCALL_NUM_uxTaskGetNumberOfTasks 14
#define SYSCALL_NUM_uxTaskGetSystemState 15
#define SYSCALL_NUM_uxTaskPriorityGet 16
#define SYSCALL_NUM_uxTimerGetReloadMode 17
#define SYSCALL_NUM_vQueueAddToRegistry 18
#define SYSCALL_NUM_vQueueUnregisterQueue 19
#define SYSCALL_NUM_vTaskDelay 20
#define SYSCALL_NUM_vTaskGetInfo 21
#define SYSCALL_NUM_vTaskResume 22
#define SYSCALL_NUM_vTaskSetTimeOutState 23
#define SYSCALL_NUM_vTaskSuspend 24
#define SYSCALL_NUM_vTaskSuspendAll 25
#define SYSCALL_NUM_vTimerSetReloadMode 26
#define SYSCALL_NUM_vTimerSetTimerID 27
#define SYSCALL_NUM_xQueueAddToSet 28
#define SYSCALL_NUM_xQueueGiveMutexRecursive 29
#define SYSCALL_NUM_xQueuePeek 30
#define SYSCALL_NUM_xQueueRemoveFromSet 31
#define SYSCALL_NUM_xQueueSelectFromSet 32
#define SYSCALL_NUM_xQueueSemaphoreTake 33
#define SYSCALL_NUM_xQueueTakeMutexRecursive 34
#define SYSCALL_NUM_xTaskCheckForTimeOut 35
#define SYSCALL_NUM_xTaskGenericNotify 36
#define SYSCALL_NUM_xTaskGenericNotifyStateClear 37
#define SYSCALL_NUM_xTaskGenericNotifyWait 38
#define SYSCALL_NUM_xTaskGetCurrentTaskHandle 39
#define SYSCALL_NUM_xTaskGetSchedulerState 40
#define SYSCALL_NUM_xTimerGetExpiryTime 41
#define SYSCALL_NUM_xTimerGetPeriod 42
#define SYSCALL_NUM_xTimerGetTimerDaemonTaskHandle 43
#define SYSCALL_NUM_xTimerIsTimerActive 44
#define SYSCALL_NUM_xTaskAbortDelay 45
#define SYSCALL_NUM_xTaskGetHandle 46
#define SYSCALL_NUM_xEventGroupCreate 47
#define SYSCALL_NUM_xEventGroupWaitBits 48
#define SYSCALL_NUM_vEventGroupDelete 49
#define SYSCALL_NUM_xStreamBufferGenericCreate 50
#define SYSCALL_NUM_xStreamBufferReceive 51
#define SYSCALL_NUM_vStreamBufferDelete 52
#define SYSCALL_NUM_xQueueGetMutexHolder 53
#define SYSCALL_NUM_xEventGroupSync 54
#define SYSCALL_NUM_xEventGroupSetBits 55
#define SYSCALL_NUM_xEventGroupClearBits 56
#define SYSCALL_NUM_xStreamBufferSend 57
#define SYSCALL_NUM_xStreamBufferIsEmpty 58
#define SYSCALL_NUM_xStreamBufferNextMessageLengthBytes 59
#define SYSCALL_NUM_xStreamBufferIsFull 60
#define SYSCALL_NUM_xStreamBufferSpacesAvailable 61
#define SYSCALL_NUM_xStreamBufferReset 62
#define SYSCALL_NUM_xStreamBufferBytesAvailable 64
static SYSTEMCALL system_calls[MAX_SYSCALLS];
static uint64_t *getpgd() {
extern StackType_t *pxCurrentTCB;
xMPU_SETTINGS * xMPUSettings = (xMPU_SETTINGS *) (pxCurrentTCB+1);
return (uint64_t *) xMPUSettings->pgd;
}
/* Check that a user space address is mapped */
int check_address_valid(uint64_t target_address) {
uint64_t *pml4=getpgd();
uint64_t addr = target_address;
if (target_address < USER_VA_START) {
return 0;
}
uint32_t pml4_index=0;
uint32_t pml3_index=0;
uint32_t pml2_index=0;
uint32_t pml1_index=0;
uint64_t *pml3, *pml2,*pml1;
pml4_index = (addr >> 39) & 0x1ff;
pml3=(uint64_t *)(pml4[pml4_index]&0xfffffffff000);
if (!pml3){
return 0;
}
pml3_index = (addr >> 30) & 0x1ff;
pml2=(uint64_t *)(pml3[pml3_index]&0xfffffffff000);
if (!pml2){
return 0;
}
pml2_index = (addr >> 21) & 0x1ff;
pml1=(uint64_t *)(pml2[pml2_index]&0xfffffffff000);
if (!pml1){
return 0;
}
pml1_index = (addr >> 12) & 0x1ff;
uint64_t phyaddr = pml1[pml1_index]&0xfffffffff000;
if (!phyaddr){
return 0;
}
return 1;
}
#define CHECK_USER_PARAM(x) \
if (!check_address_valid(argptr[x])) \
return -1
uint64_t sys_writec(uint64_t *argptr)
{
serial_send((char) argptr[0]&0xff);
return (uint64_t) 0;
}
uint64_t sys_xTaskGetTickCount(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xTaskGetTickCount();
}
uint64_t sys_xTaskDelayUntil(uint64_t *argptr)
{
CHECK_USER_PARAM(0);
return (uint64_t) (BaseType_t) xTaskDelayUntil((TickType_t * const) argptr[0],( TickType_t) argptr[1]);
}
uint64_t sys_xQueueGenericSend(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
return (uint64_t) (BaseType_t) xQueueGenericSend((QueueHandle_t) argptr[0],( const void * const) argptr[1],(TickType_t) argptr[2],( BaseType_t) argptr[3]);
}
uint64_t sys_xQueueReceive(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
return (uint64_t) (BaseType_t) xQueueReceive((QueueHandle_t) argptr[0],(void * const) argptr[1],(TickType_t) argptr[2]);
}
uint64_t sys_xTimerGenericCommandFromTask(uint64_t *argptr)
{
CHECK_USER_PARAM(3);
return (uint64_t) (BaseType_t) xTimerGenericCommandFromTask((TimerHandle_t) argptr[0],(const BaseType_t) argptr[1],( const TickType_t) argptr[2],( BaseType_t * const) argptr[3],( const TickType_t) argptr[4]);
}
uint64_t sys_vTaskDelay(uint64_t *argptr)
{
vTaskDelay((TickType_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_uxTaskPriorityGet(uint64_t *argptr)
{
return (uint64_t) (UBaseType_t) uxTaskPriorityGet((const TaskHandle_t) argptr[0]);
}
uint64_t sys_vTaskPrioritySet(uint64_t *argptr)
{
vTaskPrioritySet((TaskHandle_t) argptr[0],( UBaseType_t) argptr[1]);
return (uint64_t) 0;
}
uint64_t sys_eTaskGetState(uint64_t *argptr)
{
return (uint64_t) (eTaskState) eTaskGetState((TaskHandle_t) argptr[0]);
}
uint64_t sys_vTaskGetInfo(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
vTaskGetInfo((TaskHandle_t) argptr[0],( TaskStatus_t * ) argptr[1],( BaseType_t) argptr[2],( eTaskState) argptr[3]);
return (uint64_t) 0;
}
uint64_t sys_vTaskSuspend(uint64_t *argptr)
{
vTaskSuspend((TaskHandle_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_vTaskResume(uint64_t *argptr)
{
vTaskResume((TaskHandle_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_vTaskSuspendAll(uint64_t *argptr)
{
vTaskSuspendAll();
return (uint64_t) 0;
}
uint64_t sys_uxTaskGetNumberOfTasks(uint64_t *argptr)
{
return (uint64_t) (UBaseType_t) uxTaskGetNumberOfTasks();
}
uint64_t sys_uxTaskGetSystemState(uint64_t *argptr)
{
CHECK_USER_PARAM(0);
CHECK_USER_PARAM(2);
return (uint64_t) (UBaseType_t) uxTaskGetSystemState((TaskStatus_t *) argptr[0],( UBaseType_t) argptr[1],( configRUN_TIME_COUNTER_TYPE *) argptr[2]);
}
uint64_t sys_xTaskGetCurrentTaskHandle(uint64_t *argptr)
{
return (uint64_t) (TaskHandle_t) xTaskGetCurrentTaskHandle();
}
uint64_t sys_xTaskGetSchedulerState(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xTaskGetSchedulerState();
}
uint64_t sys_vTaskSetTimeOutState(uint64_t *argptr)
{
CHECK_USER_PARAM(0);
vTaskSetTimeOutState((TimeOut_t * const) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_xTaskCheckForTimeOut(uint64_t *argptr)
{
CHECK_USER_PARAM(0);
CHECK_USER_PARAM(1);
return (uint64_t) (BaseType_t) xTaskCheckForTimeOut((TimeOut_t * const) argptr[0],( TickType_t * const) argptr[1]);
}
uint64_t sys_xTaskGenericNotify(uint64_t *argptr)
{
CHECK_USER_PARAM(4);
return (uint64_t) (BaseType_t) xTaskGenericNotify((TaskHandle_t) argptr[0],( UBaseType_t) argptr[1],( uint32_t) argptr[2],( eNotifyAction) argptr[3],( uint32_t *) argptr[4]);
}
uint64_t sys_xTaskGenericNotifyWait(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xTaskGenericNotifyWait((UBaseType_t) argptr[0],( uint32_t) argptr[1],( uint32_t) argptr[2],( uint32_t *) argptr[3],( TickType_t) argptr[4]);
}
uint64_t sys_ulTaskGenericNotifyTake(uint64_t *argptr)
{
return (uint64_t) (uint32_t) ulTaskGenericNotifyTake((UBaseType_t) argptr[0],( BaseType_t) argptr[1],( TickType_t) argptr[2]);
}
uint64_t sys_xTaskGenericNotifyStateClear(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xTaskGenericNotifyStateClear((TaskHandle_t) argptr[0],( UBaseType_t) argptr[1]);
}
uint64_t sys_ulTaskGenericNotifyValueClear(uint64_t *argptr)
{
return (uint64_t) (uint32_t) ulTaskGenericNotifyValueClear((TaskHandle_t) argptr[0],( UBaseType_t) argptr[1],( uint32_t) argptr[2]);
}
uint64_t sys_xQueueGenericReset(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xQueueGenericReset((QueueHandle_t) argptr[0],( BaseType_t) argptr[1]);
}
uint64_t sys_uxQueueMessagesWaiting(uint64_t *argptr)
{
return (uint64_t) (UBaseType_t) uxQueueMessagesWaiting((const QueueHandle_t) argptr[0]);
}
uint64_t sys_uxQueueSpacesAvailable(uint64_t *argptr)
{
return (uint64_t) (UBaseType_t) uxQueueSpacesAvailable((const QueueHandle_t) argptr[0]);
}
uint64_t sys_xQueuePeek(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
return (uint64_t) (BaseType_t) xQueuePeek((QueueHandle_t) argptr[0],( void * const) argptr[1],( TickType_t) argptr[2]);
}
uint64_t sys_xQueueSemaphoreTake(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xQueueSemaphoreTake((QueueHandle_t) argptr[0],( TickType_t) argptr[1]);
}
uint64_t sys_xQueueCreateMutex(uint64_t *argptr)
{
return (uint64_t) (QueueHandle_t) xQueueCreateMutex((const uint8_t) argptr[0]);
}
uint64_t sys_xQueueCreateCountingSemaphore(uint64_t *argptr)
{
return (uint64_t) (QueueHandle_t) xQueueCreateCountingSemaphore((UBaseType_t) argptr[0],( UBaseType_t) argptr[1]);
}
uint64_t sys_xQueueTakeMutexRecursive(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xQueueTakeMutexRecursive((QueueHandle_t) argptr[0],( TickType_t) argptr[1]);
}
uint64_t sys_xQueueGiveMutexRecursive(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xQueueGiveMutexRecursive((QueueHandle_t) argptr[0]);
}
uint64_t sys_xQueueCreateSet(uint64_t *argptr)
{
return (uint64_t) (QueueSetHandle_t) xQueueCreateSet((UBaseType_t) argptr[0]);
}
uint64_t sys_xQueueSelectFromSet(uint64_t *argptr)
{
return (uint64_t) (QueueSetMemberHandle_t) xQueueSelectFromSet((QueueSetHandle_t) argptr[0],( TickType_t) argptr[1]);
}
uint64_t sys_xQueueAddToSet(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xQueueAddToSet((QueueSetMemberHandle_t) argptr[0],( QueueSetHandle_t) argptr[1]);
}
uint64_t sys_xQueueRemoveFromSet(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xQueueRemoveFromSet((QueueSetMemberHandle_t) argptr[0],( QueueSetHandle_t) argptr[1]);
}
uint64_t sys_vQueueAddToRegistry(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
vQueueAddToRegistry((QueueHandle_t) argptr[0],( const char *) argptr[1]);
return (uint64_t) 0;
}
uint64_t sys_vQueueUnregisterQueue(uint64_t *argptr)
{
vQueueUnregisterQueue((QueueHandle_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_pcQueueGetName(uint64_t *argptr)
{
return (uint64_t) (const char *) pcQueueGetName((QueueHandle_t) argptr[0]);
}
uint64_t sys_vQueueDelete(uint64_t *argptr)
{
vQueueDelete((QueueHandle_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_pvTimerGetTimerID(uint64_t *argptr)
{
return (uint64_t) (void *) pvTimerGetTimerID((const TimerHandle_t) argptr[0]);
}
uint64_t sys_vTimerSetTimerID(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
vTimerSetTimerID((TimerHandle_t) argptr[0],( void *) argptr[1]);
return (uint64_t) 0;
}
uint64_t sys_xTimerIsTimerActive(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xTimerIsTimerActive((TimerHandle_t) argptr[0]);
}
uint64_t sys_xTimerGetTimerDaemonTaskHandle(uint64_t *argptr)
{
return (uint64_t) (TaskHandle_t) xTimerGetTimerDaemonTaskHandle();
}
uint64_t sys_vTimerSetReloadMode(uint64_t *argptr)
{
vTimerSetReloadMode((TimerHandle_t) argptr[0],( const BaseType_t) argptr[1]);
return (uint64_t) 0;
}
uint64_t sys_uxTimerGetReloadMode(uint64_t *argptr)
{
return (uint64_t) (UBaseType_t) uxTimerGetReloadMode((TimerHandle_t) argptr[0]);
}
uint64_t sys_pcTimerGetName(uint64_t *argptr)
{
// Return a pointer.
return (uint64_t) (const char *) pcTimerGetName((TimerHandle_t) argptr[0]);
}
uint64_t sys_xTimerGetPeriod(uint64_t *argptr)
{
return (uint64_t) (TickType_t) xTimerGetPeriod((TimerHandle_t) argptr[0]);
}
uint64_t sys_xTimerGetExpiryTime(uint64_t *argptr)
{
return (uint64_t) (TickType_t) xTimerGetExpiryTime((TimerHandle_t) argptr[0]);
}
uint64_t sys_xTaskAbortDelay(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xTaskAbortDelay((TaskHandle_t) argptr[0]);
}
uint64_t sys_xTaskGetHandle(uint64_t *argptr)
{
return (uint64_t) (TaskHandle_t) xTaskGetHandle((const char *) argptr[0]);
}
uint64_t sys_xEventGroupCreate(uint64_t *argptr)
{
return (uint64_t) (EventGroupHandle_t) xEventGroupCreate();
}
uint64_t sys_xEventGroupWaitBits(uint64_t *argptr)
{
return (uint64_t) (EventBits_t) xEventGroupWaitBits((EventGroupHandle_t) argptr[0], (const EventBits_t) argptr[1], (const BaseType_t) argptr[2], (const BaseType_t)argptr[3], (TickType_t)argptr[4]);
}
uint64_t sys_vEventGroupDelete(uint64_t *argptr)
{
CHECK_USER_PARAM(0);
vEventGroupDelete((EventGroupHandle_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_xStreamBufferGenericCreate(uint64_t *argptr)
{
return (uint64_t) (StreamBufferHandle_t) xStreamBufferGenericCreate((size_t) argptr[0], (size_t) argptr[1], (BaseType_t) argptr[2], (StreamBufferCallbackFunction_t )argptr[3], (StreamBufferCallbackFunction_t)argptr[4]);
}
uint64_t sys_xStreamBufferReceive(uint64_t *argptr)
{
return (uint64_t) (size_t) xStreamBufferReceive((StreamBufferHandle_t) argptr[0], (void *) argptr[1], (size_t) argptr[2], (TickType_t)argptr[3]);
}
uint64_t sys_vStreamBufferDelete(uint64_t *argptr)
{
CHECK_USER_PARAM(0);
vStreamBufferDelete((StreamBufferHandle_t) argptr[0]);
return (uint64_t) 0;
}
uint64_t sys_xQueueGetMutexHolder(uint64_t *argptr)
{
CHECK_USER_PARAM(1);
return (uint64_t) (TaskHandle_t) xQueueGetMutexHolder((QueueHandle_t) argptr[0]);
}
uint64_t sys_xEventGroupSync(uint64_t *argptr)
{
return (uint64_t) (EventBits_t) xEventGroupSync((EventGroupHandle_t) argptr[0], (const EventBits_t) argptr[1], (const EventBits_t ) argptr[2], (TickType_t )argptr[3]);
}
uint64_t sys_xEventGroupSetBits(uint64_t *argptr)
{
return (uint64_t) ( EventBits_t) xEventGroupSetBits((EventGroupHandle_t) argptr[0], (const EventBits_t) argptr[1]);
}
uint64_t sys_xEventGroupClearBits(uint64_t *argptr)
{
return (uint64_t) ( EventBits_t) xEventGroupClearBits((EventGroupHandle_t) argptr[0], (const EventBits_t) argptr[1]);
}
uint64_t sys_xStreamBufferSend(uint64_t *argptr)
{
return (uint64_t) (size_t) xStreamBufferSend((StreamBufferHandle_t) argptr[0], (const void *) argptr[1], (size_t) argptr[2], (TickType_t)argptr[3]);
}
uint64_t sys_xStreamBufferIsEmpty(uint64_t *argptr)
{
return (uint64_t) ( size_t ) xStreamBufferIsEmpty((StreamBufferHandle_t) argptr[0]);
}
uint64_t sys_xStreamBufferNextMessageLengthBytes(uint64_t *argptr)
{
return (uint64_t) ( size_t ) xStreamBufferNextMessageLengthBytes((StreamBufferHandle_t) argptr[0]);
}
uint64_t sys_xStreamBufferIsFull(uint64_t *argptr)
{
return (uint64_t) (BaseType_t) xStreamBufferIsFull((StreamBufferHandle_t) argptr[0]);
}
uint64_t sys_xStreamBufferSpacesAvailable(uint64_t *argptr)
{
return (uint64_t) (size_t) xStreamBufferSpacesAvailable((StreamBufferHandle_t) argptr[0]);
}
uint64_t sys_xStreamBufferReset(uint64_t *argptr)
{
return (uint64_t) (size_t) xStreamBufferReset((StreamBufferHandle_t) argptr[0]);
}
uint64_t sys_xStreamBufferBytesAvailable(uint64_t *argptr)
{
return (uint64_t) (size_t) xStreamBufferBytesAvailable((StreamBufferHandle_t) argptr[0]);
}
extern StackType_t *pxCurrentTCB;
void vInitSystemCall(void)
{
int i=0;
for (i=0;i<MAX_SYSCALLS;i++) {
system_calls[i] = NULL;
}
system_calls[SYSCALL_NUM_writec] = sys_writec;
system_calls[SYSCALL_NUM_xTaskGetTickCount] = sys_xTaskGetTickCount;
system_calls[SYSCALL_NUM_xTaskDelayUntil] = sys_xTaskDelayUntil;
system_calls[SYSCALL_NUM_xQueueGenericSend] = sys_xQueueGenericSend;
system_calls[SYSCALL_NUM_xQueueReceive] = sys_xQueueReceive;
system_calls[SYSCALL_NUM_xTimerGenericCommandFromTask] = sys_xTimerGenericCommandFromTask;
system_calls[SYSCALL_NUM_eTaskGetState]=sys_eTaskGetState;
system_calls[SYSCALL_NUM_pcQueueGetName]=sys_pcQueueGetName;
system_calls[SYSCALL_NUM_pcTimerGetName]=sys_pcTimerGetName;
system_calls[SYSCALL_NUM_pvTimerGetTimerID]=sys_pvTimerGetTimerID;
system_calls[SYSCALL_NUM_ulTaskGenericNotifyTake]=sys_ulTaskGenericNotifyTake;
system_calls[SYSCALL_NUM_ulTaskGenericNotifyValueClear]=sys_ulTaskGenericNotifyValueClear;
system_calls[SYSCALL_NUM_uxQueueMessagesWaiting]=sys_uxQueueMessagesWaiting;
system_calls[SYSCALL_NUM_uxQueueSpacesAvailable]=sys_uxQueueSpacesAvailable;
system_calls[SYSCALL_NUM_uxTaskGetNumberOfTasks]=sys_uxTaskGetNumberOfTasks;
system_calls[SYSCALL_NUM_uxTaskGetSystemState]=sys_uxTaskGetSystemState;
system_calls[SYSCALL_NUM_uxTaskPriorityGet]=sys_uxTaskPriorityGet;
system_calls[SYSCALL_NUM_uxTimerGetReloadMode]=sys_uxTimerGetReloadMode;
system_calls[SYSCALL_NUM_vQueueAddToRegistry]=sys_vQueueAddToRegistry;
system_calls[SYSCALL_NUM_vQueueUnregisterQueue]=sys_vQueueUnregisterQueue;
system_calls[SYSCALL_NUM_vTaskDelay]=sys_vTaskDelay;
system_calls[SYSCALL_NUM_vTaskGetInfo]=sys_vTaskGetInfo;
system_calls[SYSCALL_NUM_vTaskResume]=sys_vTaskResume;
system_calls[SYSCALL_NUM_vTaskSetTimeOutState]=sys_vTaskSetTimeOutState;
system_calls[SYSCALL_NUM_vTaskSuspend]=sys_vTaskSuspend;
system_calls[SYSCALL_NUM_vTaskSuspendAll]=sys_vTaskSuspendAll;
system_calls[SYSCALL_NUM_vTimerSetReloadMode]=sys_vTimerSetReloadMode;
system_calls[SYSCALL_NUM_vTimerSetTimerID]=sys_vTimerSetTimerID;
system_calls[SYSCALL_NUM_xQueueAddToSet]=sys_xQueueAddToSet;
system_calls[SYSCALL_NUM_xQueueGiveMutexRecursive]=sys_xQueueGiveMutexRecursive;
system_calls[SYSCALL_NUM_xQueuePeek]=sys_xQueuePeek;
system_calls[SYSCALL_NUM_xQueueRemoveFromSet]=sys_xQueueRemoveFromSet;
system_calls[SYSCALL_NUM_xQueueSelectFromSet]=sys_xQueueSelectFromSet;
system_calls[SYSCALL_NUM_xQueueSemaphoreTake]=sys_xQueueSemaphoreTake;
system_calls[SYSCALL_NUM_xQueueTakeMutexRecursive]=sys_xQueueTakeMutexRecursive;
system_calls[SYSCALL_NUM_xTaskCheckForTimeOut]=sys_xTaskCheckForTimeOut;
system_calls[SYSCALL_NUM_xTaskGenericNotify]=sys_xTaskGenericNotify;
system_calls[SYSCALL_NUM_xTaskGenericNotifyStateClear]=sys_xTaskGenericNotifyStateClear;
system_calls[SYSCALL_NUM_xTaskGenericNotifyWait]=sys_xTaskGenericNotifyWait;
system_calls[SYSCALL_NUM_xTaskGetCurrentTaskHandle]=sys_xTaskGetCurrentTaskHandle;
system_calls[SYSCALL_NUM_xTaskGetSchedulerState]=sys_xTaskGetSchedulerState;
system_calls[SYSCALL_NUM_xTimerGetExpiryTime]=sys_xTimerGetExpiryTime;
system_calls[SYSCALL_NUM_xTimerGetPeriod]=sys_xTimerGetPeriod;
system_calls[SYSCALL_NUM_xTimerGetTimerDaemonTaskHandle]=sys_xTimerGetTimerDaemonTaskHandle;
system_calls[SYSCALL_NUM_xTimerIsTimerActive]=sys_xTimerIsTimerActive;
system_calls[SYSCALL_NUM_xTaskAbortDelay]=sys_xTaskAbortDelay;
system_calls[SYSCALL_NUM_xTaskGetHandle]=sys_xTaskGetHandle;
system_calls[SYSCALL_NUM_xEventGroupCreate]=sys_xEventGroupCreate;
system_calls[SYSCALL_NUM_xEventGroupWaitBits]=sys_xEventGroupWaitBits;
system_calls[SYSCALL_NUM_vEventGroupDelete]=sys_vEventGroupDelete;
system_calls[SYSCALL_NUM_xStreamBufferGenericCreate]=sys_xStreamBufferGenericCreate;
system_calls[SYSCALL_NUM_xStreamBufferReceive]=sys_xStreamBufferReceive;
system_calls[SYSCALL_NUM_vStreamBufferDelete]=sys_vStreamBufferDelete;
system_calls[SYSCALL_NUM_xQueueGetMutexHolder]=sys_xQueueGetMutexHolder;
system_calls[SYSCALL_NUM_xEventGroupSync]=sys_xEventGroupSync;
system_calls[SYSCALL_NUM_xEventGroupSetBits]=sys_xEventGroupSetBits;
system_calls[SYSCALL_NUM_xEventGroupClearBits]=sys_xEventGroupClearBits;
system_calls[SYSCALL_NUM_xStreamBufferSend]=sys_xStreamBufferSend;
system_calls[SYSCALL_NUM_xStreamBufferIsEmpty]=sys_xStreamBufferIsEmpty;
system_calls[SYSCALL_NUM_xStreamBufferNextMessageLengthBytes]=sys_xStreamBufferNextMessageLengthBytes;
system_calls[SYSCALL_NUM_xStreamBufferIsFull]=sys_xStreamBufferIsFull;
system_calls[SYSCALL_NUM_xStreamBufferSpacesAvailable]=sys_xStreamBufferSpacesAvailable;
system_calls[SYSCALL_NUM_xStreamBufferReset]=sys_xStreamBufferReset;
system_calls[SYSCALL_NUM_xStreamBufferBytesAvailable]=sys_xStreamBufferBytesAvailable;
}
void vSystemCall(struct TrapFrame *tf)
{
int64_t i = tf->rax;
int64_t param_count = tf->rdi;
int64_t *argptr = (int64_t*)tf->rsi;
if (param_count < 0 || i >= MAX_SYSCALLS || i < 0) {
tf->rax = -1;
return;
}
if (system_calls[i]){
tf->rax = system_calls[i](argptr);
}
else{
tf->rax = -1;
}
}

View file

@ -0,0 +1,183 @@
/* syscall
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#ifndef _SYSCALL_H_
#define _SYSCALL_H_
#include "FreeRTOS.h"
#include "event_groups.h"
#include "stream_buffer.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
void syscall_writec(char val);
BaseType_t syscall_xTaskGetTickCount(void);
BaseType_t syscall_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
TickType_t xTimeIncrement);
BaseType_t syscall_xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
BaseType_t xCopyPosition );
BaseType_t syscall_xQueueReceive( QueueHandle_t pxQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
BaseType_t syscall_xTimerGenericCommandFromTask( TimerHandle_t xTimer,
const BaseType_t xCommandID,
const TickType_t xOptionalValue,
BaseType_t * const pxHigherPriorityTaskWoken,
const TickType_t xTicksToWait );
QueueHandle_t syscall_xQueueGenericCreate( UBaseType_t uxQueueLength,
UBaseType_t uxItemSize,
uint8_t ucQueueType );
BaseType_t syscall_xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE uxStackDepth,
void * pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * pxCreatedTask );
void syscall_vTaskDelete( TaskHandle_t pxTaskToDelete );
void syscall_vTaskDelay( TickType_t xTicksToDelay );
UBaseType_t syscall_uxTaskPriorityGet( const TaskHandle_t pxTask );
void syscall_vTaskPrioritySet( TaskHandle_t pxTask,
UBaseType_t uxNewPriority );
eTaskState syscall_eTaskGetState( TaskHandle_t pxTask );
void syscall_vTaskGetInfo( TaskHandle_t xTask,
TaskStatus_t * pxTaskStatus,
BaseType_t xGetFreeStackSpace,
eTaskState eState );
void syscall_vTaskSuspend( TaskHandle_t pxTaskToSuspend );
void syscall_vTaskResume( TaskHandle_t pxTaskToResume );
UBaseType_t syscall_uxTaskGetNumberOfTasks( void );
UBaseType_t syscall_uxTaskGetSystemState( TaskStatus_t * pxTaskStatusArray,
UBaseType_t uxArraySize,
configRUN_TIME_COUNTER_TYPE * pulTotalRunTime );
TaskHandle_t syscall_xTaskGetCurrentTaskHandle( void );
BaseType_t syscall_xTaskGetSchedulerState( void );
void syscall_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );
BaseType_t syscall_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait );
BaseType_t syscall_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue );
BaseType_t syscall_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait );
uint32_t syscall_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
BaseType_t xClearCountOnExit,
TickType_t xTicksToWait );
BaseType_t syscall_xTaskGenericNotifyStateClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear );
uint32_t syscall_ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear,
uint32_t ulBitsToClear );
BaseType_t syscall_xQueueGenericReset( QueueHandle_t pxQueue,
BaseType_t xNewQueue );
UBaseType_t syscall_uxQueueMessagesWaiting( const QueueHandle_t pxQueue );
UBaseType_t syscall_uxQueueSpacesAvailable( const QueueHandle_t xQueue );
BaseType_t syscall_xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
BaseType_t syscall_xQueueSemaphoreTake( QueueHandle_t xQueue,
TickType_t xTicksToWait );
QueueHandle_t syscall_xQueueCreateMutex( const uint8_t ucQueueType );
QueueHandle_t syscall_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue,
UBaseType_t uxInitialCount );
BaseType_t syscall_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
TickType_t xBlockTime );
BaseType_t syscall_xQueueGiveMutexRecursive( QueueHandle_t xMutex );
QueueSetHandle_t syscall_xQueueCreateSet( UBaseType_t uxEventQueueLength );
QueueSetMemberHandle_t syscall_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
TickType_t xBlockTimeTicks );
BaseType_t syscall_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet );
BaseType_t syscall_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet );
void syscall_vQueueAddToRegistry( QueueHandle_t xQueue,
const char * pcName );
void syscall_vQueueUnregisterQueue( QueueHandle_t xQueue );
const char * syscall_pcQueueGetName( QueueHandle_t xQueue );
void syscall_vQueueDelete( QueueHandle_t xQueue );
void * syscall_pvTimerGetTimerID( const TimerHandle_t xTimer );
void syscall_vTimerSetTimerID( TimerHandle_t xTimer,
void * pvNewID );
BaseType_t syscall_xTimerIsTimerActive( TimerHandle_t xTimer );
TaskHandle_t syscall_xTimerGetTimerDaemonTaskHandle( void );
void syscall_vTimerSetReloadMode( TimerHandle_t xTimer,
const BaseType_t uxAutoReload );
UBaseType_t syscall_uxTimerGetReloadMode( TimerHandle_t xTimer );
const char * syscall_pcTimerGetName( TimerHandle_t xTimer );
TickType_t syscall_xTimerGetPeriod( TimerHandle_t xTimer );
TickType_t syscall_xTimerGetExpiryTime( TimerHandle_t xTimer );
void syscall_vTaskListTasks( char * pcWriteBuffer,
size_t uxBufferLength );
void syscall_vTaskSuspendAll( void );
BaseType_t syscall_xTaskResumeAll( void );
BaseType_t syscall_xTaskAbortDelay( TaskHandle_t xTask );TaskHandle_t syscall_xTaskGetHandle( const char * pcNameToQuery );
TaskHandle_t syscall_xTaskGetHandle( const char * pcNameToQuery );
EventGroupHandle_t syscall_xEventGroupCreate( void ); /* FREERTOS_SYSTEM_CALL */
EventBits_t syscall_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait ); /* FREERTOS_SYSTEM_CALL */
void syscall_vEventGroupDelete( EventGroupHandle_t xEventGroup ); /* FREERTOS_SYSTEM_CALL */
StreamBufferHandle_t syscall_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xStreamBufferType,
StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ); /* FREERTOS_SYSTEM_CALL */
size_t syscall_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
void * pvRxData,
size_t xBufferLengthBytes,
TickType_t xTicksToWait ); /* FREERTOS_SYSTEM_CALL */
void syscall_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
TaskHandle_t syscall_xQueueGetMutexHolder( QueueHandle_t xSemaphore ); /* FREERTOS_SYSTEM_CALL */
EventBits_t syscall_xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait ); /* FREERTOS_SYSTEM_CALL */
EventBits_t syscall_xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet ); /* FREERTOS_SYSTEM_CALL */
EventBits_t syscall_xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ); /* FREERTOS_SYSTEM_CALL */
size_t syscall_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void * pvTxData,
size_t xDataLengthBytes,
TickType_t xTicksToWait ); /* FREERTOS_SYSTEM_CALL */
BaseType_t syscall_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
size_t syscall_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
BaseType_t syscall_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
size_t syscall_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
BaseType_t syscall_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
size_t syscall_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ); /* FREERTOS_SYSTEM_CALL */
#endif

View file

@ -0,0 +1,439 @@
/* trap
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "trap.h"
#include "io.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "IRQ.h"
#include "ioapic.h"
#include "stdio.h"
#include "hypervisor.h"
#include "time.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
void vSystemCall(struct TrapFrame *tf);
void vInitSystemCall(void);
void process_sci(void);
void vFreeAllPages(uint64_t *p);
static struct IdtPtr idt_pointer;
static struct IdtEntry vectors[256];
extern uint64_t pml4;
/* pxCurrentTCB saved by FreeRTOS Kernel */
extern StackType_t *pxCurrentTCB;
/* Tss defined in assembly files */
extern struct TSS Tss;
extern uint32_t ulPortYieldPending;
extern uint32_t ulInterruptNesting;
extern uint32_t xTaskUsesFPU;
extern uint8_t *pucPortTaskFPUContextBuffer;
static void vInstallHandler(struct IdtEntry *entry, uint64_t addr, uint8_t attribute)
{
entry->low = (uint16_t)addr;
entry->selector = 8;
entry->attr = attribute;
entry->mid = (uint16_t)(addr>>16);
entry->high = (uint32_t)(addr>>32);
}
void vIDTInit(void)
{
vInitSystemCall();
vInstallHandler(&vectors[0],(uint64_t)vector0,0x8eUL);
vInstallHandler(&vectors[1],(uint64_t)vector1,0x8eUL);
vInstallHandler(&vectors[2],(uint64_t)vector2,0x8eUL);
vInstallHandler(&vectors[3],(uint64_t)vector3,0x8eUL);
vInstallHandler(&vectors[4],(uint64_t)vector4,0x8eUL);
vInstallHandler(&vectors[5],(uint64_t)vector5,0x8eUL);
vInstallHandler(&vectors[6],(uint64_t)vector6,0x8eUL);
vInstallHandler(&vectors[7],(uint64_t)vector7,0x8eUL);
vInstallHandler(&vectors[8],(uint64_t)vector8,0x8eUL);
vInstallHandler(&vectors[10],(uint64_t)vector10,0x8eUL);
vInstallHandler(&vectors[11],(uint64_t)vector11,0x8eUL);
vInstallHandler(&vectors[12],(uint64_t)vector12,0x8eUL);
vInstallHandler(&vectors[13],(uint64_t)vector13,0x8eUL);
vInstallHandler(&vectors[14],(uint64_t)vector14,0x8eUL);
vInstallHandler(&vectors[16],(uint64_t)vector16,0x8eUL);
vInstallHandler(&vectors[17],(uint64_t)vector17,0x8eUL);
vInstallHandler(&vectors[18],(uint64_t)vector18,0x8eUL);
vInstallHandler(&vectors[19],(uint64_t)vector19,0x8eUL);
vInstallHandler(&vectors[32],(uint64_t)vector32,0x8eUL);
vInstallHandler(&vectors[33],(uint64_t)vector33,0x8eUL);
vInstallHandler(&vectors[34],(uint64_t)vector34,0x8eUL);
vInstallHandler(&vectors[35],(uint64_t)vector35,0x8eUL);
vInstallHandler(&vectors[36],(uint64_t)vector36,0x8eUL);
vInstallHandler(&vectors[37],(uint64_t)vector37,0x8eUL);
vInstallHandler(&vectors[38],(uint64_t)vector38,0x8eUL);
vInstallHandler(&vectors[39],(uint64_t)vector39,0x8eUL);
vInstallHandler(&vectors[40],(uint64_t)vector40,0x8eUL);
vInstallHandler(&vectors[41],(uint64_t)vector41,0x8eUL);
vInstallHandler(&vectors[42],(uint64_t)vector42,0x8eUL);
vInstallHandler(&vectors[43],(uint64_t)vector43,0x8eUL);
vInstallHandler(&vectors[44],(uint64_t)vector44,0x8eUL);
vInstallHandler(&vectors[45],(uint64_t)vector45,0x8eUL);
vInstallHandler(&vectors[46],(uint64_t)vector46,0x8eUL);
vInstallHandler(&vectors[47],(uint64_t)vector47,0x8eUL);
vInstallHandler(&vectors[48],(uint64_t)vector48,0x8eUL);
vInstallHandler(&vectors[49],(uint64_t)vector49,0x8eUL);
vInstallHandler(&vectors[50],(uint64_t)vector50,0x8eUL);
vInstallHandler(&vectors[51],(uint64_t)vector51,0x8eUL);
vInstallHandler(&vectors[52],(uint64_t)vector52,0x8eUL);
vInstallHandler(&vectors[53],(uint64_t)vector53,0x8eUL);
vInstallHandler(&vectors[54],(uint64_t)vector54,0x8eUL);
vInstallHandler(&vectors[55],(uint64_t)vector55,0x8eUL);
vInstallHandler(&vectors[56],(uint64_t)vector56,0x8eUL);
vInstallHandler(&vectors[57],(uint64_t)vector57,0x8eUL);
vInstallHandler(&vectors[58],(uint64_t)vector58,0x8eUL);
vInstallHandler(&vectors[59],(uint64_t)vector59,0x8eUL);
vInstallHandler(&vectors[60],(uint64_t)vector60,0x8eUL);
vInstallHandler(&vectors[61],(uint64_t)vector61,0x8eUL);
vInstallHandler(&vectors[62],(uint64_t)vector62,0x8eUL);
vInstallHandler(&vectors[63],(uint64_t)vector63,0x8eUL);
vInstallHandler(&vectors[64],(uint64_t)vector64,0x8eUL);
vInstallHandler(&vectors[65],(uint64_t)vector65,0x8eUL);
vInstallHandler(&vectors[66],(uint64_t)vector66,0x8eUL);
vInstallHandler(&vectors[67],(uint64_t)vector67,0x8eUL);
vInstallHandler(&vectors[68],(uint64_t)vector68,0x8eUL);
vInstallHandler(&vectors[69],(uint64_t)vector69,0x8eUL);
vInstallHandler(&vectors[70],(uint64_t)vector70,0x8eUL);
vInstallHandler(&vectors[71],(uint64_t)vector71,0x8eUL);
vInstallHandler(&vectors[72],(uint64_t)vector72,0x8eUL);
vInstallHandler(&vectors[73],(uint64_t)vector73,0x8eUL);
vInstallHandler(&vectors[74],(uint64_t)vector74,0x8eUL);
vInstallHandler(&vectors[75],(uint64_t)vector75,0x8eUL);
vInstallHandler(&vectors[76],(uint64_t)vector76,0x8eUL);
vInstallHandler(&vectors[77],(uint64_t)vector77,0x8eUL);
vInstallHandler(&vectors[78],(uint64_t)vector78,0x8eUL);
vInstallHandler(&vectors[79],(uint64_t)vector79,0x8eUL);
vInstallHandler(&vectors[80],(uint64_t)vector80,0x8eUL);
vInstallHandler(&vectors[81],(uint64_t)vector81,0x8eUL);
vInstallHandler(&vectors[82],(uint64_t)vector82,0x8eUL);
vInstallHandler(&vectors[83],(uint64_t)vector83,0x8eUL);
vInstallHandler(&vectors[84],(uint64_t)vector84,0x8eUL);
vInstallHandler(&vectors[85],(uint64_t)vector85,0x8eUL);
vInstallHandler(&vectors[86],(uint64_t)vector86,0x8eUL);
vInstallHandler(&vectors[87],(uint64_t)vector87,0x8eUL);
vInstallHandler(&vectors[88],(uint64_t)vector88,0x8eUL);
vInstallHandler(&vectors[89],(uint64_t)vector89,0x8eUL);
vInstallHandler(&vectors[90],(uint64_t)vector90,0x8eUL);
vInstallHandler(&vectors[91],(uint64_t)vector91,0x8eUL);
vInstallHandler(&vectors[92],(uint64_t)vector92,0x8eUL);
vInstallHandler(&vectors[93],(uint64_t)vector93,0x8eUL);
vInstallHandler(&vectors[94],(uint64_t)vector94,0x8eUL);
vInstallHandler(&vectors[95],(uint64_t)vector95,0x8eUL);
vInstallHandler(&vectors[96],(uint64_t)vector96,0x8eUL);
vInstallHandler(&vectors[97],(uint64_t)vector97,0x8eUL);
vInstallHandler(&vectors[98],(uint64_t)vector98,0x8eUL);
vInstallHandler(&vectors[99],(uint64_t)vector99,0x8eUL);
vInstallHandler(&vectors[100],(uint64_t)vector100,0x8eUL);
vInstallHandler(&vectors[101],(uint64_t)vector101,0x8eUL);
vInstallHandler(&vectors[102],(uint64_t)vector102,0x8eUL);
vInstallHandler(&vectors[103],(uint64_t)vector103,0x8eUL);
vInstallHandler(&vectors[104],(uint64_t)vector104,0x8eUL);
vInstallHandler(&vectors[105],(uint64_t)vector105,0x8eUL);
vInstallHandler(&vectors[106],(uint64_t)vector106,0x8eUL);
vInstallHandler(&vectors[107],(uint64_t)vector107,0x8eUL);
vInstallHandler(&vectors[108],(uint64_t)vector108,0x8eUL);
vInstallHandler(&vectors[109],(uint64_t)vector109,0x8eUL);
vInstallHandler(&vectors[110],(uint64_t)vector110,0x8eUL);
vInstallHandler(&vectors[111],(uint64_t)vector111,0x8eUL);
vInstallHandler(&vectors[112],(uint64_t)vector112,0x8eUL);
vInstallHandler(&vectors[113],(uint64_t)vector113,0x8eUL);
vInstallHandler(&vectors[114],(uint64_t)vector114,0x8eUL);
vInstallHandler(&vectors[115],(uint64_t)vector115,0x8eUL);
vInstallHandler(&vectors[116],(uint64_t)vector116,0x8eUL);
vInstallHandler(&vectors[117],(uint64_t)vector117,0x8eUL);
vInstallHandler(&vectors[118],(uint64_t)vector118,0x8eUL);
vInstallHandler(&vectors[119],(uint64_t)vector119,0x8eUL);
vInstallHandler(&vectors[120],(uint64_t)vector120,0x8eUL);
vInstallHandler(&vectors[121],(uint64_t)vector121,0x8eUL);
vInstallHandler(&vectors[122],(uint64_t)vector122,0x8eUL);
vInstallHandler(&vectors[123],(uint64_t)vector123,0x8eUL);
vInstallHandler(&vectors[124],(uint64_t)vector124,0x8eUL);
vInstallHandler(&vectors[125],(uint64_t)vector125,0x8eUL);
vInstallHandler(&vectors[126],(uint64_t)vector126,0x8eUL);
vInstallHandler(&vectors[127],(uint64_t)vector127,0x8eUL);
vInstallHandler(&vectors[129],(uint64_t)vector129,0x8eUL);
vInstallHandler(&vectors[130],(uint64_t)vector130,0x8eUL);
vInstallHandler(&vectors[131],(uint64_t)vector131,0x8eUL);
vInstallHandler(&vectors[132],(uint64_t)vector132,0x8eUL);
vInstallHandler(&vectors[133],(uint64_t)vector133,0x8eUL);
vInstallHandler(&vectors[134],(uint64_t)vector134,0x8eUL);
vInstallHandler(&vectors[135],(uint64_t)vector135,0x8eUL);
vInstallHandler(&vectors[136],(uint64_t)vector136,0x8eUL);
vInstallHandler(&vectors[137],(uint64_t)vector137,0x8eUL);
vInstallHandler(&vectors[138],(uint64_t)vector138,0x8eUL);
vInstallHandler(&vectors[139],(uint64_t)vector139,0x8eUL);
vInstallHandler(&vectors[140],(uint64_t)vector140,0x8eUL);
vInstallHandler(&vectors[141],(uint64_t)vector141,0x8eUL);
vInstallHandler(&vectors[142],(uint64_t)vector142,0x8eUL);
vInstallHandler(&vectors[143],(uint64_t)vector143,0x8eUL);
vInstallHandler(&vectors[144],(uint64_t)vector144,0x8eUL);
vInstallHandler(&vectors[145],(uint64_t)vector145,0x8eUL);
vInstallHandler(&vectors[146],(uint64_t)vector146,0x8eUL);
vInstallHandler(&vectors[147],(uint64_t)vector147,0x8eUL);
vInstallHandler(&vectors[148],(uint64_t)vector148,0x8eUL);
vInstallHandler(&vectors[149],(uint64_t)vector149,0x8eUL);
vInstallHandler(&vectors[150],(uint64_t)vector150,0x8eUL);
vInstallHandler(&vectors[151],(uint64_t)vector151,0x8eUL);
vInstallHandler(&vectors[152],(uint64_t)vector152,0x8eUL);
vInstallHandler(&vectors[153],(uint64_t)vector153,0x8eUL);
vInstallHandler(&vectors[154],(uint64_t)vector154,0x8eUL);
vInstallHandler(&vectors[155],(uint64_t)vector155,0x8eUL);
vInstallHandler(&vectors[156],(uint64_t)vector156,0x8eUL);
vInstallHandler(&vectors[157],(uint64_t)vector157,0x8eUL);
vInstallHandler(&vectors[158],(uint64_t)vector158,0x8eUL);
vInstallHandler(&vectors[159],(uint64_t)vector159,0x8eUL);
vInstallHandler(&vectors[160],(uint64_t)vector160,0x8eUL);
vInstallHandler(&vectors[161],(uint64_t)vector161,0x8eUL);
vInstallHandler(&vectors[162],(uint64_t)vector162,0x8eUL);
vInstallHandler(&vectors[163],(uint64_t)vector163,0x8eUL);
vInstallHandler(&vectors[164],(uint64_t)vector164,0x8eUL);
vInstallHandler(&vectors[165],(uint64_t)vector165,0x8eUL);
vInstallHandler(&vectors[166],(uint64_t)vector166,0x8eUL);
vInstallHandler(&vectors[167],(uint64_t)vector167,0x8eUL);
vInstallHandler(&vectors[168],(uint64_t)vector168,0x8eUL);
vInstallHandler(&vectors[169],(uint64_t)vector169,0x8eUL);
vInstallHandler(&vectors[170],(uint64_t)vector170,0x8eUL);
vInstallHandler(&vectors[171],(uint64_t)vector171,0x8eUL);
vInstallHandler(&vectors[172],(uint64_t)vector172,0x8eUL);
vInstallHandler(&vectors[173],(uint64_t)vector173,0x8eUL);
vInstallHandler(&vectors[174],(uint64_t)vector174,0x8eUL);
vInstallHandler(&vectors[175],(uint64_t)vector175,0x8eUL);
vInstallHandler(&vectors[176],(uint64_t)vector176,0x8eUL);
vInstallHandler(&vectors[177],(uint64_t)vector177,0x8eUL);
vInstallHandler(&vectors[178],(uint64_t)vector178,0x8eUL);
vInstallHandler(&vectors[179],(uint64_t)vector179,0x8eUL);
vInstallHandler(&vectors[180],(uint64_t)vector180,0x8eUL);
vInstallHandler(&vectors[181],(uint64_t)vector181,0x8eUL);
vInstallHandler(&vectors[182],(uint64_t)vector182,0x8eUL);
vInstallHandler(&vectors[183],(uint64_t)vector183,0x8eUL);
vInstallHandler(&vectors[184],(uint64_t)vector184,0x8eUL);
vInstallHandler(&vectors[185],(uint64_t)vector185,0x8eUL);
vInstallHandler(&vectors[186],(uint64_t)vector186,0x8eUL);
vInstallHandler(&vectors[187],(uint64_t)vector187,0x8eUL);
vInstallHandler(&vectors[188],(uint64_t)vector188,0x8eUL);
vInstallHandler(&vectors[189],(uint64_t)vector189,0x8eUL);
vInstallHandler(&vectors[190],(uint64_t)vector190,0x8eUL);
vInstallHandler(&vectors[191],(uint64_t)vector191,0x8eUL);
vInstallHandler(&vectors[192],(uint64_t)vector192,0x8eUL);
vInstallHandler(&vectors[193],(uint64_t)vector193,0x8eUL);
vInstallHandler(&vectors[194],(uint64_t)vector194,0x8eUL);
vInstallHandler(&vectors[195],(uint64_t)vector195,0x8eUL);
vInstallHandler(&vectors[196],(uint64_t)vector196,0x8eUL);
vInstallHandler(&vectors[197],(uint64_t)vector197,0x8eUL);
vInstallHandler(&vectors[198],(uint64_t)vector198,0x8eUL);
vInstallHandler(&vectors[199],(uint64_t)vector199,0x8eUL);
vInstallHandler(&vectors[200],(uint64_t)vector200,0x8eUL);
vInstallHandler(&vectors[201],(uint64_t)vector201,0x8eUL);
vInstallHandler(&vectors[202],(uint64_t)vector202,0x8eUL);
vInstallHandler(&vectors[203],(uint64_t)vector203,0x8eUL);
vInstallHandler(&vectors[204],(uint64_t)vector204,0x8eUL);
vInstallHandler(&vectors[205],(uint64_t)vector205,0x8eUL);
vInstallHandler(&vectors[206],(uint64_t)vector206,0x8eUL);
vInstallHandler(&vectors[207],(uint64_t)vector207,0x8eUL);
vInstallHandler(&vectors[208],(uint64_t)vector208,0x8eUL);
vInstallHandler(&vectors[209],(uint64_t)vector209,0x8eUL);
vInstallHandler(&vectors[210],(uint64_t)vector210,0x8eUL);
vInstallHandler(&vectors[211],(uint64_t)vector211,0x8eUL);
vInstallHandler(&vectors[212],(uint64_t)vector212,0x8eUL);
vInstallHandler(&vectors[213],(uint64_t)vector213,0x8eUL);
vInstallHandler(&vectors[214],(uint64_t)vector214,0x8eUL);
vInstallHandler(&vectors[215],(uint64_t)vector215,0x8eUL);
vInstallHandler(&vectors[216],(uint64_t)vector216,0x8eUL);
vInstallHandler(&vectors[217],(uint64_t)vector217,0x8eUL);
vInstallHandler(&vectors[218],(uint64_t)vector218,0x8eUL);
vInstallHandler(&vectors[219],(uint64_t)vector219,0x8eUL);
vInstallHandler(&vectors[220],(uint64_t)vector220,0x8eUL);
vInstallHandler(&vectors[221],(uint64_t)vector221,0x8eUL);
vInstallHandler(&vectors[222],(uint64_t)vector222,0x8eUL);
vInstallHandler(&vectors[223],(uint64_t)vector223,0x8eUL);
vInstallHandler(&vectors[224],(uint64_t)vector224,0x8eUL);
vInstallHandler(&vectors[225],(uint64_t)vector225,0x8eUL);
vInstallHandler(&vectors[226],(uint64_t)vector226,0x8eUL);
vInstallHandler(&vectors[227],(uint64_t)vector227,0x8eUL);
vInstallHandler(&vectors[228],(uint64_t)vector228,0x8eUL);
vInstallHandler(&vectors[229],(uint64_t)vector229,0x8eUL);
vInstallHandler(&vectors[230],(uint64_t)vector230,0x8eUL);
vInstallHandler(&vectors[231],(uint64_t)vector231,0x8eUL);
vInstallHandler(&vectors[232],(uint64_t)vector232,0x8eUL);
vInstallHandler(&vectors[233],(uint64_t)vector233,0x8eUL);
vInstallHandler(&vectors[234],(uint64_t)vector234,0x8eUL);
vInstallHandler(&vectors[235],(uint64_t)vector235,0x8eUL);
vInstallHandler(&vectors[236],(uint64_t)vector236,0x8eUL);
vInstallHandler(&vectors[237],(uint64_t)vector237,0x8eUL);
vInstallHandler(&vectors[238],(uint64_t)vector238,0x8eUL);
vInstallHandler(&vectors[239],(uint64_t)vector239,0x8eUL);
vInstallHandler(&vectors[240],(uint64_t)vector240,0x8eUL);
vInstallHandler(&vectors[241],(uint64_t)vector241,0x8eUL);
vInstallHandler(&vectors[242],(uint64_t)vector242,0x8eUL);
vInstallHandler(&vectors[243],(uint64_t)vector243,0x8eUL);
vInstallHandler(&vectors[244],(uint64_t)vector244,0x8eUL);
vInstallHandler(&vectors[245],(uint64_t)vector245,0x8eUL);
vInstallHandler(&vectors[246],(uint64_t)vector246,0x8eUL);
vInstallHandler(&vectors[247],(uint64_t)vector247,0x8eUL);
vInstallHandler(&vectors[248],(uint64_t)vector248,0x8eUL);
vInstallHandler(&vectors[249],(uint64_t)vector249,0x8eUL);
vInstallHandler(&vectors[250],(uint64_t)vector250,0x8eUL);
vInstallHandler(&vectors[251],(uint64_t)vector251,0x8eUL);
vInstallHandler(&vectors[252],(uint64_t)vector252,0x8eUL);
vInstallHandler(&vectors[253],(uint64_t)vector253,0x8eUL);
vInstallHandler(&vectors[0x80],(uint64_t)sysint,0xeeUL);
vInstallHandler(&vectors[254],(uint64_t)vector254,0xeeUL);
vInstallHandler(&vectors[255],(uint64_t)vector255,0xeeUL);
idt_pointer.limit = sizeof(vectors)-1;
idt_pointer.addr = (uint64_t)vectors;
load_idt(&idt_pointer);
init_irq_handlers();
}
static void vScheduleTCB(StackType_t **nextTCB) {
struct TrapFrame *tf = (struct TrapFrame *)(*nextTCB);
xMPU_SETTINGS * xMPUSettings = (xMPU_SETTINGS *) (nextTCB+1);
Tss.rsp0 = (uint64_t) xMPUSettings->kernel_stack;
load_cr3(xMPUSettings->pgd);
starttask(*nextTCB);
}
static void vYieldHandler(struct TrapFrame *tf)
{
StackType_t **prevTCB = (StackType_t **) pxCurrentTCB;
*prevTCB = (StackType_t *) tf;
vTaskSwitchContext();
StackType_t **nextTCB = (StackType_t **)pxCurrentTCB;
if (nextTCB != prevTCB) {
vScheduleTCB(nextTCB);
}
return;
}
static void vTimerHandler(struct TrapFrame *tf)
{
if (pxCurrentTCB !=NULL) {
StackType_t **prevTCB = (StackType_t **)pxCurrentTCB;
BaseType_t rc = xTaskIncrementTick();
if (rc == pdTRUE) {
vTaskSwitchContext();
StackType_t **nextTCB = (StackType_t **)pxCurrentTCB;
if (prevTCB != nextTCB) {
*prevTCB = (StackType_t *) tf;
eoi();
vScheduleTCB(nextTCB);
}
}
}
}
void vHandler(struct TrapFrame *tf)
{
unsigned char isr_value;
switch (tf->trapno) {
case TRAP_YIELD:
{
vYieldHandler(tf);
break;
}
case TRAP_PIC_TIMER:
eoi();
break;
case TRAP_HYPERVISOR_EVENT:
do_hypervisor_callback(0);
eoi();
break;
case TRAP_SPURIOUS:
isr_value = read_isr();
if ((isr_value&(1<<7)) != 0) {
eoi();
}
break;
case TRAP_SCI:
{
process_sci();
eoi();
break;
}
case TRAP_TIMER:
{
vTimerHandler(tf);
eoi();
break;
}
case TRAP_SYSCALL:
vSystemCall(tf);
break;
default:
if (tf->trapno > TRAP_PIC_TIMER) {
if ( (ulInterruptNesting == (uint32_t)0) && xTaskUsesFPU) {
asm volatile(" fxsave %0 "::"m"(pucPortTaskFPUContextBuffer));
}
ulInterruptNesting++;
uint32_t irq = tf->trapno - TRAP_PIC_TIMER;
INT_HANDLER irq_handler = get_int_handler(irq);
if (irq_handler != NULL) {
irq_handler();
}
eoi();
ulInterruptNesting--;
if ( (ulInterruptNesting == (uint32_t)0) && xTaskUsesFPU) {
asm volatile(" fxrstor %0 "::"m"(pucPortTaskFPUContextBuffer));
}
if ((ulInterruptNesting ==(uint32_t) 0) && ulPortYieldPending) {
ulPortYieldPending = 0;
vYieldHandler(tf);
}
break;
}
printk("\n[Error %d at ring %d] errorcode:%d cr2:%p rflags: %p ss:%p\n", tf->trapno, (tf->cs & 3), tf->errorcode, read_cr2(),tf->rflags,tf->ss);
printk("Registers:rip=%p rsp=%p rbp=%p\n", tf->rip, tf->rsp, tf->rbp);
printk("Registers:rax=%p rbx=%p rcx=%p rdx=%p rsi=%p rdi=%p\n", tf->rax,tf->rbx,tf->rcx,tf->rdx,tf->rsi,tf->rdi);
printk("Registers:r8=%p r9=%p r10=%p r11=%p r12=%p r13=%p r14=%p r15=%p\n", tf->r8,tf->r9,tf->r10,tf->r11,tf->r12,tf->r13,tf->r14,tf->r15);
if ((tf->cs & 3) != 0) {
xMPU_SETTINGS * xMPUSettings = (xMPU_SETTINGS *) (pxCurrentTCB+1);
Tss.rsp0 = (uint64_t) xMPUSettings->kernel_stack;
vFreeAllPages((uint64_t *) xMPUSettings->pgd);
load_cr3(&pml4);
eoi();
vTaskDelete((TaskHandle_t)pxCurrentTCB);
}
vAssertCalled(__FILE__,__LINE__);
}
}

View file

@ -0,0 +1,372 @@
/* trap
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#ifndef _TRAP_H_
#define _TRAP_H_
#include "stdint.h"
#define TRAP_PIC_TIMER 32
#define TRAP_YIELD 33
#define TRAP_HYPERVISOR_EVENT 37
#define TRAP_SPURIOUS 39
#define TRAP_SCI 41
#define TRAP_TIMER 50
#define TRAP_SYSCALL 128
typedef uint64_t (*SYSTEMCALL)(uint64_t *argptr);
struct TSS {
uint32_t res0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t res1;
uint64_t ist1;
uint64_t ist2;
uint64_t ist3;
uint64_t ist4;
uint64_t ist5;
uint64_t ist6;
uint64_t ist7;
uint64_t res2;
uint16_t res3;
uint16_t iopb;
} __attribute__((packed));
struct IdtEntry{
uint16_t low;
uint16_t selector;
uint8_t res0;
uint8_t attr;
uint16_t mid;
uint32_t high;
uint32_t res1;
};
struct IdtPtr {
uint16_t limit;
uint64_t addr;
} __attribute__((packed));
struct TrapFrame {
int64_t r15;
int64_t r14;
int64_t r13;
int64_t r12;
int64_t r11;
int64_t r10;
int64_t r9;
int64_t r8;
int64_t rbp;
int64_t rdi;
int64_t rsi;
int64_t rdx;
int64_t rcx;
int64_t rbx;
int64_t rax;
int64_t trapno;
int64_t errorcode;
int64_t rip;
int64_t cs;
int64_t rflags;
int64_t rsp;
int64_t ss;
};
static inline void eoi(void) {
*(volatile unsigned int*)0xFEE000B0 = 0x0;
}
void sysint(void);
void vIDTInit(void);
void load_idt(struct IdtPtr *ptr);
unsigned char read_isr(void);
uint64_t read_cr2(void);
void TrapReturn(void);
uint64_t load_cr3();
void send_char_to_cli();
void starttask(void *);
void vector0(void);
void vector1(void);
void vector2(void);
void vector3(void);
void vector4(void);
void vector5(void);
void vector6(void);
void vector7(void);
void vector8(void);
void vector9(void);
void vector10(void);
void vector11(void);
void vector12(void);
void vector13(void);
void vector14(void);
void vector15(void);
void vector16(void);
void vector17(void);
void vector18(void);
void vector19(void);
void vector20(void);
void vector21(void);
void vector22(void);
void vector23(void);
void vector24(void);
void vector25(void);
void vector26(void);
void vector27(void);
void vector28(void);
void vector29(void);
void vector30(void);
void vector31(void);
void vector32(void);
void vector33(void);
void vector34(void);
void vector35(void);
void vector36(void);
void vector37(void);
void vector38(void);
void vector39(void);
void vector40(void);
void vector41(void);
void vector42(void);
void vector43(void);
void vector44(void);
void vector45(void);
void vector46(void);
void vector47(void);
void vector48(void);
void vector49(void);
void vector50(void);
void vector51(void);
void vector52(void);
void vector53(void);
void vector54(void);
void vector55(void);
void vector56(void);
void vector57(void);
void vector58(void);
void vector59(void);
void vector60(void);
void vector61(void);
void vector62(void);
void vector63(void);
void vector64(void);
void vector65(void);
void vector66(void);
void vector67(void);
void vector68(void);
void vector69(void);
void vector70(void);
void vector71(void);
void vector72(void);
void vector73(void);
void vector74(void);
void vector75(void);
void vector76(void);
void vector77(void);
void vector78(void);
void vector79(void);
void vector80(void);
void vector81(void);
void vector82(void);
void vector83(void);
void vector84(void);
void vector85(void);
void vector86(void);
void vector87(void);
void vector88(void);
void vector89(void);
void vector90(void);
void vector91(void);
void vector92(void);
void vector93(void);
void vector94(void);
void vector95(void);
void vector96(void);
void vector97(void);
void vector98(void);
void vector99(void);
void vector100(void);
void vector101(void);
void vector102(void);
void vector103(void);
void vector104(void);
void vector105(void);
void vector106(void);
void vector107(void);
void vector108(void);
void vector109(void);
void vector110(void);
void vector111(void);
void vector112(void);
void vector113(void);
void vector114(void);
void vector115(void);
void vector116(void);
void vector117(void);
void vector118(void);
void vector119(void);
void vector120(void);
void vector121(void);
void vector122(void);
void vector123(void);
void vector124(void);
void vector125(void);
void vector126(void);
void vector127(void);
void vector128(void);
void vector129(void);
void vector130(void);
void vector131(void);
void vector132(void);
void vector133(void);
void vector134(void);
void vector135(void);
void vector136(void);
void vector137(void);
void vector138(void);
void vector139(void);
void vector140(void);
void vector141(void);
void vector142(void);
void vector143(void);
void vector144(void);
void vector145(void);
void vector146(void);
void vector147(void);
void vector148(void);
void vector149(void);
void vector150(void);
void vector151(void);
void vector152(void);
void vector153(void);
void vector154(void);
void vector155(void);
void vector156(void);
void vector157(void);
void vector158(void);
void vector159(void);
void vector160(void);
void vector161(void);
void vector162(void);
void vector163(void);
void vector164(void);
void vector165(void);
void vector166(void);
void vector167(void);
void vector168(void);
void vector169(void);
void vector170(void);
void vector171(void);
void vector172(void);
void vector173(void);
void vector174(void);
void vector175(void);
void vector176(void);
void vector177(void);
void vector178(void);
void vector179(void);
void vector180(void);
void vector181(void);
void vector182(void);
void vector183(void);
void vector184(void);
void vector185(void);
void vector186(void);
void vector187(void);
void vector188(void);
void vector189(void);
void vector190(void);
void vector191(void);
void vector192(void);
void vector193(void);
void vector194(void);
void vector195(void);
void vector196(void);
void vector197(void);
void vector198(void);
void vector199(void);
void vector200(void);
void vector201(void);
void vector202(void);
void vector203(void);
void vector204(void);
void vector205(void);
void vector206(void);
void vector207(void);
void vector208(void);
void vector209(void);
void vector210(void);
void vector211(void);
void vector212(void);
void vector213(void);
void vector214(void);
void vector215(void);
void vector216(void);
void vector217(void);
void vector218(void);
void vector219(void);
void vector220(void);
void vector221(void);
void vector222(void);
void vector223(void);
void vector224(void);
void vector225(void);
void vector226(void);
void vector227(void);
void vector228(void);
void vector229(void);
void vector230(void);
void vector231(void);
void vector232(void);
void vector233(void);
void vector234(void);
void vector235(void);
void vector236(void);
void vector237(void);
void vector238(void);
void vector239(void);
void vector240(void);
void vector241(void);
void vector242(void);
void vector243(void);
void vector244(void);
void vector245(void);
void vector246(void);
void vector247(void);
void vector248(void);
void vector249(void);
void vector250(void);
void vector251(void);
void vector252(void);
void vector253(void);
void vector254(void);
void vector255(void);
#endif

View file

@ -0,0 +1,100 @@
/* x86_64
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#ifndef _X86_64_H_
#define _X86_64_H_
#include "FreeRTOS.h"
#include "task.h"
#include <memory.h>
#if defined(__x86_64__)
// Max number of heap regions
#define MAX_HEAP_REGIONS 64
// Multiboot tages that we are interested in
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_MEMORY 6
#define MULTIBOOT_TAG_TYPE_END 0
// Regions - Read Only or Read-Write
#define REGION_RO 0
#define REGION_RW 1
struct multiboot_tag {
uint32_t type;
uint32_t size;
};
struct multiboot_tag_mmap {
uint32_t type;
uint32_t size;
uint32_t entry_size;
uint32_t entry_version;
struct multiboot_mmap_entry {
uint64_t base_addr;
uint64_t length;
uint32_t type;
uint32_t reserved;
} entries[];
};
struct multiboot_info {
uint32_t total_size;
uint32_t reserved;
struct multiboot_tag tags[];
};
#define PAGE_SIZE_1GB (1ULL << 30)
#define PAGE_SIZE_4K (1ULL << 12)
#define PGD_INDEX(addr) (((addr) >> 39) & 0x1FF)
#define PUD_INDEX(addr) (((addr) >> 30) & 0x1FF)
#define PMD_INDEX(addr) (((addr) >> 21) & 0x1FF)
#define PT_INDEX(addr) (((addr) >> 12) & 0x1FF)
#define USER_VA_START 0xFFFF800000000000ULL
#define PAGE_TABLE_SIZE 512
// Extern variable defined in linker script and assembly code
extern uint64_t pml4;
extern uint64_t pud;
extern uint8_t end;
/* Setup Identity Mapping for Kernel */
void vSetupKernelPageMapping(void);
/* Parse user modules loaded as part of boot. Return
* end address of user modules
*/
void vInitMemoryAllocator(uint64_t);
void vx86_64Init(uint64_t multiboot_info_addr);
uint32_t xInitiRegionForRestrictedTask(MemoryRegion_t *regions);
void vMapPages(uint64_t start_addr,uint64_t end_addr, uint64_t *pgd, uint32_t mode);
void vFreeAllPages(uint64_t *pgd);
uint64_t *pMallocPageTable(void);
#endif
#endif

View file

@ -0,0 +1,191 @@
/* x86_64_init
*
* Copyright (C) 2025 Advanced Micro Devices, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
#include "FreeRTOS.h"
#include "x86_64.h"
#include "task.h"
#include "stdio.h"
#include "stdio.h"
#include "trap.h"
#include "xen/memory.h"
#include "e820.h"
#include "hypervisor.h"
#include "xen/hvm/params.h"
#include <xen/arch-x86/hvm/start_info.h>
HeapRegion_t xHeapRegions[MAX_HEAP_REGIONS];
// DEBUG variables for testing purpose
uint64_t pml4_w_user=0;
// Extern variable defined in linker script and assembly code
extern uint64_t pml4;
extern uint64_t pud;
extern uint8_t end;
extern char __system_calls_start;
extern char __system_calls_end;
extern char __apis_start;
extern char __apis_end;
extern char __rodata_start;
extern char __rodata_end;
/*
* Method to setup regions for restricted tasks.
* A restricted task has access to following
* user mode
* user data
* system calls
* utilities apis like strlen
* its process stack
*/
uint32_t xInitiRegionForRestrictedTask(MemoryRegion_t *regions) ;
void vInitMemoryAllocator(uint64_t multiboot_info_addr);
void vx86_64Init(uint64_t multiboot_info_addr) ;
void vSetupKernelPageMapping(void) ;
uint32_t xInitiRegionForRestrictedTask(MemoryRegion_t *regions) {
uint32_t num_region_used = 0;
regions[num_region_used].pvBaseAddress = &__system_calls_start;
regions[num_region_used].ulLengthInBytes = (uint32_t) (&__system_calls_end - &__system_calls_start);
regions[num_region_used].ulParameters = REGION_RO;
num_region_used++;
regions[num_region_used].pvBaseAddress = &__apis_start;
regions[num_region_used].ulLengthInBytes = (uint32_t) (&__apis_end - &__apis_start);
regions[num_region_used].ulParameters = REGION_RO;
num_region_used++;
regions[num_region_used].pvBaseAddress = &__rodata_start;
regions[num_region_used].ulLengthInBytes = (uint32_t) (&__rodata_end - &__rodata_start);
regions[num_region_used].ulParameters = REGION_RO;
num_region_used++;
return num_region_used;
}
#define PAGE_SIZE_1GB (1ULL << 30)
#define PML4_INDEX(va) (((va) >> 39) & 0x1FF)
#define PDPT_INDEX(va) (((va) >> 30) & 0x1FF)
/* Setup Mapping for Kernel */
void vSetupKernelPageMapping() {
uint64_t *page_table_l4_addr = &pml4;
uint64_t *page_table_l3_addr = &pud;
uint64_t addr = 0;
for (int i=0;i<256;i++) {
page_table_l4_addr[i] = (uint64_t) &page_table_l3_addr[i*512];
page_table_l4_addr[i] |= 0x03;
for (int j=0;j<512;j++) {
page_table_l3_addr[i*(int)512+j]=addr|(uint64_t)0x83;
addr += 0x40000000ULL;
}
}
addr = 0;
for (int i=256;i<512;i++) {
page_table_l4_addr[i] = (uint64_t) &page_table_l3_addr[i*512];
page_table_l4_addr[i] |= 0x03;
for (int j=0;j<512;j++) {
page_table_l3_addr[i*(int)512+j]=addr|(uint64_t)0x83;
addr += 0x40000000ULL;
}
}
}
void vInitMemoryAllocator(uint64_t multiboot_info_addr)
{
// Find the end address where kernel is loaded.
// Free Memory can started only from that address
uint64_t last_used_addr = (uint64_t) &end;
int heap_region_count = 0;
printf("kernel end: %p\n",last_used_addr);
if (multiboot_info_addr != (uint64_t)0) {
uint64_t* val = (uint64_t*) multiboot_info_addr;
uint32_t magic = *((uint64_t *)val);
if (magic != XEN_HVM_START_MAGIC_VALUE) {
struct multiboot_tag *tag = (struct multiboot_tag *)(multiboot_info_addr + (uint64_t)8); // Skip total size and reserved field
while (tag->type != (uint32_t)0) { // 0 indicates end tag
if (tag->type == (uint32_t)MULTIBOOT_TAG_TYPE_MEMORY) {
struct multiboot_tag_mmap *mmap_tag = (struct multiboot_tag_mmap *)tag;
for (uint32_t i = 0; i < (mmap_tag->size - 16) / mmap_tag->entry_size; i++) {
struct multiboot_mmap_entry *entry = &mmap_tag->entries[i];
if (entry->type == 1) {
uint64_t start_addr = entry->base_addr;
uint64_t end_addr = start_addr + entry->length;
if (start_addr > last_used_addr) {
xHeapRegions[heap_region_count].pucStartAddress = (uint8_t *) start_addr;
xHeapRegions[heap_region_count].xSizeInBytes = entry->length;
heap_region_count++;
} else if (end_addr > last_used_addr) {
xHeapRegions[heap_region_count].pucStartAddress = (uint8_t *)last_used_addr;
xHeapRegions[heap_region_count].xSizeInBytes = end_addr - last_used_addr;
heap_region_count++;
}
}
}
}
tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)); // Align tag size to 8
}
} else {
struct hvm_start_info *hsi = (struct hvm_start_info *)val;
long ret;
struct xen_memory_map memmap;
memmap.nr_entries = E820_MAX;
set_xen_guest_handle(memmap.buffer, e820_map);
ret = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
unsigned long end, start;
struct e820entry *entry = (struct e820entry *)e820_map;
for ( int i = 0; i < memmap.nr_entries; i++ )
{
if (entry[i].type == XEN_HVM_MEMMAP_TYPE_RAM) {
uint64_t start_addr = entry[i].addr;
uint64_t end_addr = entry[i].addr+entry[i].size;
if (start_addr > last_used_addr) {
xHeapRegions[heap_region_count].pucStartAddress = (uint8_t *) start_addr;
xHeapRegions[heap_region_count].xSizeInBytes = entry[i].size;
heap_region_count++;
} else if (end_addr > last_used_addr) {
xHeapRegions[heap_region_count].pucStartAddress = (uint8_t *)last_used_addr;
xHeapRegions[heap_region_count].xSizeInBytes = end_addr - last_used_addr;
heap_region_count++;
}
}
}
}
}
xHeapRegions[heap_region_count].pucStartAddress = 0;
xHeapRegions[heap_region_count].xSizeInBytes = 0;
vPortDefineHeapRegions( xHeapRegions );
return;
}
void vx86_64Init(uint64_t multiboot_info_addr) {
vIDTInit();
vSetupKernelPageMapping();
vInitMemoryAllocator(multiboot_info_addr);
}