原始版本
This commit is contained in:
10
RT_Thread/libcpu/risc-v/virt64/SConscript
Normal file
10
RT_Thread/libcpu/risc-v/virt64/SConscript
Normal file
@ -0,0 +1,10 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
59
RT_Thread/libcpu/risc-v/virt64/cache.c
Normal file
59
RT_Thread/libcpu/risc-v/virt64/cache.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-29 lizhirui first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtdef.h>
|
||||
#include <board.h>
|
||||
#include <riscv.h>
|
||||
#include <cache.h>
|
||||
|
||||
rt_inline rt_uint32_t rt_cpu_icache_line_size()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t rt_cpu_dcache_line_size()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_INVALIDATE)
|
||||
{
|
||||
rt_hw_cpu_icache_invalidate(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_FLUSH)
|
||||
{
|
||||
rt_hw_cpu_dcache_clean(addr, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_cpu_dcache_invalidate(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
rt_base_t rt_hw_cpu_icache_status_local()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_base_t rt_hw_cpu_dcache_status()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rt_hw_sync_cache_local(void *addr, int size)
|
||||
{
|
||||
}
|
||||
88
RT_Thread/libcpu/risc-v/virt64/cache.h
Normal file
88
RT_Thread/libcpu/risc-v/virt64/cache.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-11-09 RT-Thread The first version
|
||||
*/
|
||||
#ifndef __CACHE_H__
|
||||
#define __CACHE_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
/**
|
||||
* @brief These APIs may not be supported by a specified architecture
|
||||
* But we have to include to all the cases to be 'general purpose'
|
||||
*/
|
||||
|
||||
rt_always_inline void rt_hw_cpu_dcache_clean_local(void *addr, int size)
|
||||
{
|
||||
RT_UNUSED(addr);
|
||||
RT_UNUSED(size);
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_dcache_invalidate_local(void *addr, int size)
|
||||
{
|
||||
RT_UNUSED(addr);
|
||||
RT_UNUSED(size);
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_dcache_clean_and_invalidate_local(void *addr, int size)
|
||||
{
|
||||
RT_UNUSED(addr);
|
||||
RT_UNUSED(size);
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_dcache_clean_all_local(void)
|
||||
{
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_dcache_invalidate_all_local(void)
|
||||
{
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_dcache_clean_and_invalidate_all_local(void)
|
||||
{
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_icache_invalidate_local(void *addr, int size)
|
||||
{
|
||||
RT_UNUSED(addr);
|
||||
RT_UNUSED(size);
|
||||
}
|
||||
|
||||
rt_always_inline void rt_hw_cpu_icache_invalidate_all_local(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Multi-core
|
||||
*/
|
||||
|
||||
#define rt_hw_cpu_dcache_clean rt_hw_cpu_dcache_clean_local
|
||||
#define rt_hw_cpu_dcache_invalidate rt_hw_cpu_dcache_invalidate_local
|
||||
#define rt_hw_cpu_dcache_clean_and_invalidate rt_hw_cpu_dcache_clean_and_invalidate_local
|
||||
|
||||
#define rt_hw_cpu_dcache_clean_all rt_hw_cpu_dcache_clean_all_local
|
||||
#define rt_hw_cpu_dcache_invalidate_all rt_hw_cpu_dcache_invalidate_all_local
|
||||
#define rt_hw_cpu_dcache_clean_and_invalidate_all rt_hw_cpu_dcache_clean_and_invalidate_all_local
|
||||
|
||||
#define rt_hw_cpu_icache_invalidate rt_hw_cpu_icache_invalidate_local
|
||||
#define rt_hw_cpu_icache_invalidate_all rt_hw_cpu_icache_invalidate_all_local
|
||||
|
||||
#define rt_hw_icache_invalidate_all rt_hw_cpu_icache_invalidate_all
|
||||
|
||||
/** instruction barrier */
|
||||
static inline void rt_hw_cpu_sync(void) {}
|
||||
|
||||
/**
|
||||
* @brief local cpu icahce & dcache synchronization
|
||||
*
|
||||
* @param addr
|
||||
* @param size
|
||||
*/
|
||||
void rt_hw_sync_cache_local(void *addr, int size);
|
||||
|
||||
#endif /* __CACHE_H__ */
|
||||
94
RT_Thread/libcpu/risc-v/virt64/interrupt.c
Normal file
94
RT_Thread/libcpu/risc-v/virt64/interrupt.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
* 2018/12/27 Jesven Change irq enable/disable to cpu0
|
||||
*/
|
||||
#include <plic.h>
|
||||
#include <mmu.h>
|
||||
#include "tick.h"
|
||||
#include "encoding.h"
|
||||
#include "riscv.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
|
||||
static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
int rt_hw_plic_irq_enable(int irq_number)
|
||||
{
|
||||
plic_irq_enable(irq_number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_plic_irq_disable(int irq_number)
|
||||
{
|
||||
plic_irq_disable(irq_number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will un-mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
plic_set_priority(vector, 1);
|
||||
|
||||
rt_hw_plic_irq_enable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
* @param new_handler the interrupt service routine to be installed
|
||||
* @param old_handler the old interrupt service routine
|
||||
*/
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
if(vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = irq_desc[vector].handler;
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
irq_desc[vector].handler = (rt_isr_handler_t)handler;
|
||||
irq_desc[vector].param = param;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
|
||||
irq_desc[vector].counter = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_init()
|
||||
{
|
||||
/* Enable machine external interrupts. */
|
||||
// set_csr(sie, SIP_SEIP);
|
||||
int idx = 0;
|
||||
/* init exceptions table */
|
||||
for (idx = 0; idx < MAX_HANDLERS; idx++)
|
||||
{
|
||||
irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
|
||||
irq_desc[idx].param = RT_NULL;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
|
||||
irq_desc[idx].counter = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
plic_set_threshold(0);
|
||||
}
|
||||
46
RT_Thread/libcpu/risc-v/virt64/interrupt.h
Normal file
46
RT_Thread/libcpu/risc-v/virt64/interrupt.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic The first version
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPT_H__
|
||||
#define INTERRUPT_H__
|
||||
|
||||
#define MAX_HANDLERS 128
|
||||
|
||||
#include <rthw.h>
|
||||
#include "stack.h"
|
||||
|
||||
enum
|
||||
{
|
||||
EP_INSTRUCTION_ADDRESS_MISALIGNED = 0,
|
||||
EP_INSTRUCTION_ACCESS_FAULT,
|
||||
EP_ILLEGAL_INSTRUCTION,
|
||||
EP_BREAKPOINT,
|
||||
EP_LOAD_ADDRESS_MISALIGNED,
|
||||
EP_LOAD_ACCESS_FAULT,
|
||||
EP_STORE_ADDRESS_MISALIGNED,
|
||||
EP_STORE_ACCESS_FAULT,
|
||||
EP_ENVIRONMENT_CALL_U_MODE,
|
||||
EP_ENVIRONMENT_CALL_S_MODE,
|
||||
EP_RESERVED10,
|
||||
EP_ENVIRONMENT_CALL_M_MODE,
|
||||
EP_INSTRUCTION_PAGE_FAULT, /* page attr */
|
||||
EP_LOAD_PAGE_FAULT, /* read data */
|
||||
EP_RESERVED14,
|
||||
EP_STORE_PAGE_FAULT, /* write data */
|
||||
};
|
||||
|
||||
int rt_hw_plic_irq_enable(int irq_number);
|
||||
int rt_hw_plic_irq_disable(int irq_number);
|
||||
void rt_hw_interrupt_init(void);
|
||||
void rt_hw_interrupt_mask(int vector);
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name);
|
||||
void handle_trap(rt_ubase_t xcause, rt_ubase_t xtval, rt_ubase_t xepc, struct rt_hw_stack_frame *sp);
|
||||
|
||||
#endif
|
||||
40
RT_Thread/libcpu/risc-v/virt64/opcode.h
Normal file
40
RT_Thread/libcpu/risc-v/virt64/opcode.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-11-09 Shell Add portable asm support
|
||||
*/
|
||||
#ifndef __OPCODE_H__
|
||||
#define __OPCODE_H__
|
||||
|
||||
/**
|
||||
* @brief binary opcode pseudo operations
|
||||
* Used to bypass toolchain restriction on extension ISA
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RISC-V instruction formats
|
||||
*/
|
||||
|
||||
/**
|
||||
* R type: .insn r opcode6, func3, func7, rd, rs1, rs2
|
||||
*
|
||||
* +-------+-----+-----+-------+----+---------+
|
||||
* | func7 | rs2 | rs1 | func3 | rd | opcode6 |
|
||||
* +-------+-----+-----+-------+----+---------+
|
||||
* 31 25 20 15 12 7 0
|
||||
*/
|
||||
#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2)
|
||||
|
||||
#ifdef _TOOLCHAIN_SUPP_ZIFENCEI_ISA_
|
||||
#define OPC_FENCE_I "fence.i"
|
||||
#else /* !_TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */
|
||||
#define OPC_FENCE_I ".long 0x0000100F"
|
||||
#endif /* _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */
|
||||
|
||||
#endif /* __OPCODE_H__ */
|
||||
156
RT_Thread/libcpu/risc-v/virt64/plic.c
Normal file
156
RT_Thread/libcpu/risc-v/virt64/plic.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
* 2022-09-16 WangXiaoyao Porting to rv64
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
#include "plic.h"
|
||||
#include <riscv_io.h>
|
||||
#include "encoding.h"
|
||||
#include <interrupt.h>
|
||||
|
||||
#include <riscv.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include <ioremap.h>
|
||||
#else
|
||||
#define rt_ioremap(addr, ...) (addr)
|
||||
#endif
|
||||
|
||||
size_t plic_base = 0x0c000000L;
|
||||
|
||||
/*
|
||||
* Each PLIC interrupt source can be assigned a priority by writing
|
||||
* to its 32-bit memory-mapped priority register.
|
||||
* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
|
||||
* A priority value of 0 is reserved to mean "never interrupt" and
|
||||
* effectively disables the interrupt.
|
||||
* Priority 1 is the lowest active priority, and priority 7 is the highest.
|
||||
* Ties between global interrupts of the same priority are broken by
|
||||
* the Interrupt ID; interrupts with the lowest ID have the highest
|
||||
* effective priority.
|
||||
*/
|
||||
void plic_set_priority(int irq, int priority)
|
||||
{
|
||||
*(uint32_t *)PLIC_PRIORITY(irq) = priority;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each global interrupt can be enabled by setting the corresponding
|
||||
* bit in the enables registers.
|
||||
*/
|
||||
void plic_irq_enable(int irq)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t *)PLIC_ENABLE(hart) = ((*(uint32_t *)PLIC_ENABLE(hart)) | (1 << irq));
|
||||
#ifdef RISCV_VIRT64_S_MODE
|
||||
set_csr(sie, read_csr(sie) | MIP_SEIP);
|
||||
#else
|
||||
set_csr(mie, read_csr(mie) | MIP_MEIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
void plic_irq_disable(int irq)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t *)PLIC_ENABLE(hart) = (((*(uint32_t *)PLIC_ENABLE(hart)) & (~(1 << irq))));
|
||||
}
|
||||
|
||||
/*
|
||||
* PLIC will mask all interrupts of a priority less than or equal to threshold.
|
||||
* Maximum threshold is 7.
|
||||
* For example, a threshold value of zero permits all interrupts with
|
||||
* non-zero priority, whereas a value of 7 masks all interrupts.
|
||||
* Notice, the threshold is global for PLIC, not for each interrupt source.
|
||||
*/
|
||||
void plic_set_threshold(int threshold)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t *)PLIC_THRESHOLD(hart) = threshold;
|
||||
}
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
* Query the PLIC what interrupt we should serve.
|
||||
* Perform an interrupt claim by reading the claim register, which
|
||||
* returns the ID of the highest-priority pending interrupt or zero if there
|
||||
* is no pending interrupt.
|
||||
* A successful claim also atomically clears the corresponding pending bit
|
||||
* on the interrupt source.
|
||||
* RETURN VALUE:
|
||||
* the ID of the highest-priority pending interrupt or zero if there
|
||||
* is no pending interrupt.
|
||||
*/
|
||||
int plic_claim(void)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
int irq = *(uint32_t *)PLIC_CLAIM(hart);
|
||||
return irq;
|
||||
}
|
||||
|
||||
/*
|
||||
* DESCRIPTION:
|
||||
* Writing the interrupt ID it received from the claim (irq) to the
|
||||
* complete register would signal the PLIC we've served this IRQ.
|
||||
* The PLIC does not check whether the completion ID is the same as the
|
||||
* last claim ID for that target. If the completion ID does not match an
|
||||
* interrupt source that is currently enabled for the target, the completion
|
||||
* is silently ignored.
|
||||
* RETURN VALUE: none
|
||||
*/
|
||||
void plic_complete(int irq)
|
||||
{
|
||||
int hart = __raw_hartid();
|
||||
*(uint32_t *)PLIC_COMPLETE(hart) = irq;
|
||||
}
|
||||
|
||||
void plic_set_ie(rt_uint32_t word_index, rt_uint32_t val)
|
||||
{
|
||||
volatile void *plic_ie = (void *)(rt_ubase_t)(plic_base + PLIC_ENABLE_BASE + 0x80 + word_index * 4);
|
||||
writel(val, plic_ie);
|
||||
}
|
||||
|
||||
static void _set_sie(int hartid)
|
||||
{
|
||||
for (size_t i = hartid * WORD_CNT_BYTE; i < 32; i++)
|
||||
plic_set_ie(i, 0xffffffff);
|
||||
}
|
||||
|
||||
void plic_init()
|
||||
{
|
||||
// PLIC takes up 64 MB space
|
||||
plic_base = (size_t)rt_ioremap((void *)plic_base, 64 * 1024 * 1024);
|
||||
|
||||
plic_set_threshold(0);
|
||||
|
||||
for (int i = 0; i < CONFIG_IRQ_NR; i++)
|
||||
{
|
||||
plic_set_priority(i, 1);
|
||||
}
|
||||
|
||||
// in a single core system, only current context was set
|
||||
_set_sie(__raw_hartid());
|
||||
}
|
||||
|
||||
extern struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
/*
|
||||
* Handling an interrupt is a two-step process: first you claim the interrupt
|
||||
* by reading the claim register, then you complete the interrupt by writing
|
||||
* that source ID back to the same claim register. This automatically enables
|
||||
* and disables the interrupt, so there's nothing else to do.
|
||||
*/
|
||||
void plic_handle_irq(void)
|
||||
{
|
||||
int plic_irq = plic_claim();
|
||||
plic_complete(plic_irq);
|
||||
irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
|
||||
}
|
||||
80
RT_Thread/libcpu/risc-v/virt64/plic.h
Normal file
80
RT_Thread/libcpu/risc-v/virt64/plic.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic first version
|
||||
* 2021-10-20 bernard fix s-mode issue
|
||||
*/
|
||||
|
||||
#ifndef __PLIC_H__
|
||||
#define __PLIC_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#define PLIC_PRIORITY_BASE 0x0
|
||||
#define PLIC_PENDING_BASE 0x1000
|
||||
#define PLIC_ENABLE_BASE 0x2000
|
||||
#define PLIC_CONTEXT_BASE 0x200000
|
||||
|
||||
extern size_t plic_base;
|
||||
|
||||
#define VIRT_PLIC_BASE (plic_base)
|
||||
|
||||
#define PLIC_PRIORITY_OFFSET (0x0)
|
||||
#define PLIC_PENDING_OFFSET (0x1000)
|
||||
|
||||
#define PLIC_ENABLE_STRIDE 0x80
|
||||
#define PLIC_CONTEXT_STRIDE 0x1000
|
||||
|
||||
/* RT-Thread runs in S-mode on virt64 by default */
|
||||
#define RISCV_VIRT64_S_MODE
|
||||
|
||||
#ifndef RISCV_VIRT64_S_MODE
|
||||
#define PLIC_MENABLE_OFFSET (0x2000)
|
||||
#define PLIC_MTHRESHOLD_OFFSET (0x200000)
|
||||
#define PLIC_MCLAIM_OFFSET (0x200004)
|
||||
#define PLIC_MCOMPLETE_OFFSET (0x200004)
|
||||
|
||||
#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_MENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE)
|
||||
#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_MTHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE)
|
||||
#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_MCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE)
|
||||
#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_MCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE)
|
||||
|
||||
#else
|
||||
#define PLIC_SENABLE_OFFSET (0x2000 + PLIC_ENABLE_STRIDE)
|
||||
#define PLIC_STHRESHOLD_OFFSET (0x200000 + PLIC_CONTEXT_STRIDE)
|
||||
#define PLIC_SCLAIM_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE)
|
||||
#define PLIC_SCOMPLETE_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE)
|
||||
|
||||
#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_SENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE)
|
||||
#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_STHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE)
|
||||
#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_SCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE)
|
||||
#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_SCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE)
|
||||
#endif
|
||||
|
||||
#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4)
|
||||
#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32))
|
||||
|
||||
#define WORD_CNT_BYTE (1024 / 8)
|
||||
|
||||
/* IRQ config in system, max 1024 (from 0 to 1023) */
|
||||
#define CONFIG_IRQ_NR (128)
|
||||
#define CONFIG_IRQ_WORD (CONFIG_IRQ_NR / 32)
|
||||
|
||||
void plic_set_priority(int irq, int priority);
|
||||
void plic_irq_enable(int irq);
|
||||
void plic_irq_disable(int irq);
|
||||
void plic_set_threshold(int mthreshold);
|
||||
int plic_claim(void);
|
||||
void plic_complete(int irq);
|
||||
|
||||
void plic_set_thresh(rt_uint32_t val);
|
||||
void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val);
|
||||
void plic_init();
|
||||
void plic_handle_irq(void);
|
||||
|
||||
#endif
|
||||
189
RT_Thread/libcpu/risc-v/virt64/riscv_mmu.h
Normal file
189
RT_Thread/libcpu/risc-v/virt64/riscv_mmu.h
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-30 lizhirui first version
|
||||
* 2023-10-12 Shell Add permission control API
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_MMU_H__
|
||||
#define __RISCV_MMU_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include "riscv.h"
|
||||
|
||||
#undef PAGE_SIZE
|
||||
|
||||
#define PAGE_OFFSET_SHIFT 0
|
||||
#define PAGE_OFFSET_BIT 12
|
||||
#define PAGE_SIZE __SIZE(PAGE_OFFSET_BIT)
|
||||
#define PAGE_OFFSET_MASK __MASK(PAGE_OFFSET_BIT)
|
||||
#define VPN0_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT)
|
||||
#define VPN0_BIT 9
|
||||
#define VPN1_SHIFT (VPN0_SHIFT + VPN0_BIT)
|
||||
#define VPN1_BIT 9
|
||||
#define VPN2_SHIFT (VPN1_SHIFT + VPN1_BIT)
|
||||
#define VPN2_BIT 9
|
||||
|
||||
#define PPN0_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT)
|
||||
#define PPN0_BIT 9
|
||||
#define PPN1_SHIFT (PPN0_SHIFT + PPN0_BIT)
|
||||
#define PPN1_BIT 9
|
||||
#define PPN2_SHIFT (PPN1_SHIFT + PPN1_BIT)
|
||||
#define PPN2_BIT 26
|
||||
#define PPN_BITS (PPN0_BIT + PPN1_BIT + PPN2_BIT)
|
||||
|
||||
#define L1_PAGE_SIZE __SIZE(PAGE_OFFSET_BIT + VPN0_BIT + VPN1_BIT)
|
||||
#define L2_PAGE_SIZE __SIZE(PAGE_OFFSET_BIT + VPN0_BIT)
|
||||
#define L3_PAGE_SIZE __SIZE(PAGE_OFFSET_BIT)
|
||||
|
||||
#define ARCH_ADDRESS_WIDTH_BITS 64
|
||||
|
||||
#define PHYSICAL_ADDRESS_WIDTH_BITS 56
|
||||
|
||||
#define PAGE_ATTR_NEXT_LEVEL (0)
|
||||
#define PAGE_ATTR_RWX (PTE_X | PTE_W | PTE_R)
|
||||
#define PAGE_ATTR_READONLY (PTE_R)
|
||||
#define PAGE_ATTR_READEXECUTE (PTE_X | PTE_R)
|
||||
|
||||
#define PAGE_ATTR_USER (PTE_U)
|
||||
#define PAGE_ATTR_SYSTEM (0)
|
||||
|
||||
#define PAGE_DEFAULT_ATTR_LEAF (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G)
|
||||
#define PAGE_DEFAULT_ATTR_NEXT (PAGE_ATTR_NEXT_LEVEL | PTE_V | PTE_G)
|
||||
|
||||
#define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX)
|
||||
|
||||
#define PTE_USED(pte) __MASKVALUE(pte, PTE_V)
|
||||
|
||||
/**
|
||||
* encoding of SATP (Supervisor Address Translation and Protection register)
|
||||
*/
|
||||
#define SATP_MODE_OFFSET 60
|
||||
#define SATP_MODE_BARE 0
|
||||
#define SATP_MODE_SV39 8
|
||||
#define SATP_MODE_SV48 9
|
||||
#define SATP_MODE_SV57 10
|
||||
#define SATP_MODE_SV64 11
|
||||
|
||||
#define ARCH_VADDR_WIDTH 39
|
||||
#define SATP_MODE SATP_MODE_SV39
|
||||
|
||||
#define MMU_MAP_K_DEVICE (PTE_G | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_K_RWCB (PTE_G | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_K_RW (PTE_G | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RWCB (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RWCB_XN (PTE_U | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_U_RW (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V)
|
||||
#define MMU_MAP_EARLY (PAGE_ATTR_RWX | PTE_G | PTE_V)
|
||||
|
||||
#define PTE_XWR_MASK 0xe
|
||||
|
||||
#define ARCH_PAGE_SIZE PAGE_SIZE
|
||||
#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1)
|
||||
#define ARCH_PAGE_SHIFT PAGE_OFFSET_BIT
|
||||
#define ARCH_INDEX_WIDTH 9
|
||||
#define ARCH_INDEX_SIZE (1ul << ARCH_INDEX_WIDTH)
|
||||
#define ARCH_INDEX_MASK (ARCH_INDEX_SIZE - 1)
|
||||
|
||||
#define ARCH_MAP_FAILED ((void *)-1)
|
||||
|
||||
void mmu_set_pagetable(rt_ubase_t addr);
|
||||
void mmu_enable_user_page_access(void);
|
||||
void mmu_disable_user_page_access(void);
|
||||
|
||||
#define RT_HW_MMU_PROT_READ 1
|
||||
#define RT_HW_MMU_PROT_WRITE 2
|
||||
#define RT_HW_MMU_PROT_EXECUTE 4
|
||||
#define RT_HW_MMU_PROT_KERNEL 8
|
||||
#define RT_HW_MMU_PROT_USER 16
|
||||
#define RT_HW_MMU_PROT_CACHE 32
|
||||
|
||||
void rt_hw_asid_init(void);
|
||||
struct rt_aspace;
|
||||
void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl);
|
||||
|
||||
/**
|
||||
* @brief Remove permission from attribution
|
||||
*
|
||||
* @param attr architecture specified mmu attribution
|
||||
* @param prot protect that will be removed
|
||||
* @return size_t returned attribution
|
||||
*/
|
||||
rt_inline size_t rt_hw_mmu_attr_rm_perm(size_t attr, rt_base_t prot)
|
||||
{
|
||||
switch (prot)
|
||||
{
|
||||
/* remove write permission for user */
|
||||
case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER:
|
||||
attr &= ~PTE_W;
|
||||
break;
|
||||
/* remove write permission for kernel */
|
||||
case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL:
|
||||
attr &= ~PTE_W;
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add permission from attribution
|
||||
*
|
||||
* @param attr architecture specified mmu attribution
|
||||
* @param prot protect that will be added
|
||||
* @return size_t returned attribution
|
||||
*/
|
||||
rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, rt_base_t prot)
|
||||
{
|
||||
switch (prot)
|
||||
{
|
||||
/* add write permission for user */
|
||||
case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER:
|
||||
attr |= (PTE_R | PTE_W | PTE_U);
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test permission from attribution
|
||||
*
|
||||
* @param attr architecture specified mmu attribution
|
||||
* @param prot protect that will be test
|
||||
* @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE
|
||||
*/
|
||||
rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot)
|
||||
{
|
||||
rt_bool_t rc = 0;
|
||||
switch (prot & ~RT_HW_MMU_PROT_USER)
|
||||
{
|
||||
/* test write permission for user */
|
||||
case RT_HW_MMU_PROT_WRITE:
|
||||
rc = ((attr & PTE_W) && (attr & PTE_R));
|
||||
break;
|
||||
case RT_HW_MMU_PROT_READ:
|
||||
rc = !!(attr & PTE_R);
|
||||
break;
|
||||
case RT_HW_MMU_PROT_EXECUTE:
|
||||
rc = !!(attr & PTE_X);
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
if (rc && (prot & RT_HW_MMU_PROT_USER))
|
||||
{
|
||||
rc = !!(attr & PTE_U);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
24
RT_Thread/libcpu/risc-v/virt64/start.c
Normal file
24
RT_Thread/libcpu/risc-v/virt64/start.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-12-07 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "board.h"
|
||||
|
||||
void init_bss(void)
|
||||
{
|
||||
unsigned int *dst;
|
||||
|
||||
dst = &__bss_start;
|
||||
while (dst < &__bss_end)
|
||||
{
|
||||
*dst++ = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user