Squashed all commits

This commit is contained in:
Kai-Bjoern
2020-04-16 16:52:36 +02:00
parent 97e1e226f3
commit ff72483525
2019 changed files with 824245 additions and 3 deletions

392
src/Modules/MMU/mmu.c Normal file
View File

@@ -0,0 +1,392 @@
/*
****************************************************************************************************
*
* uC/OS-MMU
*
* (c) Copyright 2012, Micrium, FL
* All rights reserved.
*
* All rights reserved. Protected by international copyright laws.
* Knowledge of the source code may not be used to write a similar
* product. This file may only be used in accordance with a license
* and should not be redistributed in any way.
*
*
* Version : 3.1.2pp-35237
* File : MMU.c (#1)
* Programmer(s) : EO
****************************************************************************************************
*/
/*!
****************************************************************************************************
* \defgroup PAR_CPU_MMU Target Specific MMU Implementation
* \ingroup PAR_CORE
*
*
* The memory management unit (MMU) for the ...
*
****************************************************************************************************
*/
/*
****************************************************************************************************
* INCLUDES
****************************************************************************************************
*/
#include "mmu.h"
#include "xpseudo_asm.h"
#include "xil_cache.h"
#include "lib_mem.h"
#include "mmu_cfg.h"
/*
****************************************************************************************************
* GOBAL DATA
****************************************************************************************************
*/
extern INT32U MMUTable;
/*
****************************************************************************************************
* PRIVATE FUNCTION PROTOTYPES
****************************************************************************************************
*/
static MMU_ERR_T MMUTblAdd (PAR_MEM_REGION_REF_T mem, INT32U * pMMUTable);
static MMU_ERR_T MMUTblAdd1M (PAR_MEM_REGION_REF_T mem, INT32U off, INT32U * pMMUTable);
static void FTTSet (INT32U va, INT32U descr, INT32U * pMMUTable);
static INT32U FTTGet (INT32U va, INT32U * pMMUTable);
static INT32U FTTDescr (PAR_MEM_REGION_REF_T mem, INT32U offset, INT32U type, INT32U tbl);
static void MMUEnable (INT32U * pMMUTable);
static void MMUSwitchContext (INT32U id);
/*
****************************************************************************************************
* FUNCTIONS
****************************************************************************************************
*/
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief INIT THE MMU
*
* \ingroup PAR_CPU_MMU
*
* This function initialize the target specific MMU
*
* \note The integrator must supply the contents of the PARErrLogging() function to handle
* possible error conditions.
*/
/*------------------------------------------------------------------------------------------------*/
MMU_ERR_T MMUInit (void)
{
INT32U n; /* Local: loop counter */
MMU_ERR_T err = MMU_ERR_NONE;
Mem_Clr(&MMUTable,FTT_SIZE * sizeof(CPU_WORD_SIZE_32));
for(n = 0; n < sizeof(PARMemTbl_Core)/sizeof(PAR_MEM_REGION_T); n++){
err = MMUTblAdd((PAR_MEM_REGION_REF_T)&PARMemTbl_Core[n], &MMUTable);
if(err != MMU_ERR_NONE)
return err;
}
MMUEnable(&MMUTable); /* Enable the MMU */
return MMU_ERR_NONE;
}
/*
****************************************************************************************************
* LOCAL FUNCTIONS
****************************************************************************************************
*/
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief MMU TABLE CONSTRUCTION
*
* \ingroup PAR_CPU_MMU
*
* This function constructs the needed table entries for a single user defined memory
* region with the following rules:
*
* - build user memory size with blocks of 4K, 64K and 1M portions
*
* - ensure that each block is aligned at size (4K Block is aligned at 4K boundary, etc.)
*
* \param mem Reference to memory region
*
* \note Memory portions below 1KB will be ignored, because the MMU granularity starts with 1kB
*/
/*------------------------------------------------------------------------------------------------*/
static MMU_ERR_T MMUTblAdd(const PAR_MEM_REGION_REF_T mem, INT32U * pMMUTable)
{
INT32U vaddr; /* Local: virtual address */
INT32U off; /* Local: offset in memory region */
INT32U size; /* Local: remaining size of memory region */
MMU_ERR_T err = MMU_ERR_NONE;
/*------------------------------------------*/
vaddr = mem->VA_Start; /* set virtual memory address */
size = mem->Size; /* set size to memory region size */
off = 0; /* set memory region offset to 0 */
if ((vaddr & (MMU_SIZE_1MB - 1)) != 0) { /* see, if VA is not aligned at 4k */
return MMU_ERR_ALIGN;
}
if ((size % MMU_SIZE_1MB) != 0) { /* see, if size is not multiple of 4k */
return MMU_ERR_SIZE;
}
while(size >= MMU_SIZE_1MB) { /* create section for memory region */
err = MMUTblAdd1M(mem, off, pMMUTable); /* add a 1M section */
if(err != MMU_ERR_NONE)
return err;
vaddr += MMU_SIZE_1MB; /* update virtual address and */
off += MMU_SIZE_1MB; /* offset and */
size -= MMU_SIZE_1MB; /* remaining bytes in memory region */
}
return MMU_ERR_NONE;
}
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief INSERT 1M SECTION IN MMU TABLE
*
* \ingroup PAR_CPU_MMU
*
* This function constructs the needed table entries for a single 1M memory block.
*
* \param mem Reference to memory region
*
* \param off Offset within the referenced memory region
*/
/*------------------------------------------------------------------------------------------------*/
static MMU_ERR_T MMUTblAdd1M(PAR_MEM_REGION_REF_T mem, INT32U off, INT32U * pMMUTable)
{
INT32U vaddr; /* Local: virtual address */
INT32U descr; /* Local: translation table descriptor */
INT32U type; /* Local: descriptor type information */
/*------------------------------------------*/
vaddr = mem->VA_Start + off; /* calculate virtual address */
type = FTTGet(vaddr, pMMUTable) & FTT_TYPE; /* get descriptor type */
if (type != FTT_TYPE_FLT) { /* see, if section is already in use */
return MMU_ERR_ENTRY_IN_USE;
}
descr = FTTDescr(mem, off, FTT_TYPE_SEC, 0); /* construct first level section descr. */
FTTSet(vaddr, descr, pMMUTable); /* set section for virtual address */
return MMU_ERR_NONE;
}
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief SET FIRST LEVEL TRANSLATION TABLE DESCRIPTOR
*
* \ingroup PAR_CPU_MMU
*
* This function sets the given descriptor in the first level translation table
* which corresponds to the given virtual address.
*
* \param va Virtual Address
*
* \param descr First level descriptor
*/
/*------------------------------------------------------------------------------------------------*/
static void FTTSet(INT32U va, INT32U descr, INT32U * pMMUTable)
{
volatile INT32U *tbl; /* Local: ptr to first level table entry */
INT32U tbl_idx; /* Local: first level table index */
/*------------------------------------------*/
tbl_idx = (va >> 20) & 0x00000FFF; /* get table index out of virtual address */
tbl = pMMUTable + tbl_idx; /* set first level table base address */
/*------------------------------------------*/
*tbl = descr; /* set descriptor in first level table */
dsb();
isb();
}
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief GET FIRST LEVEL TRANSLATION TABLE DESCRIPTOR
*
* \ingroup PAR_CPU_MMU
*
* This function returns the first level translation table descriptor of the given
* virtual address.
*
* \param va Virtual Address
*
* \return The current active descriptor is returned.
*/
/*------------------------------------------------------------------------------------------------*/
static INT32U FTTGet(INT32U va, INT32U * pMMUTable)
{
volatile INT32U *tbl; /* Local: ptr to first level table entry */
INT32U tbl_idx; /* Local: first level table index */
/*------------------------------------------*/
tbl_idx = (va >> 20) & 0x00000FFF; /* get table index out of virtual address */
tbl = pMMUTable + tbl_idx; /* set first level table base address */
/*------------------------------------------*/
return (*tbl); /* get descriptor in first level table */
}
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief CONSTRUCT FIRST LEVEL TRANSLATION TABLE DESCRIPTOR
*
* \ingroup PAR_CPU_MMU
*
* This function constructs the first level translation table descriptor of the given
* type for the offset within the memory region.
*
* \param mem Reference to memory region
*
* \param offset Offset within the referenced memory region
*
* \param type Type information (section / coarse page / fine page / fault)
*
* \param base Base address of page table
*
* \return For the types FTT_TYPE_SEC, FTT_TYPE_CPT and FTT_TYPE_FPT, the
* corresponding table descriptor is returned. For any other type, the return value is
* the table descriptor for FTT_TYPE_FLT.
*
* \see FTT_TYPE_FLT, FTT_TYPE_CPT, FTT_TYPE_SEC, FTT_TYPE_FPT
*/
/*------------------------------------------------------------------------------------------------*/
static INT32U FTTDescr(PAR_MEM_REGION_REF_T mem, INT32U offset, INT32U type, INT32U base)
{
INT32U result = 0; /* Local: function result */
INT32U pa; /* Local: physical address */
switch(type){
case FTT_TYPE_SEC:
pa = mem->PA_Start + offset; /* yes: calculate physical address */
result = FTT_TYPE_SEC | /* set descriptor type to section */
((mem->HID & PAR_HID_CB_MASK) << 2u) | /* cachable & bufferable flag */
((mem->HID & PAR_HID_F_XN) >> 6u) | /* Execute-Never Flag */
((PAR_DOMAIN_MASTER) << 5) | /* owner = domain */
((mem->AP & 0x3) << 10u) | /* access permissions AP0 and AP1 */
((mem->AP & 0x4) << 13u) | /* access permissions AP2 */
((mem->HID & PAR_HID_TEX_MASK) << 10u) | /* TEX attributes */
((mem->HID & PAR_HID_F_S) << 8u) | /* shareable-flag */
((mem->HID & PAR_HID_F_NG) << 8u) | /* Non-Global-Flag */
((mem->HID & PAR_HID_F_NS) << 8u) | /* non-secure bit */
(pa & 0xFFF00000); /* bits[31:20] of physical address */
break;
case FTT_TYPE_PT:
case FTT_TYPE_FLT:
case FTT_TYPE_RES:
default:
break;
}
return result;
}
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief ENABLE MMU
*
* \ingroup PAR_CPU_MMU
*
* This function enables the MMU.
*
* \note The first level translation table and the page tables must be initialized before
* calling this function.
*/
/*------------------------------------------------------------------------------------------------*/
static void MMUEnable(INT32U * pMMUTable)
{
INT32U ctrl; /* Local: control register */
//Invalidate data and instruction cache
Xil_DCacheDisable();
__set_mmu_table(((INT32U)pMMUTable & 0xFFFFC000) | PAR_TTBR0_FLAGS); /* Set first level transl. table base addr. */
__set_domain_control(0x55555555u); /* set all domains to client */
//eo verwenden noch PD1 = 1 für tlb miss in TTBR1 wird zu translation fault.
__set_asid(0 & 0xFF);
__set_mmu_control(0x00000000); /* Set TTBCR to 0 -> Use TTBR0 and 14Bit alignment */
__clr_mmu_fault();
__dsb();
__invalidate_tlb();
__invalidate_branchpred();
__dsb();
__isb();
ctrl = __get_sys_control(); /* get current control register */
ctrl |= MMU_SCTLR_FLAGS; /* set I,C,S and M to enable MMU */
__set_sys_control(ctrl); /* write new control register */
/*------------------------------------------*/
__no_operation(); /* perform 2 flat fetches */
__no_operation();
#if (UCOS_AMP_MASTER == DEF_ENABLED)
// /* Enable L2 Cache */
// This is a "mandatory" step, don't now why, see Zynq Reference manual
*((CPU_INT32U*)0xF8000A1C) = 0x020202;
Xil_L2CacheEnable();
/* set L2 Aux register */
// CPU_INT32U dat = *((CPU_INT32U*)0xF8F02104);
// dat = 0x72760000;
// *((CPU_INT32U*)0xF8F02104) = dat;
// // /* Set all latencies of tag-ram to 2 */
// // *((CPU_INT32U*)0xF8F02108) = 0x00000111;
// // /* set data ram write and setup latencies to 2, data ram read to 3 */
// // *((CPU_INT32U*)0xF8F0210C) = 0x00000121;
// // /* set prefetch conrtol register */
// // *((CPU_INT32U*)0xF8F02F60) = 0x30000000;
// /* enable L2 Cache */
// *((CPU_INT32U*)0xF8F02100) = 0x1;
#endif
CPU_INT32U actlr = __get_actlr();
actlr &= ~(0x00000040);
__set_actlr(actlr);
/*--- MMU/address translation is enabled ---*/
}
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief Switch Address Space
*
* \ingroup PAR_CPU_MMU
*
* This function switches the address space and manipulates the virt->phys translation.
*
* \param id Partition ID
*/
/*------------------------------------------------------------------------------------------------*/
static void MMUSwitchContext(INT32U id)
{
CPU_INT32U cpu_sr = 0;
/*------------------------------------------*/
OS_ENTER_CRITICAL(); /* Enter critical section */
//We don't need to flush caches, when for all shared memory regions the L1 cache policy is correct write through or disabled
// __flush_caches(); /* Flush caches */
// MMU_DCacheClean();
//We don't need to invalidate the tlb, beacuase we have the ASID value corresponding to a partition
// __invalidate_tlb(); /* Invalidate TLB */
__dsb();
__set_asid(id & 0xFF);
__set_mmu_table(((INT32U)MMUTable & 0xFFFFC000) | PAR_TTBR0_FLAGS); /* Set first level transl. table base addr. */
__dsb();
__isb();
OS_EXIT_CRITICAL(); /* Exit critical section */
/*------------------------------------------*/
}

