Unifying External Interrupt System (#51)
authorLunaixsky <lunaixsky@qq.com>
Sun, 15 Dec 2024 01:40:25 +0000 (01:40 +0000)
committerGitHub <noreply@github.com>
Sun, 15 Dec 2024 01:40:25 +0000 (01:40 +0000)
* rework external irq system, introduce hierarchical irq

* add btrie_map() for allocating free slot, remove isrm

* rewrite the btrie key allocation algorithm for better uniformity

* optimize the tests makefiles, add unit tests for btrie key allocator

* add simple memory allocation monitor for checking leakage and usage

* reduce verbosity of unit test ouput, some clean up

* make irq specifier to be provided when assigining irq

* general fix around.

62 files changed:
lunaix-os/arch/README.md
lunaix-os/arch/generic/includes/asm-generic/isrm.h [deleted file]
lunaix-os/arch/x86/LBuild
lunaix-os/arch/x86/arch.c
lunaix-os/arch/x86/exceptions/interrupts.c
lunaix-os/arch/x86/exceptions/intr_routines.c [deleted file]
lunaix-os/arch/x86/exceptions/isrm.c [deleted file]
lunaix-os/arch/x86/hal/LBuild
lunaix-os/arch/x86/hal/apic.c
lunaix-os/arch/x86/hal/apic_timer.c
lunaix-os/arch/x86/hal/ioapic.c [deleted file]
lunaix-os/arch/x86/hal/mc146818a.c
lunaix-os/arch/x86/hal/ps2kbd.c
lunaix-os/arch/x86/includes/asm/soc/apic.h
lunaix-os/arch/x86/includes/asm/soc/ioapic.h [deleted file]
lunaix-os/arch/x86/includes/asm/x86.h
lunaix-os/arch/x86/includes/asm/x86_isrm.h [deleted file]
lunaix-os/arch/x86/includes/asm/x86_ivs.h
lunaix-os/hal/LBuild
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/ahci_pci.c
lunaix-os/hal/ahci/io_event.c
lunaix-os/hal/bus/pci.c
lunaix-os/hal/char/uart/16x50.h
lunaix-os/hal/char/uart/16x50_base.c
lunaix-os/hal/char/uart/16x50_isa.c
lunaix-os/hal/char/uart/16x50_mmio.c
lunaix-os/hal/char/uart/16x50_pci.c
lunaix-os/hal/char/uart/16x50_pmio.c
lunaix-os/hal/devtree/LBuild
lunaix-os/hal/devtree/devtree.h
lunaix-os/hal/devtree/dt.c
lunaix-os/hal/irq.c [new file with mode: 0644]
lunaix-os/includes/hal/ahci/ahci.h
lunaix-os/includes/hal/devtree.h
lunaix-os/includes/hal/devtreem.h
lunaix-os/includes/hal/irq.h [new file with mode: 0644]
lunaix-os/includes/hal/pci.h
lunaix-os/includes/listings/changeling.lst
lunaix-os/includes/listings/device_potens.lst
lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/ds/btrie.h
lunaix-os/kernel/ds/btrie.c
lunaix-os/kernel/process/sched.c
lunaix-os/tests/includes/testing/basic.h
lunaix-os/tests/includes/testing/memchk.h [new file with mode: 0644]
lunaix-os/tests/shared/framework.c
lunaix-os/tests/shared/makefile
lunaix-os/tests/shared/memchk.c [new file with mode: 0644]
lunaix-os/tests/shared/mkobj.mkinc [new file with mode: 0644]
lunaix-os/tests/units/.gitignore [new file with mode: 0644]
lunaix-os/tests/units/btrie/dut/btrie.c [new symlink]
lunaix-os/tests/units/btrie/makefile [new file with mode: 0644]
lunaix-os/tests/units/btrie/test-alloc.c [new file with mode: 0644]
lunaix-os/tests/units/btrie/tests.txt [new file with mode: 0644]
lunaix-os/tests/units/device-tree/.gitignore
lunaix-os/tests/units/device-tree/common.h
lunaix-os/tests/units/device-tree/makefile
lunaix-os/tests/units/makefile
lunaix-os/tests/units/stubs/valloc.c
lunaix-os/tests/units/test_build.mkinc [deleted file]
lunaix-os/tests/units/units_build.mkinc [new file with mode: 0644]

index 68fa2a0ba1de46e9f27bf4ed9c3d390b56751ce1..5c49276c00c986e2b9ce4f34e9befa75c5160ccc 100644 (file)
@@ -60,7 +60,6 @@ Lunaix provide bunch of headers that **MUST** be implemented in order to behave
 
 ```
 includes/asm/cpu.h
 
 ```
 includes/asm/cpu.h
-includes/asm-generic/isrm.h
 includes/asm/muldiv64.h
 includes/asm/hart.h
 includes/asm/mempart.h
 includes/asm/muldiv64.h
 includes/asm/hart.h
 includes/asm/mempart.h
diff --git a/lunaix-os/arch/generic/includes/asm-generic/isrm.h b/lunaix-os/arch/generic/includes/asm-generic/isrm.h
deleted file mode 100644 (file)
index 0d4a15a..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * @file irqm.h
- * @author Lunaixsky
- * @brief ISR Manager, managing the interrupt service routine allocations
- * @version 0.1
- * @date 2022-10-18
- *
- * @copyright Copyright (c) 2022
- *
- */
-#ifndef __LUNAIX_ISRM_H
-#define __LUNAIX_ISRM_H
-
-#include <lunaix/types.h>
-#include <lunaix/hart_state.h>
-#include <lunaix/device.h>
-
-#include <hal/devtree.h>
-
-typedef void (*isr_cb)(const struct hart_state*);
-
-typedef struct {
-    ptr_t msi_addr;
-    reg_t msi_data;
-    int mapped_iv;
-} msi_vector_t;
-#define msi_addr(msiv)   ((msiv).msi_addr)
-#define msi_data(msiv)   ((msiv).msi_data)
-#define msi_vect(msiv)   ((msiv).mapped_iv)
-
-typedef void* msienv_t;
-
-void
-isrm_init();
-
-/**
- * @brief Release a iv resource
- *
- * @param iv
- */
-void
-isrm_ivfree(int iv);
-
-/**
- * @brief Begin MSI allocation for given device
- *
- * @param iv
- */
-msienv_t
-isrm_msi_start(struct device* dev);
-
-/**
- * @brief Query number of msi avaliable for the device
- */
-int
-isrm_msi_avaliable(msienv_t msienv);
-
-/**
- * @brief Allocate a msi resource within defined msi resource list
- *        for the device, indexed by `index`
- */
-msi_vector_t
-isrm_msi_alloc(msienv_t msienv, cpu_t cpu, int index, isr_cb handler);
-
-/**
- * @brief Set the sideband information will be used for upcoming
- *        allocations
- */
-void
-isrm_msi_set_sideband(msienv_t msienv, ptr_t sideband);
-
-/**
- * @brief Done MSI allocation
- */
-void
-isrm_msi_done(msienv_t msienv);
-
-static inline must_inline msi_vector_t
-isrm_msi_alloc_simple(struct device* dev, cpu_t cpu, isr_cb handler)
-{   
-    msi_vector_t v;
-    msienv_t env;
-
-    env = isrm_msi_start(dev);
-    v = isrm_msi_alloc(env, cpu, 0, handler);
-    isrm_msi_done(env);
-
-    return v;
-}
-
-/**
- * @brief Bind the iv according to given device tree node
- *
- * @param node
- */
-int
-isrm_bind_dtn(struct dtn_intr* node);
-
-/**
- * @brief Get the handler associated with the given iv
- *
- * @param iv
- * @return isr_cb
- */
-isr_cb
-isrm_get(int iv);
-
-ptr_t
-isrm_get_payload(const struct hart_state*);
-
-void
-isrm_set_payload(int iv, ptr_t);
-
-/**
- * @brief Notify end of interrupt event
- *
- * @param id
- */
-void
-isrm_notify_eoi(cpu_t id, int iv);
-
-/**
- * @brief Notify end of scheduling event
- *
- * @param id
- */
-void
-isrm_notify_eos(cpu_t id);
-
-#endif /* __LUNAIX_ISRM_H */
index 9ae21459312017b2927ed1f986e524d25feebc81..941453b42c8eea2e2ddc29f7377b357d0087b323 100644 (file)
@@ -3,8 +3,6 @@ use("hal")
 sources([
     "exceptions/interrupts.c",
     "exceptions/isrdef.c",
 sources([
     "exceptions/interrupts.c",
     "exceptions/isrdef.c",
-    "exceptions/intr_routines.c",
-    "exceptions/isrm.c",
     "exceptions/intrhnds.S",
 ])
 
     "exceptions/intrhnds.S",
 ])
 
index e98bdd9de7b3eca8b06085598b126d7c3f273270..1d68e15518550c18b49da27043ce18b22caba38a 100644 (file)
@@ -3,8 +3,6 @@
 #include <lunaix/spike.h>
 #include <lunaix/process.h>
 
 #include <lunaix/spike.h>
 #include <lunaix/process.h>
 
-#include <asm/x86_isrm.h>
-
 #include "asm/x86.h"
 #include "asm/hart.h"
 
 #include "asm/x86.h"
 #include "asm/hart.h"
 
@@ -14,19 +12,12 @@ void
 exception_init()
 {
     exception_install_handler();
 exception_init()
 {
     exception_install_handler();
-    isrm_init();
-    intr_routine_init();
 }
 
 }
 
-extern void
-syscall_hndlr(const struct hart_state* hstate);
-
 void
 arch_preinit()
 {
     exception_init();
 void
 arch_preinit()
 {
     exception_init();
-
-    isrm_bindiv(LUNAIX_SYS_CALL, syscall_hndlr);
 }
 
 void
 }
 
 void
index ceb3853150578fa1fb8cf28a3d583bc7a81eef7b..9941a5c20940aa8fe21ee27cf813efab8e5ac2c1 100644 (file)
@@ -5,11 +5,28 @@
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/syslog.h>
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/syslog.h>
+#include <lunaix/failsafe.h>
 
 
-#include <asm/x86_isrm.h>
+#include <hal/irq.h>
 
 LOG_MODULE("INTR")
 
 
 LOG_MODULE("INTR")
 
+extern void
+intr_routine_page_fault(const struct hart_state* state);
+
+extern void
+syscall_hndlr(const struct hart_state* hstate);
+
+extern void
+apic_ack_interrupt(irq_t irq);
+
+static void noret
+__set_panic(const char* msg, const struct hart_state* state)
+{
+    ERROR("panic: %s", msg);
+    failsafe_diagnostic();
+}
+
 static inline void
 update_thread_context(struct hart_state* state)
 {
 static inline void
 update_thread_context(struct hart_state* state)
 {
@@ -26,23 +43,83 @@ update_thread_context(struct hart_state* state)
     }
 }
 
     }
 }
 
