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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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