diff --git a/portable/GCC/XEN_x86/IA32/ISR_Support.h b/portable/GCC/XEN_x86/IA32/ISR_Support.h new file mode 100644 index 0000000000..18e10bf91e --- /dev/null +++ b/portable/GCC/XEN_x86/IA32/ISR_Support.h @@ -0,0 +1,128 @@ +/* + * FreeRTOS Kernel + * 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 diff --git a/portable/GCC/XEN_x86/IA32/README.md b/portable/GCC/XEN_x86/IA32/README.md new file mode 100644 index 0000000000..8658518bc1 --- /dev/null +++ b/portable/GCC/XEN_x86/IA32/README.md @@ -0,0 +1,2 @@ +# Description +This folder contain source for FreeRTOS port for x86_32. diff --git a/portable/GCC/XEN_x86/IA32/port.c b/portable/GCC/XEN_x86/IA32/port.c new file mode 100644 index 0000000000..dd9a9de873 --- /dev/null +++ b/portable/GCC/XEN_x86/IA32/port.c @@ -0,0 +1,627 @@ +/* + * FreeRTOS Kernel + * 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 + +/* 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; +} diff --git a/portable/GCC/XEN_x86/IA32/portASM.S b/portable/GCC/XEN_x86/IA32/portASM.S new file mode 100644 index 0000000000..bdcc1391d8 --- /dev/null +++ b/portable/GCC/XEN_x86/IA32/portASM.S @@ -0,0 +1,351 @@ +/* + * FreeRTOS Kernel + * 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 diff --git a/portable/GCC/XEN_x86/IA32/portmacro.h b/portable/GCC/XEN_x86/IA32/portmacro.h new file mode 100644 index 0000000000..5c2a7265c5 --- /dev/null +++ b/portable/GCC/XEN_x86/IA32/portmacro.h @@ -0,0 +1,277 @@ +/* + * FreeRTOS Kernel + * 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 */ diff --git a/portable/GCC/XEN_x86/IA32/startup.S b/portable/GCC/XEN_x86/IA32/startup.S new file mode 100644 index 0000000000..4a983499a8 --- /dev/null +++ b/portable/GCC/XEN_x86/IA32/startup.S @@ -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 diff --git a/portable/GCC/XEN_x86/x86-64/asm_src/header.asm b/portable/GCC/XEN_x86/x86-64/asm_src/header.asm new file mode 100644 index 0000000000..dffe0d181b --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/asm_src/header.asm @@ -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: diff --git a/portable/GCC/XEN_x86/x86-64/asm_src/idt.asm b/portable/GCC/XEN_x86/x86-64/asm_src/idt.asm new file mode 100644 index 0000000000..d521fd3938 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/asm_src/idt.asm @@ -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 + diff --git a/portable/GCC/XEN_x86/x86-64/asm_src/main.asm b/portable/GCC/XEN_x86/x86-64/asm_src/main.asm new file mode 100644 index 0000000000..b7a14edb73 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/asm_src/main.asm @@ -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 diff --git a/portable/GCC/XEN_x86/x86-64/asm_src/syscall.asm b/portable/GCC/XEN_x86/x86-64/asm_src/syscall.asm new file mode 100644 index 0000000000..322bf6c379 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/asm_src/syscall.asm @@ -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 + diff --git a/portable/GCC/XEN_x86/x86-64/asm_src/xennote.S b/portable/GCC/XEN_x86/x86-64/asm_src/xennote.S new file mode 100644 index 0000000000..7752fe7147 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/asm_src/xennote.S @@ -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) + diff --git a/portable/GCC/XEN_x86/x86-64/mpu_wrappers_x86_64.c b/portable/GCC/XEN_x86/x86-64/mpu_wrappers_x86_64.c new file mode 100644 index 0000000000..f0f0fabce1 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/mpu_wrappers_x86_64.c @@ -0,0 +1,1150 @@ +/* + * FreeRTOS Kernel + * 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 + * + */ +/* + * Implementation of the wrapper functions used to raise the processor privilege + * before calling a standard FreeRTOS API function. + */ +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "timers.h" +#include "event_groups.h" +#include "stream_buffer.h" +#include "mpu_prototypes.h" +#include "syscall.h" +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskGetTickCount( void ) +{ + TickType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGetTickCount(); + } + else + { + xReturn = xTaskGetTickCount(); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + TickType_t xTimeIncrement ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_xTaskDelayUntil(pxPreviousWakeTime, xTimeIncrement); + } + else + { + xReturn = xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, + const void * const pvItemToQueue, + TickType_t xTicksToWait, + BaseType_t xCopyPosition ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + } + else + { + xReturn = xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueReceive( QueueHandle_t pxQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueReceive( pxQueue, pvBuffer, xTicksToWait ); + } + else + { + xReturn = xQueueReceive( pxQueue, pvBuffer, xTicksToWait ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTimerGenericCommandFromTask( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTimerGenericCommandFromTask( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ); + } + else + { + xReturn = xTimerGenericCommandFromTask( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, + UBaseType_t uxItemSize, + uint8_t ucQueueType ) +{ + return xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType ); +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskCreate( TaskFunction_t pvTaskCode, + const char * const pcName, + const configSTACK_DEPTH_TYPE uxStackDepth, + void * pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * pxCreatedTask ) +{ + /* This API can only be used to create priviledged tasks */ + return xTaskCreate( pvTaskCode, pcName, uxStackDepth, pvParameters, uxPriority|portPRIVILEGE_BIT, pxCreatedTask ); +} +/*-----------------------------------------------------------*/ +void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete ) +{ + vTaskDelete( pxTaskToDelete ); +} +/*-----------------------------------------------------------*/ +void MPU_vTaskDelay( TickType_t xTicksToDelay ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTaskDelay( xTicksToDelay ); + } + else + { + vTaskDelay( xTicksToDelay ); + } +} +/*-----------------------------------------------------------*/ +UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t pxTask ) +{ + UBaseType_t uxReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + uxReturn = syscall_uxTaskPriorityGet( pxTask ); + } + else + { + uxReturn = uxTaskPriorityGet( pxTask ); + } + return uxReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vTaskPrioritySet( TaskHandle_t pxTask, + UBaseType_t uxNewPriority ) +{ + vTaskPrioritySet( pxTask, uxNewPriority ); +} +/*-----------------------------------------------------------*/ +eTaskState MPU_eTaskGetState( TaskHandle_t pxTask ) +{ + eTaskState eReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + eReturn = syscall_eTaskGetState( pxTask ); + } + else + { + eReturn = eTaskGetState( pxTask ); + } + return eReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vTaskGetInfo( TaskHandle_t xTask, + TaskStatus_t * pxTaskStatus, + BaseType_t xGetFreeStackSpace, + eTaskState eState ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState ); + } + else + { + vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState ); + } +} +/*-----------------------------------------------------------*/ +void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTaskSuspend( pxTaskToSuspend ); + } + else + { + vTaskSuspend( pxTaskToSuspend ); + } +} +/*-----------------------------------------------------------*/ +void MPU_vTaskResume( TaskHandle_t pxTaskToResume ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTaskResume( pxTaskToResume ); + } + else + { + vTaskResume( pxTaskToResume ); + } +} +/*-----------------------------------------------------------*/ +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) +{ + UBaseType_t uxReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + uxReturn = syscall_uxTaskGetNumberOfTasks(); + } + else + { + uxReturn = uxTaskGetNumberOfTasks(); + } + return uxReturn; +} +/*-----------------------------------------------------------*/ +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * pxTaskStatusArray, + UBaseType_t uxArraySize, + configRUN_TIME_COUNTER_TYPE * pulTotalRunTime ) +{ + UBaseType_t uxReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + uxReturn = syscall_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); + } + else + { + uxReturn = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); + } + return uxReturn; +} +/*-----------------------------------------------------------*/ +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) +{ + TaskHandle_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGetCurrentTaskHandle(); + } + else + { + xReturn = xTaskGetCurrentTaskHandle(); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskGetSchedulerState( void ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGetSchedulerState(); + } + else + { + xReturn = xTaskGetSchedulerState(); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTaskSetTimeOutState( pxTimeOut ); + } + else + { + vTaskSetTimeOutState( pxTimeOut ); + } +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, + TickType_t * const pxTicksToWait ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait ); + } + else + { + xReturn = xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue ); + } + else + { + xReturn = xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ); + } + else + { + xReturn = xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) +{ + uint32_t ulReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + ulReturn = syscall_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ); + } + else + { + ulReturn = ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ); + } + return ulReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGenericNotifyStateClear( xTask, uxIndexToClear ); + } + else + { + xReturn = xTaskGenericNotifyStateClear( xTask, uxIndexToClear ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) +{ + uint32_t ulReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + ulReturn = syscall_ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear ); + } + else + { + ulReturn = ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear ); + } + return ulReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, + BaseType_t xNewQueue ) +{ + return xQueueGenericReset( pxQueue, xNewQueue ); +} +/*-----------------------------------------------------------*/ +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue ) +{ + uint32_t uxReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + uxReturn = syscall_uxQueueMessagesWaiting( pxQueue ); + } + else + { + uxReturn = uxQueueMessagesWaiting( pxQueue ); + } + return uxReturn; +} +/*-----------------------------------------------------------*/ +UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) +{ + UBaseType_t uxReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + uxReturn = syscall_uxQueueSpacesAvailable( xQueue ); + } + else + { + uxReturn = uxQueueSpacesAvailable( xQueue ); + } + + return uxReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueuePeek( xQueue, pvBuffer, xTicksToWait ); + } + else + { + xReturn = xQueuePeek( xQueue, pvBuffer, xTicksToWait ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, + TickType_t xTicksToWait ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueSemaphoreTake( xQueue, xTicksToWait ); + } + else + { + xReturn = xQueueSemaphoreTake( xQueue, xTicksToWait ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) +{ + return xQueueCreateMutex( ucQueueType ); +} +/*-----------------------------------------------------------*/ +QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, + UBaseType_t uxInitialCount ) +{ + return xQueueCreateCountingSemaphore( uxCountValue, uxInitialCount ); +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, + TickType_t xBlockTime ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueTakeMutexRecursive( xMutex, xBlockTime ); + } + else + { + xReturn = xQueueTakeMutexRecursive( xMutex, xBlockTime ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueGiveMutexRecursive( xMutex ); + } + else + { + xReturn = xQueueGiveMutexRecursive( xMutex ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength ) +{ + return xQueueCreateSet( uxEventQueueLength ); +} +/*-----------------------------------------------------------*/ +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, + TickType_t xBlockTimeTicks ) +{ + QueueSetMemberHandle_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueSelectFromSet( xQueueSet, xBlockTimeTicks ); + } + else + { + xReturn = xQueueSelectFromSet( xQueueSet, xBlockTimeTicks ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueAddToSet( xQueueOrSemaphore, xQueueSet ); + } + else + { + xReturn = xQueueAddToSet( xQueueOrSemaphore, xQueueSet ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ); + } + else + { + xReturn = xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, + const char * pcName ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vQueueAddToRegistry( xQueue, pcName ); + } + else + { + vQueueAddToRegistry( xQueue, pcName ); + } +} +/*-----------------------------------------------------------*/ +void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vQueueUnregisterQueue( xQueue ); + } + else + { + vQueueUnregisterQueue( xQueue ); + } +} +/*-----------------------------------------------------------*/ +const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) +{ + const char * pcReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + pcReturn = syscall_pcQueueGetName( xQueue ); + } + else + { + pcReturn = pcQueueGetName( xQueue ); + } + return pcReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vQueueDelete( QueueHandle_t xQueue ) +{ + vQueueDelete( xQueue ); +} +/*-----------------------------------------------------------*/ +void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) +{ + void * pvReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + pvReturn = syscall_pvTimerGetTimerID( xTimer ); + } + else + { + pvReturn = pvTimerGetTimerID( xTimer ); + } + return pvReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vTimerSetTimerID( TimerHandle_t xTimer, + void * pvNewID ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTimerSetTimerID( xTimer, pvNewID ); + } + else + { + vTimerSetTimerID( xTimer, pvNewID ); + } +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) +{ + BaseType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTimerIsTimerActive( xTimer ); + } + else + { + xReturn = xTimerIsTimerActive( xTimer ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) +{ + TaskHandle_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTimerGetTimerDaemonTaskHandle(); + } + else + { + xReturn = xTimerGetTimerDaemonTaskHandle(); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, + const BaseType_t uxAutoReload ) +{ + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vTimerSetReloadMode( xTimer, uxAutoReload ); + } + else + { + vTimerSetReloadMode( xTimer, uxAutoReload ); + } +} +/*-----------------------------------------------------------*/ +UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) +{ + UBaseType_t uxReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + uxReturn = syscall_uxTimerGetReloadMode( xTimer ); + } + else + { + uxReturn = uxTimerGetReloadMode( xTimer ); + } + return uxReturn; +} +/*-----------------------------------------------------------*/ +const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) +{ + const char * pcReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + pcReturn = syscall_pcTimerGetName( xTimer ); + } + else + { + pcReturn = pcTimerGetName( xTimer ); + } + return pcReturn; +} +/*-----------------------------------------------------------*/ +TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) +{ + TickType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTimerGetPeriod( xTimer ); + } + else + { + xReturn = xTimerGetPeriod( xTimer ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) +{ + TickType_t xReturn; + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTimerGetExpiryTime( xTimer ); + } + else + { + xReturn = xTimerGetExpiryTime( xTimer ); + } + return xReturn; +} +/*-----------------------------------------------------------*/ +void MPU_vTaskListTasks( char * pcWriteBuffer, + size_t uxBufferLength ) +{ + vTaskListTasks( pcWriteBuffer, uxBufferLength ); +} +/*-----------------------------------------------------------*/ +void MPU_vTaskSuspendAll( void ) +{ + vTaskSuspendAll(); +} +/*-----------------------------------------------------------*/ +BaseType_t MPU_xTaskResumeAll( void ) +{ + return xTaskResumeAll(); +} +/*-----------------------------------------------------------*/ +#if defined (INCLUDE_xTaskAbortDelay) + #if ( INCLUDE_xTaskAbortDelay == 1 ) + BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) /* FREERTOS_SYSTEM_CALL */ + { + BaseType_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskAbortDelay( xTask ); + } + else + { + xReturn = xTaskAbortDelay( xTask ); + } + + return xReturn; + } + #endif /* if ( INCLUDE_xTaskAbortDelay == 1 ) */ +#endif /* #if defined (INCLUDE_xTaskAbortDelay) */ + +#if defined (INCLUDE_xTaskGetHandle) + #if ( INCLUDE_xTaskGetHandle == 1 ) + TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) /* FREERTOS_SYSTEM_CALL */ + { + TaskHandle_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xTaskGetHandle( pcNameToQuery ); + } + else + { + xReturn = xTaskGetHandle( pcNameToQuery ); + } + + return xReturn; + } + #endif /* if ( INCLUDE_xTaskGetHandle == 1 ) */ +#endif /* #if defined (INCLUDE_xTaskGetHandle) */ + +#if defined (configSUPPORT_DYNAMIC_ALLOCATION) && defined (configUSE_EVENT_GROUPS) + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_EVENT_GROUPS == 1 ) ) + EventGroupHandle_t MPU_xEventGroupCreate( void ) /* FREERTOS_SYSTEM_CALL */ + { + EventGroupHandle_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xEventGroupCreate(); + } + else + { + xReturn = xEventGroupCreate(); + } + return xReturn; + } + #endif /* #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_EVENT_GROUPS == 1 ) ) */ +#endif /* #if defined (configUSE_EVENT_GROUPS) #if defined (configSUPPORT_DYNAMIC_ALLOCATION) */ +/*-----------------------------------------------------------*/ + +#if defined (configUSE_EVENT_GROUPS) + #if ( configUSE_EVENT_GROUPS == 1 ) + EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xClearOnExit, + const BaseType_t xWaitForAllBits, + TickType_t xTicksToWait ) /* FREERTOS_SYSTEM_CALL */ + { + EventBits_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ); + } + else + { + xReturn = xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ); + } + + return xReturn; + } + #endif /* #if ( configUSE_EVENT_GROUPS == 1 ) */ +#endif /* #if defined (configUSE_EVENT_GROUPS) */ + +#if defined (configUSE_EVENT_GROUPS) + #if ( configUSE_EVENT_GROUPS == 1 ) + void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) /* FREERTOS_SYSTEM_CALL */ + { + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vEventGroupDelete( xEventGroup ); + } + else + { + vEventGroupDelete( xEventGroup ); + } + } + #endif /* #if ( configUSE_EVENT_GROUPS == 1 ) */ +#endif /* #if defined (configUSE_EVENT_GROUPS) */ + +#if defined (configSUPPORT_DYNAMIC_ALLOCATION) + #if defined (configUSE_STREAM_BUFFERS) + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_STREAM_BUFFERS == 1 ) ) + StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xStreamBufferType, + StreamBufferCallbackFunction_t pxSendCompletedCallback, + StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) /* FREERTOS_SYSTEM_CALL */ + { + StreamBufferHandle_t xReturn; + + /** + * Stream buffer application level callback functionality is disabled for MPU + * enabled ports. + */ + configASSERT( ( pxSendCompletedCallback == NULL ) && + ( pxReceiveCompletedCallback == NULL ) ); + + if( ( pxSendCompletedCallback == NULL ) && + ( pxReceiveCompletedCallback == NULL ) ) + { + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferGenericCreate( xBufferSizeBytes, + xTriggerLevelBytes, + xStreamBufferType, + NULL, + NULL ); + + } + else + { + xReturn = xStreamBufferGenericCreate( xBufferSizeBytes, + xTriggerLevelBytes, + xStreamBufferType, + NULL, + NULL ); + } + } + else + { + traceSTREAM_BUFFER_CREATE_FAILED( xStreamBufferType ); + xReturn = NULL; + } + + return xReturn; + } + #endif /* #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_STREAM_BUFFERS == 1 ) ) */ + #endif /* #if defined (configUSE_STREAM_BUFFERS) */ +#endif /* #if defined (configSUPPORT_DYNAMIC_ALLOCATION) */ + +#if defined (configUSE_STREAM_BUFFERS) + #if ( configUSE_STREAM_BUFFERS == 1 ) + size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, + void * pvRxData, + size_t xBufferLengthBytes, + TickType_t xTicksToWait ) /* FREERTOS_SYSTEM_CALL */ + { + size_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferReceive( xStreamBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ); + } + else + { + + xReturn = xStreamBufferReceive( xStreamBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ +#endif /* #if defined (configUSE_STREAM_BUFFERS)*/ + +#if defined (configUSE_STREAM_BUFFERS) + #if ( configUSE_STREAM_BUFFERS == 1 ) + void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + if( portIS_PRIVILEGED() == pdFALSE ) + { + syscall_vStreamBufferDelete( xStreamBuffer ); + } + else + { + vStreamBufferDelete( xStreamBuffer ); + } + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ +#endif /* #if defined (configUSE_STREAM_BUFFERS)*/ + +#if defined (configUSE_MUTEXES) && defined ( INCLUDE_xSemaphoreGetMutexHolder) + #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) /* FREERTOS_SYSTEM_CALL */ + { + void * xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xQueueGetMutexHolder( xSemaphore ); + } + else + { + xReturn = xQueueGetMutexHolder( xSemaphore ); + } + + return xReturn; + } + #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ +#endif /* #if defined (configUSE_MUTEXES) && defined ( INCLUDE_xSemaphoreGetMutexHolder) */ + +#if defined (configUSE_EVENT_GROUPS) + #if ( configUSE_EVENT_GROUPS == 1 ) + EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + const EventBits_t uxBitsToWaitFor, + TickType_t xTicksToWait ) /* FREERTOS_SYSTEM_CALL */ + { + EventBits_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ); + } + else + { + xReturn = xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ); + } + + return xReturn; + } + #endif /* #if ( configUSE_EVENT_GROUPS == 1 ) */ +#endif /* #if defined (configUSE_EVENT_GROUPS) */ + +#if defined (configUSE_EVENT_GROUPS) + #if ( configUSE_EVENT_GROUPS == 1 ) + EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet ) /* FREERTOS_SYSTEM_CALL */ + { + EventBits_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xEventGroupSetBits( xEventGroup, uxBitsToSet ); + } + else + { + xReturn = xEventGroupSetBits( xEventGroup, uxBitsToSet ); + } + + return xReturn; + } + #endif /* #if ( configUSE_EVENT_GROUPS == 1 ) */ +#endif /* #if defined (configUSE_EVENT_GROUPS) */ + +#if defined (configUSE_EVENT_GROUPS) + #if ( configUSE_EVENT_GROUPS == 1 ) + EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) /* FREERTOS_SYSTEM_CALL */ + { + EventBits_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xEventGroupClearBits( xEventGroup, uxBitsToClear ); + } + else + { + xReturn = xEventGroupClearBits( xEventGroup, uxBitsToClear ); + } + + return xReturn; + } + #endif /* #if ( configUSE_EVENT_GROUPS == 1 ) */ +#endif /* #if defined (configUSE_EVENT_GROUPS) */ + +#if defined (configUSE_STREAM_BUFFERS) + #if ( configUSE_STREAM_BUFFERS == 1 ) + size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + TickType_t xTicksToWait ) /* FREERTOS_SYSTEM_CALL */ + { + size_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + + xReturn = syscall_xStreamBufferSend( xStreamBuffer, pvTxData, xDataLengthBytes, xTicksToWait ); + } + else + { + xReturn = xStreamBufferSend( xStreamBuffer, pvTxData, xDataLengthBytes, xTicksToWait ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ + + #if ( configUSE_STREAM_BUFFERS == 1 ) + BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + BaseType_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferIsEmpty( xStreamBuffer ); + } + else + { + xReturn = xStreamBufferIsEmpty( xStreamBuffer ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ + + #if ( configUSE_STREAM_BUFFERS == 1 ) + size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + size_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferNextMessageLengthBytes( xStreamBuffer ); + } + else + { + xReturn = xStreamBufferNextMessageLengthBytes( xStreamBuffer ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ + + #if ( configUSE_STREAM_BUFFERS == 1 ) + BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + BaseType_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferIsFull( xStreamBuffer ); + } + else + { + xReturn = xStreamBufferIsFull( xStreamBuffer ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ + + #if ( configUSE_STREAM_BUFFERS == 1 ) + size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + size_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferSpacesAvailable ( xStreamBuffer ); + } + else + { + xReturn = xStreamBufferSpacesAvailable( xStreamBuffer ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ + + #if ( configUSE_STREAM_BUFFERS == 1 ) + BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + BaseType_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferReset( xStreamBuffer ); + } + else + { + xReturn = xStreamBufferReset( xStreamBuffer ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ +/*-----------------------------------------------------------*/ + #if ( configUSE_STREAM_BUFFERS == 1 ) + size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) /* FREERTOS_SYSTEM_CALL */ + { + size_t xReturn; + + if( portIS_PRIVILEGED() == pdFALSE ) + { + xReturn = syscall_xStreamBufferBytesAvailable( xStreamBuffer ); + } + else + { + xReturn = xStreamBufferBytesAvailable( xStreamBuffer ); + } + + return xReturn; + } + #endif /* #if ( configUSE_STREAM_BUFFERS == 1 ) */ +/*-----------------------------------------------------------*/ +#endif /* #if defined (configUSE_STREAM_BUFFERS)*/ diff --git a/portable/GCC/XEN_x86/x86-64/page_allocate.c b/portable/GCC/XEN_x86/x86-64/page_allocate.c new file mode 100644 index 0000000000..7f4cabffdd --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/page_allocate.c @@ -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 + +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; + } +} diff --git a/portable/GCC/XEN_x86/x86-64/port.c b/portable/GCC/XEN_x86/x86-64/port.c new file mode 100644 index 0000000000..e05fe538cc --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/port.c @@ -0,0 +1,402 @@ +/* + * FreeRTOS Kernel + * 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 +#include + +/* 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 + } +} diff --git a/portable/GCC/XEN_x86/x86-64/portmacro.h b/portable/GCC/XEN_x86/x86-64/portmacro.h new file mode 100644 index 0000000000..cbb4ed743a --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/portmacro.h @@ -0,0 +1,253 @@ +/* + * FreeRTOS Kernel + * 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 */ diff --git a/portable/GCC/XEN_x86/x86-64/syscall.c b/portable/GCC/XEN_x86/x86-64/syscall.c new file mode 100644 index 0000000000..7b9e8bcda6 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/syscall.c @@ -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;irax; + 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; + } +} + diff --git a/portable/GCC/XEN_x86/x86-64/syscall.h b/portable/GCC/XEN_x86/x86-64/syscall.h new file mode 100644 index 0000000000..5ff2bf1356 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/syscall.h @@ -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 diff --git a/portable/GCC/XEN_x86/x86-64/trap.c b/portable/GCC/XEN_x86/x86-64/trap.c new file mode 100644 index 0000000000..ecef39bb03 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/trap.c @@ -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__); + } + +} diff --git a/portable/GCC/XEN_x86/x86-64/trap.h b/portable/GCC/XEN_x86/x86-64/trap.h new file mode 100644 index 0000000000..8f7467d9f4 --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/trap.h @@ -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 diff --git a/portable/GCC/XEN_x86/x86-64/x86_64.h b/portable/GCC/XEN_x86/x86-64/x86_64.h new file mode 100644 index 0000000000..096ec73e1c --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/x86_64.h @@ -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 + +#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 diff --git a/portable/GCC/XEN_x86/x86-64/x86_64_init.c b/portable/GCC/XEN_x86/x86-64/x86_64_init.c new file mode 100644 index 0000000000..3a29bdb70e --- /dev/null +++ b/portable/GCC/XEN_x86/x86-64/x86_64_init.c @@ -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 + +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); +}