Support armv8.(TODO: fix clock)
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
SRC_FILES := gicv3.c gicv3_distributer.c
|
||||
SRC_FILES := gicv3.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -1,3 +1,14 @@
|
||||
/*
|
||||
* 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 gicv3.c
|
||||
* @brief gicv3 operation
|
||||
@@ -25,47 +36,30 @@ static struct {
|
||||
char* rdist_addrs[NR_CPU];
|
||||
} gicv3;
|
||||
|
||||
static inline uint32_t
|
||||
icc_igrpen1_el1()
|
||||
static inline uint32_t icc_igrpen1_el1()
|
||||
{
|
||||
uint32_t x;
|
||||
__asm__ volatile("mrs %0, S3_0_C12_C12_7" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_icc_igrpen1_el1(uint32_t x)
|
||||
static inline void w_icc_igrpen1_el1(uint32_t x)
|
||||
{
|
||||
__asm__ volatile("msr S3_0_C12_C12_7, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
icc_pmr_el1()
|
||||
static inline uint32_t icc_pmr_el1()
|
||||
{
|
||||
uint32_t x;
|
||||
__asm__ volatile("mrs %0, S3_0_C4_C6_0" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_icc_pmr_el1(uint32_t x)
|
||||
static inline void w_icc_pmr_el1(uint32_t x)
|
||||
{
|
||||
__asm__ volatile("msr S3_0_C4_C6_0, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// static inline uint32_t
|
||||
// icc_iar1_el1()
|
||||
// {
|
||||
// uint32_t x;
|
||||
// __asm__ volatile("mrs %0, S3_0_C12_C12_0" : "=r"(x));
|
||||
// return x;
|
||||
// }
|
||||
|
||||
// static inline void
|
||||
// w_icc_eoir1_el1(uint32_t x)
|
||||
// {
|
||||
// __asm__ volatile("msr S3_0_C12_C12_1, %0" : : "r"(x));
|
||||
// }
|
||||
inline uint32_t gic_read_irq_ack()
|
||||
{
|
||||
uint32_t x;
|
||||
@@ -79,53 +73,45 @@ gic_write_end_of_irq(uint32_t x)
|
||||
__asm__ volatile("msr S3_0_C12_C12_1, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
icc_sre_el1()
|
||||
static inline uint32_t icc_sre_el1()
|
||||
{
|
||||
uint32_t x;
|
||||
__asm__ volatile("mrs %0, S3_0_C12_C12_5" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_icc_sre_el1(uint32_t x)
|
||||
static inline void w_icc_sre_el1(uint32_t x)
|
||||
{
|
||||
__asm__ volatile("msr S3_0_C12_C12_5, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static void
|
||||
gicd_write(uint32_t off, uint32_t val)
|
||||
static void gicd_write(uint32_t off, uint32_t val)
|
||||
{
|
||||
*(volatile uint32_t*)(gicv3.gicd + off) = val;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gicd_read(uint32_t off)
|
||||
static uint32_t gicd_read(uint32_t off)
|
||||
{
|
||||
return *(volatile uint32_t*)(gicv3.gicd + off);
|
||||
}
|
||||
|
||||
static void
|
||||
gicr_write(uint32_t cpuid, uint32_t off, uint32_t val)
|
||||
static void gicr_write(uint32_t cpuid, uint32_t off, uint32_t val)
|
||||
{
|
||||
*(volatile uint32_t*)(gicv3.rdist_addrs[cpuid] + off) = val;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gicr_read(uint32_t cpuid, uint32_t off)
|
||||
static uint32_t gicr_read(uint32_t cpuid, uint32_t off)
|
||||
{
|
||||
return *(volatile uint32_t*)(gicv3.rdist_addrs[cpuid] + off);
|
||||
}
|
||||
|
||||
static void
|
||||
giccinit()
|
||||
static void giccinit()
|
||||
{
|
||||
w_icc_igrpen1_el1(0);
|
||||
w_icc_pmr_el1(0xff);
|
||||
}
|
||||
|
||||
static void
|
||||
gicdinit()
|
||||
static void gicdinit()
|
||||
{
|
||||
gicd_write(D_CTLR, 0);
|
||||
|
||||
@@ -136,8 +122,7 @@ gicdinit()
|
||||
gicd_write(D_IGROUPR(i), ~0);
|
||||
}
|
||||
|
||||
static void
|
||||
gicrinit(uint32_t cpuid)
|
||||
static void gicrinit(uint32_t cpuid)
|
||||
{
|
||||
gicr_write(cpuid, R_CTLR, 0);
|
||||
|
||||
|
||||
@@ -32,59 +32,6 @@ Modification:
|
||||
|
||||
#include <mmio_access.h>
|
||||
|
||||
//! @addtogroup gic
|
||||
//! @{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Options for sending a software generated interrupt.
|
||||
//!
|
||||
//! These options are used for the @a filter_list parameter of the gic_send_sgi()
|
||||
//! function. They control how to select which CPUs that the interrupt is
|
||||
//! sent to.
|
||||
enum _gicd_sgi_filter {
|
||||
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
|
||||
kGicSgiFilter_UseTargetList = 0,
|
||||
|
||||
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
|
||||
//! the interrupt.
|
||||
kGicSgiFilter_AllOtherCPUs = 1,
|
||||
|
||||
//! Forward the interrupt only to the CPU interface of the processor that requested the
|
||||
//! interrupt.
|
||||
kGicSgiFilter_OnlyThisCPU = 2
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((__always_inline__)) static inline uint32_t get_arm_private_peripheral_base()
|
||||
{
|
||||
return MMIO_P2V(0x00A00000);
|
||||
}
|
||||
|
||||
__attribute__((__always_inline__)) static inline uint32_t irq_get_register_offset(uint32_t irqID)
|
||||
{
|
||||
return irqID / 32;
|
||||
}
|
||||
|
||||
__attribute__((__always_inline__)) static inline uint32_t irq_get_bit_offset(uint32_t irqID)
|
||||
{
|
||||
return irqID & 0x1f;
|
||||
}
|
||||
|
||||
__attribute__((__always_inline__)) static inline uint32_t irq_get_bit_mask(uint32_t irqID)
|
||||
{
|
||||
return 1 << irq_get_bit_offset(irqID);
|
||||
}
|
||||
|
||||
//! @name Initialization
|
||||
//@{
|
||||
//! @brief Init interrupt handling.
|
||||
@@ -98,13 +45,6 @@ __attribute__((__always_inline__)) static inline uint32_t irq_get_bit_mask(uint3
|
||||
//! that were pending are cleared, and all interrupts are made secure (group 0).
|
||||
void gic_init(void);
|
||||
|
||||
//! @brief Init the current CPU's GIC interface.
|
||||
//!
|
||||
//! @post Enables the CPU interface and sets the priority mask to 255. Interrupt preemption
|
||||
//! is disabled by setting the Binary Point to a value of 7.
|
||||
void gic_init_cpu(void);
|
||||
//@}
|
||||
|
||||
//! @name GIC Interrupt Distributor Functions
|
||||
//@{
|
||||
//! @brief Enable or disable the GIC Distributor.
|
||||
@@ -192,10 +132,6 @@ uint32_t gic_read_irq_ack(void);
|
||||
void gic_write_end_of_irq(uint32_t irq_id);
|
||||
//@}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* @file gicv3_distributer.c
|
||||
* @brief gicv3_distributer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2024.05.10
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: gicv3_distributer.c
|
||||
Description: gicv3_distributer operation
|
||||
Others:
|
||||
History:
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
*************************************************/
|
||||
#include "string.h"
|
||||
|
||||
#include "gicv3_common_opa.h"
|
||||
#include "gicv3_registers.h"
|
||||
|
||||
static inline gicd_t* gic_get_gicd(void)
|
||||
{
|
||||
uint64_t base = get_arm_private_peripheral_base() + kGICDBaseOffset;
|
||||
return (gicd_t*)base;
|
||||
}
|
||||
|
||||
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt)
|
||||
{
|
||||
// Make sure the CPU number is valid.
|
||||
gicd_t* gicd = gic_get_gicd();
|
||||
uint8_t cpuMask = 1 << cpuNumber;
|
||||
|
||||
if (enableIt) {
|
||||
gicd->ITARGETSRn[irqID] |= (cpuMask & 0xff);
|
||||
} else {
|
||||
gicd->ITARGETSRn[irqID] &= ~(cpuMask & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_irq_security(uint32_t irqID, bool isSecure)
|
||||
{
|
||||
gicd_t* gicd = gic_get_gicd();
|
||||
|
||||
uint32_t reg = irq_get_register_offset(irqID);
|
||||
uint32_t mask = irq_get_bit_mask(irqID);
|
||||
|
||||
uint32_t value = gicd->IGROUPRn[reg];
|
||||
if (!isSecure) {
|
||||
value &= ~mask;
|
||||
} else {
|
||||
value |= mask;
|
||||
}
|
||||
gicd->IGROUPRn[reg] = value;
|
||||
}
|
||||
|
||||
void gic_enable_irq(uint32_t irqID, bool isEnabled)
|
||||
{
|
||||
gicd_t* gicd = gic_get_gicd();
|
||||
|
||||
uint32_t reg = irq_get_register_offset(irqID);
|
||||
uint32_t mask = irq_get_bit_mask(irqID);
|
||||
|
||||
// Select set-enable or clear-enable register based on enable flag.
|
||||
if (isEnabled) {
|
||||
gicd->ISENABLERn[reg] = mask;
|
||||
} else {
|
||||
gicd->ICENABLERn[reg] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_irq_priority(uint32_t ID, uint32_t priority)
|
||||
{
|
||||
gicd_t* gicd = gic_get_gicd();
|
||||
|
||||
gicd->IPRIORITYRn[ID] = priority & 0xff;
|
||||
}
|
||||
+3
-65
@@ -24,15 +24,14 @@ Modification:
|
||||
1. Rename the file
|
||||
*************************************************/
|
||||
|
||||
#ifndef __LINUX_IRQCHIP_ARM_GIC_H
|
||||
#define __LINUX_IRQCHIP_ARM_GIC_H
|
||||
#pragma once
|
||||
|
||||
#include "memlayout.h"
|
||||
|
||||
// clang-format off
|
||||
// interrupt controller GICv3
|
||||
#define GICV3 (DEV_VRTMEM_BASE + 0x08000000L)
|
||||
#define GICV3_REDIST (DEV_VRTMEM_BASE + 0x080a0000L)
|
||||
#define GICV3 MMIO_P2V_WO(0x08000000ULL)
|
||||
#define GICV3_REDIST MMIO_P2V_WO(0x080a0000ULL)
|
||||
|
||||
#define D_CTLR 0x0
|
||||
#define D_TYPER 0x4
|
||||
@@ -57,65 +56,4 @@ Modification:
|
||||
#define R_ICFGR0 (SGI_BASE + 0xc00)
|
||||
#define R_ICFGR1 (SGI_BASE + 0xc04)
|
||||
#define R_IGRPMODR0 (SGI_BASE + 0xd00)
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum _gic_base_offsets {
|
||||
kGICDBaseOffset = 0x10000, //!< GIC distributor offset.
|
||||
kGICCBaseOffset = 0x100 //!< GIC CPU interface offset.
|
||||
};
|
||||
|
||||
//! @brief GIC distributor registers.
|
||||
//!
|
||||
//! Uses the GICv2 register names, but does not include GICv2 registers.
|
||||
//!
|
||||
//! The IPRIORITYRn and ITARGETSRn registers are byte accessible, so their types are uint8_t
|
||||
//! instead of uint32_t to reflect this. These members are indexed directly with the interrupt
|
||||
//! number.
|
||||
struct _gicd_registers {
|
||||
uint32_t CTLR; //!< Distributor Control Register.
|
||||
uint32_t TYPER; //!< Interrupt Controller Type Register.
|
||||
uint32_t IIDR; //!< Distributor Implementer Identification Register.
|
||||
uint32_t _reserved0[29];
|
||||
uint32_t IGROUPRn[8]; //!< Interrupt Group Registers.
|
||||
uint32_t _reserved1[24];
|
||||
uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers.
|
||||
uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers.
|
||||
uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers.
|
||||
uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers.
|
||||
uint32_t ICDABRn[32]; //!< Active Bit Registers.
|
||||
uint32_t _reserved2[32];
|
||||
uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible)
|
||||
uint32_t _reserved3;
|
||||
uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible)
|
||||
uint32_t _reserved4;
|
||||
uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers.
|
||||
uint32_t _reserved5[128];
|
||||
uint32_t SGIR; //!< Software Generated Interrupt Register
|
||||
};
|
||||
|
||||
//! @brief Bitfields constants for the GICD_CTLR register.
|
||||
enum _gicd_ctlr_fields {
|
||||
kBM_GICD_CTLR_EnableGrp1 = (1 << 1),
|
||||
kBM_GICD_CTLR_EnableGrp0 = (1 << 0)
|
||||
};
|
||||
|
||||
enum _gicd_sgir_fields {
|
||||
kBP_GICD_SGIR_TargetListFilter = 24,
|
||||
kBM_GICD_SGIR_TargetListFilter = (0x3 << kBP_GICD_SGIR_TargetListFilter),
|
||||
|
||||
kBP_GICD_SGIR_CPUTargetList = 16,
|
||||
kBM_GICD_SGIR_CPUTargetList = (0xff << kBP_GICD_SGIR_CPUTargetList),
|
||||
|
||||
kBP_GICD_SGIR_NSATT = 15,
|
||||
kBM_GICD_SGIR_NSATT = (1 << kBP_GICD_SGIR_NSATT),
|
||||
|
||||
kBP_GICD_SGIR_SGIINTID = 0,
|
||||
kBM_GICD_SGIR_SGIINTID = 0xf
|
||||
};
|
||||
|
||||
typedef volatile struct _gicd_registers gicd_t;
|
||||
+11
@@ -1,3 +1,14 @@
|
||||
/*
|
||||
* 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 exception_registers.h
|
||||
* @brief exception registers
|
||||
|
||||
@@ -41,18 +41,20 @@ extern void iabort_handler(struct trapframe* r);
|
||||
void kernel_abort_handler(struct trapframe* tf)
|
||||
{
|
||||
uint64_t esr = r_esr_el1();
|
||||
switch ((esr >> 26) & 0x3F) {
|
||||
switch ((esr >> 0x1A) & 0x3F) {
|
||||
case 0b100100:
|
||||
case 0b100101:
|
||||
dabort_handler(tf);
|
||||
break;
|
||||
case 0b100000:
|
||||
case 0b100001:
|
||||
iabort_handler(tf);
|
||||
break;
|
||||
default:
|
||||
uint64_t ec = (esr >> 26) & 0x3f;
|
||||
uint64_t iss = esr & 0x1ffffff;
|
||||
ERROR("esr %p %p %p\n", esr, ec, iss);
|
||||
ERROR("elr = %p far = %p\n", r_elr_el1(), r_far_el1());
|
||||
ERROR("esr: %016lx %016lx %016lx\n", esr, ec, iss);
|
||||
ERROR("elr = %016lx far = %016lx\n", r_elr_el1(), r_far_el1());
|
||||
ERROR("Current Task: %s.\n", cur_cpu()->task->name);
|
||||
panic("Unimplemented Error Occured.\n");
|
||||
}
|
||||
@@ -67,11 +69,30 @@ void kernel_intr_handler(struct trapframe* tf)
|
||||
extern void context_switch(struct context**, struct context*);
|
||||
void syscall_arch_handler(struct trapframe* tf)
|
||||
{
|
||||
uint64_t ec = (r_esr_el1() >> 0x1A) & 0x3F;
|
||||
if (ec == 0b010101) {
|
||||
w_esr_el1(0);
|
||||
|
||||
uint64_t esr = r_esr_el1();
|
||||
uint64_t ec = (esr >> 0x1A) & 0x3F;
|
||||
w_esr_el1(0);
|
||||
switch (ec) {
|
||||
case 0B010101:
|
||||
software_irq_dispatch(tf);
|
||||
} else {
|
||||
kernel_abort_handler(tf);
|
||||
break;
|
||||
case 0b100100:
|
||||
case 0b100101:
|
||||
dabort_handler(tf);
|
||||
break;
|
||||
case 0b100000:
|
||||
case 0b100001:
|
||||
iabort_handler(tf);
|
||||
break;
|
||||
default:
|
||||
printf("USYSCALL: unexpected ec: %016lx", esr);
|
||||
printf(" elr = %016lx far = %016lx\n", r_elr_el1(), r_far_el1());
|
||||
// kill error task
|
||||
xizi_enter_kernel();
|
||||
assert(cur_cpu()->task != NULL);
|
||||
sys_exit(cur_cpu()->task);
|
||||
context_switch(&cur_cpu()->task->thread_context.context, cur_cpu()->scheduler);
|
||||
panic("dabort end should never be reashed.\n");
|
||||
}
|
||||
}
|
||||
+1
-15
@@ -37,13 +37,6 @@ Modification:
|
||||
#include "log.h"
|
||||
#include "multicores.h"
|
||||
|
||||
extern void init_stack(uint64_t, uint64_t);
|
||||
extern void user_trap_swi_enter(void);
|
||||
extern void trap_iabort(void);
|
||||
extern void trap_dabort(void);
|
||||
extern void trap_irq_enter(void);
|
||||
extern void trap_undefined_instruction(void);
|
||||
|
||||
static struct XiziTrapDriver xizi_trap_driver;
|
||||
|
||||
void panic(char* s)
|
||||
@@ -53,13 +46,6 @@ void panic(char* s)
|
||||
;
|
||||
}
|
||||
|
||||
/* stack for different mode*/
|
||||
static char mode_stack_pages[NR_CPU][NR_MODE_STACKS][MODE_STACK_SIZE];
|
||||
|
||||
extern uint64_t _vector_jumper;
|
||||
extern uint64_t _vector_start;
|
||||
extern uint64_t _vector_end;
|
||||
|
||||
extern void alltraps();
|
||||
static void _sys_irq_init(int cpu_id)
|
||||
{
|
||||
@@ -84,7 +70,7 @@ static void _cpu_irq_disable(void)
|
||||
|
||||
static void _single_irq_enable(int irq, int cpu, int prio)
|
||||
{
|
||||
gic_setup_spi(cpu, irq);
|
||||
gic_setup_spi((uint32_t)cpu, (uint32_t)irq);
|
||||
}
|
||||
|
||||
static void _single_irq_disable(int irq, int cpu)
|
||||
|
||||
@@ -33,7 +33,6 @@ Modification:
|
||||
#include "core.h"
|
||||
|
||||
.macro savereg
|
||||
msr daifset, #0xf
|
||||
// make room to save registers.
|
||||
sub sp, sp, #272
|
||||
|
||||
@@ -183,6 +182,7 @@ alltraps:
|
||||
b .
|
||||
|
||||
el1sync:
|
||||
msr daifset, #0xf
|
||||
savereg
|
||||
|
||||
mov x0, sp
|
||||
@@ -190,12 +190,16 @@ el1sync:
|
||||
b .
|
||||
|
||||
el1irq:
|
||||
savereg
|
||||
|
||||
msr daifset, #0xf
|
||||
usavereg
|
||||
|
||||
mov x0, sp
|
||||
# this should never happen by design
|
||||
bl kernel_intr_handler
|
||||
b .
|
||||
bl intr_irq_dispatch
|
||||
|
||||
urestorereg
|
||||
msr daifclr, #0xf
|
||||
|
||||
eret
|
||||
|
||||
el0sync:
|
||||
msr daifset, #0xf
|
||||
|
||||
Reference in New Issue
Block a user