+
+static bool
+__handle_internal_vectors(const struct hart_state* state)
+{
+    switch (hart_vector_stamp(state))
+    {
+    case FAULT_DIVISION_ERROR:
+        __set_panic("div zero", state);
+        break;
+
+    case FAULT_GENERAL_PROTECTION:
+        __set_panic("general protection", state);
+        break;
+
+    case FAULT_PAGE_FAULT:
+        intr_routine_page_fault(state);
+        break;
+
+    case FAULT_INVALID_OPCODE:
+        __set_panic("invalid opcode", state);;
+        break;
+
+    case LUNAIX_SCHED:
+        apic_ack_interrupt(NULL);
+        schedule();
+        break;
+
+    case APIC_SPIV_IV:
+        break;
+
+    case APIC_ERROR_IV:
+        __set_panic("apic error", state);;
+        break;
+
+    case LUNAIX_SYS_CALL:
+        syscall_hndlr(state);
+        break;
+    
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+static bool
+__handle_external_irq(const struct hart_state* state)
+{
+    irq_t irq;
+    int ex_iv;
+
+    ex_iv = hart_vector_stamp(state);
+    irq   = irq_find(irq_get_default_domain(), ex_iv);
+
+    if (unlikely(!irq)) {
+        return false;
+    }
+
+    irq_serve(irq, state);
+    apic_ack_interrupt(irq);
+    return true;
+}
+
 struct hart_state*
 intr_handler(struct hart_state* state)
 {
     update_thread_context(state);
 
     volatile struct exec_param* execp = state->execp;
 struct hart_state*
 intr_handler(struct hart_state* state)
 {
     update_thread_context(state);
 
     volatile struct exec_param* execp = state->execp;
-    if (execp->vector <= 255) {
-        isr_cb subscriber = isrm_get(execp->vector);
-        subscriber(state);
-        goto done;
+    
+    if (__handle_internal_vectors(state)) {
+        return state;
     }
 
     }
 
-done:
-
-    if (execp->vector > IV_BASE_END) {
-        isrm_notify_eoi(0, execp->vector);
+    if (__handle_external_irq(state)) {
+        return state;
     }
 
     }
 
-    return state;
+    __set_panic("unknown interrupt", state);
 }
\ No newline at end of file
 }
\ No newline at end of file
diff --git a/lunaix-os/arch/x86/exceptions/intr_routines.c b/lunaix-os/arch/x86/exceptions/intr_routines.c
deleted file mode 100644 (file)
index 5e18496..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <asm/hart.h>
-
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
-#include <lunaix/spike.h>
-#include <lunaix/syslog.h>
-#include <lunaix/trace.h>
-#include <lunaix/failsafe.h>
-
-#include <klibc/strfmt.h>
-
-#include <asm/x86_isrm.h>
-#include "asm/soc/apic.h"
-#include "asm/x86.h"
-
-LOG_MODULE("INTR")
-
-extern void
-intr_routine_page_fault(const struct hart_state* state);
-
-extern u32_t debug_resv;
-
-void
-__print_panic_msg(const char* msg, const struct hart_state* state)
-{
-    ERROR("panic: %s", msg);
-    failsafe_diagnostic();
-}
-
-void
-intr_routine_divide_zero(const struct hart_state* state)
-{
-    __print_panic_msg("div zero", state);
-}
-
-void
-intr_routine_general_protection(const struct hart_state* state)
-{
-    __print_panic_msg("general protection", state);
-}
-
-void
-intr_routine_invl_opcode(const struct hart_state* state)
-{
-    __print_panic_msg("invalid opcode", state);
-}
-
-void
-intr_routine_sys_panic(const struct hart_state* state)
-{
-#ifdef CONFIG_ARCH_X86_64
-    __print_panic_msg((char*)(state->registers.rdi), state);
-#else
-    __print_panic_msg((char*)(state->registers.edi), state);
-#endif
-}
-
-void
-intr_routine_fallback(const struct hart_state* state)
-{
-    __print_panic_msg("unknown interrupt", state);
-}
-
-/**
- * @brief ISR for Spurious interrupt
- *
- * @param struct hart_state passed by CPU
- */
-void
-intr_routine_apic_spi(const struct hart_state* state)
-{
-    // FUTURE: do nothing for now
-}
-
-void
-intr_routine_apic_error(const struct hart_state* state)
-{
-    u32_t error_reg = apic_read_reg(APIC_ESR);
-    char buf[32];
-    ksprintf(buf, "APIC error, ESR=0x%x", error_reg);
-
-    failsafe_diagnostic();
-}
-
-void
-intr_routine_sched(const struct hart_state* state)
-{
-    schedule();
-}
-
-void
-intr_routine_init()
-{
-    isrm_bindiv(FAULT_DIVISION_ERROR, intr_routine_divide_zero);
-    isrm_bindiv(FAULT_GENERAL_PROTECTION, intr_routine_general_protection);
-    isrm_bindiv(FAULT_PAGE_FAULT, intr_routine_page_fault);
-    isrm_bindiv(FAULT_STACK_SEG_FAULT, intr_routine_page_fault);
-    isrm_bindiv(FAULT_INVALID_OPCODE, intr_routine_invl_opcode);
-
-    isrm_bindiv(LUNAIX_SYS_PANIC, intr_routine_sys_panic);
-    isrm_bindiv(LUNAIX_SCHED, intr_routine_sched);
-
-    isrm_bindiv(APIC_SPIV_IV, intr_routine_apic_spi);
-    isrm_bindiv(APIC_ERROR_IV, intr_routine_apic_error);
-}
\ No newline at end of file
diff --git a/lunaix-os/arch/x86/exceptions/isrm.c b/lunaix-os/arch/x86/exceptions/isrm.c
deleted file mode 100644 (file)
index 86eec04..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-#include <lunaix/spike.h>
-#include <lunaix/device.h>
-#include <asm/x86_isrm.h>
-
-#include "asm/x86.h"
-#include "asm/soc/ioapic.h"
-#include "asm/soc/apic.h"
-
-/*
-    total: 256 ivs
-    0~31: reserved for sys use (x32)
-    32~47: reserved for os use (x16)
-    48~  : free to allocate for external hardware use. (x208)
-*/
-
-static char iv_bmp[(IV_EX_END - IV_BASE_END) / 8];
-static isr_cb handlers[TOTAL_IV];
-static ptr_t ivhand_payload[TOTAL_IV];
-
-static struct x86_intc arch_intc_ctx;
-
-extern void
-intr_routine_fallback(const struct hart_state* state);
-
-void
-isrm_init()
-{
-    for (size_t i = 0; i < TOTAL_IV; i++) {
-        handlers[i] = intr_routine_fallback;
-    }
-}
-
-static inline int
-__ivalloc_within(size_t a, size_t b, isr_cb handler)
-{
-    a = (a - IV_BASE_END);
-    b = (b - IV_BASE_END);
-    u8_t j = a % 8;
-    u8_t k = 0;
-
-    for (size_t i = a / 8; i < b / 8; i++, k += 8) {
-        u8_t chunk = iv_bmp[i];
-
-        if (chunk == 0xff)
-            continue;
-
-        chunk >>= j;
-        while ((chunk & 0x1) && k <= b) {
-            chunk >>= 1;
-            j++;
-            k++;
-        }
-
-        if (j == 8) {
-            j = 0;
-            continue;
-        }
-
-        if (k > b) {
-            break;
-        }
-
-        iv_bmp[i] |= 1 << j;
-
-        int iv = IV_BASE_END + i * 8 + j;
-        handlers[iv] = handler ? handler : intr_routine_fallback;
-
-        return iv;
-    }
-
-    return 0;
-}
-
-int
-isrm_ivosalloc(isr_cb handler)
-{
-    return __ivalloc_within(IV_BASE_END, IV_EX_BEGIN, handler);
-}
-
-int
-isrm_ivexalloc(isr_cb handler)
-{
-    return __ivalloc_within(IV_EX_BEGIN, IV_EX_END, handler);
-}
-
-void
-isrm_ivfree(int iv)
-{
-    assert(iv < 256);
-
-    if (iv >= IV_BASE_END) {
-        iv_bmp[(iv - IV_BASE_END) / 8] &= ~(1 << ((iv - IV_BASE_END) % 8));
-    }
-
-    handlers[iv] = intr_routine_fallback;
-}
-
-int
-isrm_bindirq(int irq, isr_cb irq_handler)
-{
-    int iv;
-    if (!(iv = isrm_ivexalloc(irq_handler))) {
-        fail("out of IV resource.");
-        return 0; // never reach
-    }
-
-    // fixed, edge trigged, polarity=high
-    isrm_irq_attach(irq, iv, 0, IRQ_DEFAULT);
-
-    return iv;
-}
-
-void
-isrm_bindiv(int iv, isr_cb handler)
-{
-    assert(iv < 256);
-
-    if (iv >= IV_BASE_END) {
-        iv_bmp[(iv - IV_BASE_END) / 8] |= 1 << ((iv - IV_BASE_END) % 8);
-    }
-
-    handlers[iv] = handler;
-}
-
-isr_cb
-isrm_get(int iv)
-{
-    assert(iv < 256);
-
-    return handlers[iv];
-}
-
-ptr_t
-isrm_get_payload(const struct hart_state* state)
-{
-    int iv = state->execp->vector;
-    assert(iv < 256);
-
-    return ivhand_payload[iv];
-}
-
-void
-isrm_set_payload(int iv, ptr_t payload)
-{
-    assert(iv < 256);
-
-    ivhand_payload[iv] = payload;
-}
-
-void
-isrm_irq_attach(int irq, int iv, cpu_t dest, u32_t flags)
-{
-    arch_intc_ctx.irq_attach(&arch_intc_ctx, irq, iv, dest, flags);
-}
-
-void
-isrm_notify_eoi(cpu_t id, int iv)
-{
-    arch_intc_ctx.notify_eoi(&arch_intc_ctx, id, iv);
-}
-
-void
-isrm_notify_eos(cpu_t id)
-{
-    isrm_notify_eoi(id, LUNAIX_SCHED);
-}
-
-msienv_t
-isrm_msi_start(struct device* dev)
-{
-    /*
-     *  In x86, the MSI topology is rather simple, as the only
-     *  source is the PCI itself, and the write destination is
-     *  explictly defined in specification, so we don't need the
-     *  msienv to hold dynamically probed address
-     */
-    return NULL;
-}
-
-int
-isrm_msi_avaliable(msienv_t msienv)
-{
-    return 1;
-}
-
-msi_vector_t
-isrm_msi_alloc(msienv_t msienv, cpu_t cpu, int index, isr_cb handler)
-{
-    unsigned int iv = isrm_ivexalloc(handler);
-
-    // we ignore the cpu redirection for now.
-    return (msi_vector_t){ 
-        .msi_addr  = __APIC_BASE_PADDR,
-        .msi_data  = iv,
-        .mapped_iv = iv
-    };
-}
-
-void
-isrm_msi_set_sideband(msienv_t msienv, ptr_t sideband)
-{
-    return;
-}
-
-void
-isrm_msi_done(msienv_t msienv)
-{
-    return;
-}
-
-
-
-int
-isrm_bind_dtn(struct dtn_intr* node)
-{
-    fail("not supported");
-}
-
-
-static int
-__intc_create(struct device_def* devdef, morph_t* obj)
-{
-    apic_init();
-    ioapic_init();
-
-    arch_intc_ctx.name = "i386_apic";
-    arch_intc_ctx.irq_attach = ioapic_irq_remap;
-    arch_intc_ctx.notify_eoi = apic_on_eoi;
-
-    return 0;
-}
-
-
-static struct device_def i386_intc = {
-    def_device_class(INTEL, CFG, INTC),
-    def_device_name("i386 apic"),
-    def_on_create(__intc_create)
-};
-EXPORT_DEVICE(i386_intc, &i386_intc, load_sysconf);
\ No newline at end of file
index f3a3cae2abf28b9a22cdc2783f8c2407b8f139ef..870f743cf2a499f22421d02504d2c52712bc66ec 100644 (file)
@@ -4,7 +4,6 @@ sources([
     "cpu.c",
     "ps2kbd.c",
     "apic_timer.c",
     "cpu.c",
     "ps2kbd.c",
     "apic_timer.c",
-    "ioapic.c",
     "mc146818a.c",
     "pci.c"
 ])
\ No newline at end of file
     "mc146818a.c",
     "pci.c"
 ])
\ No newline at end of file
index ddc2e31ef2471557122b8b6ddb4ab11d0b7b68bd..8e9a01367b7feef10654ffc2ae554ef55be3b12a 100644 (file)
 
 #include "asm/x86.h"
 #include "asm/x86_cpu.h"
 
 #include "asm/x86.h"
 #include "asm/x86_cpu.h"
-
 #include "asm/soc/apic.h"
 #include "asm/soc/apic.h"
+
 #include <asm/hart.h>
 
 #include <lunaix/mm/mmio.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 #include <asm/hart.h>
 
 #include <lunaix/mm/mmio.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
+#include <lunaix/device.h>
+
+#include <hal/irq.h>
+#include <hal/acpi/acpi.h>
 
 #include "pic.h"
 
 LOG_MODULE("APIC")
 
 
 #include "pic.h"
 
 LOG_MODULE("APIC")
 
+#define IOAPIC_IOREGSEL 0x00
+#define IOAPIC_IOWIN 0x10
+#define IOAPIC_IOREDTBL_BASE 0x10
+
+#define IOAPIC_REG_ID 0x00
+#define IOAPIC_REG_VER 0x01
+#define IOAPIC_REG_ARB 0x02
+
+#define IOAPIC_DELMOD_FIXED 0b000
+#define IOAPIC_DELMOD_LPRIO 0b001
+#define IOAPIC_DELMOD_NMI 0b100
+
+#define IOAPIC_MASKED (1 << 16)
+#define IOAPIC_TRIG_LEVEL (1 << 15)
+#define IOAPIC_INTPOL_L (1 << 13)
+#define IOAPIC_DESTMOD_LOGIC (1 << 11)
+
+#define IOAPIC_BASE_VADDR 0x2000
+
+#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL))
+#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN))
+
+
+#define LVT_ENTRY_LINT0(vector) (LVT_DELIVERY_FIXED | vector)
+
+// Pin LINT#1 is configured for relaying NMI, but we masked it here as I think
+//  it is too early for that
+// LINT#1 *must* be edge trigged (Intel manual vol3. 10-14)
+#define LVT_ENTRY_LINT1 (LVT_DELIVERY_NMI | LVT_MASKED | LVT_TRIGGER_EDGE)
+#define LVT_ENTRY_ERROR(vector) (LVT_DELIVERY_FIXED | vector)
+
+
+static volatile ptr_t _ioapic_base;
 static volatile ptr_t _apic_base;
 
 void
 static volatile ptr_t _apic_base;
 
 void
-apic_setup_lvts();
+apic_write_reg(unsigned int reg, unsigned int val)
+{
+    *(unsigned int*)(_apic_base + reg) = val;
+}
 
 void
 
 void
+apic_ack_interrupt(irq_t irq)
+{
+    *(unsigned int*)(_apic_base + APIC_EOI) = 0;
+}
+
+unsigned int
+apic_read_reg(unsigned int reg)
+{
+    return *(unsigned int*)(_apic_base + (reg));
+}
+
+
+static void
+apic_setup_lvts()
+{
+    apic_write_reg(APIC_LVT_LINT0, LVT_ENTRY_LINT0(APIC_LINT0_IV));
+    apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1);
+    apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV));
+}
+
+static void
 apic_init()
 {
     // ensure that external interrupt is disabled
 apic_init()
 {
     // ensure that external interrupt is disabled
@@ -85,40 +146,109 @@ apic_init()
     apic_write_reg(APIC_SPIVR, spiv);
 }
 
     apic_write_reg(APIC_SPIVR, spiv);
 }
 
-#define LVT_ENTRY_LINT0(vector) (LVT_DELIVERY_FIXED | vector)
+static void
+ioapic_init()
+{
+    acpi_context* acpi_ctx = acpi_get_context();
 
 
-// Pin LINT#1 is configured for relaying NMI, but we masked it here as I think
-//  it is too early for that
-// LINT#1 *must* be edge trigged (Intel manual vol3. 10-14)
-#define LVT_ENTRY_LINT1 (LVT_DELIVERY_NMI | LVT_MASKED | LVT_TRIGGER_EDGE)
-#define LVT_ENTRY_ERROR(vector) (LVT_DELIVERY_FIXED | vector)
+    _ioapic_base =
+        ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096);
+}
 
 
-void
-apic_setup_lvts()
+static void
+ioapic_write(u8_t sel, u32_t val)
 {
 {
-    apic_write_reg(APIC_LVT_LINT0, LVT_ENTRY_LINT0(APIC_LINT0_IV));
-    apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1);
-    apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV));
+    IOAPIC_REG_SEL = sel;
+    IOAPIC_REG_WIN = val;
 }
 
 }
 
-void
-apic_on_eoi(struct x86_intc* intc_ctx, cpu_t cpu, int iv)
+static u32_t
+ioapic_read(u8_t sel)
+{
+    IOAPIC_REG_SEL = sel;
+    return IOAPIC_REG_WIN;
+}
+
+static void
+__ioapic_install_line(struct irq_domain *domain, irq_t irq)
+{
+    struct irq_line_wire *line;
+    u8_t reg_sel;
+    u32_t ioapic_fg;
+
+    line = irq->line;
+    reg_sel = IOAPIC_IOREDTBL_BASE + line->domain_mapped * 2;
+    ioapic_fg = IOAPIC_DELMOD_FIXED;
+
+    // Write low 32 bits
+    ioapic_write(reg_sel, (irq->vector | ioapic_fg) & 0x1FFFF);
+
+    // Write high 32 bits
+    ioapic_write(reg_sel + 1, 0);
+}
+
+static int
+__ioapic_translate_irq(struct irq_domain *domain, irq_t irq, void *irq_extra)
 {
 {
-    // for all external interrupts except the spurious interrupt
-    //  this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
-    if (iv >= IV_EX_BEGIN && iv != APIC_SPIV_IV) {
-        *(unsigned int*)(_apic_base + APIC_EOI) = 0;
+    struct irq_line_wire *line;
+
+    if (irq->type == IRQ_LINE) {
+        line = irq->line;
+        line->domain_mapped = acpi_gsimap(line->domain_local);
     }
     }
+
+    return 0;
 }
 
 }
 
-unsigned int
-apic_read_reg(unsigned int reg)
+static int
+__ioapic_install_irq(struct irq_domain *domain, irq_t irq)
 {
 {
-    return *(unsigned int*)(_apic_base + (reg));
+    if (irq->vector == IRQ_VECTOR_UNSET) {
+        irq->vector = btrie_map(&domain->irq_map, IV_EX_BEGIN, IV_EX_END, irq);
+    }
+    else {
+        irq_record(domain, irq);
+    }
+
+    if (irq->type == IRQ_MESSAGE) {
+        irq->msi->wr_addr = __APIC_BASE_PADDR;
+    }
+    else {
+        __ioapic_install_line(domain, irq);
+    }
+
+    return 0;
 }
 
 }
 
-void
-apic_write_reg(unsigned int reg, unsigned int val)
+
+static struct irq_domain_ops apic_domain_ops = {
+    .map_irq = __ioapic_translate_irq,
+    .install_irq = __ioapic_install_irq
+};
+
+static int
+apic_device_create(struct device_def* def, morph_t* morph)
 {
 {
-    *(unsigned int*)(_apic_base + reg) = val;
-}
\ No newline at end of file
+    int err;
+    struct device* dev;
+    struct irq_domain* domain;
+
+    apic_init();
+    ioapic_init();
+
+    dev = device_allocsys(NULL, NULL);
+    domain = irq_create_domain(dev, &apic_domain_ops);
+
+    irq_set_default_domain(domain);
+    register_device(dev, &def->class, "apic");
+    irq_attach_domain(NULL, domain);
+    
+    return 0;
+}
+
+static struct device_def apic_devdef = {
+    def_device_class(INTEL, CFG, INTC),
+    def_device_name("x86 APIC"),
+    def_on_create(apic_device_create)
+};
+EXPORT_DEVICE(x86_apic, &apic_devdef, load_sysconf);
\ No newline at end of file
index 816fde3c93719b287e26d04a5a5a22bfb30d2c5e..178928cae3f205d51599d1a788a4fcf2d0883a18 100644 (file)
@@ -1,12 +1,12 @@
 #include "apic_timer.h"
 #include <hal/hwtimer.h>
 #include "apic_timer.h"
 #include <hal/hwtimer.h>
+#include <hal/irq.h>
 
 #include <lunaix/clock.h>
 #include <lunaix/compiler.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 
 
 #include <lunaix/clock.h>
 #include <lunaix/compiler.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 
-#include <asm/x86_isrm.h>
 #include "asm/soc/apic.h"
 
 LOG_MODULE("timer(apic)")
 #include "asm/soc/apic.h"
 
 LOG_MODULE("timer(apic)")
@@ -15,20 +15,20 @@ LOG_MODULE("timer(apic)")
 #define APIC_BASETICKS 0x100000
 
 static void
 #define APIC_BASETICKS 0x100000
 
 static void
-temp_intr_routine_apic_timer(const struct hart_state* state)
+apic_timer_count_stop(irq_t irq, const struct hart_state* state)
 {
     struct hwtimer_pot* pot;
 
 {
     struct hwtimer_pot* pot;
 
-    pot = (struct hwtimer_pot*)isrm_get_payload(state);
+    pot = irq_payload(irq, struct hwtimer_pot);
     pot->systick_raw = (ticks_t)-1;
 }
 
 static void
     pot->systick_raw = (ticks_t)-1;
 }
 
 static void
