MMU usage vListInsert issues

friesen wrote on Thursday, January 17, 2019:

I have been working on MMU support with task stack protection for the Cortex A5, and have the MMU working as intended on my part. However, I am running into this issue, that the vListInsert(and probably more) create a list that writes into a different task space, which causes a permission fault.

	pxNewListItem->pxNext = pxIterator->pxNext;
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;//<--- fault location
	pxNewListItem->pxPrevious = pxIterator;
	pxIterator->pxNext = pxNewListItem;

It faults because pxNewListItem->pxNext->pxPrevious is in the other tasks space.

Any ideas what to do, or whether to just give this up entirely?

rtel wrote on Thursday, January 17, 2019:

I don’t know how you have set up the MPU on the Cortex-A, but in the
Cortex-M MPU port we run the kernel code in privileged mode, then it can
access the memory allocated to unprivileged tasks.

friesen wrote on Thursday, January 17, 2019:

When does it switch? Is the kernel code started yet after you call vTaskDelay() which ends up calling vListInsert?

The Cortex A5 doesn’t have an MPU, rather an MMU, which takes a bit different thinking. So the createtask allocates out of a page aligned pool, then each allocated pool is set to be protected from other asid’s.

On the A port, it would appear that tasks are running in SYS mode, I’m not sure about the thinking behind that.

rtel wrote on Thursday, January 17, 2019:

I’m afraid it is not clear to me what you are trying to achieve. Our
MPU (noting that you have MMU, which in the past we have used as a kind
of MPU just without virtual memory) port is used to enable different
tasks to run at different privilege levels, and to isolate different
memory regions. A task can run unprivileged, with a switch to privilege
being effected using an SVC instruction each time it calls a FreeRTOS
API function. I think in all memory protected cases the OS has to run
with privileges (kernel mode) otherwise you are going to get the issue
you are reporting - the kernel is isolated from the memory it needs to

friesen wrote on Thursday, January 17, 2019:

I’m trying to achieve task memory protection.

It isn’t clear to me where to insert elevation, as the task calls vtaskdelay and there isn’t really a defined place to say it is no longer user mode.

rtel wrote on Thursday, January 17, 2019:

Elevation should happen prior to calling vTaskDelay(). This is normally
done by having the API function not a direct C subroutine call, but an
SVC call, SVC being the only way to programmatically raise privilege.
We take a slightly simpler approach though by wrapping vTaskDelay() in a
function called MPU_vTaskDelay() that raises privilege then calls the
standard vTaskDelay(). The standard vTaskDelay() must be in a memory
areas that is marked as privileged execution only, and the raising of
the privilege must check that the source of the SVC was one of the
MPU_nnn() function wrappers.

friesen wrote on Friday, January 18, 2019:

Thank you, this is making sense now. I don’t see anywhere in the present code where the source of the SVC is checked though.

So is this whole MPU thing just a leftover from someone elses project, or is this active?

I suppose MMU support is too outside of what average FreeRTOS applications need. For me, it is more about developing a complex program and reducing development time.

Anyway, I suppose it was done this way as to keep code uncluttered, but it seems it would be cleaner if it was something like this.

#if config_USEMMU == 1)
#define vPortResetPriviledge LowerPriviledge(xRunningPrivileged)
#define vPortRaisePriviledge BaseType_t xRunningPrivileged =  xPortRaisePrivilege()
#define vPortResetPriviledge
#define vPortRaisePriviledge

	BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
							const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
							const configSTACK_DEPTH_TYPE usStackDepth,
							void * const pvParameters,
							UBaseType_t uxPriority,
							TaskHandle_t * const pxCreatedTask )
	TCB_t *pxNewTCB;
	BaseType_t xReturn;
    /* code */

For me,

rtel wrote on Friday, January 18, 2019:

Thank you, this is making sense now. I don’t see anywhere in the present
code where the source of the SVC is checked though.

That may be the case in the code in SVN, which was created with safety
in mind rather than security. Our Cortex-M33 code on the other hand is
more security focused, so does not permit any code other than the API
function to use an SVC instruction.