aa64: finalise context switch, page fault handler and syscall
authorLunaixsky <lunaixsky@qq.com>
Tue, 14 Jan 2025 13:39:33 +0000 (13:39 +0000)
committerLunaixsky <lunaixsky@qq.com>
Tue, 14 Jan 2025 13:39:33 +0000 (13:39 +0000)
* 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

33 files changed:
lunaix-os/arch/aarch64/LBuild
lunaix-os/arch/aarch64/boot/LBuild [new file with mode: 0644]
lunaix-os/arch/aarch64/boot/init.c
lunaix-os/arch/aarch64/boot/kremap.c
lunaix-os/arch/aarch64/boot/start.S
lunaix-os/arch/aarch64/exception/LBuild [new file with mode: 0644]
lunaix-os/arch/aarch64/exception/context.S
lunaix-os/arch/aarch64/exception/handler.c
lunaix-os/arch/aarch64/exception/hart_fields.inc
lunaix-os/arch/aarch64/exception/syscall.c [new file with mode: 0644]
lunaix-os/arch/aarch64/exception/syscall_nr.S [new file with mode: 0644]
lunaix-os/arch/aarch64/exception/vmswitch.c [new file with mode: 0644]
lunaix-os/arch/aarch64/fault.c
lunaix-os/arch/aarch64/includes/arch-listings/devnum_fn.lst [deleted file]
lunaix-os/arch/aarch64/includes/asm/aa64_exception.h
lunaix-os/arch/aarch64/includes/asm/aa64_gic.h
lunaix-os/arch/aarch64/includes/asm/aa64_mmu.h
lunaix-os/arch/aarch64/includes/asm/aa64_msrs.h
lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h
lunaix-os/arch/aarch64/includes/asm/aa64_sysinst.h
lunaix-os/arch/aarch64/includes/asm/abi.h
lunaix-os/arch/aarch64/includes/asm/bits.h
lunaix-os/arch/aarch64/includes/asm/hart.h
lunaix-os/arch/aarch64/includes/asm/pagetable.h
lunaix-os/arch/aarch64/includes/asm/tlb.h
lunaix-os/arch/aarch64/klibc/LBuild [new file with mode: 0644]
lunaix-os/arch/aarch64/klibc/crc.c [new file with mode: 0644]
lunaix-os/arch/aarch64/klibc/string.c [new file with mode: 0644]
lunaix-os/arch/aarch64/soc/gic/common.c
lunaix-os/arch/aarch64/soc/gic/gic_v3.c
lunaix-os/arch/aarch64/vmutils.c [new file with mode: 0644]
lunaix-os/includes/lunaix/bits.h
lunaix-os/includes/lunaix/process.h

index bfc3e6d6b4d4ccae445f20b672abbc9c38b22c82..f04a202a195300cbcfa1c7a9fa612f0c0d0c2dc1 100644 (file)
@@ -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 (file)
index 0000000..437dcaf
--- /dev/null
@@ -0,0 +1,5 @@
+sources([
+    "init.c",
+    "kremap.c",
+    "start.S"
+])
\ No newline at end of file
index 42aba1fa6c917ff5108708c7c60ab654035019aa..45c1621dce214a73ee951867e81a5265009c544a 100644 (file)
@@ -1,6 +1,7 @@
 #include <lunaix/boot_generic.h>
 #include <asm/aa64.h>
 #include <asm/aa64_spsr.h>
+#include <hal/devtree.h>
 
 #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();
index b91d1d5f5ee86fe4d05b5f716292725ddf1e1b3f..9cddb4d9d1c4a849081844218288200472512028 100644 (file)
@@ -8,7 +8,7 @@
 
 static pte_t kpt[LEVEL_SIZE][32];
 