-apic_timer_tick_isr(const struct hart_state* state)
+apic_timer_tick_isr(irq_t irq, const struct hart_state* state)
 {
     struct hwtimer_pot* pot;
 
 {
     struct hwtimer_pot* pot;
 
-    pot = (struct hwtimer_pot*)isrm_get_payload(state);
+    pot = irq_payload(irq, struct hwtimer_pot);
     pot->systick_raw++;
 
     if (likely(__ptr(pot->callback))) {
     pot->systick_raw++;
 
     if (likely(__ptr(pot->callback))) {
@@ -39,20 +39,19 @@ apic_timer_tick_isr(const struct hart_state* state)
 static void
 __apic_timer_calibrate(struct hwtimer_pot* pot, u32_t hertz)
 {
 static void
 __apic_timer_calibrate(struct hwtimer_pot* pot, u32_t hertz)
 {
+    irq_t irq;
     ticks_t base_freq = 0;
 
     cpu_disable_interrupt();
 
     ticks_t base_freq = 0;
 
     cpu_disable_interrupt();
 
-    // Setup APIC timer
-
-    // grab ourselves these irq numbers
-    u32_t iv_timer = isrm_ivexalloc(temp_intr_routine_apic_timer);
-    isrm_set_payload(iv_timer, __ptr(pot));
+    irq = irq_declare_direct(apic_timer_count_stop);
+    irq_set_payload(irq, pot);
+    irq_assign(irq_get_default_domain(), irq, NULL);
 
     // Setup a one-shot timer, we will use this to measure the bus speed. So we
     // can then calibrate apic timer to work at *nearly* accurate hz
     apic_write_reg(APIC_TIMER_LVT,
 
     // Setup a one-shot timer, we will use this to measure the bus speed. So we
     // can then calibrate apic timer to work at *nearly* accurate hz
     apic_write_reg(APIC_TIMER_LVT,
-                   LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_ONESHOT));
+                   LVT_ENTRY_TIMER(irq->vector, LVT_TIMER_ONESHOT));
 
     // Set divider to 64
     apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64);
 
     // Set divider to 64
     apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64);
@@ -89,7 +88,6 @@ __apic_timer_calibrate(struct hwtimer_pot* pot, u32_t hertz)
     wait_until(!(pot->systick_raw + 1));
 
     cpu_disable_interrupt();
     wait_until(!(pot->systick_raw + 1));
 
     cpu_disable_interrupt();
-    isrm_ivfree(iv_timer);
 
     sysrtc->ops->set_proactive(sysrtc, false);
     
 
     sysrtc->ops->set_proactive(sysrtc, false);
     
@@ -101,14 +99,12 @@ __apic_timer_calibrate(struct hwtimer_pot* pot, u32_t hertz)
     assert_msg(base_freq, "Fail to initialize timer (NOFREQ)");
     INFO("hw: %u Hz; os: %u Hz", base_freq, hertz);
 
     assert_msg(base_freq, "Fail to initialize timer (NOFREQ)");
     INFO("hw: %u Hz; os: %u Hz", base_freq, hertz);
 
+    irq_set_servant(irq, apic_timer_tick_isr);
+
     apic_write_reg(APIC_TIMER_ICR, base_freq / hertz);
     apic_write_reg(APIC_TIMER_ICR, base_freq / hertz);
-    
-    iv_timer = isrm_ivexalloc(apic_timer_tick_isr);
-    isrm_set_payload(iv_timer, __ptr(pot));
-    
     apic_write_reg(
         APIC_TIMER_LVT,
     apic_write_reg(
         APIC_TIMER_LVT,
-        LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_PERIODIC));
+        LVT_ENTRY_TIMER(irq->vector, LVT_TIMER_PERIODIC));
 }
 
 static struct hwtimer_pot_ops potops = {
 }
 
 static struct hwtimer_pot_ops potops = {
diff --git a/lunaix-os/arch/x86/hal/ioapic.c b/lunaix-os/arch/x86/hal/ioapic.c
deleted file mode 100644 (file)
index e03d4b5..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#include <hal/acpi/acpi.h>
-
-#include <lunaix/mm/mmio.h>
-
-#include <asm/hart.h>
-#include "asm/soc/ioapic.h"
-#include "asm/x86.h"
-
-#define IOAPIC_IOREGSEL 0x00
-#define IOAPIC_IOWIN 0x10
-#define IOAPIC_IOREDTBL_BASE 0x10
-
-#define IOAPIC_REG_ID 0x00
-#define IOAPIC_REG_VER 0x01
-#define IOAPIC_REG_ARB 0x02
-
-#define IOAPIC_DELMOD_FIXED 0b000
-#define IOAPIC_DELMOD_LPRIO 0b001
-#define IOAPIC_DELMOD_NMI 0b100
-
-#define IOAPIC_MASKED (1 << 16)
-#define IOAPIC_TRIG_LEVEL (1 << 15)
-#define IOAPIC_INTPOL_L (1 << 13)
-#define IOAPIC_DESTMOD_LOGIC (1 << 11)
-
-#define IOAPIC_BASE_VADDR 0x2000
-
-#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL))
-#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN))
-
-static volatile ptr_t _ioapic_base;
-
-void
-ioapic_init()
-{
-    // Remapping the IRQs
-
-    acpi_context* acpi_ctx = acpi_get_context();
-
-    _ioapic_base =
-        ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096);
-}
-
-void
-ioapic_write(u8_t sel, u32_t val)
-{
-    IOAPIC_REG_SEL = sel;
-    IOAPIC_REG_WIN = val;
-}
-
-u32_t
-ioapic_read(u8_t sel)
-{
-    IOAPIC_REG_SEL = sel;
-    return IOAPIC_REG_WIN;
-}
-
-void
-ioapic_irq_remap(struct x86_intc* intc, int irq, int iv, cpu_t dest, u32_t flags)
-{
-    /*
-        FIXME move it to HAL level. since every platform might have their own
-       wiring, thus gsi mapping is required all the time
-    */
-    irq = acpi_gsimap(irq);
-    u8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2;
-
-    u32_t ioapic_fg = 0;
-
-    if ((flags & IRQ_TYPE) == IRQ_TYPE_FIXED) {
-        ioapic_fg |= IOAPIC_DELMOD_FIXED;
-    } else {
-        ioapic_fg |= IOAPIC_DELMOD_NMI;
-    }
-
-    if ((flags & IRQ_TRIG_LEVEL)) {
-        ioapic_fg |= IOAPIC_TRIG_LEVEL;
-    }
-
-    if (!(flags & IRQ_VE_HI)) {
-        ioapic_fg |= IOAPIC_INTPOL_L;
-    }
-
-    // Write low 32 bits
-    ioapic_write(reg_sel, (iv | ioapic_fg) & 0x1FFFF);
-
-    // Write high 32 bits
-    ioapic_write(reg_sel + 1, (dest << 24));
-}
\ No newline at end of file
index f5bc285b2425a579c8eceb8eddf74621688530ea..fcb5d7f77f293dbe6f1115ee2dfa56b24bf354cc 100644 (file)
 #include <lunaix/hart_state.h>
 
 #include <hal/hwrtc.h>
 #include <lunaix/hart_state.h>
 
 #include <hal/hwrtc.h>
+#include <hal/irq.h>
 
 #include <klibc/string.h>
 
 
 #include <klibc/string.h>
 
-#include <asm/x86_isrm.h>
 #include <asm/x86_pmio.h>
 
 #define RTC_INDEX_PORT 0x70
 #include <asm/x86_pmio.h>
 
 #define RTC_INDEX_PORT 0x70
@@ -57,7 +57,7 @@
 struct mc146818
 {
     struct hwrtc_potens* rtc_context;
 struct mc146818
 {
     struct hwrtc_potens* rtc_context;
-    u32_t rtc_iv;
+    irq_t irq;
 };
 
 #define rtc_state(data) ((struct mc146818*)(data))
 };
 
 #define rtc_state(data) ((struct mc146818*)(data))
@@ -132,10 +132,11 @@ rtc_setwalltime(struct hwrtc_potens* rtc, datetime_t* datetime)
 }
 
 static void
 }
 
 static void
-__rtc_tick(const struct hart_state* hstate)
+__rtc_tick(irq_t irq, const struct hart_state* hstate)
 {
 {
-    struct mc146818* state = (struct mc146818*)isrm_get_payload(hstate);
+    struct mc146818* state;
 
 
+    state = irq_payload(irq, struct mc146818);
     state->rtc_context->live++;
 
     (void)rtc_read_reg(RTC_REG_C);
     state->rtc_context->live++;
 
     (void)rtc_read_reg(RTC_REG_C);
@@ -164,8 +165,12 @@ static int
 __rtc_calibrate(struct hwrtc_potens* pot)
 {
     struct mc146818* state;
 __rtc_calibrate(struct hwrtc_potens* pot)
 {
     struct mc146818* state;
+    struct device* rtc_dev;
+    u8_t reg;
+
+    rtc_dev = potens_dev(pot);
 
 
-    u8_t reg = rtc_read_reg(RTC_REG_A);
+    reg = rtc_read_reg(RTC_REG_A);
     reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ;
     rtc_write_reg(RTC_REG_A, reg);
 
     reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ;
     rtc_write_reg(RTC_REG_A, reg);
 
@@ -177,9 +182,12 @@ __rtc_calibrate(struct hwrtc_potens* pot)
 
     pot->base_freq = RTC_TIMER_BASE_FREQUENCY;
 
 
     pot->base_freq = RTC_TIMER_BASE_FREQUENCY;
 
-    state = (struct mc146818*)potens_dev(pot)->underlay;
-    state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick);
-    isrm_set_payload(state->rtc_iv, __ptr(state));
+    state = (struct mc146818*)rtc_dev->underlay;
+
+    state->irq = irq_declare_line(__rtc_tick, PC_AT_IRQ_RTC);
+    irq_set_payload(state->irq, state);
+
+    irq_assign(irq_owning_domain(rtc_dev), state->irq, NULL);
 
     return 0;
 }
 
     return 0;
 }
index ee4a67e0f99855acb884cd8fc5b87fe386ddcea6..1df42bdb59ec0af1a1f4e34ebd39216241612227 100644 (file)
@@ -6,12 +6,13 @@
 #include <lunaix/timer.h>
 #include <lunaix/hart_state.h>
 
 #include <lunaix/timer.h>
 #include <lunaix/hart_state.h>
 
+#include <hal/irq.h>
+
 #include "asm/x86.h"
 
 #include <klibc/string.h>
 
 #include "asm/x86_cpu.h"
 #include "asm/x86.h"
 
 #include <klibc/string.h>
 
 #include "asm/x86_cpu.h"
-#include <asm/x86_isrm.h>
 #include <asm/x86_pmio.h>
 
 #define PS2_PORT_ENC_DATA 0x60
 #include <asm/x86_pmio.h>
 
 #define PS2_PORT_ENC_DATA 0x60
@@ -189,7 +190,7 @@ static struct input_device* kbd_idev;
 // #define KBD_DBGLOG
 
 static void
 // #define KBD_DBGLOG
 
 static void
-intr_ps2_kbd_handler(const struct hart_state* hstate);
+intr_ps2_kbd_handler(irq_t irq, const struct hart_state* hstate);
 
 static u8_t
 ps2_issue_cmd_wretry(char cmd, u16_t arg);
 
 static u8_t
 ps2_issue_cmd_wretry(char cmd, u16_t arg);
@@ -309,7 +310,9 @@ ps2_kbd_create(struct device_def* devdef, morph_t* obj)
      *
      *  所以,保险的方法是:在初始化后才去设置ioapic,这样一来我们就能有一个稳定的IRQ#1以放心使用。
      */
      *
      *  所以,保险的方法是:在初始化后才去设置ioapic,这样一来我们就能有一个稳定的IRQ#1以放心使用。
      */
-    isrm_bindirq(PC_AT_IRQ_KBD, intr_ps2_kbd_handler);
+    
+    irq_t irq = irq_declare_line(intr_ps2_kbd_handler, PC_AT_IRQ_KBD);    
+    irq_assign(irq_owning_domain(kbd_idev->dev_if), irq, NULL);
 
     return 0;
 
 
     return 0;
 
@@ -401,7 +404,7 @@ kbd_buffer_key_event(kbd_keycode_t key, u8_t scancode, kbd_kstate_t state)
 }
 
 static void
 }
 
 static void
