From: Lunaixsky Date: Tue, 14 Jan 2025 13:39:33 +0000 (+0000) Subject: aa64: finalise context switch, page fault handler and syscall X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/bb5ae5c85c0812c52e8d53187f2c6b0ee9525c8c?hp=3d33d9c0d1894c447324d8327200c212ddad3716 aa64: finalise context switch, page fault handler and syscall * context switch: pre-switch signposting check, signal handling and ttbr switching * mm_abort: complement page fault handler, fault context gathering for aa64 * klibc: aa64 optimization of str/mem functions * page: page permission fix; proper use of AF and AP[2] * irq: async exception handling with gic framework * other fix arounds and refactorings --- diff --git a/lunaix-os/arch/aarch64/LBuild b/lunaix-os/arch/aarch64/LBuild index bfc3e6d..f04a202 100644 --- a/lunaix-os/arch/aarch64/LBuild +++ b/lunaix-os/arch/aarch64/LBuild @@ -1,20 +1,13 @@ -use("soc/gic") - -sources([ - "boot/init.c", - "boot/kremap.c", - "boot/start.S" -]) +use("boot") +use("exception") +use("klibc") -sources([ - "exception/entries.S", - "exception/context.S", - "exception/handler.c" -]) +use("soc/gic") sources([ "fault.c", - "trace.c" + "trace.c", + "vmutils.c" ]) headers([ diff --git a/lunaix-os/arch/aarch64/boot/LBuild b/lunaix-os/arch/aarch64/boot/LBuild new file mode 100644 index 0000000..437dcaf --- /dev/null +++ b/lunaix-os/arch/aarch64/boot/LBuild @@ -0,0 +1,5 @@ +sources([ + "init.c", + "kremap.c", + "start.S" +]) \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/boot/init.c b/lunaix-os/arch/aarch64/boot/init.c index 42aba1f..45c1621 100644 --- a/lunaix-os/arch/aarch64/boot/init.c +++ b/lunaix-os/arch/aarch64/boot/init.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "init.h" @@ -77,12 +78,62 @@ setup_ttbr() set_sysreg(TCR_EL1, tcr); } +#define MMAP_ENTS_CHUNK_SIZE 16 + static inline void extract_dtb_bootinfo(ptr_t dtb, struct boot_handoff* handoff) { + struct fdt_blob fdt; + struct fdt_memscan mscan; + struct dt_memory_node mnode; + + int mmap_len = 0, mmap_max_len = 16; + size_t pmem_size = 0; + struct boot_mmapent* mmap; + + mmap = bootmem_alloc(sizeof(*mmap) * MMAP_ENTS_CHUNK_SIZE); handoff->kexec.dtb_pa = dtb; // TODO extract /memory, /reserved-memories from dtb + + fdt_load(&fdt, dtb); + fdt_memscan_begin(&mscan, &fdt); + + struct boot_mmapent* mmap_ent; + + while(fdt_memscan_nextnode(&mscan, &fdt)) + { + while (fdt_memscan_nextrange(&mscan, &mnode)) + { + mmap_ent = &mmap[mmap_len++]; + *mmap_ent = (struct boot_mmapent) { + .size = mnode.size, + .start = mnode.base + }; + + if (mnode.type == FDT_MEM_FREE) { + mmap_ent->type = BOOT_MMAP_FREE; + pmem_size += mnode.size; + } + else { + mmap_ent->type = BOOT_MMAP_RSVD; + } + + + if (mmap_len < mmap_max_len) { + continue; + } + + mmap_max_len += MMAP_ENTS_CHUNK_SIZE; + + // another allocation is just expanding the previous allocation. + bootmem_alloc(sizeof(*mmap) * MMAP_ENTS_CHUNK_SIZE); + } + } + + handoff->mem.mmap = mmap; + handoff->mem.mmap_len = mmap_len; + handoff->mem.size = pmem_size; } static inline void @@ -119,13 +170,13 @@ setup_gic_sysreg() sysreg_flagging(ICC_SRE_EL1, ICC_SRE_SRE, 0); } -void +void boot_text aarch64_pre_el1_init() { setup_gic_sysreg(); } -bool +bool boot_text aarch64_prepare_el1_transfer() { ptr_t spsr; @@ -134,11 +185,12 @@ aarch64_prepare_el1_transfer() el = read_sysreg(CurrentEL) >> 2; if (el == 1) { + // no transfer required return false; } - spsr = SPSR_AllInt | SPSR_I | SPSR_F | SPSR_SP; - spsr = BITS_SET(spsr, SPSR_EL, 1); + spsr = SPSR_EL1_preset; + spsr |= SPSR_AllInt | SPSR_I | SPSR_F | SPSR_A; if (el == 2) { set_sysreg(SPSR_EL2, spsr); @@ -150,7 +202,7 @@ aarch64_prepare_el1_transfer() return true; } -struct boot_handoff* +struct boot_handoff* boot_text aarch64_init(ptr_t dtb) { setup_evbar(); diff --git a/lunaix-os/arch/aarch64/boot/kremap.c b/lunaix-os/arch/aarch64/boot/kremap.c index b91d1d5..9cddb4d 100644 --- a/lunaix-os/arch/aarch64/boot/kremap.c +++ b/lunaix-os/arch/aarch64/boot/kremap.c @@ -8,7 +8,7 @@ static pte_t kpt[LEVEL_SIZE][32]; -ptr_t +ptr_t boot_text kremap() { struct pt_alloc alloc; diff --git a/lunaix-os/arch/aarch64/boot/start.S b/lunaix-os/arch/aarch64/boot/start.S index 05787b6..489d4f7 100644 --- a/lunaix-os/arch/aarch64/boot/start.S +++ b/lunaix-os/arch/aarch64/boot/start.S @@ -38,8 +38,8 @@ 1: mov x0, x19 adr x4, aarch64_init - bl x4 + blr x4 // x0: ptr to boot_handoff adr x4, kernel_bootstrap - bl x4 \ No newline at end of file + blr x4 \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/exception/LBuild b/lunaix-os/arch/aarch64/exception/LBuild new file mode 100644 index 0000000..db6ee25 --- /dev/null +++ b/lunaix-os/arch/aarch64/exception/LBuild @@ -0,0 +1,8 @@ +sources([ + "entries.S", + "context.S", + "syscall_nr.S", + "handler.c", + "syscall.c", + "vmswitch.c" +]) \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/exception/context.S b/lunaix-os/arch/aarch64/exception/context.S index e30f72d..23e875b 100644 --- a/lunaix-os/arch/aarch64/exception/context.S +++ b/lunaix-os/arch/aarch64/exception/context.S @@ -1,7 +1,13 @@ #define __ASM__ #include +#include #include "hart_fields.inc" +.section .data + .align 4 + .skip 256 + _aa64_csw_temp_stack: + .section .text .globl _aa64_evec_prehandle @@ -85,4 +91,22 @@ _aa64_switch_task: // TODO - b do_eret \ No newline at end of file + adr sp, _aa64_csw_temp_stack + + bl aa64_switch_ttbr + + bl switch_signposting + cbnz x0, _aa64_handle_signal + + b do_eret + + _aa64_handle_signal: + mov x1, #SPSR_EL0_preset + msr SPSR_EL1, x1 + + ldr x1, [x0, #sigact] + msr ELR_E1, x1 + + msr SP_EL0, x0 + + eret \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/exception/handler.c b/lunaix-os/arch/aarch64/exception/handler.c index 0c861bb..a6e601b 100644 --- a/lunaix-os/arch/aarch64/exception/handler.c +++ b/lunaix-os/arch/aarch64/exception/handler.c @@ -2,6 +2,11 @@ #include #include +extern void +handle_mm_abort(struct hart_state* state); + +extern void +aa64_syscall(struct hart_state* hstate); static inline void update_thread_context(struct hart_state* state) @@ -21,10 +26,7 @@ update_thread_context(struct hart_state* state) } } -extern void -handle_mm_abort(struct hart_state* state); - -static void +static inline void handle_sync_exception(struct hart_state* hstate) { unsigned int ec; @@ -40,16 +42,27 @@ handle_sync_exception(struct hart_state* hstate) handle_mm_abort(hstate); break; + case EC_SVC: + aa64_syscall(hstate); + break; + default: fail("unhandled exception (synced)"); break; } } -static void +static inline void handle_async_exception(struct hart_state* hstate) { + int err = 0; + + err = gic_handle_irq(hstate); + if (!err) { + return; + } + // TODO do we have other cases of async exception? } struct hart_state* diff --git a/lunaix-os/arch/aarch64/exception/hart_fields.inc b/lunaix-os/arch/aarch64/exception/hart_fields.inc index 5e9d63b..0792638 100644 --- a/lunaix-os/arch/aarch64/exception/hart_fields.inc +++ b/lunaix-os/arch/aarch64/exception/hart_fields.inc @@ -30,3 +30,14 @@ hart_regs: hart_execp: .struct hart_execp + execp_end hart_end: + + .struct 0 +sig_num: + .struct sig_pend + 4 +sigact: + .struct sigact + 8 +sighand: + .struct sighand + 8 +saved_hstate: + .struct saved_hstate + 8 +sig_end: \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/exception/syscall.c b/lunaix-os/arch/aarch64/exception/syscall.c new file mode 100644 index 0000000..39224c0 --- /dev/null +++ b/lunaix-os/arch/aarch64/exception/syscall.c @@ -0,0 +1,45 @@ +#include +#include + +#include +#include "asm/aa64_exception.h" + +extern ptr_t syscall_table[__SYSCALL_MAX]; + +void +aa64_syscall(struct hart_state* hstate) +{ + unsigned int call_id; + + call_id = esr_iss(hstate->execp.syndrome); + call_id = call_id & 0xffff; + + if (call_id >= __SYSCALL_MAX) { + return EINVAL; + } + + if (!syscall_table[call_id]) { + return EINVAL; + } + + register reg_t param0 asm("x0") = hstate->registers.x[0]; + register reg_t param1 asm("x1") = hstate->registers.x[1]; + register reg_t param2 asm("x2") = hstate->registers.x[2]; + register reg_t param3 asm("x3") = hstate->registers.x[3]; + register reg_t param4 asm("x4") = hstate->registers.x[4]; + + asm volatile ( + "blr %[call_fn]" + : + "=r"(param0) + : + [call_fn] "r"(syscall_table[call_id]), + "r"(param0), + "r"(param1), + "r"(param2), + "r"(param3), + "r"(param4) + ); + + hstate->registers.x[0] = param0; +} \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/exception/syscall_nr.S b/lunaix-os/arch/aarch64/exception/syscall_nr.S new file mode 100644 index 0000000..121951e --- /dev/null +++ b/lunaix-os/arch/aarch64/exception/syscall_nr.S @@ -0,0 +1,4 @@ + +.globl syscall_table + +#include \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/exception/vmswitch.c b/lunaix-os/arch/aarch64/exception/vmswitch.c new file mode 100644 index 0000000..0bf02ca --- /dev/null +++ b/lunaix-os/arch/aarch64/exception/vmswitch.c @@ -0,0 +1,42 @@ +#include +#include +#include + +void +aa64_switch_ttbr() +{ + ptr_t ttbr; + struct proc_mm* vms; + + vms = proc_vmroot(); + + ttbr = read_sysreg(TTBR0_EL1); + + /* + We don't differentiate ASID for now + and CnP=1 + */ + + if (!BITS_GET(ttbr, TTBR_BADDR) == vms->vmroot) { + return; + } + + BITS_SET(ttbr, TTBR_BADDR, vms->vmroot); + + set_sysreg(TTBR0_EL1, ttbr); + + /* + TODO a more fine grain control of flushing + Unlike x86, hardware will not flush TLB upon switching + the translation base. + + as kernel address space are shared, flushing should be avoided, + thus the apporachs: + 1. enable the use of ASID and flush accordingly + 2. enable the use of ASID and TTBR1 to house kernel, + use TCR_EL1.A1 to switch between ASIDs in TTBR0 and TTBR1. + 3. range flushing (RVAAE1) on all memory regions used by user space. + + */ + __tlb_flush_all(); +} \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/fault.c b/lunaix-os/arch/aarch64/fault.c index e551d68..29f8e97 100644 --- a/lunaix-os/arch/aarch64/fault.c +++ b/lunaix-os/arch/aarch64/fault.c @@ -1,9 +1,36 @@ #include #include +#include #include +bool +__arch_prepare_fault_context(struct fault_context* fault) +{ + struct hart_state* hs = fault->hstate; + + ptr_t ptr = read_sysreg(FAR_EL1); + if (!ptr) { + return false; + } + + fault->fault_ptep = mkptep_va(VMS_SELF, ptr); + fault->fault_data = esr_ec(hs->execp.syndrome); + fault->fault_instn = hart_pc(hs); + fault->fault_va = ptr; + + return true; +} + void handle_mm_abort(struct hart_state* state) { - // TODO + struct fault_context fault; + + __arch_prepare_fault_context(&fault); + + if (!handle_page_fault(&fault)) { + fault_resolving_failed(&fault); + } + + return; } \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/includes/arch-listings/devnum_fn.lst b/lunaix-os/arch/aarch64/includes/arch-listings/devnum_fn.lst deleted file mode 100644 index e69de29..0000000 diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h b/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h index db74b88..776eac4 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h @@ -23,6 +23,7 @@ #define EC_BTI 0b001101 #define EC_EXEC_STATE 0b001110 #define EC_SYS_INST 0b011000 +#define EC_SVC 0b010101 #define EC_I_ABORT 0b100000 #define EC_I_ABORT_EL 0b100001 diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_gic.h b/lunaix-os/arch/aarch64/includes/asm/aa64_gic.h index dfc7e7e..03942cb 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_gic.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_gic.h @@ -3,6 +3,7 @@ #include #include "aa64_msrs.h" +#include "hart.h" #define FRAME_SIZE 0x10000 @@ -130,4 +131,7 @@ typedef unsigned long gicreg64_t; #define GITS_CWRRD_OFF BITFIELD(19, 5) +int +gic_handle_irq(struct hart_state* hs); + #endif /* __LUNAIX_AA64_GIC_H */ diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_mmu.h b/lunaix-os/arch/aarch64/includes/asm/aa64_mmu.h index 9f5c914..5bb176b 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_mmu.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_mmu.h @@ -2,6 +2,7 @@ #define __LUNAIX_AA64_MMU_H #include "aa64_asm.h" +#include #if defined(CONFIG_AA64_PAGE_GRAN_4K) #define _MMU_TG 0b01 @@ -47,4 +48,8 @@ #define TCR_EPD0 (1UL << 7) #define TCR_A1 (1UL << 22) +#define TTBR_ASID BITFIELD(63, 48) +#define TTBR_BADDR BITFIELD(47, 1) +#define TTBR_CnP BITFLAG(0) + #endif /* __LUNAIX_AA64_MMU_H */ diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_msrs.h b/lunaix-os/arch/aarch64/includes/asm/aa64_msrs.h index 546a241..7add284 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_msrs.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_msrs.h @@ -21,6 +21,8 @@ #define SP_EL0 __sr_encode(3, 0, 4, 1, 0) #define SP_EL1 __sr_encode(3, 4, 4, 1, 0) +#define FAR_EL1 __sr_encode(3, 0, 6, 0, 0) + #define ID_AA64PFR0_EL1 __sr_encode(3, 0, 0, 4, 0) #ifndef __ASM__ diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h b/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h index 04482b2..dfe770b 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h @@ -7,10 +7,15 @@ #define SPSR_EL BITFIELD(3, 2) #define SPSR_SP BITFLAG(0) -#define SPSR_I BITFLAG(7) #define SPSR_F BITFLAG(6) #define SPSR_I BITFLAG(7) +#define SPSR_A BITFLAG(8) #define SPSR_AllInt BITFLAG(13) +#define SPSR_PAN BITFLAG(22) +#define SPSR_UAO BITFLAG(23) + +#define SPSR_EL0_preset (BITS_AT(0, SPSR_EL) | SPSR_SP) +#define SPSR_EL1_preset (BITS_AT(1, SPSR_EL) | SPSR_SP | SPSR_UAO) static inline bool spsr_from_el0(reg_t spsr) diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_sysinst.h b/lunaix-os/arch/aarch64/includes/asm/aa64_sysinst.h index 230c455..f2a69a5 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_sysinst.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_sysinst.h @@ -22,4 +22,6 @@ _x; \ }) +#define data_barrier asm ("dsb sy") + #endif /* __LUNAIX_AA64_SYSINST_H */ diff --git a/lunaix-os/arch/aarch64/includes/asm/abi.h b/lunaix-os/arch/aarch64/includes/asm/abi.h index cc18bba..dac3d26 100644 --- a/lunaix-os/arch/aarch64/includes/asm/abi.h +++ b/lunaix-os/arch/aarch64/includes/asm/abi.h @@ -5,15 +5,21 @@ #ifndef __ASM__ +#include +#include + #define align_stack(ptr) ((ptr) & ~15) -#define store_retval(retval) current_thread->hstate->registers.x[0] = (retval) -#define store_retval_to(th, retval) (th)->hstate->registers.x[0] = (retval) +#define store_retval(retval) \ + current_thread->hstate->registers.x[0] = (retval) + +#define store_retval_to(th, retval) \ + (th)->hstate->registers.x[0] = (retval) static inline void must_inline noret -switch_context() { - // TODO +switch_context() +{ asm ("b _aa64_switch_task"); unreachable; } @@ -45,7 +51,12 @@ abi_get_callframe() static inline void must_inline j_usr(ptr_t sp, ptr_t pc) { - // TODO + set_sysreg(SPSR_EL1, SPSR_EL0_preset); + set_sysreg(SP_EL0, sp); + set_sysreg(ELR_E1, pc); + asm ("eret"); + + unreachable; } #endif diff --git a/lunaix-os/arch/aarch64/includes/asm/bits.h b/lunaix-os/arch/aarch64/includes/asm/bits.h index 29ed7bf..9e2e319 100644 --- a/lunaix-os/arch/aarch64/includes/asm/bits.h +++ b/lunaix-os/arch/aarch64/includes/asm/bits.h @@ -3,6 +3,7 @@ #include +#ifndef __ASM__ #undef _BITS_EXTRACT #undef _BITS_INSERT @@ -27,5 +28,5 @@ _r; \ }) - +#endif #endif /* __LUNAIX_ARCH_BITS_H */ diff --git a/lunaix-os/arch/aarch64/includes/asm/hart.h b/lunaix-os/arch/aarch64/includes/asm/hart.h index fa1f4bf..52571e6 100644 --- a/lunaix-os/arch/aarch64/includes/asm/hart.h +++ b/lunaix-os/arch/aarch64/includes/asm/hart.h @@ -43,12 +43,14 @@ struct hart_state } compact align(16); static inline int -hart_vector_stamp(struct hart_state* hstate) { +hart_vector_stamp(struct hart_state* hstate) +{ return BITS_GET(hstate->execp.syndrome, SYNDROME_ETYPE); } static inline unsigned int -hart_ecause(struct hart_state* hstate) { +hart_ecause(struct hart_state* hstate) +{ return hstate->execp.syndrome; } @@ -79,8 +81,10 @@ hart_sp(struct hart_state* hstate) static inline bool kernel_context(struct hart_state* hstate) { - // TODO - return false; + reg_t spsr; + + spsr = hstate->execp.spsr; + return !spsr_from_el0(spsr); } static inline ptr_t diff --git a/lunaix-os/arch/aarch64/includes/asm/pagetable.h b/lunaix-os/arch/aarch64/includes/asm/pagetable.h index a6a4195..bdfee2a 100644 --- a/lunaix-os/arch/aarch64/includes/asm/pagetable.h +++ b/lunaix-os/arch/aarch64/includes/asm/pagetable.h @@ -5,6 +5,7 @@ #include #include "aa64_mmu.h" +#include /* ******** Page Table Manipulation ******** */ @@ -62,11 +63,11 @@ struct __pte { // upper attributes -#define _PTE_UXN (1UL << 54) -#define _PTE_PXN (1UL << 53) +#define _PTE_UXN BITFLAG(54) +#define _PTE_PXN BITFLAG(53) #define _PTE_XN (_PTE_UXN | _PTE_PXN) -#define _PTE_Contig (1UL << 52) -#define _PTE_DBM (1UL << 51) +#define _PTE_Contig BITFLAG(52) +#define _PTE_DBM BITFLAG(51) #ifdef _MMU_USE_OA52 #if CONFIG_AA64_PAGE_GRAN_64K @@ -88,17 +89,24 @@ struct __pte { // lower attributes -#define _PTE_nG (1UL << 11) -#define _PTE_AF (1UL << 10) +#define _PTE_nG BITFLAG(11) +#define _PTE_AF BITFLAG(10) // AP bits: R_RNGJG #define _PTE_AP(p, u) ((((p) & 1) << 1 | ((u) & 1)) << 6) -#define _PTE_PRW _PTE_AP(0 , 0) // priv rw, unpriv none -#define _PTE_PRWURW _PTE_AP(0 , 1) // priv rw, unpriv rw -#define _PTE_U _PTE_AP(0 , 1) // generic unpriv flag -#define _PTE_PRO _PTE_AP(1 , 0) // priv ro, unpriv none -#define _PTE_PROURO _PTE_AP(1 , 1) // priv ro, unpriv ro + +// el1 rw, el0 deny all +#define _PTE_PRW _PTE_AP(0 , 0) +// el1 rw, el0 rw +#define _PTE_PRWURW _PTE_AP(0 , 1) +// el0 allow +#define _PTE_U _PTE_AP(0 , 1) +#define _PTE_nDIRTY _PTE_AP(1 , 0) +// el1 ro, el0 deny all +#define _PTE_PRO _PTE_AP(1 , 0) | _PTE_DBM +// el1 ro, el0 ro +#define _PTE_PROURO _PTE_AP(1 , 1) | _PTE_DBM #define _PTE_BLKDESC (0b01) #define _PTE_TABDESC (0b11) @@ -381,13 +389,13 @@ pte_istouched(pte_t pte) static inline pte_t pte_mkclean(pte_t pte) { - return __mkpte_from(pte.val & ~_PTE_DBM); + return __mkpte_from(pte.val | _PTE_nDIRTY); } static inline bool pte_dirty(pte_t pte) { - return !!(pte.val & _PTE_DBM); + return (pte.val & _PTE_DBM) && (pte.val & ~_PTE_nDIRTY); } static inline void diff --git a/lunaix-os/arch/aarch64/includes/asm/tlb.h b/lunaix-os/arch/aarch64/includes/asm/tlb.h index d59f846..6b26a70 100644 --- a/lunaix-os/arch/aarch64/includes/asm/tlb.h +++ b/lunaix-os/arch/aarch64/includes/asm/tlb.h @@ -28,6 +28,7 @@ static inline void must_inline __tlb_invalidate(ptr_t va) { sys_a1(tlbi_vaae1, pack_va(0, 0, va)); + data_barrier; } /** @@ -40,6 +41,7 @@ static inline void must_inline __tlb_flush_asid(unsigned int asid, ptr_t va) { sys_a1(tlbi_vae1, pack_va(asid, 0, va)); + data_barrier; } /** @@ -62,6 +64,7 @@ static inline void must_inline __tlb_flush_all() { sys_a0(tlbi_alle1); + data_barrier; } /** @@ -73,6 +76,7 @@ static inline void must_inline __tlb_flush_asid_all(unsigned int asid) { sys_a1(tlbi_aside1, pack_va(asid, 0, 0)); + data_barrier; } @@ -93,6 +97,7 @@ tlb_flush_range(ptr_t addr, unsigned int npages) } #else sys_a1(tlbi_rvaae1, pack_rva(0, 0, addr, npages, 0)); + data_barrier; #endif } @@ -114,6 +119,7 @@ tlb_flush_asid_range(unsigned int asid, ptr_t addr, unsigned int npages) } #else sys_a1(tlbi_rvae1, pack_rva(asid, 0, addr, npages, 0)); + data_barrier; #endif } diff --git a/lunaix-os/arch/aarch64/klibc/LBuild b/lunaix-os/arch/aarch64/klibc/LBuild new file mode 100644 index 0000000..5e7bc79 --- /dev/null +++ b/lunaix-os/arch/aarch64/klibc/LBuild @@ -0,0 +1,4 @@ +sources([ + "crc.c", + "string.c" +]) \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/klibc/crc.c b/lunaix-os/arch/aarch64/klibc/crc.c new file mode 100644 index 0000000..f2ae189 --- /dev/null +++ b/lunaix-os/arch/aarch64/klibc/crc.c @@ -0,0 +1,25 @@ +#include +#include + +unsigned int +crc32b(unsigned char* data, unsigned int size) +{ + unsigned int register ret asm("x0"); + + asm volatile( + "1: \n" + "ldrb x2, [%[dest], %[l]] \n" + "crc32b %0, %0, x2 \n" + "sub %[l], %[l], %1 \n" + "cbnz %[l], 1b \n" + : + "=r"(ret) + : + "I"(1), + [dest] "r"(data), + [l] "r"(size) + : "x2" + ); + + return ret; +} diff --git a/lunaix-os/arch/aarch64/klibc/string.c b/lunaix-os/arch/aarch64/klibc/string.c new file mode 100644 index 0000000..f590e0b --- /dev/null +++ b/lunaix-os/arch/aarch64/klibc/string.c @@ -0,0 +1,91 @@ +#include +#include + +void* +memcpy(void* dest, const void* src, unsigned long num) +{ + if (unlikely(!num)) + return dest; + + asm volatile( + "1: \n" + "ldrb x0, [%[src], %[l]] \n" + "strb x0, [%[dest], %[l]] \n" + "sub %[l], %[l], %0 \n" + "cbnz %[l], 1b \n" + :: + "I"(1), + [src] "r"(dest), + [dest] "r"(src), + [l] "r"(num) + : "x0" "x1" + ); + + return dest; +} + +void* +memset(void* ptr, int value, unsigned long num) +{ + asm volatile( + "1: \n" + "strb %[val], [%[dest], %[l]] \n" + "sub %[l], %[l], %0 \n" + "cbnz %[l], 1b \n" + :: + "I"(1), + [val] "r"(value), + [dest] "r"(ptr), + [l] "r"(num) + : "x1" + ); + + return ptr; +} + +unsigned long +strlen(const char* str) +{ + unsigned long register _c asm("x0"); + + _c = 0; + asm volatile( + "1: \n" + "ldrb x1, [%[ptr], %0] \n" + "add %0, %0, %1 \n" + "cbnz %0, 1b \n" + : + "=r"(_c) + : + "I"(1), + [ptr] "r"(str) + : "x1" + ); + + return _c; +} + +unsigned long +strnlen(const char* str, unsigned long max_len) +{ + unsigned long register _c asm("x0"); + + _c = 0; + asm volatile( + "1: \n" + "ldrb x1, [%[ptr], %0] \n" + "add %0, %0, %1 \n" + "sub x2, %[len], %0 \n" + "ands x2, x2, x1 \n" + "bne 1b \n" + : + "=r"(_c) + : + "I"(1), + [ptr] "r"(str), + [len] "r"(max_len) + : "x1", "x2" + ); + + return _c; +} \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/soc/gic/common.c b/lunaix-os/arch/aarch64/soc/gic/common.c index 9f270bc..049ff55 100644 --- a/lunaix-os/arch/aarch64/soc/gic/common.c +++ b/lunaix-os/arch/aarch64/soc/gic/common.c @@ -245,8 +245,40 @@ gic_create_context(struct device* gicdev) gic = valloc(sizeof(*gic)); domain = irq_create_domain(gicdev, &gic_domain_ops); + irq_set_default_domain(domain); irq_set_domain_object(gic, domain); gic->domain = domain; return gic; +} + +int +gic_handle_irq(struct hart_state* hs) +{ + int err = 0; + struct gic* gic; + struct gic_pe* pe; + struct irq_domain* domain; + irq_t irq; + + domain = irq_get_default_domain(); + gic = irq_domain_obj(domain, struct gic); + + pe = gic->cores[current_cpu]; + if (!pe->ops->ack_int(pe)) { + return ENOENT; + } + + err = gic_get_interrupt(gic, pe->active_id, &pe->active_int); + if (err) { + return err; + } + + irq = pe->active_int.irq; + assert(irq); + + irq->serve(irq, hs); + + pe->has_active_int = false; + return pe->ops->notify_eoi(pe); } \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/soc/gic/gic_v3.c b/lunaix-os/arch/aarch64/soc/gic/gic_v3.c index 501daf1..401f441 100644 --- a/lunaix-os/arch/aarch64/soc/gic/gic_v3.c +++ b/lunaix-os/arch/aarch64/soc/gic/gic_v3.c @@ -734,6 +734,7 @@ v3_init_its_domain(struct gic* gic, if (type == 0b001) { nr_ents = BITS_GET(gits->typer, GITS_TYPER_Devbits); + nr_ents = 1 << (nr_ents + 1); } else if (type) { nr_ents = gic->nr_cpus; @@ -815,6 +816,11 @@ v3_map_redistributors(struct gic* gic, val = dt_getprop(dtn, "redistributor-stride"); red_stride = val ? val->ref->u32_val : 0; + /* + We assume only a max 16 cores in all scenarios, + no doubt a bad assumption, but the kernel is uniprocessor, + just show some respects to the gic. + */ struct gic_pe *pe, *pes[16]; for (int i = 0; i < nr_red_regions; i++) { diff --git a/lunaix-os/arch/aarch64/vmutils.c b/lunaix-os/arch/aarch64/vmutils.c new file mode 100644 index 0000000..aef8c4c --- /dev/null +++ b/lunaix-os/arch/aarch64/vmutils.c @@ -0,0 +1,33 @@ +#include +#include + +struct leaflet* +dup_leaflet(struct leaflet* leaflet) +{ + ptr_t dest_va, src_va; + struct leaflet* new_leaflet; + + new_leaflet = alloc_leaflet(leaflet_order(leaflet)); + + src_va = leaflet_mount(leaflet); + dest_va = vmap(new_leaflet, KERNEL_DATA); + + memcpy((void*)dest_va, (void*)src_va, PAGE_SIZE); + + leaflet_unmount(leaflet); + vunmap(dest_va, new_leaflet); + + return new_leaflet; +} + +ptr_t +pmm_arch_init_remap(struct pmem* memory, struct boot_handoff* bctx) +{ + unsigned long plist_len; + + plist_len = leaf_count(bctx->mem.size) * sizeof(struct ppage); + + for (int i = 0; i < bctx->mem.mmap_len; i++) { + + } +} diff --git a/lunaix-os/includes/lunaix/bits.h b/lunaix-os/includes/lunaix/bits.h index 65a6ef8..fca3f67 100644 --- a/lunaix-os/includes/lunaix/bits.h +++ b/lunaix-os/includes/lunaix/bits.h @@ -1,9 +1,13 @@ #ifndef __LUNAIX_BITS_H #define __LUNAIX_BITS_H -#include #include +#define BITS_AT(val, bitfield) _BITS_STATIC(val, bitfield) + +#ifndef __ASM__ +#include + #define BITFIELD(h, l) (h), (l) #define BIT(p) BITFIELD(p, p) @@ -15,4 +19,6 @@ #define BITS_SET(to, bitfield, val) _BITS_INSERT(to, val, bitfield) +#endif + #endif /* __LUNAIX_BITS_H */ diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 86e485e..2c8d740 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -379,6 +379,9 @@ exit_thread(void* val); void thread_release_mem(struct thread* thread); +ptr_t +proc_vmroot(); + /* ========= Signal ========= */