-ptr_t
+ptr_t boot_text
 kremap()
 {
     struct pt_alloc alloc;
index 05787b6f1f7dfcc3ca62b3215d0ef19ca1d24451..489d4f7c32da933c23828c7adc98b5516c036d24 100644 (file)
@@ -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 (file)
index 0000000..db6ee25
--- /dev/null
@@ -0,0 +1,8 @@
+sources([
+    "entries.S",
+    "context.S",
+    "syscall_nr.S",
+    "handler.c",
+    "syscall.c",
+    "vmswitch.c"
+])
\ No newline at end of file
index e30f72d8e574453c926d964f01f3bef0ee327ace..23e875b99639707de984273d346f1052f43f30be 100644 (file)
@@ -1,7 +1,13 @@
 #define __ASM__
 #include <asm/aa64_msrs.h>
+#include <asm/bits.h>
 #include "hart_fields.inc"
 
+.section .data
+    .align 4
+    .skip 256
+    _aa64_csw_temp_stack:
+
 .section .text
     
     .globl _aa64_evec_prehandle
 
     _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
index 0c861bbc6e4c2b33c79938ae3c5577ef41db13d8..a6e601bc15e65f0ef9386d5ed9da6f9f19d13aca 100644 (file)
@@ -2,6 +2,11 @@
 #include <asm/hart.h>
 #include <asm/aa64_exception.h>
 
+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*
index 5e9d63b4181c4c34a2d31a1e746c9f7116e6e7c2..0792638a9c42a23e5f8f01fe12889a5eb7cf2c98 100644 (file)
@@ -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 (file)
index 0000000..39224c0
--- /dev/null
@@ -0,0 +1,45 @@
+#include <lunaix/syscall.h>
+#include <lunaix/status.h>
+
+#include <asm/hart.h>
+#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 (file)
index 0000000..121951e
--- /dev/null
@@ -0,0 +1,4 @@
+
+.globl syscall_table
+
+#include <asm-generic/syscall_nr.inc>
\ 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 (file)
index 0000000..0bf02ca
--- /dev/null
@@ -0,0 +1,42 @@
+#include <lunaix/process.h>
+#include <asm/aa64_mmu.h>
+#include <asm/tlb.h>
+
+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
index e551d683d2d91c5f0d403549ce5d178ef37bc0a8..29f8e97195486260fa226cbdf0ee0087820c0e91 100644 (file)
@@ -1,9 +1,36 @@
 #include <lunaix/mm/fault.h>
 #include <asm/aa64_exception.h>
+#include <asm/aa64_msrs.h>
 #include <asm/hart.h>
 
+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 (file)
index e69de29..0000000
index db74b8869cf4e00aca66491e3af782d0eca0317d..776eac4bc5a1b502e43df4bb3cd7b2041ef2fab7 100644 (file)
@@ -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
index dfc7e7e0170d42c0dd3eeff1aaa62e75ef439cfd..03942cba159a766ce3fc8c9c4eae582e0a7d2e9a 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <lunaix/bits.h>
 #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 */
index 9f5c914cca0772cf82814c8addd748995afbef80..5bb176b2b54ed02d7d79ca9de1c3428aba44a10c 100644 (file)
@@ -2,6 +2,7 @@
 #define __LUNAIX_AA64_MMU_H
 
 #include "aa64_asm.h"
+#include <lunaix/bits.h>
 
 #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 */
index 546a2413a579fa9f78dd77831df5127763b59a76..7add2848c98858de87bc57fe56f9df0676af11a4 100644 (file)
@@ -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__
index 04482b2c3d16ff0b8da39aa29dd6eb69b90a02c1..dfe770bc5eeb02180808af1da4ced5d4f51e8d32 100644 (file)
@@ -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)
index 230c4559e1ae1bad920a3137778b8ace548c35b2..f2a69a501e5300650f35eab3028e4d049f0965f7 100644 (file)
@@ -22,4 +22,6 @@
         _x;                                             \
     })
 
+#define data_barrier        asm ("dsb sy")
+
 #endif /* __LUNAIX_AA64_SYSINST_H */
index cc18bba28d47d3cef59165ba4d8e719063680d7d..dac3d269a0188674c2c12d9c7583414795f8cf38 100644 (file)
@@ -5,15 +5,21 @@
 
 #ifndef __ASM__
 
+#include <asm/aa64_msrs.h>
+#include <asm/aa64_spsr.h>
+
 #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
index 29ed7bf552975ace889653de0990e0e5cab943c2..9e2e319f6014013dca27a987463d99a9b5d8aa87 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm-generic/bits.h>
 
+#ifndef __ASM__
 #undef _BITS_EXTRACT
 #undef _BITS_INSERT
 
@@ -27,5 +28,5 @@
             _r;                         \
         })
 
-
+#endif
 #endif /* __LUNAIX_ARCH_BITS_H */
index fa1f4bfd165f7b30322d84bc398c9b98e27ff13c..52571e67a07664f5aee5379a8834c51e7655ed39 100644 (file)
@@ -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
index a6a41957ab21ba50bfe232bfe1b73a49148618af..bdfee2af157bbb35c8b49dd9cad5aeef169ccfd3 100644 (file)
@@ -5,6 +5,7 @@
 #include <lunaix/compiler.h>
 
 #include "aa64_mmu.h"
+#include <lunaix/bits.h>
 
 /* ******** 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
index d59f846df4c058a3f1f1e1686046f80bea5aa1de..6b26a70a7cb59784ea8e8cc19f473936e7980505 100644 (file)
@@ -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 (file)
index 0000000..5e7bc79
--- /dev/null
@@ -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 (file)
index 0000000..f2ae189
--- /dev/null
@@ -0,0 +1,25 @@
+#include <lunaix/types.h>
+#include <klibc/crc.h>
+
+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 (file)
index 0000000..f590e0b
--- /dev/null
@@ -0,0 +1,91 @@
+#include <klibc/string.h>
+#include <lunaix/compiler.h>
+
+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
index 9f270bc4a55e82193aa9a17ec7246819b1d07d91..049ff550c50c6031be0fe97f4e8690e7f7f616f9 100644 (file)
@@ -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
index 501daf18d035aafb02fcf3276e7be5a434bc55ae..401f441e1245027fa7f11607d11d9ffe2b367a8d 100644 (file)
@@ -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 (file)
index 0000000..aef8c4c
--- /dev/null
@@ -0,0 +1,33 @@
+#include <lunaix/mm/pagetable.h>
+#include <lunaix/mm/page.h>
+
+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++) {
+        
+    }
+}
index 65a6ef81ff513a0962233f3cbb2ff2c878af2e67..fca3f6753bf680fe742ed6ee1746b42c77a4f860 100644 (file)
@@ -1,9 +1,13 @@
 #ifndef __LUNAIX_BITS_H
 #define __LUNAIX_BITS_H
 
-#include <lunaix/compiler.h>
 #include <asm/bits.h>
 
+#define BITS_AT(val, bitfield)       _BITS_STATIC(val, bitfield)
+
+#ifndef __ASM__
+#include <lunaix/compiler.h>
+
 #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 */
index 86e485e27a599d78c051d1d9879e3f4b8153f87c..2c8d740ef71d802c64a696bf2c2e7e73848990ef 100644 (file)
@@ -379,6 +379,9 @@ exit_thread(void* val);
 void
 thread_release_mem(struct thread* thread);
 
+ptr_t 
+proc_vmroot();
+
 /* 
     ========= Signal =========
 */