-intr_ps2_kbd_handler(const struct hart_state* hstate)
+intr_ps2_kbd_handler(irq_t irq, const struct hart_state* hstate)
 {
 
     // This is important! Don't believe me? try comment it out and run on Bochs!
 {
 
     // This is important! Don't believe me? try comment it out and run on Bochs!
index 40c395cee55619389d7e57d29c5074df2ad7c59e..83ad3ed2bbace3d02c36d3690243b7a240c9c6c8 100644 (file)
@@ -72,10 +72,4 @@ apic_read_reg(unsigned int reg);
 void
 apic_write_reg(unsigned int reg, unsigned int val);
 
 void
 apic_write_reg(unsigned int reg, unsigned int val);
 
-void
-apic_init();
-
-void
-apic_on_eoi(struct x86_intc* intc_ctx, cpu_t cpu, int iv);
-
 #endif /* __LUNAIX_APIC_H */
 #endif /* __LUNAIX_APIC_H */
diff --git a/lunaix-os/arch/x86/includes/asm/soc/ioapic.h b/lunaix-os/arch/x86/includes/asm/soc/ioapic.h
deleted file mode 100644 (file)
index d87ab18..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __LUNAIX_IOAPIC_H
-#define __LUNAIX_IOAPIC_H
-
-#include "asm/x86.h"
-
-void
-ioapic_init();
-
-void
-ioapic_irq_remap(struct x86_intc*,
-                 int irq,
-                 int iv,
-                 cpu_t dest,
-                 u32_t flags);
-
-#endif /* __LUNAIX_IOAPIC_H */
index 33515a1193b7a76439dd40b4c60456d34e1164fd..8f1e3d0df1aee6f9c4a8517165f1e3446ad33ab9 100644 (file)
@@ -95,8 +95,5 @@ typedef struct x86_sysdesc x86_segdesc_t;
 void
 exception_install_handler();
 
 void
 exception_install_handler();
 
-void
-intr_routine_init();
-
 #endif
 #endif /* __LUNAIX_I386_ASM_H */
 #endif
 #endif /* __LUNAIX_I386_ASM_H */
diff --git a/lunaix-os/arch/x86/includes/asm/x86_isrm.h b/lunaix-os/arch/x86/includes/asm/x86_isrm.h
deleted file mode 100644 (file)
index b486080..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __LUNAIX_X86_ISRM_H
-#define __LUNAIX_X86_ISRM_H
-
-#include <asm-generic/isrm.h>
-
-/**
- * @brief Bind a given irq and associated handler to an iv
- *
- * @param iv iv allocated by system
- */
-int
-isrm_bindirq(int irq, isr_cb irq_handler);
-
-/**
- * @brief Bind given iv with it's associated handler
- *
- * @param iv
- * @param handler
- */
-void
-isrm_bindiv(int iv, isr_cb handler);
-
-void
-isrm_irq_attach(int irq, int iv, cpu_t dest, u32_t flags);
-
-/**
- * @brief Allocate an iv resource for os services
- *
- * @param iv
- */
-int
-isrm_ivosalloc(isr_cb handler);
-
-/**
- * @brief Allocate an iv resource for external events
- *
- * @param iv
- */
-int
-isrm_ivexalloc(isr_cb handler);
-
-#endif /* __LUNAIX_X86_ISRM_H */
index 0a5eed2669db28780904e4f0329e97c3abc6c675..0dbe9219e942ddb4447568f7651027fbdaaac45b 100644 (file)
 #define LUNAIX_SYS_CALL                 33
 
 // begin allocatable iv resources
 #define LUNAIX_SYS_CALL                 33
 
 // begin allocatable iv resources
-#define IV_EX_BEGIN                     50
 #define LUNAIX_SCHED                    50
 #define LUNAIX_SCHED                    50
+#define IV_EX_BEGIN                     51
 
 // end allocatable iv resources
 
 // end allocatable iv resources
-#define IV_EX_END             249
+#define IV_EX_END                       249
 
 // 来自APIC的中断有着最高的优先级。
 // APIC related
 
 // 来自APIC的中断有着最高的优先级。
 // APIC related
index 673a8fcdc7191102b0211ac38878a3585ab94628..6ff2713d2e5de227f582fd588ce6b683e671e035 100644 (file)
@@ -8,4 +8,8 @@ use("timer")
 use("bus")
 
 if config("use_devicetree"):
 use("bus")
 
 if config("use_devicetree"):
-    use("devtree")
\ No newline at end of file
+    use("devtree")
+
+sources([
+    "irq.c"
+])
\ No newline at end of file
index 04a71047b6708f4f06e8a3465a4900aead0acd88..5ff1cc218afc737ef871f4992b31e46817a8331d 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <klibc/string.h>
 #include <lunaix/block.h>
 
 #include <klibc/string.h>
 #include <lunaix/block.h>
-#include <asm-generic/isrm.h>
 #include <lunaix/mm/mmio.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/mmio.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/page.h>
@@ -35,7 +34,7 @@
 
 LOG_MODULE("AHCI")
 
 
 LOG_MODULE("AHCI")
 
-DEFINE_LLIST(ahcis);
+static DEFINE_LLIST(ahcis);
 
 static char sata_ifs[][20] = { "Not detected",
                                "SATA I (1.5Gbps)",
 
 static char sata_ifs[][20] = { "Not detected",
                                "SATA I (1.5Gbps)",
@@ -80,10 +79,9 @@ ahci_driver_init(struct ahci_driver_param* param)
 {
     struct ahci_driver* ahci_drv = vzalloc(sizeof(*ahci_drv));
     struct ahci_hba* hba = &ahci_drv->hba;
 {
     struct ahci_driver* ahci_drv = vzalloc(sizeof(*ahci_drv));
     struct ahci_hba* hba = &ahci_drv->hba;
-    ahci_drv->id = param->ahci_iv;
-
-    isrm_set_payload(param->ahci_iv, (ptr_t)&ahcis);
+    ahci_drv->id = param->irq->vector;
 
 
+    irq_set_payload(param->irq, &ahcis);
     llist_append(&ahcis, &ahci_drv->ahci_drvs);
 
     hba->base = (hba_reg_t*)ioremap(param->mmio_base, param->mmio_size);
     llist_append(&ahcis, &ahci_drv->ahci_drvs);
 
     hba->base = (hba_reg_t*)ioremap(param->mmio_base, param->mmio_size);
index 4435da12431ddc6a451f716664a02dcfcbf0c156..2bc0ad979dcdb04a15d3b132b293cb5606053830 100644 (file)
@@ -11,7 +11,7 @@ ahci_pci_create(struct device_def* def, morph_t* morphed)
     struct device* dev;
     struct pci_base_addr* bar6;
     struct ahci_driver* ahci_drv;
     struct device* dev;
     struct pci_base_addr* bar6;
     struct ahci_driver* ahci_drv;
-    msi_vector_t msiv;
+    irq_t irq;
 
     probe = changeling_try_reveal(morphed, pci_probe_morpher);
     if (!probe) {
 
     probe = changeling_try_reveal(morphed, pci_probe_morpher);
     if (!probe) {
@@ -29,12 +29,13 @@ ahci_pci_create(struct device_def* def, morph_t* morphed)
     
     assert(pci_capability_msi(probe));
 
     
     assert(pci_capability_msi(probe));
 
-    msiv = pci_msi_setup_simple(probe, ahci_hba_isr);
+    irq = pci_declare_msi_irq(ahci_hba_isr, probe);
+    pci_assign_msi(probe, irq, NULL);
 
     struct ahci_driver_param param = {
         .mmio_base = bar6->start,
         .mmio_size = bar6->size,
 
     struct ahci_driver_param param = {
         .mmio_base = bar6->start,
         .mmio_size = bar6->size,
-        .ahci_iv = msi_vect(msiv),
+        .irq = irq,
     };
 
     ahci_drv = ahci_driver_init(&param);
     };
 
     ahci_drv = ahci_driver_init(&param);
index 608634d84e5fdbd52151441380a4ea099ee55e5f..b751cdcbfff3f7e2ad6cf2c85257ed2929346623 100644 (file)
@@ -1,18 +1,18 @@
 #include <hal/ahci/ahci.h>
 #include <hal/ahci/sata.h>
 #include <hal/ahci/ahci.h>
 #include <hal/ahci/sata.h>
-#include <asm-generic/isrm.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/syslog.h>
 
 LOG_MODULE("io_evt")
 
 void
 #include <lunaix/mm/valloc.h>
 #include <lunaix/syslog.h>
 
 LOG_MODULE("io_evt")
 
 void
-ahci_hba_isr(const struct hart_state* hstate)
+ahci_hba_isr(irq_t irq, const struct hart_state* hstate)
 {
     struct ahci_hba* hba;
     struct ahci_driver *pos, *n;
 {
     struct ahci_hba* hba;
     struct ahci_driver *pos, *n;
-    struct llist_header* ahcis = (struct llist_header*)isrm_get_payload(hstate);
+    struct llist_header* ahcis;
 
 
+    ahcis = irq_payload(irq, struct llist_header);
     llist_for_each(pos, n, ahcis, ahci_drvs)
     {
         if (pos->id == hart_vector_stamp(hstate)) {
     llist_for_each(pos, n, ahcis, ahci_drvs)
     {
         if (pos->id == hart_vector_stamp(hstate)) {
index 3052a90eea05bc70b5128d41d96f90682ea6c218..0543d0aef8e9ba943e58845b5ab8d1ab1ac22c0e 100644 (file)
@@ -107,6 +107,7 @@ __pci_add_prober(pciaddr_t loc, ptr_t pci_base, int devinfo)
     prober->cspace_base = pci_base;
     prober->intr_info = intr;
     prober->loc = loc;
     prober->cspace_base = pci_base;
     prober->intr_info = intr;
     prober->loc = loc;
+    prober->irq_domain = irq_get_domain(pci_bridge);
 
     changeling_morph_anon(pci_probers, prober->mobj, pci_probe_morpher);
 
 
     changeling_morph_anon(pci_probers, prober->mobj, pci_probe_morpher);
 
@@ -271,12 +272,12 @@ pci_scan()
 }
 
 static void
 }
 
 static void
-__pci_config_msi(struct pci_probe* probe, msi_vector_t msiv)
+__pci_config_msi(struct pci_probe* probe, irq_t irq)
 {
     // PCI LB Spec. (Rev 3) Section 6.8 & 6.8.1
 
 {
     // PCI LB Spec. (Rev 3) Section 6.8 & 6.8.1
 
-    ptr_t msi_addr = msi_addr(msiv);
-    u32_t msi_data = msi_data(msiv);
+    ptr_t msi_addr = irq->msi->wr_addr;
+    u32_t msi_data = irq->msi->message;
 
     pci_reg_t reg1 = pci_read_cspace(probe->cspace_base, probe->msi_loc);
     pci_reg_t msg_ctl = reg1 >> 16;
 
     pci_reg_t reg1 = pci_read_cspace(probe->cspace_base, probe->msi_loc);
     pci_reg_t msg_ctl = reg1 >> 16;
@@ -306,39 +307,26 @@ __pci_config_msi(struct pci_probe* probe, msi_vector_t msiv)
     pci_write_cspace(probe->cspace_base, probe->msi_loc, reg1);
 }
 
     pci_write_cspace(probe->cspace_base, probe->msi_loc, reg1);
 }
 
-msienv_t
-pci_msi_start(struct pci_probe* probe)
+irq_t
+pci_declare_msi_irq(irq_servant callback, struct pci_probe* probe)
 {
 {
-    /*
-        As a PCI bridge/root complex can be initialised from device tree node,
-        in that case, general information such as routing, rid remapping, 
-        are vital to all msi setup of all peripherals under it.
-
-        Therefore, a wrapper around isrm_msi_* is needed in order to
-        improve overall readability and usability, where the bridge
-        device instance that contain these information will be 
-        automatically passed to the underlay as credential to perform
-        configuration.
-    */
-
-    msienv_t env;
-    
-    env = isrm_msi_start(pci_bridge);
-    isrm_msi_set_sideband(env, pci_requester_id(probe));
-
-    return env;
+    return irq_declare_msg(callback, probe->loc, probe->loc);
 }
 
 }
 
-msi_vector_t
-pci_msi_setup_at(msienv_t msienv, struct pci_probe* probe, 
-                 int i, isr_cb handler)
+int
+pci_assign_msi(struct pci_probe* probe, irq_t irq, void* irq_spec)
 {
 {
-    msi_vector_t msiv;
+    int err = 0;
 
 
-    msiv = isrm_msi_alloc(msienv, 0, i, handler);
-    __pci_config_msi(probe, msiv);
+    assert(irq->type == IRQ_MESSAGE);
 
 
-    return msiv;
+    err = irq_assign(probe->irq_domain, irq, irq_spec);
+    if (err) {
+        return err;
+    }
+
+    __pci_config_msi(probe, irq);
+    return 0;
 }
 
 size_t
 }
 
 size_t
@@ -532,6 +520,29 @@ EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping);
 
 /*---------- PCI 3.0 HBA device definition ----------*/
 
 
 /*---------- PCI 3.0 HBA device definition ----------*/
 
+static int
+__pci_irq_install(struct irq_domain* domain, irq_t irq)
+{
+    struct irq_domain* parent;
+    int err;
+
+    parent = domain->parent;
+    err = parent->ops->install_irq(parent, irq);
+    if (err) {
+        return err;
+    }
+
+    if (irq->type == IRQ_MESSAGE) {
+        irq->msi->message = irq->vector;
+    }
+
+    return 0;
+}
+
+static struct irq_domain_ops pci_irq_ops = {
+    .install_irq = __pci_irq_install
+};
+
 static int
 pci_register(struct device_def* def)
 {
 static int
 pci_register(struct device_def* def)
 {
@@ -543,15 +554,19 @@ pci_register(struct device_def* def)
 static int
 pci_create(struct device_def* def, morph_t* obj)
 {
 static int
 pci_create(struct device_def* def, morph_t* obj)
 {
-    devtree_link_t devtree_node;
+    struct irq_domain *pci_domain;
+    pci_bridge = device_allocsys(NULL, NULL);
 
 
+#ifdef CONFIG_USE_DEVICETREE
+    devtree_link_t devtree_node;
     devtree_node = changeling_try_reveal(obj, dt_node_morpher);
     devtree_node = changeling_try_reveal(obj, dt_node_morpher);
-
-    pci_bridge = device_allocsys(NULL, NULL);
     device_set_devtree_node(pci_bridge, devtree_node);
     device_set_devtree_node(pci_bridge, devtree_node);
+#endif
 
 
-    register_device(pci_bridge, &def->class, "pci_bridge");
+    pci_domain = irq_create_domain(pci_bridge, &pci_irq_ops);
+    irq_attach_domain(irq_get_default_domain(), pci_domain);
 
 
+    register_device(pci_bridge, &def->class, "pci_bridge");
     pci_scan();
 
     return 0;
     pci_scan();
 
     return 0;
@@ -564,4 +579,4 @@ static struct device_def pci_def = {
     def_on_register(pci_register),
     def_on_create(pci_create)
 };
     def_on_register(pci_register),
     def_on_create(pci_create)
 };
-EXPORT_DEVICE(pci3hba, &pci_def, load_sysconf);
+EXPORT_DEVICE(pci3hba, &pci_def, load_onboot);
index 40ebe94a421a7cda1fa47cb1d87ba9af175f6abb..4a2c8a5b61e9b6012b380ffbd68db82fdfbf076d 100644 (file)
@@ -2,6 +2,7 @@
 #define __LUNAIX_16550_H
 
 #include <hal/serial.h>
 #define __LUNAIX_16550_H
 
 #include <hal/serial.h>
+#include <hal/irq.h>
 #include <lunaix/types.h>
 
 #define UART_rRxTX 0
 #include <lunaix/types.h>
 
 #define UART_rRxTX 0
@@ -70,7 +71,7 @@ struct uart16550
     struct serial_dev* sdev;
     ptr_t base_addr;
     unsigned int base_clk;
     struct serial_dev* sdev;
     ptr_t base_addr;
     unsigned int base_clk;
-    int iv;
+    irq_t irq;
 
     struct
     {
 
     struct
     {
@@ -227,10 +228,10 @@ int
 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len);
 
 void
 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len);
 
 void
-uart_handle_irq_overlap(int iv, struct llist_header* ports);
+uart_handle_irq_overlap(irq_t irq, struct llist_header* ports);
 
 void
 
 void
-uart_handle_irq(int iv, struct uart16550 *uart);
+uart_handle_irq(irq_t irq, struct uart16550 *uart);
 
 static inline struct serial_dev*
 uart_create_serial(struct uart16550* uart, struct devclass* class, 
 
 static inline struct serial_dev*
 uart_create_serial(struct uart16550* uart, struct devclass* class, 
index 8b3930f29779973071d45facf65f4a56ece92f76..5b14445521c5c9f92345ee0caea9fe960da37998 100644 (file)
@@ -103,13 +103,13 @@ uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args)
 }
 
 void
 }
 
 void
-uart_handle_irq_overlap(int iv, struct llist_header* ports)
+uart_handle_irq_overlap(irq_t irq, struct llist_header* ports)
 {
     struct uart16550 *pos, *n;
     llist_for_each(pos, n, ports, local_ports)
     {
         int is = uart_intr_identify(pos);
 {
     struct uart16550 *pos, *n;
     llist_for_each(pos, n, ports, local_ports)
     {
         int is = uart_intr_identify(pos);
-        if (iv == pos->iv && (is == UART_CHR_TIMEOUT)) {
+        if (irq == pos->irq && (is == UART_CHR_TIMEOUT)) {
             goto done;
         }
     }
             goto done;
         }
     }
@@ -117,11 +117,11 @@ uart_handle_irq_overlap(int iv, struct llist_header* ports)
     return;
 
 done:
     return;
 
 done:
-    uart_handle_irq(iv, pos);
+    uart_handle_irq(irq, pos);
 }
 
 void
 }
 
 void
-uart_handle_irq(int iv, struct uart16550 *uart)
+uart_handle_irq(irq_t irq, struct uart16550 *uart)
 {
     char tmpbuf[32];
     char recv;
 {
     char tmpbuf[32];
     char recv;
index 39582236364660f4a1e21144eadf27a69ffd45ff..152317a5cdeb71dc97eace2d0c49287263b612cb 100644 (file)
@@ -2,7 +2,6 @@
 #include <lunaix/syslog.h>
 
 #include <asm/x86_pmio.h>
 #include <lunaix/syslog.h>
 
 #include <asm/x86_pmio.h>
-#include <asm/x86_isrm.h>
 
 #include "16x50.h"
 
 
 #include "16x50.h"
 
@@ -11,10 +10,9 @@ LOG_MODULE("16x50-isa");
 static DEFINE_LLIST(com_ports);
 
 static void
 static DEFINE_LLIST(com_ports);
 
 static void
-com_irq_handler(const struct hart_state* hstate)
+com_irq_handler(irq_t irq, const struct hart_state* hstate)
 {
 {
-    int vector = hart_vector_stamp(hstate);
-    uart_handle_irq_overlap(vector, &com_ports);
+    uart_handle_irq_overlap(irq, &com_ports);
 }
 
 int
 }
 
 int
@@ -25,6 +23,7 @@ isa16x50_create_once(struct device_def* def)
     int* irqs[] = { &irq4, &irq3, &irq4, &irq3 };
 
     struct uart16550* uart = NULL;
     int* irqs[] = { &irq4, &irq3, &irq4, &irq3 };
 
     struct uart16550* uart = NULL;
+    struct serial_dev* sdev;
     ptr_t base;
 
     // COM 1...4
     ptr_t base;
 
     // COM 1...4
@@ -37,20 +36,20 @@ isa16x50_create_once(struct device_def* def)
             continue;
         }
 
             continue;
         }
 
+        sdev = uart_create_serial(uart, &def->class, &com_ports, "S");
+        
         int irq = *irqs[i];
         if (irq) {
             /*
              *  Since these irqs are overlapped, this particular setup is needed
              * to avoid double-bind
              */
         int irq = *irqs[i];
         if (irq) {
             /*
              *  Since these irqs are overlapped, this particular setup is needed
              * to avoid double-bind
              */
-            uart->iv = isrm_bindirq(irq, com_irq_handler);
+            uart->irq = irq_declare_line(com_irq_handler, irq);
+            irq_assign(irq_owning_domain(sdev->dev), uart->irq, NULL);
             *((volatile int*)irqs[i]) = 0;
         }
             *((volatile int*)irqs[i]) = 0;
         }
-
-        INFO("base: 0x%x, irq=%d", 
-                base, irq, uart->iv);
-
-        uart_create_serial(uart, &def->class, &com_ports, "S");
+        
+        INFO("base: 0x%x, irq=%d", base, irq);
     }
 
     return 0;
     }
 
     return 0;
index e2116253a37701bda9b4a1c36871a22076b3bebd..4762ef17189a718bde411d1f05e4366e242830cb 100644 (file)
@@ -1,5 +1,4 @@
 #include <lunaix/device.h>
 #include <lunaix/device.h>
-#include <asm-generic/isrm.h>
 #include <lunaix/mm/mmio.h>
 
 #include "16x50.h"
 #include <lunaix/mm/mmio.h>
 
 #include "16x50.h"
index 20beda12244206a04454e5e132c5b9cd18483d26..bba016fd09959ec5994d183a1651b05838245569 100644 (file)
@@ -1,5 +1,4 @@
 #include <lunaix/device.h>
 #include <lunaix/device.h>
-#include <asm-generic/isrm.h>
 #include <lunaix/syslog.h>
 #include <lunaix/mm/mmio.h>
 
 #include <lunaix/syslog.h>
 #include <lunaix/mm/mmio.h>
 
@@ -15,23 +14,14 @@ static DEFINE_LLIST(pci_ports);
 
 
 static void
 
 
 static void
-uart_msi_irq_handler(const struct hart_state* hstate)
+uart_msi_irq_handler(irq_t irq, const struct hart_state* hstate)
 {
 {
-    int vector;
     struct uart16550* uart;
     
     struct uart16550* uart;
     
-    vector = hart_vector_stamp(hstate);
-    uart = (struct uart16550*)isrm_get_payload(hstate);
+    uart = irq_payload(irq, struct uart16550);
 
     assert(uart);
 
     assert(uart);
-    uart_handle_irq(vector, uart);
-}
-
-static void
-uart_intx_irq_handler(const struct hart_state* hstate)
-{
-    int vector = hart_vector_stamp(hstate);
-    uart_handle_irq_overlap(vector, &pci_ports);
+    uart_handle_irq(irq, uart);
 }
 
 static bool
 }
 
 static bool
@@ -56,7 +46,7 @@ pci16x50_pci_create(struct device_def* def, morph_t* obj)
     struct pci_probe* probe;
     struct uart16550* uart;
     struct serial_dev* sdev;
     struct pci_probe* probe;
     struct uart16550* uart;
     struct serial_dev* sdev;
-    msi_vector_t msiv;
+    irq_t irq;
     
     probe = changeling_reveal(obj, pci_probe_morpher);
 
     
     probe = changeling_reveal(obj, pci_probe_morpher);
 
@@ -102,16 +92,16 @@ pci16x50_pci_create(struct device_def* def, morph_t* obj)
 
         sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI");
 
 
         sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI");
 
-        msiv = pci_msi_setup_simple(probe, uart_msi_irq_handler);
-        isrm_set_payload(msi_vect(msiv), __ptr(uart));
+        irq = pci_declare_msi_irq(uart_msi_irq_handler, probe);
+        irq_set_payload(irq, uart);
+        pci_assign_msi(probe, irq, NULL);
 
 
-        INFO("base: 0x%x (%s), irq=%d (%s)", 
+        INFO("base: 0x%x (%s), %s", 
                 bar->start, 
                 pci_bar_mmio_space(bar) ? "mmio" : "pmio",
                 bar->start, 
                 pci_bar_mmio_space(bar) ? "mmio" : "pmio",
-                msi_vect(msiv), 
                 pci_capability_msi(probe) ? "msi" : "intx, re-routed");
         
                 pci_capability_msi(probe) ? "msi" : "intx, re-routed");
         
-        uart->iv = msi_vect(msiv);
+        uart->irq = irq;
 
         pci_bind_instance(probe, sdev->dev);
     }
 
         pci_bind_instance(probe, sdev->dev);
     }
index ea550cbb995f57e664b190d64d001a4851e4ab84..3b97105021a9822445040bfe9f3f42992a655ea5 100644 (file)
@@ -9,7 +9,6 @@
  *
  */
 #include <lunaix/device.h>
  *
  */
 #include <lunaix/device.h>
-#include <asm-generic/isrm.h>
 
 #include <asm/x86_pmio.h>
 
 
 #include <asm/x86_pmio.h>
 
index 97f3109f78589eaa5b7cc2017f33fd0e349b0395..000d52b4ab085169fe27cb818476753cb1afd342 100644 (file)
@@ -1,6 +1,6 @@
 sources([
     "dt_interrupt.c",
     "dt.c",
 sources([
     "dt_interrupt.c",
     "dt.c",
-    "dtm.c"
+    "dtm.c",
     "dtspec.c"
 ])
\ No newline at end of file
     "dtspec.c"
 ])
\ No newline at end of file
index 1bfe891b5b2540a3adcb9443bfde5a9560278f52..66fe7dc0c9bac28809f99607cc6e2caabc62475f 100644 (file)
@@ -11,10 +11,16 @@ propeq(struct fdt_blob* fdt, fdt_loc_t loc, const char* key)
     return streq(fdt_prop_key(fdt, loc), key);
 }
 
     return streq(fdt_prop_key(fdt, loc), key);
 }
 
+static inline ptr_t
+__prop_val_ptr(struct fdt_prop* prop)
+{
+    return __ptr(prop) + sizeof(struct fdt_prop);
+}
+
 static inline void
 __mkprop_ptr(fdt_loc_t loc, struct dtp_val* val)
 {
 static inline void
 __mkprop_ptr(fdt_loc_t loc, struct dtp_val* val)
 {
-    val->ptr_val = __ptr(loc.prop->val);
+    val->ptr_val = __prop_val_ptr(loc.prop);
     val->size = loc.prop->len;
 }
 
     val->size = loc.prop->len;
 }
 
index a4265512c5e7effc6d39f7a30821189e33239c4b..63286b10398f6aa714c3cc30d27da3d7378f8070 100644 (file)
@@ -121,7 +121,7 @@ fdt_find_prop(const struct fdt_blob* fdt, fdt_loc_t loc,
         }
         
         if (likely(val)) {
         }
         
         if (likely(val)) {
-            val->encoded = (dt_enc_t)loc.prop->val;
+            val->encoded = (dt_enc_t)__prop_val_ptr(loc.prop);
             val->size    = loc.prop->len;
         }
         return true;
             val->size    = loc.prop->len;
         }
         return true;
@@ -152,6 +152,8 @@ fdt_memscan_begin(struct fdt_memscan* mscan, const struct fdt_blob* fdt)
 
     mscan->loc = loc;
     mscan->node_type = FDT_MEM_FREE;
 
     mscan->loc = loc;
     mscan->node_type = FDT_MEM_FREE;
+
+    return true;
 }
 
 #define get_size(mscan, val)    \
 }
 
 #define get_size(mscan, val)    \
diff --git a/lunaix-os/hal/irq.c b/lunaix-os/hal/irq.c
new file mode 100644 (file)
index 0000000..cee6767
--- /dev/null
@@ -0,0 +1,194 @@
+#include <hal/irq.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/owloysius.h>
+
+static struct irq_domain* default_domain = NULL;
+static DEFINE_LLIST(irq_domains);
+
+static void
+__default_servant(irq_t irq, const struct hart_state* state)
+{
+    return;
+}
+
+struct irq_domain*
+irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops)
+{
+    struct irq_domain* domain;
+
+    assert(ops->install_irq);
+
+    domain = new_potens(potens(INT_DOMAIN), struct irq_domain);
+    device_grant_potens(intc_dev, potens_meta(domain));
+
+    btrie_init(&domain->irq_map, ilog2(8));
+    llist_append(&irq_domains, &domain->list);
+    domain->ops = ops;
+    
+    return domain;
+}
+
+struct irq_domain*
+irq_owning_domain(struct device* dev)
+{
+#ifdef CONFIG_USE_DEVICETREE
+    struct device* intc;
+    struct dtn* intr_parent;
+    struct potens_meta* domain_m;
+
+    intr_parent = dev->devtree_node->intr.parent;
+    intc = resolve_device_morph(dt_mobj(intr_parent));
+
+    if (!intc) {
+        return NULL;
+    }
+
+    domain_m = device_get_potens(intc, potens(INT_DOMAIN));
+    return !domain_m ?: get_potens(domain_m, struct irq_domain);
+#else
+    return default_domain;
+#endif
+}
+
+int
+irq_attach_domain(struct irq_domain* parent, struct irq_domain* child)
+{
+#ifndef CONFIG_USE_DEVICETREE
+    parent = parent ?: default_domain;
+    child->parent = parent;
+#endif
+    return 0;
+}
+
+static void
+__irq_create_line(irq_t irq, ptr_t local_int)
+{
+    struct irq_line_wire *line;
+
+    line = valloc(sizeof(*line));
+    line->domain_local = local_int;
+    line->domain_mapped = local_int;
+
+    irq->line = line;
+}
+
+static void
+__irq_create_msi(irq_t irq, ptr_t message)
+{
+    struct irq_msi_wire *msi;
+
+    msi = valloc(sizeof(*msi));
+    msi->message  = message;
+
+    irq->msi = msi;
+}
+
+irq_t
+irq_declare(enum irq_type type, irq_servant callback, ptr_t data)
+{
+    irq_t irq;
+
+    irq  = valloc(sizeof(*irq));
+    *irq = (struct irq_object) {
+        .type = type,
+        .serve = callback ?: __default_servant,
+        .vector = IRQ_VECTOR_UNSET
+    };
+
+    if (type == IRQ_LINE) {
+        __irq_create_line(irq, data);
+    }
+
+    else if (type == IRQ_MESSAGE) {
+        __irq_create_msi(irq, data);
+    }
+
+    return irq;
+}
+
+void
+irq_revoke(irq_t irq)
+{
+    if (--(irq->ref) > 0) {
+        return;
+    }
+    vfree(irq);
+}
+
+int
+irq_assign(struct irq_domain* domain, irq_t irq, void* irq_spec)
+{
+    int err = 0;    
+    if (domain->ops->map_irq) {
+        err = domain->ops->map_irq(domain, irq, irq_spec);
+        if (err) {
+            return err;
+        }
+    }
+
+    /*
+        A domain controller may choose to forward the interrupt
+        (i.e., irq became transparent and belongs to the higher domain)
+        We allow controller decide whether to record the irq under its wing
+    */
+    err = domain->ops->install_irq(domain, irq);
+    if (err) {
+        return err;
+    }
+
+    irq->domain = domain;
+    return 0;
+}
+
+irq_t
+irq_find(struct irq_domain* domain, int local_irq)
+{
+    irq_t irq = NULL;
+    struct irq_domain* current;
+
+    // Find recursively, in case of irq forwarding
+
+    current = domain ?: default_domain;
+    while (current && !irq) {
+        irq = (irq_t)btrie_get(&current->irq_map, local_irq);
+        current = irq_parent_domain(current);
+    }
+    
+    return irq;
+}
+
+void
+irq_record(struct irq_domain* domain, irq_t irq)
+{
+    irq->ref++;
+    btrie_set(&domain->irq_map, irq->vector, irq);
+}
+
+void
+irq_set_default_domain(struct irq_domain* domain)
+{
+    assert(!default_domain);
+    default_domain = domain;
+}
+
+int
+irq_forward_install(struct irq_domain* current, irq_t irq)
+{
+    struct irq_domain* parent;
+
+    parent = irq_parent_domain(current);
+
+    if (irq->type == IRQ_LINE) {
+        irq->line->domain_local = irq->line->domain_mapped;
+    }
+
+    irq->domain = parent;
+    return parent->ops->install_irq(parent, irq);
+}
+
+struct irq_domain*
+irq_get_default_domain()
+{
+    assert(default_domain);
+    return default_domain;
+}
index 7eaf10d4e012d73f231c457eeddf84a76f1cf57c..9cf80fcef47845ad800d0ab844cb9f62e93a5cfa 100644 (file)
@@ -2,7 +2,7 @@
 #define __LUNAIX_AHCI_H
 
 #include "hba.h"
 #define __LUNAIX_AHCI_H
 
 #include "hba.h"
-#include <asm-generic/isrm.h>
+#include <hal/irq.h>
 
 /*
  * Macro naming rule:
 
 /*
  * Macro naming rule:
@@ -26,7 +26,7 @@ struct ahci_driver_param
 {
     ptr_t mmio_base;
     size_t mmio_size;
 {
     ptr_t mmio_base;
     size_t mmio_size;
-    int ahci_iv;
+    irq_t irq;
 };
 
 void
 };
 
 void
@@ -59,6 +59,6 @@ struct ahci_driver*
 ahci_driver_init(struct ahci_driver_param* param);
 
 void
 ahci_driver_init(struct ahci_driver_param* param);
 
 void
-ahci_hba_isr(const struct hart_state* hstate);
+ahci_hba_isr(irq_t irq, const struct hart_state* hstate);
 
 #endif /* __LUNAIX_AHCI_H */
 
 #endif /* __LUNAIX_AHCI_H */
index e7e0cf37ce0a32c36ece6877426e7db109ec8ab2..111617e7626c786e3afa5c4af5780ab0da90b7b5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LUNAIX_DEVTREE_H
 #define __LUNAIX_DEVTREE_H
 
 #ifndef __LUNAIX_DEVTREE_H
 #define __LUNAIX_DEVTREE_H
 
+#ifdef CONFIG_USE_DEVICETREE
 #include <lunaix/types.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/hstr.h>
 #include <lunaix/types.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/hstr.h>
@@ -46,14 +47,14 @@ struct dtp_val
 {
     union
     {
 {
     union
     {
-        union {
-            const char*  str_val;
-            const char*  str_lst;
-        };
         ptr_t        ptr_val;
         dt_enc_t     encoded;
         
         union dtp_baseval* ref;
         ptr_t        ptr_val;
         dt_enc_t     encoded;
         
         union dtp_baseval* ref;
+        union {
+            const char*  str_val;
+            const char*  str_lst;
+        };
     };
     unsigned int size;
 };
     };
     unsigned int size;
 };
@@ -669,7 +670,7 @@ static inline void
 dtpi_init_empty(struct dtpropi* dtpi)
 {
     *dtpi = (struct dtpropi) {
 dtpi_init_empty(struct dtpropi* dtpi)
 {
     *dtpi = (struct dtpropi) {
-        .prop = { 0, 0 },
+        .prop = { {0}, 0 },
         .loc = 0
     };
 }
         .loc = 0
     };
 }
@@ -727,4 +728,5 @@ dtpi_next_val(struct dtpropi* dtpi, struct dtp_val* val, int cells)
     return true;
 }
 
     return true;
 }
 
+#endif
 #endif /* __LUNAIX_DEVTREE_H */
 #endif /* __LUNAIX_DEVTREE_H */
index 2b0904d6babf6d257873d3a4eab4773d70032e1b..d235cd7f3375cc90c2cb0147bc31da927230f5e0 100644 (file)
@@ -13,7 +13,7 @@ struct device;
 
 typedef struct dtn* devtree_link_t;
 
 
 typedef struct dtn* devtree_link_t;
 
-#define dt_node_morpher     morphable_attrs(dt_node, mobj)
+#define dt_node_morpher     morphable_attrs(dtn, mobj)
 
 struct dtm_driver_info
 {
 
 struct dtm_driver_info
 {
diff --git a/lunaix-os/includes/hal/irq.h b/lunaix-os/includes/hal/irq.h
new file mode 100644 (file)
index 0000000..41be4b0
--- /dev/null
@@ -0,0 +1,180 @@
+#ifndef __LUNAIX_IRQ_H
+#define __LUNAIX_IRQ_H
+
+#include <lunaix/changeling.h>
+#include <lunaix/device.h>
+#include <lunaix/ds/btrie.h>
+#include <asm/hart.h>
+
+#define IRQ_VECTOR_UNSET    ((unsigned)-1)
+
+struct irq_domain;
+typedef struct irq_object* irq_t;
+typedef void (*irq_servant)(irq_t, const struct hart_state*);
+
+struct irq_domain_ops
+{
+    int
+    (*install_irq)(struct irq_domain*, irq_t);
+
+    int
+    (*map_irq)(struct irq_domain*, irq_t, void* irq_extra);
+
+    int
+    (*remove_irq)(struct irq_domain*, irq_t);
+};
+
+struct irq_domain
+{
+    POTENS_META;
+
+    struct llist_header list;
+
+    struct irq_domain* parent;
+    struct btrie irq_map;
+    const struct irq_domain_ops* ops;
+    void* object;
+};
+
+enum irq_type
+{
+    IRQ_DIRECT,
+    IRQ_LINE,
+    IRQ_MESSAGE
+};
+
+struct irq_line_wire
+{
+    ptr_t domain_local;
+    ptr_t domain_mapped;
+};
+
+struct irq_msi_wire
+{
+    ptr_t message;
+    ptr_t sideband;
+    ptr_t wr_addr;
+};
+
+struct irq_object
+{    
+    enum irq_type type;
+    unsigned int vector;
+    
+    union {
+        struct irq_line_wire* line;
+        struct irq_msi_wire* msi;
+    };
+
+    irq_servant serve;
+    void* payload;
+
+    struct irq_domain* domain;
+    int ref;
+};
+
+struct irq_domain*
+irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops);
+
+struct irq_domain*
+irq_owning_domain(struct device* dev);
+
+int
+irq_attach_domain(struct irq_domain* parent, struct irq_domain* child);
+
+irq_t
+irq_declare(enum irq_type, irq_servant, ptr_t);
+
+void
+irq_revoke(irq_t);
+
+int
+irq_assign(struct irq_domain* domain, irq_t, void*);
+
+irq_t
+irq_find(struct irq_domain* domain, int local_irq);
+
+void
+irq_record(struct irq_domain* domain, irq_t irq);
+
+void
+irq_set_default_domain(struct irq_domain*);
+
+struct irq_domain*
+irq_get_default_domain();
+
+int
+irq_forward_install(struct irq_domain* current, irq_t irq);
+
+static inline void
+irq_serve(irq_t irq, struct hart_state* state)
+{
+    irq->serve(irq, state);
+}
+
+static inline void
+irq_set_servant(irq_t irq, irq_servant callback)
+{
+    irq->serve = callback;
+}
+
+static inline void
+irq_bind_vector(irq_t irq, int vector)
+{
+    irq->vector = vector;
+}
+
+static inline void
+irq_set_payload(irq_t irq, void* payload)
+{
+    irq->payload = payload;
+}
+
+static inline void
+irq_set_domain_object(struct irq_domain* domain, void* obj)
+{
+    domain->object = obj;
+}
+
+#define irq_payload(irq, type)              ((type*)(irq)->payload)
+#define irq_domain_obj(domain, type)        ((type*)(domain)->object)
+
+static inline irq_t
+irq_declare_line(irq_servant callback, int local_irq)
+{
+    return irq_declare(IRQ_LINE, callback, (int)local_irq);
+}
+
+static inline irq_t
+irq_declare_msg(irq_servant callback, 
+                ptr_t message, ptr_t sideband)
+{
+    irq_t irq;
+    irq = irq_declare(IRQ_MESSAGE, callback, message);
+    irq->msi->sideband = sideband;
+
+    return irq;
+}
+
+static inline irq_t
+irq_declare_direct(irq_servant callback)
+{
+    return irq_declare(IRQ_DIRECT, callback, 0);
+}
+
+static inline struct irq_domain*
+irq_get_domain(struct device* maybe_intc)
+{
+    struct potens_meta* domain_m;
+
+    domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN));
+    return domain_m ? get_potens(domain_m, struct irq_domain) : NULL;
+}
+
+static inline struct irq_domain*
+irq_parent_domain(struct irq_domain* domain)
+{
+    return domain->parent;
+}
+
+#endif /* __LUNAIX_IRQ_H */
index 37815fefb8a41e71a12ce0981225dae5fc438128..22b3dd918a5ff86c83bca5c29e8a707e8f86c691 100644 (file)
@@ -8,7 +8,7 @@
 #include <lunaix/types.h>
 #include <lunaix/changeling.h>
 
 #include <lunaix/types.h>
 #include <lunaix/changeling.h>
 
