TODO: Support armv8
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
SRC_FILES := vector.S trampoline.S $(BOARD)/trap_common.c error_debug.c hard_spinlock.S
|
||||
SRC_FILES := trampoline.S $(BOARD)/trap_common.c $(BOARD)/trap.c error_debug.c hard_spinlock.S
|
||||
|
||||
ifeq ($(BOARD), ok1028a-c)
|
||||
SRC_DIR := gicv3
|
||||
|
||||
@@ -38,48 +38,21 @@ Modification:
|
||||
1. Take only armv8 abort reason part(_abort_reason).
|
||||
2. Modify iabort and dabort handler(in dabort_handler() and iabort_handler())
|
||||
*************************************************/
|
||||
#include <stddef.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "core.h"
|
||||
#include "log.h"
|
||||
#include "multicores.h"
|
||||
#include "spinlock.h"
|
||||
// #include "syscall.h"
|
||||
|
||||
__attribute__((always_inline)) static inline void _abort_reason(uint32_t fault_status)
|
||||
{
|
||||
if ((fault_status & 0x3f) == 0x21) // Alignment failure
|
||||
KPrintf("reason: alignment\n");
|
||||
else if ((fault_status & 0x3f) == 0x4) // Translation fault, level 0
|
||||
KPrintf("reason: sect. translation level 0\n");
|
||||
else if ((fault_status & 0x3f) == 0x5) // Translation fault, level 1
|
||||
KPrintf("reason: sect. translation level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0x6) // Translation fault, level 2
|
||||
KPrintf("reason: sect. translation level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0x7) // Translation fault, level 3
|
||||
KPrintf("reason: sect. translation level 3\n");
|
||||
else if ((fault_status & 0x3f) == 0x3d) // Section Domain fault
|
||||
KPrintf("reason: sect. domain\n");
|
||||
else if ((fault_status & 0x3f) == 0x13) // Permission level 1
|
||||
KPrintf("reason: sect. permission level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0x14) // Permission level 2
|
||||
KPrintf("reason: sect. permission level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0x15) // Permission level 3
|
||||
KPrintf("reason: sect. permission level 3\n");
|
||||
else if ((fault_status & 0x3f) == 0x8) // External abort
|
||||
KPrintf("reason: ext. abort\n");
|
||||
else if ((fault_status & 0x3f) == 0x9) // Access flag fault, level 1
|
||||
KPrintf("reason: sect. Access flag fault level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0xa) // Access flag fault, level 2
|
||||
KPrintf("reason: sect. Access flag fault level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0xb) // Access flag fault, level 3
|
||||
KPrintf("reason: sect. Access flag fault level 3\n");
|
||||
else
|
||||
KPrintf("reason: unknown???\n");
|
||||
}
|
||||
#include "task.h"
|
||||
#include "trap_common.h"
|
||||
|
||||
void dump_tf(struct trapframe* tf)
|
||||
{
|
||||
KPrintf(" elr_el1: 0x%x\n", tf->elr_el1);
|
||||
KPrintf(" spsr_el1: 0x%x\n", tf->spsr_el1);
|
||||
KPrintf(" sp: 0x%x\n", tf->sp);
|
||||
KPrintf(" pc: 0x%x\n", tf->pc);
|
||||
KPrintf(" spsr: 0x%x\n", tf->spsr);
|
||||
KPrintf(" x0: 0x%x\n", tf->x0);
|
||||
KPrintf(" x1: 0x%x\n", tf->x1);
|
||||
KPrintf(" x2: 0x%x\n", tf->x2);
|
||||
@@ -110,12 +83,85 @@ void dump_tf(struct trapframe* tf)
|
||||
KPrintf(" x27: 0x%x\n", tf->x27);
|
||||
KPrintf(" x28: 0x%x\n", tf->x28);
|
||||
KPrintf(" x29: 0x%x\n", tf->x29);
|
||||
KPrintf(" pc: 0x%x\n", tf->pc);
|
||||
KPrintf(" x30: 0x%x\n", tf->x30);
|
||||
}
|
||||
|
||||
void handle_undefined_instruction(struct trapframe* tf)
|
||||
void dabort_reason(struct trapframe* r)
|
||||
{
|
||||
// unimplemented trap handler
|
||||
KPrintf("undefined instruction at %x\n", tf->pc);
|
||||
panic("");
|
||||
uint32_t fault_status, fault_address;
|
||||
__asm__ __volatile__("mrs %0, esr_el1" : "=r"(fault_status));
|
||||
__asm__ __volatile__("mrs %0, far_el1" : "=r"(fault_address));
|
||||
LOG("program counter: 0x%x caused\n", r->pc);
|
||||
LOG("data abort at 0x%x, status 0x%x\n", fault_address, fault_status);
|
||||
if ((fault_status & 0x3f) == 0x21) // Alignment failure
|
||||
KPrintf("reason: alignment\n");
|
||||
else if ((fault_status & 0x3f) == 0x4) // Translation fault, level 0
|
||||
KPrintf("reason: sect. translation level 0\n");
|
||||
else if ((fault_status & 0x3f) == 0x5) // Translation fault, level 1
|
||||
KPrintf("reason: sect. translation level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0x6) // Translation fault, level 2
|
||||
KPrintf("reason: sect. translation level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0x7) // Translation fault, level 3
|
||||
KPrintf("reason: sect. translation level 3\n");
|
||||
else if ((fault_status & 0x3f) == 0x3d) // Section Domain fault
|
||||
KPrintf("reason: sect. domain\n");
|
||||
else if ((fault_status & 0x3f) == 0xd) // Permission level 1
|
||||
KPrintf("reason: sect. permission level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0xe) // Permission level 2
|
||||
KPrintf("reason: sect. permission level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0xf) // Permission level 3
|
||||
KPrintf("reason: sect. permission level 3\n");
|
||||
else if ((fault_status & 0x3f) == 0x14) // External abort
|
||||
KPrintf("reason: ext. abort\n");
|
||||
else if ((fault_status & 0x3f) == 0x9) // Access flag fault, level 1
|
||||
KPrintf("reason: sect. Access flag fault level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0xa) // Access flag fault, level 2
|
||||
KPrintf("reason: sect. Access flag fault level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0xb) // Access flag fault, level 3
|
||||
KPrintf("reason: sect. Access flag fault level 3\n");
|
||||
else
|
||||
KPrintf("reason: unknown???\n");
|
||||
|
||||
dump_tf(r);
|
||||
return;
|
||||
}
|
||||
|
||||
void iabort_reason(struct trapframe* r)
|
||||
{
|
||||
uint32_t fault_status, fault_address;
|
||||
__asm__ __volatile__("mrs %0, esr_el1" : "=r"(fault_status));
|
||||
__asm__ __volatile__("mrs %0, far_el1" : "=r"(fault_address));
|
||||
LOG("program counter: 0x%x caused\n", r->pc);
|
||||
LOG("data abort at 0x%x, status 0x%x\n", fault_address, fault_status);
|
||||
if ((fault_status & 0x3f) == 0x21) // Alignment failure
|
||||
KPrintf("reason: alignment\n");
|
||||
else if ((fault_status & 0x3f) == 0x4) // Translation fault, level 0
|
||||
KPrintf("reason: sect. translation level 0\n");
|
||||
else if ((fault_status & 0x3f) == 0x5) // Translation fault, level 1
|
||||
KPrintf("reason: sect. translation level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0x6) // Translation fault, level 2
|
||||
KPrintf("reason: sect. translation level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0x7) // Translation fault, level 3
|
||||
KPrintf("reason: sect. translation level 3\n");
|
||||
else if ((fault_status & 0x3f) == 0x3d) // Section Domain fault
|
||||
KPrintf("reason: sect. domain\n");
|
||||
else if ((fault_status & 0x3f) == 0xd) // Permission level 1
|
||||
KPrintf("reason: sect. permission level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0xe) // Permission level 2
|
||||
KPrintf("reason: sect. permission level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0xf) // Permission level 3
|
||||
KPrintf("reason: sect. permission level 3\n");
|
||||
else if ((fault_status & 0x3f) == 0x14) // External abort
|
||||
KPrintf("reason: ext. abort\n");
|
||||
else if ((fault_status & 0x3f) == 0x9) // Access flag fault, level 1
|
||||
KPrintf("reason: sect. Access flag fault level 1\n");
|
||||
else if ((fault_status & 0x3f) == 0xa) // Access flag fault, level 2
|
||||
KPrintf("reason: sect. Access flag fault level 2\n");
|
||||
else if ((fault_status & 0x3f) == 0xb) // Access flag fault, level 3
|
||||
KPrintf("reason: sect. Access flag fault level 3\n");
|
||||
else
|
||||
KPrintf("reason: unknown???\n");
|
||||
|
||||
dump_tf(r);
|
||||
return;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
SRC_FILES :=giv3.c
|
||||
SRC_FILES := gicv3.c gicv3_distributer.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -15,14 +15,12 @@ Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
*************************************************/
|
||||
#include "string.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "gicv3_common_opa.h"
|
||||
#include "gicv3_registers.h"
|
||||
|
||||
static void gic_setup_ppi(uint32_t cpuid, uint32_t intid) __attribute__((unused));
|
||||
static void gic_setup_spi(uint32_t intid);
|
||||
|
||||
static struct {
|
||||
char* gicd;
|
||||
char* rdist_addrs[NR_CPU];
|
||||
@@ -56,16 +54,28 @@ 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()
|
||||
// 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;
|
||||
__asm__ volatile("mrs %0, S3_0_C12_C12_0" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_icc_eoir1_el1(uint32_t x)
|
||||
inline void
|
||||
gic_write_end_of_irq(uint32_t x)
|
||||
{
|
||||
__asm__ volatile("msr S3_0_C12_C12_1, %0" : : "r"(x));
|
||||
}
|
||||
@@ -84,12 +94,6 @@ w_icc_sre_el1(uint32_t x)
|
||||
__asm__ volatile("msr S3_0_C12_C12_5, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline gicc_t* gic_get_gicc(void)
|
||||
{
|
||||
uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset;
|
||||
return (gicc_t*)base;
|
||||
}
|
||||
|
||||
static void
|
||||
gicd_write(uint32_t off, uint32_t val)
|
||||
{
|
||||
@@ -129,8 +133,6 @@ gicdinit()
|
||||
uint32_t typer = gicd_read(D_TYPER);
|
||||
uint32_t lines = typer & 0x1f;
|
||||
|
||||
printf("lines %d\n", lines);
|
||||
|
||||
for (int i = 0; i < lines; i++)
|
||||
gicd_write(D_IGROUPR(i), ~0);
|
||||
}
|
||||
@@ -151,8 +153,7 @@ gicrinit(uint32_t cpuid)
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
gic_enable()
|
||||
void gic_enable()
|
||||
{
|
||||
gicd_write(D_CTLR, (1 << 1));
|
||||
w_icc_igrpen1_el1(1);
|
||||
@@ -166,13 +167,9 @@ void gic_init()
|
||||
}
|
||||
|
||||
gicdinit();
|
||||
|
||||
gic_setup_spi(UART0_IRQ);
|
||||
gic_setup_spi(VIRTIO0_IRQ);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
cpuid()
|
||||
static inline uint64_t cpuid()
|
||||
{
|
||||
uint64_t x;
|
||||
__asm__ volatile("mrs %0, mpidr_el1" : "=r"(x));
|
||||
@@ -181,13 +178,11 @@ cpuid()
|
||||
|
||||
void gicv3inithart()
|
||||
{
|
||||
int cpu = cpuid();
|
||||
uint32_t cpu = cpuid();
|
||||
|
||||
giccinit();
|
||||
gicrinit(cpu);
|
||||
|
||||
gic_setup_ppi(cpu, TIMER0_IRQ);
|
||||
|
||||
gic_enable();
|
||||
}
|
||||
|
||||
@@ -254,22 +249,18 @@ gicr_set_prio0(uint32_t cpuid, uint32_t intid)
|
||||
gicr_write(cpuid, R_IPRIORITYR(intid / 4), p);
|
||||
}
|
||||
|
||||
static void
|
||||
gic_setup_ppi(uint32_t cpuid, uint32 intid)
|
||||
void gic_setup_ppi(uint32_t cpuid, uint32_t intid)
|
||||
{
|
||||
gicr_set_prio0(cpuid, intid);
|
||||
gicr_clear_pending(cpuid, intid);
|
||||
gicr_enable_int(cpuid, intid);
|
||||
}
|
||||
|
||||
static void
|
||||
gic_setup_spi(uint32_t intid)
|
||||
void gic_setup_spi(uint32_t cpuid, uint32_t intid)
|
||||
{
|
||||
gic_set_prio0(intid);
|
||||
|
||||
// all interrupts are handled by cpu0
|
||||
gic_set_target(intid, 0);
|
||||
|
||||
gic_set_target(intid, cpuid);
|
||||
gic_clear_pending(intid);
|
||||
gic_enable_int(intid);
|
||||
}
|
||||
@@ -282,14 +273,13 @@ int gic_iar_irq(uint32_t iar)
|
||||
|
||||
// interrupt acknowledge register:
|
||||
// ask GIC what interrupt we should serve.
|
||||
uint32_t
|
||||
gic_iar()
|
||||
uint32_t gic_iar()
|
||||
{
|
||||
return icc_iar1_el1();
|
||||
return gic_read_irq_ack();
|
||||
}
|
||||
|
||||
// tell GIC we've served this IRQ.
|
||||
void gic_eoi(uint32_t iar)
|
||||
{
|
||||
w_icc_eoir1_el1(iar);
|
||||
gic_write_end_of_irq(iar);
|
||||
}
|
||||
|
||||
@@ -142,6 +142,9 @@ void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt);
|
||||
//! 0 being the highest priority.
|
||||
void gic_set_irq_priority(uint32_t irq_id, uint32_t priority);
|
||||
|
||||
void gic_setup_spi(uint32_t cpuid, uint32_t intid);
|
||||
|
||||
void gicv3inithart();
|
||||
//! @brief Send a software generated interrupt to a specific CPU.
|
||||
//!
|
||||
//! @param irq_id The interrupt number to send.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
+30
-22
@@ -1,5 +1,4 @@
|
||||
/*
|
||||
* include/linux/irqchip/gicv3_registers.h
|
||||
*
|
||||
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
|
||||
*
|
||||
@@ -8,7 +7,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
/**
|
||||
* @file gicv3_registers.c
|
||||
* @file gicv3_registers.h
|
||||
* @brief gicv3 registers
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
@@ -28,29 +27,36 @@ Modification:
|
||||
#ifndef __LINUX_IRQCHIP_ARM_GIC_H
|
||||
#define __LINUX_IRQCHIP_ARM_GIC_H
|
||||
|
||||
// clang-format off
|
||||
// interrupt controller GICv3
|
||||
#define GICV3 (DEV_VRTMEM_BASE + 0x08000000L)
|
||||
#define GICV3_REDIST (DEV_VRTMEM_BASE + 0x080a0000L)
|
||||
|
||||
#define D_CTLR 0x0
|
||||
#define D_TYPER 0x4
|
||||
#define D_IGROUPR(n) (0x80 + (uint64)(n) * 4)
|
||||
#define D_ISENABLER(n) (0x100 + (uint64)(n) * 4)
|
||||
#define D_ICENABLER(n) (0x180 + (uint64)(n) * 4)
|
||||
#define D_ISPENDR(n) (0x200 + (uint64)(n) * 4)
|
||||
#define D_ICPENDR(n) (0x280 + (uint64)(n) * 4)
|
||||
#define D_IPRIORITYR(n) (0x400 + (uint64)(n) * 4)
|
||||
#define D_ITARGETSR(n) (0x800 + (uint64)(n) * 4)
|
||||
#define D_ICFGR(n) (0xc00 + (uint64)(n) * 4)
|
||||
#define D_IGROUPR(n) (0x80 + (uint64_t)(n) * 4)
|
||||
#define D_ISENABLER(n) (0x100 + (uint64_t)(n) * 4)
|
||||
#define D_ICENABLER(n) (0x180 + (uint64_t)(n) * 4)
|
||||
#define D_ISPENDR(n) (0x200 + (uint64_t)(n) * 4)
|
||||
#define D_ICPENDR(n) (0x280 + (uint64_t)(n) * 4)
|
||||
#define D_IPRIORITYR(n) (0x400 + (uint64_t)(n) * 4)
|
||||
#define D_ITARGETSR(n) (0x800 + (uint64_t)(n) * 4)
|
||||
#define D_ICFGR(n) (0xc00 + (uint64_t)(n) * 4)
|
||||
|
||||
#define R_CTLR 0x0
|
||||
#define R_WAKER 0x14
|
||||
#define R_CTLR 0x0
|
||||
#define R_WAKER 0x14
|
||||
|
||||
#define SGI_BASE 0x10000
|
||||
#define R_IGROUPR0 (SGI_BASE + 0x80)
|
||||
#define R_ISENABLER0 (SGI_BASE + 0x100)
|
||||
#define R_ICENABLER0 (SGI_BASE + 0x180)
|
||||
#define R_ICPENDR0 (SGI_BASE + 0x280)
|
||||
#define R_IPRIORITYR(n) (SGI_BASE + 0x400 + (n) * 4)
|
||||
#define R_ICFGR0 (SGI_BASE + 0xc00)
|
||||
#define R_ICFGR1 (SGI_BASE + 0xc04)
|
||||
#define R_IGRPMODR0 (SGI_BASE + 0xd00)
|
||||
#define SGI_BASE 0x10000
|
||||
#define R_IGROUPR0 (SGI_BASE + 0x80)
|
||||
#define R_ISENABLER0 (SGI_BASE + 0x100)
|
||||
#define R_ICENABLER0 (SGI_BASE + 0x180)
|
||||
#define R_ICPENDR0 (SGI_BASE + 0x280)
|
||||
#define R_IPRIORITYR(n) (SGI_BASE + 0x400 + (n) * 4)
|
||||
#define R_ICFGR0 (SGI_BASE + 0xc00)
|
||||
#define R_ICFGR1 (SGI_BASE + 0xc04)
|
||||
#define R_IGRPMODR0 (SGI_BASE + 0xd00)
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
||||
@@ -108,4 +114,6 @@ enum _gicd_sgir_fields {
|
||||
|
||||
kBP_GICD_SGIR_SGIINTID = 0,
|
||||
kBM_GICD_SGIR_SGIINTID = 0xf
|
||||
};
|
||||
};
|
||||
|
||||
typedef volatile struct _gicd_registers gicd_t;
|
||||
@@ -58,18 +58,21 @@ Modification:
|
||||
.func _spinlock_lock
|
||||
_spinlock_lock:
|
||||
|
||||
ldxr x1, [x0] // check if the spinlock is currently unlocked
|
||||
sevl
|
||||
wfe
|
||||
// wait for an event signal
|
||||
ldaxrb w1, [x0] // check if the spinlock is currently unlocked
|
||||
cmp x1, #UNLOCKED
|
||||
|
||||
wfe // wait for an event signal
|
||||
bne _spinlock_lock
|
||||
// wfe // wait for an event signal
|
||||
bne _spinlock_lock
|
||||
|
||||
mrs x1, mpidr_el1 // get our CPU ID
|
||||
and x1, x1, #3
|
||||
stxr w2, x1, [x0]
|
||||
cbnz x2, _spinlock_lock // check if the write was successful, if the write failed, start over
|
||||
stxrb w2, w1, [x0]
|
||||
cbnz x2, _spinlock_lock // check if the write was successful, if the write failed, start over
|
||||
|
||||
dmb ish // Ensure that accesses to shared resource have completed
|
||||
dmb ish // Ensure that accesses to shared resource have completed
|
||||
|
||||
mov x0, #0
|
||||
ret
|
||||
@@ -85,17 +88,18 @@ _spinlock_unlock:
|
||||
mrs x1, mpidr_el1 // get our CPU ID
|
||||
and x1, x1, #3
|
||||
|
||||
ldr x2, [x0]
|
||||
cmp x1, x2
|
||||
bne 1f //doesn't match,jump to 1
|
||||
ldr x2, [x0]
|
||||
cmp x1, x2
|
||||
bne 1f //doesn't match,jump to 1
|
||||
|
||||
dmb ish
|
||||
|
||||
dmb ish
|
||||
|
||||
mov x1, #UNLOCKED
|
||||
str x1, [x0]
|
||||
str x1, [x0]
|
||||
|
||||
dsb ish //Ensure that no instructions following the barrier execute until
|
||||
// all memory accesses prior to the barrier have completed.
|
||||
dsb ish //Ensure that no instructions following the barrier execute until
|
||||
// all memory accesses prior to the barrier have completed.
|
||||
|
||||
|
||||
sev // send event to wake up other cores waiting on spinlock
|
||||
@@ -107,3 +111,7 @@ ret
|
||||
mov x0, #1 //doesn't match, so exit with failure
|
||||
ret
|
||||
|
||||
.endfunc
|
||||
|
||||
.end
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file exception_registers.h
|
||||
* @brief exception registers
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2024.05.09
|
||||
*/
|
||||
|
||||
static inline void w_vbar_el1(uint64_t x)
|
||||
{
|
||||
asm volatile("msr vbar_el1, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
r_esr_el1()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mrs %0, esr_el1" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_esr_el1(uint64_t x)
|
||||
{
|
||||
asm volatile("msr esr_el1, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
r_elr_el1()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mrs %0, elr_el1" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
r_far_el1()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mrs %0, far_el1" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
daif()
|
||||
{
|
||||
uint64_t x;
|
||||
asm volatile("mrs %0, daif" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// enable interrupts(irq)
|
||||
static inline void
|
||||
intr_on()
|
||||
{
|
||||
asm volatile("msr daifclr, #0xf" ::: "memory");
|
||||
}
|
||||
|
||||
// disable interrupts(irq)
|
||||
static inline void
|
||||
intr_off()
|
||||
{
|
||||
asm volatile("msr daifset, #0xf" ::: "memory");
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 trap.c
|
||||
* @brief trap interface of hardkernel
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.05.06
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: trap.c
|
||||
Description: trap interface of hardkernel
|
||||
Others:
|
||||
History:
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. first version
|
||||
*************************************************/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "exception_registers.h"
|
||||
#include "multicores.h"
|
||||
#include "syscall.h"
|
||||
#include "task.h"
|
||||
|
||||
extern void dabort_handler(struct trapframe* r);
|
||||
extern void iabort_handler(struct trapframe* r);
|
||||
|
||||
void kernel_abort_handler(struct trapframe* tf)
|
||||
{
|
||||
uint64_t esr = r_esr_el1();
|
||||
switch ((esr & 0x3F) >> 26) {
|
||||
case 0b100100:
|
||||
case 0b100101:
|
||||
dabort_handler(tf);
|
||||
case 0b100000:
|
||||
case 0b100001:
|
||||
iabort_handler(tf);
|
||||
default:
|
||||
panic("Unimplemented Error Occured.\n");
|
||||
}
|
||||
panic("Return from abort handler.\n");
|
||||
}
|
||||
|
||||
void kernel_intr_handler(struct trapframe* tf)
|
||||
{
|
||||
panic("Intr at kernel mode should never happen by design.\n");
|
||||
}
|
||||
|
||||
extern void context_switch(struct context**, struct context*);
|
||||
void syscall_arch_handler(struct trapframe* tf)
|
||||
{
|
||||
uint64_t ec = (r_esr_el1() >> 0x1A) & 0x3F;
|
||||
w_esr_el1(0);
|
||||
if (ec == 0b010101) {
|
||||
software_irq_dispatch(tf);
|
||||
} else {
|
||||
printf("USYSCALL: unexpected ec %p", r_esr_el1());
|
||||
printf(" elr=%p far=%p\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->main_thread.context, cur_cpu()->scheduler);
|
||||
panic("dabort end should never be reashed.\n");
|
||||
}
|
||||
}
|
||||
+30
-73
@@ -29,6 +29,8 @@ Modification:
|
||||
#include <string.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "cortex_a72.h"
|
||||
#include "exception_registers.h"
|
||||
#include "gicv3_common_opa.h"
|
||||
#include "trap_common.h"
|
||||
|
||||
@@ -46,8 +48,6 @@ static struct XiziTrapDriver xizi_trap_driver;
|
||||
|
||||
void panic(char* s)
|
||||
{
|
||||
xizi_trap_driver.cpu_irq_disable();
|
||||
spinlock_unlock(&whole_kernel_lock);
|
||||
KPrintf("panic: %s\n", s);
|
||||
for (;;)
|
||||
;
|
||||
@@ -60,80 +60,55 @@ extern uint64_t _vector_jumper;
|
||||
extern uint64_t _vector_start;
|
||||
extern uint64_t _vector_end;
|
||||
|
||||
void init_cpu_mode_stacks(int cpu_id)
|
||||
{
|
||||
uint32_t modes[] = { ARM_MODE_EL0_t, ARM_MODE_EL1_t, ARM_MODE_EL2_t, ARM_MODE_EL3_t };
|
||||
// initialize the stacks for different mode
|
||||
for (int i = 0; i < sizeof(modes) / sizeof(uint64_t); i++) {
|
||||
memset(mode_stack_pages[cpu_id][i], 0, MODE_STACK_SIZE);
|
||||
init_stack(modes[i], (uint64_t)mode_stack_pages[cpu_id][i]);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_reserved(void)
|
||||
{
|
||||
// unimplemented trap handler
|
||||
LOG("Unimplemented Reserved\n");
|
||||
panic("");
|
||||
}
|
||||
|
||||
void handle_fiq(void)
|
||||
{
|
||||
LOG("Unimplemented FIQ\n");
|
||||
panic("");
|
||||
}
|
||||
// void init_cpu_mode_stacks(int cpu_id)
|
||||
// {
|
||||
// uint32_t modes[] = { ARM_MODE_EL0_t, ARM_MODE_EL1_t, ARM_MODE_EL2_t, ARM_MODE_EL3_t };
|
||||
// // initialize the stacks for different mode
|
||||
// for (int i = 0; i < sizeof(modes) / sizeof(uint64_t); i++) {
|
||||
// memset(mode_stack_pages[cpu_id][i], 0, MODE_STACK_SIZE);
|
||||
// init_stack(modes[i], (uint64_t)mode_stack_pages[cpu_id][i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
extern void alltraps();
|
||||
static void _sys_irq_init(int cpu_id)
|
||||
{
|
||||
/* load exception vectors */
|
||||
init_cpu_mode_stacks(cpu_id);
|
||||
if (cpu_id == 0) {
|
||||
volatile uint64_t* vector_base = &_vector_start;
|
||||
// primary core init intr
|
||||
xizi_trap_driver.switch_hw_irqtbl((uintptr_t*)alltraps);
|
||||
|
||||
// Set Interrupt handler start address
|
||||
vector_base[1] = (uint64_t)trap_undefined_instruction; // Undefined Instruction
|
||||
vector_base[2] = (uint64_t)user_trap_swi_enter; // Software Interrupt
|
||||
vector_base[3] = (uint64_t)trap_iabort; // Prefetch Abort
|
||||
vector_base[4] = (uint64_t)trap_dabort; // Data Abort
|
||||
vector_base[5] = (uint64_t)handle_reserved; // Reserved
|
||||
vector_base[6] = (uint64_t)trap_irq_enter; // IRQ
|
||||
vector_base[7] = (uint64_t)handle_fiq; // FIQ
|
||||
if (cpu_id == 0) {
|
||||
xizi_trap_driver.switch_hw_irqtbl((uintptr_t*)alltraps);
|
||||
gic_init();
|
||||
}
|
||||
/* active hardware irq responser */
|
||||
gic_init();
|
||||
xizi_trap_driver.switch_hw_irqtbl((uint32_t*)&_vector_jumper);
|
||||
gicv3inithart();
|
||||
}
|
||||
|
||||
static void _cpu_irq_enable(void)
|
||||
{
|
||||
arm_set_interrupt_state(true);
|
||||
// arm_set_interrupt_state(true);
|
||||
intr_on();
|
||||
}
|
||||
|
||||
static void _cpu_irq_disable(void)
|
||||
{
|
||||
arm_set_interrupt_state(false);
|
||||
intr_off();
|
||||
}
|
||||
|
||||
static void _single_irq_enable(int irq, int cpu, int prio)
|
||||
{
|
||||
gic_enable();
|
||||
gic_setup_spi(cpu, irq);
|
||||
}
|
||||
|
||||
static void _single_irq_disable(int irq, int cpu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#define VBAR
|
||||
static inline uint32_t _switch_hw_irqtbl(uint32_t* new_tbl_base)
|
||||
static inline uintptr_t* _switch_hw_irqtbl(uintptr_t* new_tbl_base)
|
||||
{
|
||||
uint32_t old_tbl_base = 0;
|
||||
// get old irq table base addr
|
||||
__asm__ volatile("mrs %0, vbar_el1" : "=r"(old_tbl_base));
|
||||
w_vbar_el1((uint64_t)new_tbl_base);
|
||||
|
||||
// set new irq table base addr
|
||||
__asm__ volatile("msr vbar_el1, %0" : : "r"(new_tbl_base));
|
||||
|
||||
return old_tbl_base;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _bind_irq_handler(int irq, irq_handler_t handler)
|
||||
@@ -144,22 +119,13 @@ static void _bind_irq_handler(int irq, irq_handler_t handler)
|
||||
static uint32_t _hw_before_irq()
|
||||
{
|
||||
|
||||
uint32_t vectNum = gic_read_irq_ack();
|
||||
if (vectNum & 0x200) {
|
||||
gic_write_end_of_irq(vectNum);
|
||||
return 0;
|
||||
}
|
||||
return vectNum;
|
||||
uint32_t iar = gic_read_irq_ack();
|
||||
return iar;
|
||||
}
|
||||
|
||||
static uint32_t _hw_cur_int_num(uint32_t int_info)
|
||||
{
|
||||
return int_info & 0x1FF;
|
||||
}
|
||||
|
||||
static __attribute__((unused)) uint32_t _hw_cur_int_cpu(uint32_t int_info)
|
||||
{
|
||||
return (int_info >> 10) & 0x7;
|
||||
return int_info & 0x3FF;
|
||||
}
|
||||
|
||||
static void _hw_after_irq(uint32_t int_info)
|
||||
@@ -167,15 +133,6 @@ static void _hw_after_irq(uint32_t int_info)
|
||||
gic_write_end_of_irq(int_info);
|
||||
}
|
||||
|
||||
static __attribute__((unused)) int _is_interruptable(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
asm volatile("mrs %0, spsr_el1" : "=r"(val));
|
||||
|
||||
return !(val & DIS_INT);
|
||||
}
|
||||
|
||||
int _cur_cpu_id()
|
||||
{
|
||||
return cpu_get_current();
|
||||
@@ -189,7 +146,7 @@ static struct XiziTrapDriver xizi_trap_driver = {
|
||||
.cpu_irq_disable = _cpu_irq_disable,
|
||||
.single_irq_enable = _single_irq_enable,
|
||||
.single_irq_disable = _single_irq_disable,
|
||||
//.switch_hw_irqtbl = _switch_hw_irqtbl,
|
||||
.switch_hw_irqtbl = _switch_hw_irqtbl,
|
||||
|
||||
.bind_irq_handler = _bind_irq_handler,
|
||||
|
||||
|
||||
@@ -35,9 +35,10 @@ Modification:
|
||||
.global trap_irq_enter
|
||||
.global trap_return
|
||||
.global usertrapret
|
||||
.global init_stack
|
||||
|
||||
trap_return:
|
||||
/* Restore registers. */
|
||||
// Restore registers
|
||||
ldp x1, x2, [sp], #16
|
||||
ldp x3, x0, [sp], #16
|
||||
msr sp_el0, x1
|
||||
@@ -92,7 +93,7 @@ user_trap_swi_enter:
|
||||
b trap_return
|
||||
|
||||
trap_irq_enter:
|
||||
/* Build trapframe. */
|
||||
// Build trapframe.
|
||||
stp x29, x30, [sp, #-16]!
|
||||
stp x27, x28, [sp, #-16]!
|
||||
stp x25, x26, [sp, #-16]!
|
||||
@@ -115,15 +116,225 @@ trap_irq_enter:
|
||||
stp x3, x0, [sp, #-16]!
|
||||
stp x1, x2, [sp, #-16]!
|
||||
|
||||
/* Call trap(struct trapframe*). */
|
||||
//Call trap(struct trapframe*)
|
||||
mov x0, sp
|
||||
bl intr_irq_dispatch
|
||||
b trap_return
|
||||
|
||||
|
||||
|
||||
/* Help forkret to call trap_return in an expected way. */
|
||||
// Help forkret to call trap_return in an expected way
|
||||
//usertrapret:
|
||||
// Overlay stack pointer in trap_return
|
||||
// mov sp, x0
|
||||
// b trap_return
|
||||
|
||||
|
||||
init_stack:
|
||||
mrs x2, spsr_el1
|
||||
bic x2, x2, #SPSR_MODE_MASK
|
||||
orr x2, x2, x0
|
||||
msr spsr_el1, x2
|
||||
mov sp, x1
|
||||
bic x2, x2, #SPSR_MODE_MASK
|
||||
orr x2, x2, #ARM_MODE_EL1_t
|
||||
msr spsr_el1, x2
|
||||
ret
|
||||
|
||||
.section ".text"
|
||||
|
||||
.macro savereg
|
||||
msr daifset, #0xf
|
||||
// make room to save registers.
|
||||
sub sp, sp, #272
|
||||
|
||||
// save the registers.
|
||||
stp x0, x1, [sp, #16 * 0]
|
||||
stp x2, x3, [sp, #16 * 1]
|
||||
stp x4, x5, [sp, #16 * 2]
|
||||
stp x6, x7, [sp, #16 * 3]
|
||||
stp x8, x9, [sp, #16 * 4]
|
||||
stp x10, x11, [sp, #16 * 5]
|
||||
stp x12, x13, [sp, #16 * 6]
|
||||
stp x14, x15, [sp, #16 * 7]
|
||||
stp x16, x17, [sp, #16 * 8]
|
||||
stp x18, x19, [sp, #16 * 9]
|
||||
stp x20, x21, [sp, #16 * 10]
|
||||
stp x22, x23, [sp, #16 * 11]
|
||||
stp x24, x25, [sp, #16 * 12]
|
||||
stp x26, x27, [sp, #16 * 13]
|
||||
stp x28, x29, [sp, #16 * 14]
|
||||
mrs x9, elr_el1
|
||||
mrs x10, spsr_el1
|
||||
add x11, sp, #272
|
||||
stp x30, x9, [sp, #16 * 15]
|
||||
stp x10, x11, [sp, #16 * 16]
|
||||
.endm
|
||||
|
||||
.macro restorereg
|
||||
ldp x30, x9, [sp, #16 * 15]
|
||||
ldp x10, x11, [sp, #16 * 16]
|
||||
|
||||
msr elr_el1, x9
|
||||
msr spsr_el1, x10
|
||||
|
||||
ldp x0, x1, [sp, #16 * 0]
|
||||
ldp x2, x3, [sp, #16 * 1]
|
||||
ldp x4, x5, [sp, #16 * 2]
|
||||
ldp x6, x7, [sp, #16 * 3]
|
||||
ldp x8, x9, [sp, #16 * 4]
|
||||
ldp x10, x11, [sp, #16 * 5]
|
||||
ldp x12, x13, [sp, #16 * 6]
|
||||
ldp x14, x15, [sp, #16 * 7]
|
||||
ldp x16, x17, [sp, #16 * 8]
|
||||
ldp x18, x19, [sp, #16 * 9]
|
||||
ldp x20, x21, [sp, #16 * 10]
|
||||
ldp x22, x23, [sp, #16 * 11]
|
||||
ldp x24, x25, [sp, #16 * 12]
|
||||
ldp x26, x27, [sp, #16 * 13]
|
||||
ldp x28, x29, [sp, #16 * 14]
|
||||
add sp, sp, #272
|
||||
.endm
|
||||
|
||||
.macro usavereg
|
||||
msr daifset, #0xf
|
||||
sub sp, sp, #272
|
||||
|
||||
stp x0, x1, [sp, #16 * 0]
|
||||
stp x2, x3, [sp, #16 * 1]
|
||||
stp x4, x5, [sp, #16 * 2]
|
||||
stp x6, x7, [sp, #16 * 3]
|
||||
stp x8, x9, [sp, #16 * 4]
|
||||
stp x10, x11, [sp, #16 * 5]
|
||||
stp x12, x13, [sp, #16 * 6]
|
||||
stp x14, x15, [sp, #16 * 7]
|
||||
stp x16, x17, [sp, #16 * 8]
|
||||
stp x18, x19, [sp, #16 * 9]
|
||||
stp x20, x21, [sp, #16 * 10]
|
||||
stp x22, x23, [sp, #16 * 11]
|
||||
stp x24, x25, [sp, #16 * 12]
|
||||
stp x26, x27, [sp, #16 * 13]
|
||||
stp x28, x29, [sp, #16 * 14]
|
||||
|
||||
mrs x9, elr_el1
|
||||
mrs x10, spsr_el1
|
||||
mrs x11, sp_el0
|
||||
|
||||
stp x30, x9, [sp, #16 * 15]
|
||||
stp x10, x11, [sp, #16 * 16]
|
||||
.endm
|
||||
|
||||
.macro urestorereg
|
||||
ldp x30, x9, [sp, #16 * 15]
|
||||
ldp x10, x11, [sp, #16 * 16]
|
||||
|
||||
msr elr_el1, x9
|
||||
msr spsr_el1, x10
|
||||
msr sp_el0, x11
|
||||
|
||||
ldp x0, x1, [sp, #16 * 0]
|
||||
ldp x2, x3, [sp, #16 * 1]
|
||||
ldp x4, x5, [sp, #16 * 2]
|
||||
ldp x6, x7, [sp, #16 * 3]
|
||||
ldp x8, x9, [sp, #16 * 4]
|
||||
ldp x10, x11, [sp, #16 * 5]
|
||||
ldp x12, x13, [sp, #16 * 6]
|
||||
ldp x14, x15, [sp, #16 * 7]
|
||||
ldp x16, x17, [sp, #16 * 8]
|
||||
ldp x18, x19, [sp, #16 * 9]
|
||||
ldp x20, x21, [sp, #16 * 10]
|
||||
ldp x22, x23, [sp, #16 * 11]
|
||||
ldp x24, x25, [sp, #16 * 12]
|
||||
ldp x26, x27, [sp, #16 * 13]
|
||||
ldp x28, x29, [sp, #16 * 14]
|
||||
|
||||
add sp, sp, #272
|
||||
.endm
|
||||
|
||||
|
||||
.global alltraps
|
||||
.balign 0x800
|
||||
alltraps:
|
||||
// Current EL with sp0
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
|
||||
// Current EL with spx
|
||||
.balign 0x80
|
||||
b el1sync
|
||||
.balign 0x80
|
||||
b el1irq
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
|
||||
// Lower EL using aarch64
|
||||
.balign 0x80
|
||||
b el0sync
|
||||
.balign 0x80
|
||||
b el0irq
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
|
||||
// Lower EL using aarch32
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
.balign 0x80
|
||||
b .
|
||||
|
||||
el1sync:
|
||||
savereg
|
||||
|
||||
mov x0, sp
|
||||
bl kernel_abort_handler
|
||||
|
||||
restorereg
|
||||
|
||||
eret
|
||||
el1irq:
|
||||
savereg
|
||||
|
||||
mov x0, sp
|
||||
# this should never happen by design
|
||||
bl kernel_intr_handler
|
||||
|
||||
restorereg
|
||||
|
||||
eret
|
||||
|
||||
el0sync:
|
||||
usavereg
|
||||
|
||||
mov x0, sp
|
||||
bl syscall_arch_handler
|
||||
|
||||
urestorereg
|
||||
|
||||
eret
|
||||
el0irq:
|
||||
usavereg
|
||||
|
||||
mov x0, sp
|
||||
bl intr_irq_dispatch
|
||||
|
||||
trapret:
|
||||
urestorereg
|
||||
|
||||
eret
|
||||
|
||||
.global usertrapret
|
||||
usertrapret:
|
||||
/* Overlay stack pointer in trap_return. */
|
||||
mov sp, x0
|
||||
b trap_return
|
||||
mov sp, x0
|
||||
b trapret
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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 vector.S
|
||||
* @brief define vector table function
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2024.4.22
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: vector.S
|
||||
Description: cortex-a9 vector table
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2024.4.22
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. first version
|
||||
*************************************************/
|
||||
|
||||
#include "memlayout.h"
|
||||
|
||||
#define ventry .align 7; b trap_irq_enter
|
||||
|
||||
#define verror(type) .align 7; mov x0, #(type); b irq_error
|
||||
|
||||
.globl vectors
|
||||
|
||||
.align 11
|
||||
vectors:
|
||||
el1_sp0:
|
||||
verror(0)
|
||||
verror(1)
|
||||
verror(2)
|
||||
verror(3)
|
||||
|
||||
el1_spx:
|
||||
/* Current EL with SPx */
|
||||
verror(4)
|
||||
verror(5)
|
||||
verror(6)
|
||||
verror(7)
|
||||
|
||||
el0_aarch64:
|
||||
/* Lower EL using AArch64 */
|
||||
ventry
|
||||
ventry
|
||||
verror(10)
|
||||
verror(11)
|
||||
|
||||
el0_aarch32:
|
||||
/* Lower EL using AArch32 */
|
||||
verror(12)
|
||||
verror(13)
|
||||
verror(14)
|
||||
verror(15)
|
||||
@@ -59,7 +59,7 @@ __attribute__((optimize("O0"))) void spinlock_init(struct spinlock* lock, char*
|
||||
}
|
||||
|
||||
extern int _spinlock_lock(struct spinlock* lock, uint32_t timeout);
|
||||
void _spinlock_unlock(struct spinlock* lock);
|
||||
extern void _spinlock_unlock(struct spinlock* lock);
|
||||
|
||||
__attribute__((optimize("O0"))) void spinlock_lock(struct spinlock* lock)
|
||||
{
|
||||
|
||||
@@ -32,12 +32,11 @@ Modification:
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "actracer.h"
|
||||
#include "core.h"
|
||||
#include "irq_numbers.h"
|
||||
#include "memlayout.h"
|
||||
|
||||
#include "actracer.h"
|
||||
|
||||
#define NR_IRQS HW_NR_IRQS
|
||||
#define NR_MODE_STACKS 4
|
||||
|
||||
@@ -65,7 +64,7 @@ struct XiziTrapDriver {
|
||||
void (*single_irq_enable)(int irq, int cpu, int prio);
|
||||
void (*single_irq_disable)(int irq, int cpu);
|
||||
|
||||
uint32_t* (*switch_hw_irqtbl)(uint32_t*);
|
||||
uintptr_t* (*switch_hw_irqtbl)(uintptr_t*);
|
||||
void (*bind_irq_handler)(int, irq_handler_t);
|
||||
|
||||
/* check if no if interruptable */
|
||||
|
||||
Reference in New Issue
Block a user