201
src/Modules/MMU/mmu.h Normal file
View File

@@ -0,0 +1,201 @@
/*
****************************************************************************************************
*
* uC/OS-MMU
*
* (c) Copyright 2012, Micrium, FL
* All rights reserved.
*
* All rights reserved. Protected by international copyright laws.
* Knowledge of the source code may not be used to write a similar
* product. This file may only be used in accordance with a license
* and should not be redistributed in any way.
*
*
* Version : 3.1.2pp-35237
* File : par_mmu.h (#1)
* Programmer(s) : EO
****************************************************************************************************
*/
#ifndef _MMU_H_
#define _MMU_H_
/*
****************************************************************************************************
* INCLUDES
****************************************************************************************************
*/
#include "ucos_ii.h"
/*
****************************************************************************************************
* ERROR DEFINITIONS
****************************************************************************************************
*/
typedef enum{
MMU_ERR_NONE = 0,
MMU_ERR_STT_NOT_IMPLEMENTED,
MMU_ERR_ALIGN,
MMU_ERR_SIZE,
MMU_ERR_ENTRY_IN_USE
}MMU_ERR_T;
/*
****************************************************************************************************
* GENERAL DEFINES FOR MEMORY SPACE CONFIG
****************************************************************************************************
*/
typedef CPU_INT32U PAR_MEM_SIZE_T;
#define MMU_SIZE_1MB (CPU_INT32U)0x00100000 /*!< Region size 1Mbytes */
#define MMU_SIZE_2MB (CPU_INT32U)0x00200000 /*!< Region size 2Mbytes */
#define MMU_SIZE_4MB (CPU_INT32U)0x00400000 /*!< Region size 4Mbytes */
#define MMU_SIZE_8MB (CPU_INT32U)0x00800000 /*!< Region size 8Mbytes */
#define MMU_SIZE_16MB (CPU_INT32U)0x01000000 /*!< Region size 16Mbytes */
#define MMU_SIZE_32MB (CPU_INT32U)0x02000000 /*!< Region size 32Mbytes */
#define MMU_SIZE_64MB (CPU_INT32U)0x04000000 /*!< Region size 64Mbytes */
#define MMU_SIZE_128MB (CPU_INT32U)0x08000000 /*!< Region size 128Mbytes */
#define MMU_SIZE_256MB (CPU_INT32U)0x10000000 /*!< Region size 256Mbytes */
#define MMU_SIZE_512MB (CPU_INT32U)0x20000000 /*!< Region size 512Mbytes */
#define MMU_SIZE_1GB (CPU_INT32U)0x40000000 /*!< Region size 1Gbytes */
#define MMU_SIZE_2GB (CPU_INT32U)0x80000000 /*!< Region size 2Gbytes */
#define MMU_SIZE_4GB (CPU_INT32U)0x00000000 /*!< Region size 4Gbytes */
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief GENERAL ACCESS PERMISSION DEFINES
*
*/
/*------------------------------------------------------------------------------------------------*/
typedef enum{
PAR_AP_P____U___ = 0, /* No Access */
PAR_AP_PRW__U___, /* Priviledged: R+W User: no access */
PAR_AP_PRW__UR__, /* Priviledged: R+W User: R */
PAR_AP_PRW__URW_, /* Priviledged: R+W User: R+W */
PAR_AP_RESERVED1, /* Reserved */
PAR_AP_PR___U___, /* Priviledged: R User: no access */
PAR_AP_PR___UR__, /* Priviledged: R User: R */
PAR_AP_RESERVED2 /* Reserved */
}PAR_MEM_AP_T;
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief GENERAL HARDWARE IMPLEMENTATION DEPENDENT FLAGS
*
* \ingroup PAR_CPU_MMU
*
* This definitions must be used to configure the memory region hardware implementation
* dependent flags within the memory map (\ref PARMemTbl) table:
*/
/*------------------------------------------------------------------------------------------------*/
#define PAR_HID_F__ (CPU_INT32U)(0x00000000)
#define PAR_HID_F_S (CPU_INT32U)(0x00000100) /* Shareable: YES */
#define PAR_HID_F_NG (CPU_INT32U)(0x00000200) /* Non-Global: YES */
#define PAR_HID_F_XN (CPU_INT32U)(0x00000400) /* Execute-Never: YES */
#define PAR_HID_F_NS (CPU_INT32U)(0x00000800) /* Non-secure bit (only available for L1 page table) */
#define PAR_HID_CACHE_INNER___ (CPU_INT32U)(0x00000000) /* Non-Cachable */
#define PAR_HID_CACHE_INNER__B (CPU_INT32U)(0x00000001) /* Write Back, Write Allocate */
#define PAR_HID_CACHE_INNER_C_ (CPU_INT32U)(0x00000002) /* Write through, no write-allocate */
#define PAR_HID_CACHE_INNER_CB (CPU_INT32U)(0x00000003) /* Write Back, no write-allocate */
#define PAR_HID_CACHE_OUTER___ (CPU_INT32U)(0x00000000) /* Non-Cachable */
#define PAR_HID_CACHE_OUTER__B (CPU_INT32U)(0x00000004) /* Write Back, Write Allocate */
#define PAR_HID_CACHE_OUTER_C_ (CPU_INT32U)(0x00000008) /* Write through, no write-allocate */
#define PAR_HID_CACHE_OUTER_CB (CPU_INT32U)(0x0000000C) /* Write Back, no write-allocate */
#define PAR_HID_TEX_CB_STRONGLY_ORDERED (CPU_INT32U)(0x00000000) /* Strongly Ordered */
#define PAR_HID_TEX_CB_SHAREABLE_DEVICE (CPU_INT32U)(0x00000001) /* Shareable device */
#define PAR_HIT_TEX_CB_WRITE_THR_NO_ALLOCATE (CPU_INT32U)(0x00000002) /* Outer and inner write through, no allocate on write */
#define PAR_HID_TEX_CB_WRITEBACK_NO_ALLOCATE (CPU_INT32U)(0x00000003) /* Outer and inner write BACK, no allocate on write */
#define PAR_HID_TEX_CB_OUT_IN_NON_CACHABLE (CPU_INT32U)(0x00000004) /* Outer and inner non-cachable */
#define PAR_HID_TEX_CB_NON_SHAREABLE_DEVICE (CPU_INT32U)(0x0000000A) /* Non-Shareable device */
#define PAR_HID_TEX_CB_CACHED_MEMORY (CPU_INT32U)(0x00000010) /* Cached Memory, use PAR_HID_CACHE_OUTER_XX and PAR_HID_CACHE_INNER_XX to define policies */
#define PAR_HID_TEX_MASK (CPU_INT32U)(0x0000001C)
#define PAR_HID_CB_MASK (CPU_INT32U)(0x00000003)
/* short version for standard system device only accessible from hypervisor and cpu0, not shared between anyone, also called "Mein Schatz!" ;-) */
#define PAR_HID_EXCLUSIVE_SYS_DEVICE (CPU_INT32U)(PAR_HID_TEX_CB_NON_SHAREABLE_DEVICE | PAR_HID_F_NG | PAR_HID_F_XN)
/*
****************************************************************************************************
* TYPE DEFINITIONS
****************************************************************************************************
*/
/*------------------------------------------------------------------------------------------------*/
/*!
* \brief MEMORY SPACE CONFIGURATION STRUCT
*
* \ingroup PAR_CPU_MMU
*
* This structure holds the memory region definitions.
*/
/*------------------------------------------------------------------------------------------------*/
typedef struct {
CPU_INT32U VA_Start; /*!< Virtual Start Address */
CPU_INT32U PA_Start; /*!< Physical Start Address */
PAR_MEM_SIZE_T Size; /*!< Size of Memory Region */
PAR_MEM_AP_T AP; /*!< Access Permission of Memory Region */
CPU_INT32U HID; /*!< Hardware Implementation Dependent Field*/
} PAR_MEM_REGION_T, *PAR_MEM_REGION_REF_T;
/*
****************************************************************************************************
* TARGET SPECIFIC DEFINES
****************************************************************************************************
*/
#define FTT_SIZE 4096 /*!< Size of First Level Translation Table */
/*----- First Level Translation Table ------*/
#define FTT_TYPE (CPU_INT32U)0x00000003 /*!< First Level Descriptor Type Mask */
#define FTT_TYPE_FLT (CPU_INT32U)0x00000000 /*!< Type: Fault */
#define FTT_TYPE_PT (CPU_INT32U)0x00000001 /*!< Type: Page Table */
#define FTT_TYPE_SEC (CPU_INT32U)0x00000002 /*!< Type: Section (1MB) */
#define FTT_TYPE_RES (CPU_INT32U)0x00000003 /*!< Type: Reserved */
#define FTT_OWNER (CPU_INT32U)0x000001E0 /*!< First Level Descriptor Owner Mask */
/*----- Domain Management ------------------*/
#define PAR_DOMAIN_NOACCESS (CPU_INT32U)0x0 /*!< Domain: diable domain */
#define PAR_DOMAIN_CLIENT (CPU_INT32U)0x1 /*!< Domain: domain owner is client */
#define PAR_DOMAIN_MASTER (CPU_INT32U)0x3 /*!< Domain: domain owner is master */
/* TTBR0 Config (armv7refman B4.1.154) Outer Region | not-outer-shareable | inner region | shareable */
#define PAR_TTBR0_FLAGS (CPU_INT32U)((0x41 << 0) | (0x00 << 5u) | (0x03 << 3u) | (0x00 << 1u))
#define MMU_SCTLR_ACCESS_FLAG_ENABLE (0x01 << 29u) //Enable Access flag mode
#define MMU_SCTLR_RR_EN (0x01 << 14u) //Enable RoundRobin Cache Replacement
#define MMU_SCTLR_ICACHE_EN (0x01 << 12u) //Enable Instruction Cache
#define MMU_SCTLR_BRANCH_EN (0x01 << 11u) //Enable Branch Prediction
#define MMU_SCTLR_CACHE_EN (0x01 << 2u) //Enable Data and unified cache
#define MMU_SCTLR_MMU_EN (0x01 << 0u) //Enable MMU
#define MMU_SCTLR_SWP_EN (0x01 << 10u)
#define MMU_SCTLR_FLAGS (CPU_INT32U) (MMU_SCTLR_RR_EN \
| MMU_SCTLR_ICACHE_EN \
| MMU_SCTLR_BRANCH_EN \
| MMU_SCTLR_CACHE_EN \
| MMU_SCTLR_SWP_EN \
| MMU_SCTLR_MMU_EN )
/*
****************************************************************************************************
* FUNCTION PROTOTYPES
****************************************************************************************************
*/
MMU_ERR_T MMUInit (void);
#endif /* #ifndef _MMU_H_ */