-#include <asm-generic/isrm.h>
+#include "irq.h"
 
 #define PCI_VENDOR_INVLD 0xffff
 
 
 #define PCI_VENDOR_INVLD 0xffff
 
@@ -86,6 +86,7 @@ struct pci_probe
     struct pci_base_addr bar[6];
 
     struct device* bind;
     struct pci_base_addr bar[6];
 
     struct device* bind;
+    struct irq_domain* irq_domain;
 };
 #define pci_probe_morpher   morphable_attrs(pci_probe, mobj)
 
 };
 #define pci_probe_morpher   morphable_attrs(pci_probe, mobj)
 
@@ -115,6 +116,12 @@ pci_register_driver(struct device_def* def, pci_id_checker_t checker);
 size_t
 pci_bar_sizing(struct pci_probe* probe, u32_t* bar_out, u32_t bar_num);
 
 size_t
 pci_bar_sizing(struct pci_probe* probe, u32_t* bar_out, u32_t bar_num);
 
+irq_t
+pci_declare_msi_irq(irq_servant callback, struct pci_probe* probe);
+
+int
+pci_assign_msi(struct pci_probe* probe, irq_t irq, void* irq_spec);
+
 /**
  * @brief Bind an abstract device instance to the pci device
  *
 /**
  * @brief Bind an abstract device instance to the pci device
  *
@@ -128,32 +135,6 @@ pci_bind_instance(struct pci_probe* probe, struct device* dev)
 
 }
 
 
 }
 
-msienv_t
-pci_msi_start(struct pci_probe* probe);
-
-msi_vector_t
-pci_msi_setup_at(msienv_t msienv, struct pci_probe* probe, 
-                 int i, isr_cb handler);
-
-static inline void
-pci_msi_done(msienv_t env)
-{
-    isrm_msi_done(env);
-}
-
-static inline msi_vector_t
-pci_msi_setup_simple(struct pci_probe* probe, isr_cb handler)
-{
-    msienv_t env;
-    msi_vector_t msiv;
-    
-    env = pci_msi_start(probe);
-    msiv = pci_msi_setup_at(env, probe, 0, handler);
-    pci_msi_done(env);
-
-    return msiv;
-}
-
 int
 pci_bind_driver(struct pci_registry* reg);
 
 int
 pci_bind_driver(struct pci_registry* reg);
 
index aecd7d4d2446d820d0974b9098427996c7a76506..62253e91d4cab426f17fc006fb542cbd7675a3a3 100644 (file)
@@ -4,4 +4,5 @@ morphable(pci_probe),
 morphable(device_meta),
 morphable(device_cat),
 morphable(device_alias),
 morphable(device_meta),
 morphable(device_cat),
 morphable(device_alias),
-morphable(device),
\ No newline at end of file
+morphable(device),
+morphable(irq_object),
\ No newline at end of file
index 9534b9a700fc7bb3dabe95d138a3c37556480c28..9b80f90a6b25b85e1ba2eaad13ad060d6368fc5b 100644 (file)
@@ -17,4 +17,10 @@ potens(HWTIMER),
  * @brief RTC capability.
  * 
  */
  * @brief RTC capability.
  * 
  */
