TODO: Port ok1028a-c.

This commit is contained in:
liuqh
2024-05-08 15:35:21 +08:00
parent f5ad8437b5
commit 6b91caac18
43 changed files with 2862 additions and 2 deletions

View File

@@ -1,3 +1,8 @@
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )
SRC_DIR := cortex-a9
endif
ifneq ($(findstring $(BOARD), ok1028a-c), )
SRC_DIR := cortex-a72
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,3 @@
SRC_FILES := l1_cache.c
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,285 @@
/**
* @file: l1_cache.c
* @brief: the general management of L1 cache
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2024/04/23
*
*/
/*************************************************
File name: l1_cache.c
Description: the general management of L1 cache
Others:
History:
Author: AIIT XUOS Lab
Modification:
1. implement the l1 cache operations
2. function names are modified to apply softkernel developement
3. function implementations are from modifications of imx6 SDK package
*************************************************/
#include "l1_cache.h"
void InvalidateL1Dcache(uintptr_t start, uintptr_t end)
{
uintptr_t length = end - start;
uintptr_t addr = start;
uint64_t ccsidr_el1;
uint64_t line_size;
uint64_t va;
// get the cache line size
__asm__ __volatile__("mrs %0, ccsidr_el1" : : "=r" (ccsidr_el1));
line_size = 1 << ((ccsidr_el1 & 0x7) + 4);
// align the address with line
const void * end_addr = (const void *)((uint64_t)addr + length);
while (addr < end_addr){
va = (uint64_t)addr & (~(line_size - 1));
//Invalidate data cache line to PoC (Point of Coherence) by va.
__asm__ __volatile__("dc ivac, %0 " : : "r" (va));
// increment addres to next line and decrement lenght
addr = (void*)((uint64_t)addr + line_size);
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void InvalidateL1DcacheAll(void)
{
uint64_t ccsidr_el1; // Cache Size ID
int num_sets; // number of sets
int num_ways; // number of ways
uint32_t wayset; // wayset parameter
__asm__ __volatile__("mrs %0, ccsidr_el1" : : "=r" (ccsidr_el1));// Read Cache Size ID
// Fill number of sets and number of ways from ccsidr_el1 register
num_sets = ((ccsidr_el1 >> 32) & 0x7FFF) + 1;
num_ways = ((ccsidr_el1 >> 0) & 0x7FFF) + 1;
// Invalidation all lines (all Sets in all ways)
for (int way = 0 ; way < num_ways; way++){
for (int set = 0 ;set < num_sets; set++){
wayset = (way << 30) | (set << 5);
__asm__ __volatile__("dc isw, %0" : : "r" (wayset));
}
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void CleanL1Dcache(uintptr_t start, uintptr_t end)
{
void* addr = (void*)start;
uintptr_t length = end - start;
const void * end_addr = (const void *)((uint64_t)addr + length);
uint64_t ccsidr_el1;
uint64_t line_size;
uint64_t va;
// get the cache line size
__asm__ __volatile__("mrs %0, ccsidr_el1" : "=r" (ccsidr_el1));
line_size = 1 << ((ccsidr_el1 & 0x7) + 4);
do
{
va = (uint64_t)addr & (~(line_size - 1));
// Clean data cache line to PoC (Point of Coherence) by va.
__asm__ __volatile__("dc cvac, %0" : : "r" (va));
// increment addres to next line and decrement lenght
addr = (void*)((uint64_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void CleanL1DcacheAll(void)
{
uint64_t ccsidr_el1; // Cache Size ID
int num_sets; // number of sets
int num_ways; // number of ways
uint32_t wayset; // wayset parameter
__asm__ __volatile__("mrs %0, ccsidr_el1" : : "=r" (ccsidr_el1));// Read Cache Size ID
// Fill number of sets and number of ways from ccsidr_el1 register This walues are decremented by 1
num_sets = ((ccsidr_el1 >> 32) & 0x7FFF) + 1;
num_ways = ((ccsidr_el1 >> 0) & 0x7FFF) + 1;
// clean all lines (all Sets in all ways)
for (int way = 0 ; way < num_ways; way++){
for (int set = 0 ;set < num_sets; set++){
wayset = (way << 30) | (set << 5);
__asm__ __volatile__("dc csw, %0" : : "r" (wayset));
}
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void FlushL1Dcache(uintptr_t start, uintptr_t end)
{
void* addr = (void*)start;
// size_t length=end-start;
uint64_t va;
uint64_t ccsidr_el1 = 0, line_size = 0;
const void * end_addr = (const void *)((uint64_t)end);
// get the cache line size
__asm__ __volatile__("mrs %0, ccsidr_el1" : "=r" (ccsidr_el1));
line_size = 1 << ((ccsidr_el1 & 0x7) + 4);
do
{
// Clean data cache line to PoC (Point of Coherence) by va.
va = (uint64_t) ((uint64_t)addr & (~(line_size - 1))); //addr & va_VIRTUAL_ADDRESS_MASK
__asm__ __volatile__("dc civac, %0" : : "r" (va));
// increment addres to next line and decrement lenght
addr = (void*)((uint64_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void FlushL1DcacheAll(void)
{
uint64_t ccsidr_el1; // Cache Size ID
int num_sets; // number of sets
int num_ways; // number of ways
uint32_t wayset; // wayset parameter
__asm__ __volatile__("mrs %0, ccsidr_el1" : : "=r" (ccsidr_el1));// Read Cache Size ID
// Fill number of sets and number of ways from ccsidr_el1 register This walues are decremented by 1
num_sets = ((ccsidr_el1 >> 32) & 0x7FFF) + 1;
num_ways = ((ccsidr_el1 >> 0) & 0x7FFF) + 1;
// clean and invalidate all lines (all Sets in all ways)
for (int way = 0 ; way < num_ways; way++){
for (int set = 0 ;set < num_sets; set++){
wayset = (way << 30) | (set << 5);
__asm__ __volatile__("dc cisw, %0" : : "r" (wayset));
}
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void InvalidateL1IcacheAll()
{
__asm__ __volatile__("ic iallu\n\t");
// synchronize context on this processor
ISB();
}
void InvalidateL1Icache(uintptr_t start, uintptr_t end)
{
uintptr_t length = end - start;
uintptr_t addr = start;
uint64_t ccsidr_el1;
uint64_t line_size;
uint64_t va;
// get the cache line size
__asm__ __volatile__("mrs %0, ccsidr_el1" : : "=r" (ccsidr_el1));
line_size = 1 << ((ccsidr_el1 & 0x7) + 4);
while (addr < end){
va = (uint64_t)addr & (~(line_size - 1));
//Invalidate data cache line to PoC (Point of Coherence) by va.
__asm__ __volatile__("dc ivau, %0 " : : "r" (va));
// increment addres to next line and decrement lenght
addr = (void*)((uint64_t)addr + line_size);
}
// synchronize context on this processor
ISB();
}
void EnableL1Dcache()
{
uint64_t sctlr_el1; // System Control Register
// read sctlr_el1
__asm__ __volatile__("mrs %0, sctlr_el1" : :"=r" (sctlr_el1));
if (!(sctlr_el1 & SCTLR_EL1_DCACHE_ENABLE))
{
// set C bit (data caching enable)
sctlr_el1 |= SCTLR_EL1_DCACHE_ENABLE;
// write modified sctlr_el1
__asm__ __volatile__("msr sctlr_el1, %0" : : "r" (sctlr_el1));
//data synchronization barrier
DSB();
}
}
void DisableL1Dcache()
{
uint64_t sctlr_el1; // System Control Register
// read sctlr_el1
__asm__ __volatile__("mrs %0, sctlr_el1" : : "=r" (sctlr_el1));
// set C bit (data caching enable)
sctlr_el1 &= ~ SCTLR_EL1_DCACHE_ENABLE;
// write modified sctlr_el1
__asm__ __volatile__("msr sctlr_el1, %0" : : "r" (sctlr_el1));
//data synchronization barrier
DSB();
}
void EnableL1Icache()
{
uint64_t sctlr_el1; // System Control Register
// read sctlr_el1
__asm__ __volatile__("mrs %0, sctlr_el1" : : "=r" (sctlr_el1));
if (!(sctlr_el1 & SCTLR_EL1_ICACHE_ENABLE))
{
// set I bit (data caching enable)
sctlr_el1 |= SCTLR_EL1_ICACHE_ENABLE;
// write modified sctlr_el1
__asm__ __volatile__("msr sctlr_el1, %0" : : "r" (sctlr_el1));
//Instruction synchronization barrier
ISB();
}
}
void DisableL1Icache()
{
uint64_t sctlr_el1; // System Control Register
// read sctlr_el1
__asm__ __volatile__("mrs %0, sctlr_el1" : : "=r" (sctlr_el1));
// set I bit (data caching enable)
sctlr_el1 &= ~ SCTLR_EL1_ICACHE_ENABLE;
// write modified sctlr_el1
__asm__ __volatile__("msr sctlr_el1, %0" : : "r" (sctlr_el1));
//Instruction synchronization barrier
ISB();
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: l1_cache.h
* @brief: the general management of L1 cache
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2024/4/23
*
*/
/*************************************************
File name: l1_cache.h
Description: the general management of L1 cache
Others:
History:
Author: AIIT XUOS Lab
Modification:
1、define the l1 cache operations
*************************************************/
#include "cortex-a72/core.h"
#include <stdint.h>
/*
* L1 Cache Operation:
*
* IVAC -Invalidate by Virtual Address, to Point of Coherency AArch32Equivalent :DCIMVAC
*
* ISW -Invalidate by Set/Way AArch32Equivalent :DCISW
*
*CVAC -Clean by Virtual Address to Point of Coherency AArch32Equivalent :DCCMVAC
*
*CSW -Clean by Set/Way AArch32Equivalent :DCCSW
*
*CVAU -Clean by Virtual Address to Point of Unification AArch32Equivalent :DCCMVAU
*
*CIVAC -Clean and invalidate data cache line by VA to PoC. AArch32Equivalent :DCCIMVAC
*
*ISW -Clean and invalidate data cache line by Set/Way. AArch32Equivalent :DCCISW
*/
#define SCTLR_EL1_ICACHE_ENABLE(1 << 12) //!< Instruction cache enable
#define SCTLR_EL1_DCACHE_ENABLE (1 << 2) //!< Data cache enable
void InvalidateL1Dcache(uintptr_t start, uintptr_t end);
void InvalidateL1DcacheAll(void);
void CleanL1Dcache(uintptr_t start, uintptr_t end);
void CleanL1DcacheAll(void);
void FlushL1Dcache(uintptr_t start, uintptr_t end);
void FlushL1DcacheAll(void);
void InvalidateL1IcacheAll(void);
void InvalidateL1Icache(uintptr_t start, uintptr_t end);
void EnableL1Icache(void);
void DisableL1Icache();
void EnableL1Dcache();
void DisableL1Dcache();