Commit ffde8814 authored by Carolina Pinto dos Santos Serra's avatar Carolina Pinto dos Santos Serra

Merge branch '40-arm-spcontext-test' into 'dev'

Resolve "ARM spcontext test"

Closes #40

See merge request AIR/air-dev!33
parents c3fd6e7c c9f47e2e
......@@ -4,7 +4,7 @@
<Partition PartitionIdentifier="1" PartitionName="p0"
Criticality="LEVEL_A" SystemPartition="false" EntryPoint="entry_point">
<PartitionConfiguration Personality="RTEMS5" Cores="1">
<Libs>LIBAIR;LIBPRINTF</Libs>
<Libs>LIBAIR;LIBPRINTF;IMASPEX;</Libs>
<Cache>CODE; DATA</Cache>
<Memory Size="0x2000000" />
<Permissions>
......
......@@ -18,6 +18,7 @@
#include "tmacros.h"
#include <pprintf.h>
#include <air.h>
const char rtems_test_name[] = "SPCONTEXT 1";
......@@ -41,7 +42,11 @@ static test_context test_instance;
static void validate_task(rtems_task_argument arg)
{
//pprintf("VALIDATE TEST\n");
_CPU_Context_validate(arg);
pprintf("end validate\n");
air_syscall_print_frame();
rtems_test_assert(0);
}
......@@ -75,7 +80,8 @@ static void reset_timer_or_finish(test_context *self, rtems_id timer)
{
rtems_status_code sc;
int i = self->iteration_counter;
if (!(i%10))
pprintf("%d|", i);
if (i < ITERATION_COUNT) {
self->iteration_counter = i + 1;
......@@ -84,6 +90,7 @@ static void reset_timer_or_finish(test_context *self, rtems_id timer)
} else {
sc = rtems_event_send(self->control_task, FINISH_EVENT);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
printf("FINISH!\n");
}
}
......@@ -146,6 +153,8 @@ static void wait_for_finish(void)
RTEMS_NO_TIMEOUT,
&out
);
//pprintf("event received\n");
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(out == FINISH_EVENT);
}
......@@ -186,17 +195,24 @@ static void test(
start_timer(self);
wait_for_finish();
pprintf("wait complete");
sc = rtems_task_delete(self->validate_tasks[0]);
pprintf("1");
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
sc = rtems_task_delete(self->validate_tasks[1]);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
pprintf("2");
sc = rtems_task_delete(self->validate_tasks[2]);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
pprintf("3");
sc = rtems_timer_delete(self->timer);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
pprintf("4");
}
static void test_context_is_executing(void)
......@@ -263,9 +279,9 @@ static void Init(rtems_task_argument arg)
for (i = 0; i < 2; ++i) {
for (j = 0; j < 2; ++j) {
for (k = 0; k < 2; ++k) {
printf("Test configuration %s %s %s... ", desc(i), desc(j), desc(k));
pprintf("Test configuration %s %s %s... ", desc(i), desc(j), desc(k));
test(self, is_fp(i), is_fp(j), is_fp(k));
printf("done\n");
pprintf("done\n");
}
}
}
......
......@@ -58,7 +58,7 @@ air_u32_t iop_xuart_open(iop_device_driver_t *iop_dev, void *arg) {
air_u32_t iop_xuart_read(iop_device_driver_t *iop_dev, void *arg) {
static air_u32_t receive_count = 0;
int i;
/*Current UART device*/
iop_uart_device_t *device = (iop_uart_device_t *) iop_dev;
uart_priv *pDev = (uart_priv *) (device->dev.driver);
......@@ -108,7 +108,7 @@ air_u32_t iop_xuart_read(iop_device_driver_t *iop_dev, void *arg) {
air_u32_t iop_xuart_write(iop_device_driver_t *iop_dev, void *arg) {
air_u32_t sent_count = 0, b_length = 0, i;
air_u32_t sent_count = 0;
/*Current UART device*/
iop_uart_device_t *device = (iop_uart_device_t *) iop_dev;
......
......@@ -32,7 +32,7 @@ int main(void) {
OFFSETOF(arm_core_context_t, trash);
OFFSETOF(arm_core_context_t, isf_pointer);
OFFSETOF(arm_core_context_t, idle_isf_pointer);
OFFSETOF(arm_core_context_t, vfp_context);
//OFFSETOF(arm_core_context_t, vfp_context);
OFFSETOF(arm_core_context_t, isr_nesting_level);
OFFSETOF(arm_core_context_t, state);
......
......@@ -56,9 +56,9 @@ void core_context_init(core_context_t *context, air_u32_t id) {
#if PMK_FPU_SUPPORT
/* allocate space to hold an FPU context */
context->vfp_context = (arm_vfp_context_t *)pmk_workspace_alloc(sizeof(arm_vfp_context_t));
//context->vfp_context = (arm_vfp_context_t *)pmk_workspace_alloc(sizeof(arm_vfp_context_t));
#else
context->vfp_context = (arm_vfp_context_t *)NULL;
//context->vfp_context = (arm_vfp_context_t *)NULL;
#endif
/* initialize the IPC event */
......@@ -76,9 +76,9 @@ void core_context_init(core_context_t *context, air_u32_t id) {
printk(" idle_isf_pointer at 0x%08x to 0x%08x\n",
context->idle_isf_pointer,
context->idle_isf_pointer + sizeof(arm_interrupt_stack_frame_t));
printk(" fpu_context at 0x%08x to 0x%08x\n",
context->vfp_context,
context->vfp_context + sizeof(arm_vfp_context_t));
//printk(" fpu_context at 0x%08x to 0x%08x\n",
// context->vfp_context,
// context->vfp_context + sizeof(arm_vfp_context_t));
printk(" hm_event at 0x%08x to 0x%08x\n",
context->hm_event,
context->hm_event + sizeof(pmk_hm_event_t));
......@@ -118,7 +118,7 @@ void core_context_setup_idle(core_context_t *context) {
void core_context_setup_partition(core_context_t *context, pmk_partition_t *partition) {
/* initialize the virtual core */
context->vcpu.psr = (ARM_PSR_USR);
context->vcpu.psr = (ARM_PSR_SVC);
context->vcpu.vbar = NULL;
/* initialize the System State and HM event */
......@@ -152,11 +152,12 @@ void core_context_setup_partition(core_context_t *context, pmk_partition_t *part
}
if ((partition->permissions & AIR_PERMISSION_FPU_CONTROL) != 0) {
context->vfp_context->fpexc = (ARM_VFP_FPEXC_ENABLE);
arm_enable_fpu();
//context->vfp_context->fpscr &=0xFFF8FFFF;
isf->vfp_context.fpexc = (ARM_VFP_FPEXC_ENABLE);
arm_enable_fpu();
} else {
context->vfp_context->fpexc = 0;
//context->vfp_context->fpexc = 0;
isf->vfp_context.fpexc = 0;
}
/* setup the partition entry point */
......@@ -170,9 +171,11 @@ void core_context_setup_partition(core_context_t *context, pmk_partition_t *part
#endif
/* setup the stack pointer of the partition */
air_u32_t stack = (air_u32_t)partition->mmap->v_addr + partition->mmap->size;
air_u32_t stack = (air_u32_t)partition->mmap->v_addr + (partition->mmap->size)/2;
stack = (stack & ~(32 - 1));
isf->usr_sp = stack;
context->sp_svc = stack - (336*4*15);
context->sp_irq = stack;
isf->usr_sp = context->sp_svc;
/*Enable virtual interrupts*/
context->vgic.vm_ctrl = 1;
......
......@@ -45,12 +45,19 @@ global(exception_undef)
cpsid aif, #ARM_PSR_IRQ
sub sp, #24
#if PMK_FPU_SUPPORT
sub sp, #264
#endif
push {r0-r11}
add r7, sp, #48
ldm r12, {r5, r6}
stmia r7!, {r5, r6}
#if PMK_FPU_SUPPORT
add r7, #264
#endif
ldr r0, [r7, #12] // spsr
b save_previous
......@@ -58,7 +65,7 @@ global(exception_undef)
global(exception_svc)
srsdb sp, #ARM_PSR_IRQ
/*----*/
/* Checks if svc is air_syscall_rett*/
push {r0,r1}
mrs r1, spsr
tst r1, #ARM_PSR_T
......@@ -69,51 +76,105 @@ global(exception_svc)
cmp r0, #(AIR_SYSCALL_ARM_RETT)
pop {r0,r1}
/**/
mov r14, #ARM_EXCEPTION_SWI
stmdb sp, {r12, r14}
sub r12, sp, #8
cpsid aif, #ARM_PSR_IRQ
/**/
beq arm_rett
/**/
sub sp, #24
#if PMK_FPU_SUPPORT
sub sp, #264
#endif
push {r0-r11}
add r7, sp, #48
ldm r12, {r5, r6}
stmia r7!, {r5, r6}
#if PMK_FPU_SUPPORT
add r7, #264
#endif
ldr r0, [r7, #12] // spsr
b save_previous
arm_rett:
push {r0, r1, lr}
ldr r0, [sp, #80]
mov r2, sp
#if PMK_FPU_SUPPORT
add r2, 264
#endif
ldr r0, [r2, #68]
and r0, #(ARM_PSR_MODE_MASK)
cmp r0, #(ARM_PSR_SVC) //if previous mode was svc, how do we know there was a context switch?
beq arm_return
//mrc p15, 0, r1, c13, c0, 4 // get Per_CPU core
//ldr r1, [r1, #offsetof_pmk_core_ctrl_t_context]
//ldr r1, [r1, #144] // virtual svc sp //get virtual svc sp
mrs r0, cpsr
mov r1, r0
orr r0, #(ARM_PSR_SYS) //change to system mode
msr cpsr, r0
mov r0, sp //get user sp
orr r1, #(ARM_PSR_SYS) //change to system mode
msr cpsr, r1
ldr r1, [sp, #68] //get return sp
cmp r0, r1 //if return sp is different from
bne arm_return //user sp, there was a context switch
mrc p15, 0, r0, c13, c0, 4 // get Per_CPU core
BL2C arm_syscall_rett
pop {r0, r1, lr}
b restore
//TODO: check if there are pending interrupts before returning to the partition!
mov r1, sp //get user sp
msr cpsr, r0
ldr r0, [r2, #56] //get return sp
cmp r1, r0 //if return sp is different from
beq arm_return //user sp, there was a context switch
add r4, sp, #0
search_context_above:
add r4, #72
#if PMK_FPU_SUPPORT
add r4, #264
ldr r0, [r4, #320]
#else
ldr r0, [r4, #56]
#endif
cmp r0, #0
addeq r4, sp, #0
beq search_context_below
ldr r2, [r4, #52]
cmp r2, #ARM_EXCEPTION_IRQ
bne search_context_above
cmp r0, r1
bne search_context_above
mov sp, r4
b arm_return
search_context_below:
sub r4, #72
#if PMK_FPU_SUPPORT
sub r4, #264
ldr r0, [r4, #320]
#else
ldr r0, [r4, #56]
#endif
cmp r0, #0
beq arm_return
ldr r2, [r4, #52]
cmp r2, #ARM_EXCEPTION_IRQ
bne search_context_below
cmp r0, r1
bne search_context_below
mov sp, r4
arm_return:
mrc p15, 0, r0, c13, c0, 4 // get Per_CPU core
BL2C arm_syscall_rett
pop {r0, r1, lr}
b restore
//TODO: check if there are pending interrupts before returning to the partition!
no_context:
//mov r0, sp//mrc p15, 0, r0, c13, c0, 4 // get Per_CPU core
//BL2C arm_syscall_print_frame
b arm_return
global(exception_pref_abort)
......@@ -126,12 +187,20 @@ global(exception_pref_abort)
cpsid aif, #ARM_PSR_IRQ
sub sp, #24
#if PMK_FPU_SUPPORT
sub sp, #264
#endif
push {r0-r11}
add r7, sp, #48
ldm r12, {r5, r6}
stmia r7!, {r5, r6}
#if PMK_FPU_SUPPORT
add r7, #264
#endif
ldr r0, [r7, #12] // spsr
b save_previous
......@@ -147,12 +216,20 @@ global(exception_data_abort)
cpsid aif, #ARM_PSR_IRQ
sub sp, #24
#if PMK_FPU_SUPPORT
sub sp, #264
#endif
push {r0-r11}
add r7, sp, #48
ldm r12, {r5, r6}
stmia r7!, {r5, r6}
#if PMK_FPU_SUPPORT
add r7, #264
#endif
ldr r0, [r7, #12] // spsr
b save_previous
......@@ -169,11 +246,20 @@ global(exception_fiq)
cpsid aif, #ARM_PSR_IRQ
sub sp, #16
#if PMK_FPU_SUPPORT
sub sp, #264
#endif
push {r0-r11}
add r7, sp, #48
ldr r11, [r12]
stmia r7!, {r11, r14}
#if PMK_FPU_SUPPORT
add r7, #264
#endif
ldr r0, [r7, #12] // spsr
b save_previous
......@@ -182,13 +268,46 @@ global(exception_fiq)
global(exception_irq)
sub lr, #4
//If previous exception was IRQ, leave space for an svc context
//This will avoid corrupting the stack when there is a context switch inside the partition
push {r0, r1}
mov r1, sp
add sp, #8
ldr r0, [sp, #52] // get previous exception name
cmp r0, #(ARM_EXCEPTION_IRQ)
subeq sp, #72
#if PMK_FPU_SUPPORT
subeq sp, #264
#endif
/*Check if the exception we're overwriting was returned */
/*If not, look for an empty space
check_overwrite:
sub r0, sp, #20
#if PMK_FPU_SUPPORT
sub r0, #264
#endif
ldr r0, [r0, #0]
cmp r0, #0
beq continue
subne sp, #72
subne sp, #264
bne check_overwrite
continue:*/
ldm r1, {r0, r1}
srsdb sp, #ARM_PSR_IRQ
mov r14, #ARM_EXCEPTION_IRQ
sub sp, #16
#if PMK_FPU_SUPPORT
sub sp, #264
#endif
push {r0-r12, r14}
add r7, sp, #56
#if PMK_FPU_SUPPORT
add r7, #264
#endif
mrs r0, spsr
save_previous: /* requires the SPSR in r0 */
......@@ -217,10 +336,11 @@ save_previous: /* requires the SPSR in r0 */
#if PMK_FPU_SUPPORT
vmrs r4, fpexc
cmp r4, #0
orr r4, #(ARM_VFP_FPEXC_ENABLE)
vmsr fpexc, r4
beq c_handler
vmrs r5, fpscr
ldr r6, [r2, #offsetof_arm_core_context_t_vfp_context]
add r6, sp, #56
stm r6!, {r4, r5}
vstmia r6!, {d0-d15}
vstmia r6, {d16-d31}
......@@ -238,13 +358,18 @@ c_handler:
cpsid aif, #ARM_PSR_IRQ
/*trcpse*/
cmp r0, 0
bne virtual
/**/
restore:
mov r0, #0
str r0, [sp, #52]
add sp, #56 // usr_sp
#if PMK_FPU_SUPPORT
add sp, #264
#endif
pop {r0-r3}
mov lr, r2 // return address
......@@ -264,20 +389,74 @@ restore:
msr cpsr, r5
sub sp, #72
#if PMK_FPU_SUPPORT
vmrs r4, fpexc
orr r4, #(ARM_VFP_FPEXC_ENABLE)
vmsr fpexc, r4
sub sp, #264
add r6, sp, #56
ldmia r6!, {r4, r5}
vldmia r6!, {d0-d15}
vldmia r6, {d16-d31}
vmsr fpscr, r5
vmsr fpexc, r4
#endif
pop {r0-r12}
dmb
add sp, #20
#if PMK_FPU_SUPPORT
add sp, #264
#endif
b return
/*trcpse*/
virtual:
mov lr, r0
mrs r0, spsr
bic r0, #(ARM_PSR_T)
bic r0, #(0xF) // return to the virtual trap table in user mode
msr spsr, r0
mov lr, r0 //puts return address in lr
add sp, #56
#if PMK_FPU_SUPPORT
add sp, #264
#endif
pop {r0-r3} // usr_sp, usr_lr, ret_addr, ret_psr
bic r3, #(ARM_PSR_T)
orr r4, r3, #(ARM_PSR_EXC_MASK)
bic r3, #(0xF) // return to the virtual trap table in user mode
msr spsr, r3 // return psr
and r5, r4, #(ARM_PSR_MODE_MASK)
teq r5, #(ARM_PSR_USR) // check if previous is USR mode
bne virtual_return
orr r4, #(ARM_PSR_SYS) // if true, change to SYS
mrs r5, cpsr
msr cpsr, r4
mov sp, r0
//mrc p15, 0, r0, c13, c0, 4 // get Per_CPU core
//ldr r0, [r0, #offsetof_pmk_core_ctrl_t_context]
//ldr sp, [r0, #148] // virtual irq sp
msr cpsr, r5
virtual_return:
sub sp, #72
#if PMK_FPU_SUPPORT
vmrs r4, fpexc
orr r4, #(ARM_VFP_FPEXC_ENABLE)
vmsr fpexc, r4
sub sp, #264
add r6, sp, #56
ldmia r6!, {r4, r5}
vldmia r6!, {d0-d15}
vldmia r6, {d16-d31}
vmsr fpscr, r5
vmsr fpexc, r4
#endif
//sub sp, #72
pop {r0-r12}
dmb
sub sp, #52
......
......@@ -30,7 +30,7 @@ global(arm_restore_fpu)
mcr p15, 0, r4, c1, c0, 2
isb
add r0, #56
ldm r0!, {r4-r5}
vmsr fpexc, r4
......
......@@ -117,7 +117,6 @@ air_uptr_t *arm_hm_handler(arm_interrupt_stack_frame_t *frame, pmk_core_ctrl_t *
if (ret != NULL)
printk("hm_handler ret = 0x%x\n", (int)ret);
#endif
return ret;
}
......@@ -140,6 +139,11 @@ static air_uptr_t *arm_partition_hm_handler(air_u32_t id, pmk_core_ctrl_t *core)
air_uptr_t *ret_addr = NULL;
arm_interrupt_stack_frame_t *frame = (arm_interrupt_stack_frame_t *)core->context->isf_pointer;
if ((frame->usr_sp > (air_u32_t)(core->partition)->mmap->v_addr) && ((core->context->vcpu.psr & ARM_PSR_MODE_MASK) != ARM_PSR_IRQ))
core->context->sp_svc = frame->usr_sp;
if (!psr_a) {
pmk_hm_event_t *hm_event = (pmk_hm_event_t *)core->context->hm_event;
......@@ -170,10 +174,12 @@ static air_uptr_t *arm_partition_hm_handler(air_u32_t id, pmk_core_ctrl_t *core)
break;
case AIR_FLOAT_ERROR:
core->context->vfp_context->fpexc|=ARM_VFP_FPEXC_ENABLE; //cheat!!!
//TODO why is the fpu being disabled in the partition?
arm_restore_fpu(core->context->vfp_context);
//core->context->vfp_context->fpexc|=ARM_VFP_FPEXC_ENABLE;
frame->vfp_context.fpexc|=ARM_VFP_FPEXC_ENABLE;
//arm_restore_fpu(core->context->vfp_context);
arm_restore_fpu(frame);
arm_syscall_rett(core);
ret_addr = vbar + 1;
break;
case AIR_ARITHMETIC_ERROR: //overflow
......
......@@ -143,6 +143,9 @@ typedef struct {
air_u32_t r11;
air_u32_t r12;
arm_exception_e exception_name; /**< here due to ISF faster save */
#if PMK_FPU_SUPPORT
arm_vfp_context_t vfp_context;
#endif
air_u32_t usr_sp; /**< pre-exception sp */
air_u32_t usr_lr; /**< pre-exception lr */
air_u32_t ret_addr; /**< return addr after the exception*/
......@@ -197,12 +200,12 @@ typedef struct {
void *entry_point; /**< core entry point */
void *isf_pointer; /**< core stack pointer */
void *idle_isf_pointer; /**< core ISF stack */
arm_vfp_context_t *vfp_context; /**< core fpu context */
air_u32_t isr_nesting_level; /**< core interrupt nesting level */
air_u32_t ipc_event; /**< IPC event */
air_u32_t state; /**< system state */
void *hm_event; /**< health-monitor event */
air_u32_t reserved;
air_u32_t sp_svc; /* < virtual svc stack pointer */
air_u32_t sp_irq; /* < virtual irq stack pointer */
} arm_core_context_t;
/**
......
......@@ -18,7 +18,7 @@
* \brief ARM Stack spaces
*/
#define DEFAULT_STACK_SIZE 0x10000
#define STACK_SIZE 7*DEFAULT_STACK_SIZE
#define STACK_SIZE 14*DEFAULT_STACK_SIZE
#define svc_stack_size DEFAULT_STACK_SIZE
#define fiq_stack_size DEFAULT_STACK_SIZE
#define irq_stack_size DEFAULT_STACK_SIZE
......@@ -36,7 +36,7 @@
/**
* \brief Level of allowed IRQ nesting
*/
#define MAX_NESTING_LEVEL 7
#define MAX_NESTING_LEVEL 14
/**
* \brief Double-word alignment
......
......@@ -29,6 +29,7 @@ air_uptr_t *arm_hm_handler(arm_interrupt_stack_frame_t *frame, pmk_core_ctrl_t *
* \brief Restores the FPU with the current context values
* \param vfp_context Current context fpu registers
*/
void arm_restore_fpu(arm_vfp_context_t *vfp_context);
//void arm_restore_fpu(arm_vfp_context_t *vfp_context);
void arm_restore_fpu(arm_interrupt_stack_frame_t *frame);
#endif /* HM_H_ */
......@@ -83,20 +83,21 @@ air_uptr_t * arm_isr_handler(arm_interrupt_stack_frame_t *frame, pmk_core_ctrl_t
frame = (arm_interrupt_stack_frame_t *)core->context->isf_pointer;
core->partition_switch = 0;
#ifdef PMK_DEBUG_ISR
if (core->partition != NULL) {
printk(" ISR :: Switching to Partition %d \n\n", core->partition->id);
} else {
printk(" ISR :: Switching to Partition IDLE\n\n");
}
arm_isr_handler_print_frame(frame, "EXIT ");
arm_isr_handler_print_frame(frame, "EXIT ");
#endif
}
if ((frame->usr_sp > (air_u32_t)(core->partition)->mmap->v_addr) && ((core->context->vcpu.psr & ARM_PSR_MODE_MASK) != ARM_PSR_IRQ))
core->context->sp_svc = frame->usr_sp;
/* will it route to the partition */
if (core->partition != NULL) {
ret = arm_partition_isr_handler(id, core);
}
......@@ -167,13 +168,15 @@ air_uptr_t * arm_partition_isr_handler(air_u32_t id, pmk_core_ctrl_t *core) {
return ret;
}
}
/*the IRQ exception can only be taken if the IRQ mask bit is 0*/
if (!psr_i) {