-potens(HWRTC),
\ No newline at end of file
+potens(HWRTC),
+
+/**
+ * @brief Interrupt controller (domain) capability
+ * 
+ */
+potens(INT_DOMAIN),
\ No newline at end of file
index f1ce4d0df9a1bbfa19f4cc14cdf28f2875b74932..7a469a113c725b31e1fba06cb0c0667788f9dcb1 100644 (file)
@@ -353,11 +353,13 @@ device_create(struct device* dev,
 struct device*
 device_alloc(struct device_meta* parent, u32_t type, void* underlay);
 
 struct device*
 device_alloc(struct device_meta* parent, u32_t type, void* underlay);
 
+#ifdef CONFIG_USE_DEVICETREE
 static inline void
 device_set_devtree_node(struct device* dev, devtree_link_t node)
 {
     dev->devtree_node = node;
 }
 static inline void
 device_set_devtree_node(struct device* dev, devtree_link_t node)
 {
     dev->devtree_node = node;
 }
+#endif
 
 static inline struct device* must_inline
 device_allocsys(struct device_meta* parent, void* underlay)
 
 static inline struct device* must_inline
 device_allocsys(struct device_meta* parent, void* underlay)
index bcf02500de3122a9ba7e8681cc6e0cfb55b93d14..d24cf84e56ae30bf762aaa8e3575b22cfeae324d 100644 (file)
@@ -6,6 +6,9 @@
 
 #define BTRIE_BITS 4
 
 
 #define BTRIE_BITS 4
 
+/**
+ * key-sorted prefix tree
+ */
 struct btrie
 {
     struct btrie_node* btrie_root;
 struct btrie
 {
     struct btrie_node* btrie_root;
@@ -14,12 +17,13 @@ struct btrie
 
 struct btrie_node
 {
 
 struct btrie_node
 {
-    struct llist_header children;
-    struct llist_header siblings;
     struct llist_header nodes;
     struct btrie_node* parent;
     unsigned long index;
     void* data;
     struct llist_header nodes;
     struct btrie_node* parent;
     unsigned long index;
     void* data;
+
+    struct btrie_node** children;
+    int children_cnt;
 };
 
 void
 };
 
 void
@@ -28,9 +32,21 @@ btrie_init(struct btrie* btrie, unsigned int order);
 void*
 btrie_get(struct btrie* root, unsigned long index);
 
 void*
 btrie_get(struct btrie* root, unsigned long index);
 
+/**
+ * Set an object into btrie tree at given location,
+ * override if another object is already present.
+ */
 void
 btrie_set(struct btrie* root, unsigned long index, void* data);
 
 void
 btrie_set(struct btrie* root, unsigned long index, void* data);
 
+/**
+ * Map an object into btrie tree, return the index the object
+ * mapped to
+ */
+unsigned long
+btrie_map(struct btrie* root, 
+          unsigned long start, unsigned long end, void* data);
+
 void*
 btrie_remove(struct btrie* root, unsigned long index);
 
 void*
 btrie_remove(struct btrie* root, unsigned long index);
 
index 72758fb4517d822bfcf8b5bc1dced14d2ed80bfe..8971759e931baa27195b92d6f7b0ddf5ea82b462 100644 (file)
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 
-#define BTRIE_INSERT 1
+enum btrie_query_mode {
+    BTRIE_FIND,
+    BTRIE_FIND_PARENT,
+    BTRIE_INSERT
+};
 
 
-struct btrie_node*
-__btrie_traversal(struct btrie* root, unsigned long index, int options)
+#define remove_visit_flag(node)     ((struct btrie_node*)(__ptr(node) & ~1))
+
+static inline void
+__btrie_addchild(struct btrie* root,
+                 struct btrie_node* parent, struct btrie_node* child)
+{
+    if (unlikely(!parent->children)) {
+        parent->children = vcalloc(sizeof(parent), 1 << root->order);
+    }
+
+    parent->children_cnt++;
+    parent->children[child->index] = child;
+}
+
+static inline struct btrie_node*
+__btrie_get_child(struct btrie_node* node, int index)
+{
+    if (unlikely(!node || !node->children)) {
+        return NULL;
+    }
+
+    return remove_visit_flag(node->children[index]);
+}
+
+static inline bool
+__btrie_child_visited(struct btrie_node* node, int index)
+{
+    if (unlikely(!node || !node->children)) {
+        return false;
+    }
+
+    return !!(__ptr(node->children[index]) & 1);
+}
+
+static inline void
+__btrie_visit_child(struct btrie_node* node, int index)
+{
+    if (unlikely(!node || !node->children)) {
+        return;
+    }
+
+    node->children[index] 
+            = (struct btrie_node*)(__ptr(node->children[index]) | 1); 
+}
+
+static inline void
+__btrie_unvisit_child(struct btrie_node* node, int index)
+{
+    if (unlikely(!node || !node->children)) {
+        return;
+    }
+
+    node->children[index] = remove_visit_flag(node->children[index]); 
+}
+
+static inline void
+__btrie_free_node(struct btrie_node* node)
+{
+    vfree_safe(node->children);
+    vfree(node);
+}
+
+static inline bool
+__full_node(struct btrie* root, struct btrie_node* node)
+{
+    return node->children_cnt == 1 << root->order;
+}
+
+static inline struct btrie_node*
+__btrie_create(struct btrie* root, struct btrie_node* parent, int index)
 {
 {
-    unsigned long lz;
-    unsigned long bitmask;
-    unsigned long i = 0;
-    struct btrie_node* tree = root->btrie_root;
+    struct btrie_node* node;
 
 
-    lz = index ? ICEIL(msbitl - clzl(index), root->order) : 0;
+    node = vzalloc(sizeof(struct btrie_node));
+    node->index = index;
+    node->parent = parent;
+    
+    if (likely(parent)) {
+        llist_append(&root->btrie_root->nodes, &node->nodes);
+        __btrie_addchild(root, parent, node);
+    }
+
+    return node;
+}
+
+static struct btrie_node*
+__btrie_traversal(struct btrie* root, 
+                  unsigned long key, enum btrie_query_mode mode)
+{
+    unsigned long lz, bitmask, i = 0;
+    struct btrie_node *subtree, *tree = root->btrie_root;
+    
+    lz = !key ? 0 : (msbitl - clzl(key)) / root->order;
     lz = lz * root->order;
     bitmask = ((1 << root->order) - 1) << lz;
 
     lz = lz * root->order;
     bitmask = ((1 << root->order) - 1) << lz;
 
-    // Time complexity: O(log_2(log_2(N))) where N is the index to lookup
+    // Time complexity: O(log_2(log_2(N))) where N is the key to lookup
     while (bitmask && tree) {
     while (bitmask && tree) {
-        i = (index & bitmask) >> lz;
-        struct btrie_node *subtree = 0, *pos, *n;
-
-        llist_for_each(pos, n, &tree->children, siblings)
-        {
-            if (pos->index == i) {
-                subtree = pos;
-                break;
-            }
-        }
+        i = (key & bitmask) >> lz;
+        subtree = __btrie_get_child(tree, i);
 
 
-        if (!subtree && (options & BTRIE_INSERT)) {
-            struct btrie_node* new_tree = vzalloc(sizeof(struct btrie_node));
-            new_tree->index = i;
-            new_tree->parent = tree;
-            llist_init_head(&new_tree->children);
+        if (!lz && mode == BTRIE_FIND_PARENT) {
+            break;
+        }
 
 
-            llist_append(&tree->children, &new_tree->siblings);
-            llist_append(&root->btrie_root->nodes, &new_tree->nodes);
-            tree = new_tree;
-        else {
+        if (!subtree && (mode != BTRIE_FIND)) {
+            tree = __btrie_create(root, tree, i);
+        }
+        else {
             tree = subtree;
         }
             tree = subtree;
         }
+
         bitmask = bitmask >> root->order;
         lz -= root->order;
     }
         bitmask = bitmask >> root->order;
         lz -= root->order;
     }
@@ -59,29 +138,149 @@ __btrie_traversal(struct btrie* root, unsigned long index, int options)
     return tree;
 }
 
     return tree;
 }
 
+#define check_partial(loc, start, end, mask)    \
+        (((long)(start) - (long)mask - 1) <= (long)loc && loc < end)
+
+static inline struct btrie_node*
+__get_immediate_node(struct btrie* tree, struct btrie_node *root, 
+                     unsigned long start, unsigned long end, unsigned long loc)
+{
+    unsigned int index;
+    unsigned long mask;
+    struct btrie_node *node;
+
+    mask  = (1UL << tree->order) - 1;
+    index = loc & mask;
+    for (unsigned long i = 0; i <= mask; ++i, index = (index + 1) & mask) 
+    {    
+        loc = (loc & ~mask) + index;
+        node = __btrie_get_child(root, index);
+
+        if (loc < start || loc >= end) {
+            continue;
+        }
+
+        if (!node) {
+            return __btrie_create(tree, root, index);
+        }
+
+        if (!node->data) {
+            return node;
+        }
+    }
+
+    return NULL;
+}
+
+static struct btrie_node*
+__btrie_find_free(struct btrie* tree, struct btrie_node *root, 
+                  unsigned long start, unsigned long end, unsigned long loc)
+{
+    unsigned long mask, next_loc;
+    struct btrie_node *node, *found;
+
+    if (!root) return NULL;
+
+    mask  = (1UL << tree->order) - 1;
+
+    __btrie_visit_child(root->parent, root->index);
+    
+    if (!__full_node(tree, root)) {
+        found = __get_immediate_node(tree, root, start, end, loc);
+        if (found) goto done;
+    }
+
+    for (unsigned int i = 0; i <= mask; i++)
+    {
+        next_loc = ((loc & ~mask) + i) << tree->order;
+
+        if (!next_loc || !check_partial(next_loc, start, end, mask)) {
+            continue;
+        }
+
+        if (__btrie_child_visited(root, i)) {
+            continue;
+        }
+
+        node = __btrie_get_child(root, i);
+        node = node ?: __btrie_create(tree, root, i);
+
+        found = __btrie_find_free(tree, node, start, end, next_loc);
+
+        if (found) {
+            goto done;
+        }
+    }
+
+    loc >>= tree->order;
+    found = __btrie_find_free(tree, root->parent, start, end, loc + 1);
+
+done:
+    __btrie_unvisit_child(root->parent, root->index);
+    return found;
+}
+
+static unsigned long
+__btrie_alloc_slot(struct btrie* tree, struct btrie_node **slot, 
+                   unsigned long start, unsigned long end)
+{
+    unsigned int od;
+    unsigned long result, mask;
+    struct btrie_node *found, *node;
+    
+    od   = 0;
+    mask = (1 << od) - 1;
+    found = tree->btrie_root;
+    result = 0;
+
+    if (!start && !__btrie_get_child(found, 0)) {
+        *slot = __btrie_create(tree, found, 0);
+        return 0;
+    }
+
+    found = __btrie_traversal(tree, start, BTRIE_FIND_PARENT);
+    found = __btrie_find_free(tree, found, start, end, start);
+    
+    node = found;
+    while (node) 
+    {
+        result |= node->index << od;
+        od += tree->order;
+        node = node->parent;
+    }
+
+    *slot = found;
+    return found ? result : -1UL;
+}
+
 void
 btrie_init(struct btrie* btrie, unsigned int order)
 {
 void
 btrie_init(struct btrie* btrie, unsigned int order)
 {
-    btrie->btrie_root = vzalloc(sizeof(struct btrie_node));
-    llist_init_head(&btrie->btrie_root->nodes);
-    llist_init_head(&btrie->btrie_root->children);
+    btrie->btrie_root = __btrie_create(btrie, NULL, 0);
     btrie->order = order;
     btrie->order = order;
+
+    llist_init_head(&btrie->btrie_root->nodes);
 }
 
 void*
 btrie_get(struct btrie* root, unsigned long index)
 {
 }
 
 void*
 btrie_get(struct btrie* root, unsigned long index)
 {
-    struct btrie_node* node = __btrie_traversal(root, index, 0);
+    struct btrie_node* node;
+
+    node = __btrie_traversal(root, index, BTRIE_FIND);
     if (!node) {
         return NULL;
     }
     if (!node) {
         return NULL;
     }
+
     return node->data;
 }
 
 void
 btrie_set(struct btrie* root, unsigned long index, void* data)
 {
     return node->data;
 }
 
 void
 btrie_set(struct btrie* root, unsigned long index, void* data)
 {
-    struct btrie_node* node = __btrie_traversal(root, index, BTRIE_INSERT);
+    struct btrie_node* node;
+
+    node = __btrie_traversal(root, index, BTRIE_INSERT);
     node->data = data;
 }
 
     node->data = data;
 }
 
@@ -90,29 +289,53 @@ __btrie_rm_recursive(struct btrie_node* node)
 {
     struct btrie_node* parent = node->parent;
 
 {
     struct btrie_node* parent = node->parent;
 
-    if (parent) {
-        llist_delete(&node->siblings);
-        llist_delete(&node->nodes);
-        vfree(node);
-        if (llist_empty(&parent->children) && !parent->data) {
-            __btrie_rm_recursive(parent);
-        }
+    if (!parent) {
+        return;
+    }
+
+    parent->children[node->index] = NULL;
+    parent->children_cnt--;
+    __btrie_free_node(node);
+
+    if (!parent->children_cnt && !parent->data) {
+        __btrie_rm_recursive(parent);
     }
 }
 
     }
 }
 
+unsigned long
+btrie_map(struct btrie* root, 
+          unsigned long start, unsigned long end, void* data)
+{
+    struct btrie_node* node = NULL;
+    unsigned long alloced;
+
+    alloced = __btrie_alloc_slot(root, &node, start, end);
+    
+    if (!node)
+        return -1;
+
+    node->data = data;
+    return alloced;
+}
+
 void*
 btrie_remove(struct btrie* root, unsigned long index)
 {
 void*
 btrie_remove(struct btrie* root, unsigned long index)
 {
-    struct btrie_node* node = __btrie_traversal(root, index, 0);
+    void* data;
+    struct btrie_node* node;
+
+    node = __btrie_traversal(root, index, BTRIE_FIND);
     if (!node) {
         return 0;
     }
     if (!node) {
         return 0;
     }
-    void* data = node->data;
-    if (!llist_empty(&node->children)) {
+    
+    data = node->data;
+    if (!node->children_cnt) {
         node->data = NULL;
     } else {
         __btrie_rm_recursive(node);
     }
         node->data = NULL;
     } else {
         __btrie_rm_recursive(node);
     }
+
     return data;
 }
 
     return data;
 }
 
@@ -122,8 +345,8 @@ btrie_release(struct btrie* tree)
     struct btrie_node *pos, *n;
     llist_for_each(pos, n, &tree->btrie_root->nodes, nodes)
     {
     struct btrie_node *pos, *n;
     llist_for_each(pos, n, &tree->btrie_root->nodes, nodes)
     {
-        vfree(pos);
+        __btrie_free_node(pos);
     }
 
     }
 
-    vfree(tree->btrie_root);
+    __btrie_free_node(tree->btrie_root);
 }
\ No newline at end of file
 }
\ No newline at end of file
index 31775bfdf7c36d19c77120c3a67d76da2e11d747..e9f61b313af2bf466cb71656ccb27dd3cd1dfea1 100644 (file)
@@ -20,8 +20,6 @@
 #include <lunaix/hart_state.h>
 #include <lunaix/kpreempt.h>
 
 #include <lunaix/hart_state.h>
 #include <lunaix/kpreempt.h>
 
-#include <asm-generic/isrm.h>
-
 #include <klibc/string.h>
 
 struct thread empty_thread_obj;
 #include <klibc/string.h>
 
 struct thread empty_thread_obj;
@@ -221,7 +219,6 @@ schedule()
     sched_ctx.procs_index = to_check->process->pid;
 
 done:
     sched_ctx.procs_index = to_check->process->pid;
 
 done:
-    isrm_notify_eos(0);
     run(to_check);
 
     fail("unexpected return from scheduler");
     run(to_check);
 
     fail("unexpected return from scheduler");
index a81dc4fc1bac7fa16b2c543bc8942e81e1514b96..ea2261bc17b8689f682b655aae5a0b9cdae6491e 100644 (file)
@@ -13,35 +13,44 @@ struct test_context
             struct {
                 int passed;
                 int failed;
             struct {
                 int passed;
                 int failed;
+                int skipped;
             };
             };
-            int countings[2];
+            int countings[3];
         };
 
         union {
             struct {
                 int total_passed;
                 int total_failed;
         };
 
         union {
             struct {
                 int total_passed;
                 int total_failed;
+                int total_skipped;
             };
             };
-            int total_countings[2];
+            int total_countings[3];
         };
     } stats;
 };
 
 #define fmt_passed  "[\x1b[32;49mPASS\x1b[0m]"
 #define fmt_failed  "[\x1b[31;49mFAIL\x1b[0m]"
         };
     } stats;
 };
 
 #define fmt_passed  "[\x1b[32;49mPASS\x1b[0m]"
 #define fmt_failed  "[\x1b[31;49mFAIL\x1b[0m]"
+#define fmt_skiped  "[\x1b[33;49mSKIP\x1b[0m]"
 
 #define active_context      \
     ({ extern struct test_context* __test_ctx; __test_ctx; })
 
 #define _expect(expr, act, exp, type_fmt)                                   \
     do {                                                                    \
 
 #define active_context      \
     ({ extern struct test_context* __test_ctx; __test_ctx; })
 
 #define _expect(expr, act, exp, type_fmt)                                   \
     do {                                                                    \
+        if(should_skip_test()) {                                            \
+            printf("  @%s:%03d ....... ", __FILE__, __LINE__);              \
+            printf(fmt_skiped "\n");                                        \
+            active_context->stats.skipped++;                                \
+            break;                                                          \
+        }                                                                   \
+                                                                            \
         int failed = !(expr);                                               \
         int failed = !(expr);                                               \
-        printf("  @%s:%03d ....... ", __FILE__, __LINE__);                    \
-        if (failed)                                                         \
+        if (failed) {                                                       \
+            printf("  @%s:%03d ....... ", __FILE__, __LINE__);              \
             printf(fmt_failed " (expect: " type_fmt ", got: " type_fmt ")\n",\
                     exp, act);                                              \
             printf(fmt_failed " (expect: " type_fmt ", got: " type_fmt ")\n",\
                     exp, act);                                              \
-        else                                                                \
-            printf(fmt_passed "\n");                                       \
+        }                                                                   \
         active_context->stats.countings[failed]++;                          \
     } while(0)
 
         active_context->stats.countings[failed]++;                          \
     } while(0)
 
@@ -88,4 +97,10 @@ end_testcase();
 void 
 run_test(int argc, const char* argv[]);
 
 void 
 run_test(int argc, const char* argv[]);
 
+static inline int
+should_skip_test()
+{
+    return active_context->stats.failed;
+}
+
 #endif /* __COMMON_TEST_BASIC_H */
 #endif /* __COMMON_TEST_BASIC_H */
diff --git a/lunaix-os/tests/includes/testing/memchk.h b/lunaix-os/tests/includes/testing/memchk.h
new file mode 100644 (file)
index 0000000..77db92d
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __COMMON_TEST_MEMCHK_H
+#define __COMMON_TEST_MEMCHK_H
+
+struct valloc_stats
+{
+    unsigned long alloced;
+    unsigned long freed;
+    unsigned long nr_vfree_calls;
+    
+    unsigned int nr_valloc_calls;
+};
+
+extern struct valloc_stats valloc_stat;
+
+void
+memchk_log_alloc(unsigned long addr, unsigned long size);
+
+void
+memchk_log_free(unsigned long addr);
+
+void
+memchk_print_stats();
+
+#endif /* __COMMON_TEST_MEMCHK_H */
index ad1aebc10a6629a22935b7bc0b4b1ae268f10e68..e8adb4367891dc1cfb50e9806919f462b6d59dfa 100644 (file)
@@ -1,4 +1,5 @@
 #include <testing/basic.h>
 #include <testing/basic.h>
+#include <testing/memchk.h>
 #include <stdlib.h>
 
 struct test_context* __test_ctx;
 #include <stdlib.h>
 
 struct test_context* __test_ctx;
@@ -13,11 +14,15 @@ main(int argc, const char* argv[])
     run_test(argc, argv);
 
     printf(
     run_test(argc, argv);
 
     printf(
-        "All test done: %d passed, %d failed\n",
+        "All test done: %d passed, %d failed, %d skipped\n\n",
         __test_ctx->stats.total_passed,
         __test_ctx->stats.total_passed,
-        __test_ctx->stats.total_failed
+        __test_ctx->stats.total_failed,
+        __test_ctx->stats.total_skipped
     );
     );
-    printf("************\n\n");
+
+    memchk_print_stats();
+
+    printf("\n************\n\n");
 
     exit(__test_ctx->stats.total_failed > 0);
 }
 
     exit(__test_ctx->stats.total_failed > 0);
 }
@@ -33,6 +38,7 @@ begin_testcase(const char* name)
     __test_ctx->name = name;
     __test_ctx->stats.countings[0] = 0;
     __test_ctx->stats.countings[1] = 0;
     __test_ctx->name = name;
     __test_ctx->stats.countings[0] = 0;
     __test_ctx->stats.countings[1] = 0;
+    __test_ctx->stats.countings[2] = 0;
 
     printf("%s\n", name);
 }
 
     printf("%s\n", name);
 }
@@ -40,11 +46,14 @@ begin_testcase(const char* name)
 void
 end_testcase()
 {
 void
 end_testcase()
 {
-    printf("..... passed: %d, failed: %d\n\n", 
-            __test_ctx->stats.passed, __test_ctx->stats.failed);
+    printf("..... passed: %d, failed: %d, %d skipped\n\n", 
+            __test_ctx->stats.passed, 
+            __test_ctx->stats.failed,
+            __test_ctx->stats.skipped);
 
     __test_ctx->stats.total_passed += __test_ctx->stats.passed;
     __test_ctx->stats.total_failed += __test_ctx->stats.failed;
 
     __test_ctx->stats.total_passed += __test_ctx->stats.passed;
     __test_ctx->stats.total_failed += __test_ctx->stats.failed;
+    __test_ctx->stats.total_skipped += __test_ctx->stats.skipped;
     __test_ctx->name = NULL;
 
 }
\ No newline at end of file
     __test_ctx->name = NULL;
 
 }
\ No newline at end of file
index 0484be25384408401701dd1eccc1464a38f7a9cf..6d38283951ed680fd1a1c7466f78657a075fef1c 100644 (file)
@@ -9,12 +9,9 @@ CFLAGS += -idirafter $(lunaix-root)/includes   \
                  -I $(test-root)/includes \
                  -Wno-discarded-qualifiers \
                  -Wno-scalar-storage-order \
                  -I $(test-root)/includes \
                  -Wno-discarded-qualifiers \
                  -Wno-scalar-storage-order \
-                 -g
+                 -Werror \
+                 -g \
+                 -D__off_t_defined
 
 
-
-%.o: %.c
-       $(call status,CC,$(@F))
-       @$(CC) $(CFLAGS) -c $< -o $@
-
-
-obj-shared := $(test-shared-root)/framework.o
+obj-shared := $(test-shared-root)/framework.o  \
+                               $(test-shared-root)/memchk.o
diff --git a/lunaix-os/tests/shared/memchk.c b/lunaix-os/tests/shared/memchk.c
new file mode 100644 (file)
index 0000000..b695201
--- /dev/null
@@ -0,0 +1,72 @@
+#include <testing/memchk.h>
+#include <stdio.h>
+
+#include <lunaix/ds/llist.h>
+
+extern void *malloc(size_t);
+extern void *calloc(size_t, size_t);
+extern void free(void*);
+
+struct valloc_stats valloc_stat = { };
+static DEFINE_LLIST(records);
+
+struct addr_record {
+    struct llist_header link;
+    unsigned long addr;
+    unsigned long size;
+};
+
+void
+memchk_log_alloc(unsigned long addr, unsigned long size)
+{
+    valloc_stat.alloced += size;
+    valloc_stat.nr_valloc_calls++;
+
+    struct addr_record *record;
+
+    record = malloc(sizeof(struct addr_record));
+    record->addr = addr;
+    record->size = size;
+
+    llist_append(&records, &record->link);
+}
+
+void
+memchk_log_free(unsigned long addr)
+{
+    valloc_stat.nr_vfree_calls++;
+
+    struct addr_record *pos, *n;
+    llist_for_each(pos, n, &records, link)
+    {
+        if (pos->addr == addr) {
+            valloc_stat.freed += pos->size;
+            llist_delete(&pos->link);
+
+            free(pos);
+            return;
+        }
+    }
+
+    printf("[\x1b[33;49mWARN\x1b[0m] freeing undefined pointer: 0x%lx\n", addr);
+}
+
+
+void
+memchk_print_stats()
+{
+    long leaked;
+
+    leaked = valloc_stat.alloced - valloc_stat.freed;
+    printf("valloc() statistics:\n");
+    printf("  allocated:   %lu bytes\n", valloc_stat.alloced);
+    printf("  freed:       %lu bytes\n", valloc_stat.freed);
+    printf("  leaked:      %lu bytes\n", leaked);
+    printf("  vfree_call:  %u  times\n", valloc_stat.nr_vfree_calls);
+    printf("  valloc_call: %u  times\n", valloc_stat.nr_valloc_calls);
+
+    if (leaked)
+    {
+        printf("[\x1b[33;49mWARN\x1b[0m] memory leakage detected\n");
+    }
+}
\ No newline at end of file
diff --git a/lunaix-os/tests/shared/mkobj.mkinc b/lunaix-os/tests/shared/mkobj.mkinc
new file mode 100644 (file)
index 0000000..edbc75f
--- /dev/null
@@ -0,0 +1,3 @@
+%.o: %.c
+       $(call status,CC,$(@F))
+       @$(CC) $(CFLAGS) -c $< -o $@
diff --git a/lunaix-os/tests/units/.gitignore b/lunaix-os/tests/units/.gitignore
new file mode 100644 (file)
index 0000000..70105d4
--- /dev/null
@@ -0,0 +1 @@
+**.test
\ No newline at end of file
diff --git a/lunaix-os/tests/units/btrie/dut/btrie.c b/lunaix-os/tests/units/btrie/dut/btrie.c
new file mode 120000 (symlink)
index 0000000..3abae1b
--- /dev/null
@@ -0,0 +1 @@
+../../../../kernel/ds/btrie.c
\ No newline at end of file
diff --git a/lunaix-os/tests/units/btrie/makefile b/lunaix-os/tests/units/btrie/makefile
new file mode 100644 (file)
index 0000000..7a4f83b
--- /dev/null
@@ -0,0 +1,3 @@
+obj-dut := dut/btrie.o
+
+include units_build.mkinc
\ No newline at end of file
diff --git a/lunaix-os/tests/units/btrie/test-alloc.c b/lunaix-os/tests/units/btrie/test-alloc.c
new file mode 100644 (file)
index 0000000..92439d9
--- /dev/null
@@ -0,0 +1,201 @@
+#include <lunaix/ds/btrie.h>
+#include <testing/basic.h>
+#include <lunaix/spike.h>
+#include <lunaix/compiler.h>
+
+#define WIDTH   8
+
+static void no_inline
+__alloc_simple()
+{
+    struct btrie tree;
+    struct btrie_node *root;
+    btrie_init(&tree, ilog2(WIDTH));
+
+    expect_long(btrie_map(&tree, 0, 100, (void*)1), 0);
+    expect_long(btrie_map(&tree, 0, 100, (void*)2), 1);
+    expect_long(btrie_map(&tree, 0, 100, (void*)3), 2);
+    expect_long(btrie_map(&tree, 0, 100, (void*)4), 3);
+
+    root = tree.btrie_root;
+    expect_notnull(root->children);
+    expect_int(root->children_cnt, 4);
+
+    for (int i = 0; i < 4; i++)
+    {
+        expect_notnull(root->children[i]);
+        expect_int(root->children[i]->index, i);
+        expect_ulong((ptr_t)root->children[i]->data, i + 1);
+    }
+    
+    for (int i = 4; i < WIDTH; i++)
+    {
+        expect_null(root->children[i]);
+    }
+
+    btrie_release(&tree);
+}
+
+static void no_inline
+__alloc_edge()
+{
+    struct btrie tree;
+    struct btrie_node *root;
+    btrie_init(&tree, ilog2(WIDTH));
+
+    expect_long(btrie_map(&tree, 7, 100, (void*)1), 7);
+    expect_long(btrie_map(&tree, 7, 100, (void*)2), 8);
+    expect_long(btrie_map(&tree, 7, 100, (void*)3), 9);
+    expect_long(btrie_map(&tree, 7, 100, (void*)4), 10);
+
+    root = tree.btrie_root;
+    expect_notnull(root->children);
+    expect_int(root->children_cnt, 2);
+
+    expect_notnull(root->children[7]);
+    expect_int(root->children[7]->index, 7);
+    expect_ulong((ptr_t)root->children[7]->data, 1);
+
+    expect_notnull(root->children[1]);
+    root = root->children[1];
+
+    for (int i = 0; i < 3; i++)
+    {
+        expect_notnull(root->children[i]);
+        expect_int(root->children[i]->index, i);
+        expect_ulong((ptr_t)root->children[i]->data, i + 2);
+    }
+
+    btrie_release(&tree);
+}
+
+static void no_inline
+__alloc_narrow()
+{
+    struct btrie tree;
+    struct btrie_node *root;
+    btrie_init(&tree, ilog2(WIDTH));
+
+    expect_long(btrie_map(&tree, 4, 7, (void*)1), 4);
+    expect_long(btrie_map(&tree, 4, 7, (void*)2), 5);
+    expect_long(btrie_map(&tree, 4, 7, (void*)3), 6);
+    expect_long(btrie_map(&tree, 4, 7, (void*)4), -1);
+
+    root = tree.btrie_root;
+    expect_notnull(root->children);
+    expect_int(root->children_cnt, 3);
+
+    for (int i = 0; i < 4; ++i)
+    {
+        expect_null(root->children[i]);
+    }
+
+    for (int i = 4, j = 1; i < WIDTH - 1; ++i, ++j)
+    {
+        expect_notnull(root->children[i]);
+        expect_int(root->children[i]->index, i);
+        expect_ulong((ptr_t)root->children[i]->data, j);
+    }
+
+    btrie_release(&tree);
+}
+
+static void no_inline
+__alloc_narrow_partial()
+{
+    struct btrie tree;
+    struct btrie_node *root;
+    btrie_init(&tree, ilog2(WIDTH));
+
+    expect_long(btrie_map(&tree, 15, 17, (void*)1), 15);
+    expect_long(btrie_map(&tree, 15, 17, (void*)2), 16);
+    expect_long(btrie_map(&tree, 15, 17, (void*)3), -1);
+
+    root = tree.btrie_root;
+    expect_notnull(root->children);
+    expect_int(root->children_cnt, 2);
+
+    // check left subtree
+    
+    root = root->children[1];
+    expect_notnull(root);
+    expect_int(root->children_cnt, 1);
+
+    int i = 0;
+    for (; i < WIDTH - 1; ++i)
+    {
+        expect_null(root->children[i]);
+    }
+
+    // i = WIDTH - 1
+    expect_notnull(root->children[i]);
+    expect_int(root->children[i]->index, i);
+    expect_ulong((ptr_t)root->children[i]->data, 1);
+
+    // check right subtree
+
+    root = tree.btrie_root;
+    root = root->children[2];
+    expect_notnull(root);
+    expect_int(root->children_cnt, 1);
+    
+    i = 0;
+    expect_notnull(root->children[i]);
+    expect_int(root->children[i]->index, i);
+    expect_ulong((ptr_t)root->children[i]->data, 2);
+
+    for (i++; i < WIDTH; ++i)
+    {
+        expect_null(root->children[i]);
+    }
+
+    btrie_release(&tree);
+}
+
+static void no_inline
+__alloc_dense()
+{
+    int mis_alloc = 0;
+    struct btrie tree;
+    btrie_init(&tree, ilog2(WIDTH));
+
+    for (size_t i = 0; i < 1000; i++)
+    {
+        if (btrie_map(&tree, 0, 1001, (void*)i+1) == -1UL)
+        {
+            mis_alloc++;
+        }
+    }
+    
+    expect_int(mis_alloc, 0);
+    btrie_release(&tree);
+}
+
+static void no_inline
+__alloc_retrive()
+{
+    struct btrie tree;
+    struct btrie_node *root;
+    btrie_init(&tree, ilog2(WIDTH));
+
+    expect_long(btrie_map(&tree, 4, 7, (void*)1), 4);
+    expect_long(btrie_map(&tree, 4, 7, (void*)2), 5);
+    expect_long(btrie_map(&tree, 4, 7, (void*)3), 6);
+
+    expect_ulong(__ptr(btrie_get(&tree, 6)), 3);
+    expect_ulong(__ptr(btrie_get(&tree, 5)), 2);
+    expect_ulong(__ptr(btrie_get(&tree, 4)), 1);
+
+    btrie_release(&tree);
+}
+
+void 
+run_test(int argc, const char* argv[])
+{
+    testcase("simple_alloc", __alloc_simple());
+    testcase("simple_edge",  __alloc_edge());
+    testcase("simple_narrow",  __alloc_narrow());
+    testcase("narrow_partial",  __alloc_narrow_partial());
+    testcase("alloc_dense",  __alloc_dense());
+    testcase("alloc_get",  __alloc_retrive());
+}
\ No newline at end of file
diff --git a/lunaix-os/tests/units/btrie/tests.txt b/lunaix-os/tests/units/btrie/tests.txt
new file mode 100644 (file)
index 0000000..a85a68a
--- /dev/null
@@ -0,0 +1 @@
+alloc
index 06e925ae82f296d1f279e3f49ce90099ea8d244a..662a34eae51b72c18a7daff51e3b4a68a294d0c9 100644 (file)
@@ -1,3 +1,2 @@
 test
 test
-*.dtb
-*.test
\ No newline at end of file
+*.dtb
\ No newline at end of file
index 94c2370b757be6be6e460186426fde33e88f9e5d..0eeb50885592a9bb2fc8ea38e5c90c35d6b6c246 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __DTTEST_COMMON_H
 #define __DTTEST_COMMON_H
 
 #ifndef __DTTEST_COMMON_H
 #define __DTTEST_COMMON_H
 
-#define __off_t_defined
 #include "dut/devtree.h"
 
 #include <lunaix/types.h>
 #include "dut/devtree.h"
 
 #include <lunaix/types.h>
index 4d9d53095f134ac796f29a6ed626a965a4b63231..b008c5fb39ebeb32a18fe2f5513a8aaead9813ba 100644 (file)
@@ -1,38 +1,18 @@
-include test_build.mkinc
+obj-dut := dut/dt_interrupt.o \
+                       dut/dt.o \
+                       dut/dtspec.o \
+                       dut/changeling.o
 
 
-tests := $(shell cat tests.txt)
-
-obj = dut/dt_interrupt.o \
-         dut/dt.o \
-         dut/dtspec.o \
-         dut/changeling.o \
-
-dtbs := $(addprefix samples/,$(addsuffix .dtb,$(tests)))
-
-tests := $(addsuffix .test,$(tests))
-run_tests := $(addprefix run.,$(tests))
+BIN_DEPS += load.%.o
+CFLAGS   += -DCONFIG_USE_DEVICETREE -Wp,-w
 
 
+.PRECIOUS: %.dtb
 %.dtb: %.dts
        $(call status,DTC,$^)
        @dtc -q -I dts -O dtb $^ -o $@
 
 %.dtb: %.dts
        $(call status,DTC,$^)
        @dtc -q -I dts -O dtb $^ -o $@
 
-.PHONY: all run clean
-
-load.%.o:: load.c
+load.%.o: load.c samples/%.dtb
        $(call status,CC,$@)
        $(call status,CC,$@)
-       @$(CC) $(CFLAGS) -DTEST_DTBFILE=\"samples/$*.dtb\" -c $^ -o $@
-
-%.test: $(obj-shared) $(obj-stubs) $(obj) test-%.o load.%.o
-       $(call status,LD,$@)
-       @$(CC) $^ -o $@
-
-run.%.test: %.test
-       $(call status,RUN,$^)
-       @./$^
-
-all: $(dtbs) $(tests)
-
-run: $(dtbs) $(tests) $(run_tests)
+       @$(CC) $(CFLAGS) -DTEST_DTBFILE=\"samples/$*.dtb\" -c $< -o $@
 
 
-clean:
-       @rm -f *.o $(obj) $(test) $(dtbs)
\ No newline at end of file
+include units_build.mkinc
\ No newline at end of file
index 66cf8ab06ecee77e17bbc30120953c24d6ea516e..866c71822f45b42c0a49fe03aa0eae0a8f490b9a 100644 (file)
@@ -1,8 +1,12 @@
 LUNAIX_ROOT ?= $(shell realpath ../../)
 
 LUNAIX_ROOT ?= $(shell realpath ../../)
 
-include test_build.mkinc
+include $(LUNAIX_ROOT)/tests/shared/makefile
+include $(LUNAIX_ROOT)/tests/shared/mkobj.mkinc
 
 
-__test-dir := device-tree
+MAKEFLAGS += --no-print-directory
+CFLAGS += -isystem $(unit-test-root)/stubs/includes
+
+__test-dir := device-tree btrie
 test-dir := $(addprefix test-,$(__test-dir))
 
 obj-stubs := 
 test-dir := $(addprefix test-,$(__test-dir))
 
 obj-stubs := 
@@ -11,7 +15,9 @@ obj-tmp :=
 include stubs/makefile
 obj-stubs += $(addprefix $(unit-test-root)/stubs/,$(obj-tmp))
 
 include stubs/makefile
 obj-stubs += $(addprefix $(unit-test-root)/stubs/,$(obj-tmp))
 
-export obj-stubs LUNAIX_ROOT
+BIN_DEPS := $(obj-stubs) $(obj-shared)
+
+export BIN_DEPS CFLAGS LUNAIX_ROOT
 test-%:
        $(call status,MK,$*)
        @$(MAKE) $(MKFLAGS) -C $* $(_ACT) -I $(CURDIR)
 test-%:
        $(call status,MK,$*)
        @$(MAKE) $(MKFLAGS) -C $* $(_ACT) -I $(CURDIR)
index 0d0292206be1858416f413f4654648bdf9e2e6f5..c8897e2405a1b3b7a144bc8e04d7d272c54b01e2 100644 (file)
@@ -1,56 +1,85 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/valloc.h>
+#include <testing/memchk.h>
 #include <stddef.h>
 
 extern void *malloc(size_t);
 extern void *calloc(size_t, size_t);
 extern void free(void*);
 
 #include <stddef.h>
 
 extern void *malloc(size_t);
 extern void *calloc(size_t, size_t);
 extern void free(void*);
 
+static inline void*
+_my_malloc(size_t size)
+{
+    void* ptr;
+
+    ptr = malloc(size);
+    memchk_log_alloc((unsigned long)ptr, size);
+    
+    return ptr;
+}
+
+static inline void*
+_my_calloc(size_t size, int n)
+{
+    void* ptr;
+
+    ptr = calloc(size, n);
+    memchk_log_alloc((unsigned long)ptr, size * n);
+    
+    return ptr;
+}
+
+static inline void
+_my_free(void* addr)
+{
+    memchk_log_free((unsigned long)addr);
+}
+
 void*
 valloc(unsigned int size)
 {
 void*
 valloc(unsigned int size)
 {
-    return malloc(size);
+    return _my_malloc(size);
 }
 
 void*
 vzalloc(unsigned int size)
 {
 }
 
 void*
 vzalloc(unsigned int size)
 {
-    return calloc(size, 1);
+    return _my_calloc(size, 1);
 }
 
 void*
 vcalloc(unsigned int size, unsigned int count)
 {
 }
 
 void*
 vcalloc(unsigned int size, unsigned int count)
 {
-    return calloc(size, count);
+    return _my_calloc(size, count);
 }
 
 void
 vfree(void* ptr)
 {
 }
 
 void
 vfree(void* ptr)
 {
-    free(ptr);
+    _my_free(ptr);
 }
 
 void
 vfree_safe(void* ptr)
 {
 }
 
 void
 vfree_safe(void* ptr)
 {
-    if (ptr) free(ptr);
+    if (ptr) _my_free(ptr);
 }
 
 void*
 valloc_dma(unsigned int size)
 {
 }
 
 void*
 valloc_dma(unsigned int size)
 {
-    return malloc(size);
+    return _my_malloc(size);
 }
 
 void*
 vzalloc_dma(unsigned int size)
 {
 }
 
 void*
 vzalloc_dma(unsigned int size)
 {
-    return calloc(size, 1);
+    return _my_calloc(size, 1);
 }
 
 void
 vfree_dma(void* ptr)
 {
 }
 
 void
 vfree_dma(void* ptr)
 {
-    free(ptr);
+    _my_free(ptr);
 }
 
 void
 }
 
 void
diff --git a/lunaix-os/tests/units/test_build.mkinc b/lunaix-os/tests/units/test_build.mkinc
deleted file mode 100644 (file)
index 1a3fcdb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-MAKEFLAGS += --no-print-directory
-
-include $(LUNAIX_ROOT)/tests/shared/makefile
-
-CFLAGS += -isystem $(unit-test-root)/stubs/includes
\ No newline at end of file
diff --git a/lunaix-os/tests/units/units_build.mkinc b/lunaix-os/tests/units/units_build.mkinc
new file mode 100644 (file)
index 0000000..29b64ad
--- /dev/null
@@ -0,0 +1,24 @@
+include $(LUNAIX_ROOT)/tests/shared/mkobj.mkinc
+include $(LUNAIX_ROOT)/makeinc/utils.mkinc
+
+tests := $(addsuffix .test,$(shell cat tests.txt))
+run_tests := $(addprefix run.,$(tests))
+
+BIN_DEPS += $(obj-dut)
+
+.PHONY: all run clean
+
+%.test: $(BIN_DEPS) test-%.o
+       $(call status,LD,$@)
+       @$(CC) $^ -o $@
+
+run.%.test: %.test
+       $(call status,RUN,$^)
+       @./$^
+
+all: $(tests)
+
+run: $(tests) $(run_tests)
+
+clean:
+       @rm -f *.o $(tests) $(obj-dut) $(TO_CLEAN)
\ No newline at end of file