From e16f5f81dfb2e97a554ec19b941ec05a7942fd2d Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 4 Aug 2023 20:50:41 +0300 Subject: add initial smp bringup --- arch/riscv64/conf/mkimage.sh | 2 +- arch/riscv64/init/init.c | 5 +- arch/riscv64/kernel/arch.c | 43 +++++++++++++ arch/riscv64/kernel/arch.h | 48 ++++++++++++++ arch/riscv64/kernel/asm.h | 30 +++++++++ arch/riscv64/kernel/core_bringup.S | 23 +++++++ arch/riscv64/kernel/cpu.c | 14 ++-- arch/riscv64/kernel/entry.S | 9 +-- arch/riscv64/kernel/sbi.h | 29 +++++++++ arch/riscv64/kernel/smp.c | 129 +++++++++++++++++++++++++++++++++++++ arch/riscv64/kernel/vmem.c | 34 ++++++---- common/debug.c | 9 +-- common/fdt.c | 15 ----- common/main.c | 7 +- common/pmem.c | 8 ++- common/proc.c | 6 ++ include/arch/smp.h | 22 +++++++ include/arch/tcb.h | 10 +++ include/kmi/assert.h | 1 + include/kmi/tcb.h | 6 +- include/libfdt.h | 17 ++--- 21 files changed, 394 insertions(+), 73 deletions(-) create mode 100644 arch/riscv64/kernel/arch.c create mode 100644 arch/riscv64/kernel/arch.h create mode 100644 arch/riscv64/kernel/asm.h create mode 100644 arch/riscv64/kernel/core_bringup.S create mode 100644 arch/riscv64/kernel/smp.c create mode 100644 include/arch/smp.h diff --git a/arch/riscv64/conf/mkimage.sh b/arch/riscv64/conf/mkimage.sh index 1726e57..fbad869 100755 --- a/arch/riscv64/conf/mkimage.sh +++ b/arch/riscv64/conf/mkimage.sh @@ -33,6 +33,6 @@ qemu-system-riscv${XLEN} \ -bios ../rv${XLEN}/opensbi/build/platform/generic/firmware/fw_jump.elf \ -device virtio-blk-device,drive=hd0 \ -drive file=rootfs.img,format=raw,id=hd0 \ - -icount 0 \ -S -s -m 2G \ + -smp 2 \ -serial stdio diff --git a/arch/riscv64/init/init.c b/arch/riscv64/init/init.c index 38639d7..a4fa696 100644 --- a/arch/riscv64/init/init.c +++ b/arch/riscv64/init/init.c @@ -43,9 +43,10 @@ void flush_tlb_full() */ static pm_t __fdt_ram_base(void *fdt) { - struct cell_info ci = get_reginfo(fdt, "/memory"); int mem_offset = fdt_path_offset(fdt, "/memory"); - uint8_t *mem_reg = (uint8_t *)fdt_getprop(fdt, mem_offset, "reg", NULL); + const void *mem_reg = fdt_getprop(fdt, mem_offset, "reg", NULL); + + struct cell_info ci = get_cellinfo(fdt, mem_offset); return (pm_t)fdt_load_int_ptr(ci.addr_cells, mem_reg); } diff --git a/arch/riscv64/kernel/arch.c b/arch/riscv64/kernel/arch.c new file mode 100644 index 0000000..c4009e7 --- /dev/null +++ b/arch/riscv64/kernel/arch.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +/** + * @file arch.c + * Misc riscv specific stuff implementations. + */ + +#include +#include +#include "csr.h" +#include "arch.h" + +id_t __cpuid_to_hartid[MAX_CPUS]; + +id_t hartid_to_cpuid(id_t hart) +{ + for (size_t i = 0; i < MAX_CPUS; ++i) + if (cpuid_to_hartid(i) == hart) + return i; + + error("failed to match hart id %d to cpu id\n", hart); + /* default to zero, though this should maybe be a panic? */ + return 0; +} + +pm_t branch_to_satp(struct vmem *branch, enum mm_mode mode) +{ + /* Sv57 && Sv64 in the future? */ + branch = (struct vmem *)__pa(branch); + pm_t pn = (pm_t)(branch) >> page_shift(); + + pm_t m = DEFAULT_Sv_MODE; + + switch (mode) { + case Sv32: m = SATP_MODE_Sv32; break; + case Sv39: m = SATP_MODE_Sv39; break; + case Sv48: m = SATP_MODE_Sv48; break; + default: bug("unknown satp mode\n"); break; + } + + return m | pn; +} diff --git a/arch/riscv64/kernel/arch.h b/arch/riscv64/kernel/arch.h new file mode 100644 index 0000000..d38dad0 --- /dev/null +++ b/arch/riscv64/kernel/arch.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +/** + * @file arch.h + * + * Random tools common to riscv. + */ + +#ifndef KMI_RISCV_ARCH_H +#define KMI_RISCV_ARCH_H + +#include + +/** Actual map of cpu id to hart id. */ +extern id_t __cpuid_to_hartid[MAX_CPUS]; + +/** + * Map cpu id to hart id. + * Defined as a macro to allow for stuff like + * @code + * cpuid_to_hartid(0) = 20; + * @endcode + * + * @param x Hart ID. + */ +#define cpuid_to_hartid(x) __cpuid_to_hartid[x] + +/** + * Find the cpu id that corresponds to hart id. + * + * @param hart Hart to find corresponding cpu id for. + * @return Corresponding cpu id. 0 if not found, though this should maybe be a + * panic situation. + */ +id_t hartid_to_cpuid(id_t hart); + +/** + * Format branch and mode information into something that can be written to + * SATP. + * + * @param branch Top branch of virtual memory. + * @param mode Mode to use. Sv32/Sv39/etc. + * @return Corresponding SATP value. + */ +pm_t branch_to_satp(struct vmem *branch, enum mm_mode mode); + +#endif /* KMI_RISCV_ARCH_H */ diff --git a/arch/riscv64/kernel/asm.h b/arch/riscv64/kernel/asm.h new file mode 100644 index 0000000..f8ad202 --- /dev/null +++ b/arch/riscv64/kernel/asm.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +/** + * @file asm.h + * Stuff to make assembly easier to write on both riscv64 and riscv32. + */ + +#if __riscv_xlen == 64 + +/** Store register. */ +#define sr sd + +/** Load register. */ +#define lr ld + +/** Shift count to get a register sized value. */ +#define RW_SHIFT 3 + +#else + +/** Store register. */ +#define sr sw + +/** Load register. */ +#define lr lw + +/** Shift count to get register sized value. */ +#define RW_SHIFT 2 +#endif diff --git a/arch/riscv64/kernel/core_bringup.S b/arch/riscv64/kernel/core_bringup.S new file mode 100644 index 0000000..aff9b0b --- /dev/null +++ b/arch/riscv64/kernel/core_bringup.S @@ -0,0 +1,23 @@ +#include "asm.h" + +/* pic forces core_bringup to be placed in .got that we can access both from + * direct mapped and virtual memory. Which is kind of strange, as core_bringup() + * is fixed in place by the VM, so it could be possible to just load the address + * directly into a register, but apparently that's annoying to do */ +.option pic +.global riscv_bringup +riscv_bringup: + /* immediately switch to virtual memory through argument in a1 */ + csrw satp, a1 + sfence.vma + + /* fetch the stack allocated to us at our hart index in smp_init_stacks */ + la t0, smp_init_stacks + slli t1, a0, RW_SHIFT + add t0, t0, t1 + lr sp, 0(t0) + mv tp, sp + + /* jump to C to handle rest of bringup */ + la t0, core_bringup + jr t0 diff --git a/arch/riscv64/kernel/cpu.c b/arch/riscv64/kernel/cpu.c index dc87a13..0cb3d4c 100644 --- a/arch/riscv64/kernel/cpu.c +++ b/arch/riscv64/kernel/cpu.c @@ -13,18 +13,16 @@ #include "sbi.h" -/** Keeps track of initialized cpus. */ -static atomic_long cpus = 0; - void cpu_assign(struct tcb *t) { - /* bounce cpu id forward, or if first time here, get a cpu id */ + /* bounce cpu id forward */ struct tcb *c = cur_tcb(); - if (likely(c)) - t->cpu_id = c->cpu_id; - else - t->cpu_id = cpus++; + t->cpu_id = c->cpu_id; + __asm__ volatile ("mv tp, %0\n" : : "r" (t) :); +} +void tcb_assign(struct tcb *t) +{ __asm__ volatile ("mv tp, %0\n" : : "r" (t) :); } diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S index 698dae7..2959e2f 100644 --- a/arch/riscv64/kernel/entry.S +++ b/arch/riscv64/kernel/entry.S @@ -3,14 +3,7 @@ #include "../kernel/gen/asm-offsets.h" #include "../kernel/csr.h" - -#if __riscv_xlen == 64 -#define sr sd -#define lr ld -#else -#define sr sw -#define lr lw -#endif +#include "asm.h" /* very much based on linux, but why change it if works, eh? */ .section .text diff --git a/arch/riscv64/kernel/sbi.h b/arch/riscv64/kernel/sbi.h index 8abff25..fe75c85 100644 --- a/arch/riscv64/kernel/sbi.h +++ b/arch/riscv64/kernel/sbi.h @@ -133,6 +133,14 @@ static inline struct sbiret sbi_send_ipi(unsigned long hart_mask, /** Hart start function ID. */ #define FID_HSM_START 0 +/** + * Start hart. + * + * @param hartid Hart to start. + * @param start_addr Address to jump to in S mode. + * @param opaque OS-specific argument passed to hart. + * @return SBI call return. \see sbiret. + */ static inline struct sbiret sbi_hart_start(unsigned long hartid, unsigned long start_addr, unsigned long opaque) @@ -141,4 +149,25 @@ static inline struct sbiret sbi_hart_start(unsigned long hartid, 0, 0, 0); } +/** Hart status function ID. */ +#define FID_HSM_STATUS 2 + +/** + * Get hart status. + * + * @param hartid Hart ID. + * @return SBI call return. \see sbiret. + */ +static inline struct sbiret sbi_hart_status(unsigned long hartid) +{ + return sbi_ecall(EID_HSM, FID_HSM_STATUS, hartid, + 0, 0, 0, 0, 0); +} + +/** + * Status code \ref sbi_hart_status() returns for a started hart. + * The only one we're currently interested in. + */ +#define SBI_HART_STARTED 0 + #endif /* KMI_RISCV_SBI_H */ diff --git a/arch/riscv64/kernel/smp.c b/arch/riscv64/kernel/smp.c new file mode 100644 index 0000000..88a796e --- /dev/null +++ b/arch/riscv64/kernel/smp.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +/** + * @file smp.c + * riscv multicore bringup implementation. + */ + +#include +#include +#include +#include +#include "arch.h" +#include "sbi.h" + +/** + * Array of stacks for bringing up harts. + * Note not static since we want to access it from core_bringup.S. + */ +void *smp_init_stacks[MAX_CPUS]; + +/** + * Check if FDT node is a cpu and that its status is 'okay'. + * Helper for smp_bringup(), cpu nodes that are marked 'okay' in the FDT should + * be brought up. + * + * @param fdt Flattened device tree. + * @param node Node to check. + * @return true if node is a cpu node and it should be brought up, false + * otherwise. + */ +static bool riscv_cpu_okay(void *fdt, int node) +{ + const char *s = fdt_getprop(fdt, node, "device_type", NULL); + if (!s || strcmp(s, "cpu") != 0) + return false; + + s = fdt_getprop(fdt, node, "status", NULL); + if (!s) + return false; + + if (strcmp(s, "okay") == 0) + return true; + + return false; +} + +/** Counter for how many cores system has. */ +static size_t cpus = 1; + +/* called from main to start other cores */ +void smp_bringup(struct vmem *b, void *fdt) +{ + /* defined in core_bringup.S */ + extern void riscv_bringup(void); + + /* mark first hart available */ + cpuid_to_hartid(0) = -1; + + /* assume we're in default Sv mode, in the future this will have to be + * fixed if we start implementing Sv48 etc. */ + pm_t satp = branch_to_satp(b, DEFAULT_Sv_MODE); + int cpu_offset = fdt_path_offset(fdt, "/cpus"); + struct cell_info ci = get_cellinfo(fdt, cpu_offset); + + /* almost directly lifted from netbsd */ + int node; + fdt_for_each_subnode(node, fdt, cpu_offset) { + if (!riscv_cpu_okay(fdt, node)) + continue; + + const void *reg = fdt_getprop(fdt, node, "reg", NULL); + id_t hartid = fdt_load_reg_addr(ci, reg, 0); + + struct sbiret r = sbi_hart_status(hartid); + if (r.error) { + warn("failed getting hart %d status: %ld\n", + hartid, + r.error); + continue; + } + + if (r.value == SBI_HART_STARTED) { + /* there should ever only be one started hart */ + catastrophic_assert(cpuid_to_hartid(0) == -1); + cpuid_to_hartid(0) = hartid; + continue; + } + + /** @todo should check that cpus doesn't go over MAX_CPUS */ + cpuid_to_hartid(cpus++) = hartid; + + /** @todo try to remember to free these as well */ + smp_init_stacks[hartid] = (void *)alloc_page(BASE_PAGE) + + BASE_PAGE_SIZE; + r = sbi_hart_start(hartid, + (unsigned long)__pa(riscv_bringup), satp); + + if (r.error) { + warn("failed bringing up hart %d: %ld\n", + hartid, + r.error); + continue; + } + } +} + +/** + * Called from secondary_bringup.S to finish bringing up core we're running on. + * + * @param hartid Hart that's being brought up. + */ +void core_bringup(long hartid) +{ + /* assume smp_bringup assigned our cpuid correctly */ + id_t cpuid = hartid_to_cpuid(hartid); + info("core %d online\n", cpuid); + + /* add us as a thread to init program that cpu 0 is hopefully running by + * now */ + struct tcb *t = create_thread(cpu_tcb(0)); + t->cpu_id = cpuid; + tcb_assign(t); + use_tcb(t); + + /* eventually we should jump to init and start running stuff, but for + * now take it easy */ + while (1); +} diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index 9edd246..e2d0fa3 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -13,6 +13,7 @@ #include #include #include "pages.h" +#include "arch.h" #include "csr.h" /** @@ -386,28 +387,33 @@ void flush_tlb_all() */ static void __use_vmem(struct vmem *branch, enum mm_mode m) { - branch = (struct vmem *)__pa(branch); - pm_t pn = (pm_t)(branch) >> page_shift(); - - pm_t mode = DEFAULT_Sv_MODE; - - if (m == Sv32) - mode = SATP_MODE_Sv32; - else if (m == Sv39) - mode = SATP_MODE_Sv39; - else if (m == Sv48) - mode = SATP_MODE_Sv48; - - csr_write(CSR_SATP, mode | pn); + pm_t satp = branch_to_satp(branch, m); + csr_write(CSR_SATP, satp); flush_tlb_full(); - /* Sv57 && Sv64 in the future? */ /** @todo ASID table for maybe faster context switches? */ } +/** + * Populate \p branch with direct mapping. + * Mainly intended for bringup and init stuff. + * Arguably works only for riscv64 and is sort of shared with init.c, so could + * still be improved. + * + * @param branch Branch to populate. + */ +static void __populate_dmap(struct vmem *branch) +{ + size_t flags = VM_V | VM_R | VM_W | VM_X | VM_G | VM_D | VM_A; + for (size_t i = 0; i < CSTACK_PAGE; ++i) + branch->leaf[i] = + (struct vmem *)to_pte(TOP_PAGE_SIZE * i, flags); +} + struct vmem *init_vmem(void *fdt) { UNUSED(fdt); struct vmem *b = create_vmem(); + __populate_dmap(b); /* update which memory branch to use */ use_vmem(b); return b; diff --git a/common/debug.c b/common/debug.c index ff9dc18..526bfdc 100644 --- a/common/debug.c +++ b/common/debug.c @@ -199,14 +199,15 @@ static struct dbg_info __dbg_from_fdt(const void *fdt) enum serial_dev dev = __serial_dev_enum(dev_name); /* get serial device address */ - struct cell_info ci = get_reginfo(fdt, stdout); - void *reg_ptr = (void *)fdt_getprop(fdt, stdout_offset, "reg", NULL); + const void *reg_ptr = fdt_getprop(fdt, stdout_offset, "reg", NULL); + struct cell_info ci = get_cellinfo(fdt, stdout_offset); pm_t dbg_ptr = (pm_t)fdt_load_reg_addr(ci, reg_ptr, 0); /* get serial device offset if present */ size_t shift = 0; - void *shift_ptr = (void *)fdt_getprop(fdt, stdout_offset, "reg-shift", - NULL); + const void *shift_ptr = fdt_getprop(fdt, stdout_offset, "reg-shift", + NULL); + if (shift_ptr) shift = (size_t)fdt_load_int32_ptr(shift_ptr); diff --git a/common/fdt.c b/common/fdt.c index 3f20d72..677be7b 100644 --- a/common/fdt.c +++ b/common/fdt.c @@ -13,18 +13,3 @@ struct cell_info get_cellinfo(const void *fdt, const int offset) return (struct cell_info){ fdt_size_cells(fdt, offset), fdt_address_cells(fdt, offset) }; } - -/* how "reg" is interpreted depends on the parent node */ -struct cell_info get_reginfo(const void *fdt, const char *path) -{ - const char *i = strrchr(path, '/'); - if (!i) - return (struct cell_info){ 0, 0 }; - - size_t baselen = i - path; - if (baselen == 0) - /* root node */ - baselen = 1; - - return get_cellinfo(fdt, fdt_path_offset_namelen(fdt, path, baselen)); -} diff --git a/common/main.c b/common/main.c index 30d9ed5..7291387 100644 --- a/common/main.c +++ b/common/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include /** @@ -51,9 +52,9 @@ void __main main(void *fdt, uintptr_t ram_base) init_irq(fdt); init_timer(fdt); init_proc(fdt); - /* free temporary virtual memory now that we're in the init process - * space */ - destroy_vmem(b); + + /* try to bring up other cores on system */ + smp_bringup(b, fdt); /* start running init program */ run_init(cur_tcb(), fdt); diff --git a/common/pmem.c b/common/pmem.c index 02c5146..ed79e4a 100644 --- a/common/pmem.c +++ b/common/pmem.c @@ -550,7 +550,7 @@ static void __mark_area_used(pm_t base, pm_t top) static void __mark_reserved_mem(void *fdt) { int rmem_offset = fdt_path_offset(fdt, "/reserved-memory"); - struct cell_info ci = get_reginfo(fdt, "/reserved-memory"); + struct cell_info ci = get_cellinfo(fdt, rmem_offset); int node = 0; fdt_for_each_subnode(node, fdt, rmem_offset) { @@ -576,10 +576,12 @@ static void __mark_reserved_mem(void *fdt) */ static pm_t __get_ramtop(void *fdt) { - struct cell_info ci = get_reginfo(fdt, "/memory"); int mem_offset = fdt_path_offset(fdt, "/memory"); - uint8_t *mem_reg = (uint8_t *)fdt_getprop(fdt, mem_offset, "reg", NULL); + const void *mem_reg = fdt_getprop(fdt, mem_offset, "reg", NULL); + /* here we actually want the root offset because /memory itself doesn't + * have children, I guess? */ + struct cell_info ci = get_cellinfo(fdt, fdt_path_offset(fdt, "/")); pm_t base = (pm_t)fdt_load_reg_addr(ci, mem_reg, 0); return (pm_t)fdt_load_reg_size(ci, mem_reg, 0) + base; } diff --git a/common/proc.c b/common/proc.c index 0f0c7f8..e6c2769 100644 --- a/common/proc.c +++ b/common/proc.c @@ -36,6 +36,12 @@ stat_t init_proc(void *fdt) if (!t) return ERR_OOMEM; + /* we're the first cpu, so we always have ID 0 */ + t->cpu_id = 0; + + /* force tcb for core */ + tcb_assign(t); + /* set current tcb */ use_tcb(t); diff --git a/include/arch/smp.h b/include/arch/smp.h new file mode 100644 index 0000000..16c29d5 --- /dev/null +++ b/include/arch/smp.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +/** + * @file smp.h + * Arch specific multicore bringup stuff. + */ + +#ifndef KMI_ARCH_SMP_H +#define KMI_ARCH_SMP_H + +#include + +/** + * Bring up other cores in system. + * + * @param b Direct + kernel mappin virtual memory to use. + * @param fdt Flattened device tree. + */ +void smp_bringup(struct vmem *b, void *fdt); + +#endif /* KMI_ARCH_SMP_H */ diff --git a/include/arch/tcb.h b/include/arch/tcb.h index 0687954..f4c80c6 100644 --- a/include/arch/tcb.h +++ b/include/arch/tcb.h @@ -15,4 +15,14 @@ #include "../../arch/riscv32/include/tcb.h" #endif +/** + * Force store tcb \p t in arch-specific way. + * cpu_assign() is allowed to assume there's always a valid tcb + * set, so during init we have to force set a tcb before cpu_assign() can be + * used. + * + * @param t tcb to set. + */ +void tcb_assign(struct tcb *t); + #endif /* KMI_ARCH_TCB_H */ diff --git a/include/kmi/assert.h b/include/kmi/assert.h index 4512a21..291f15f 100644 --- a/include/kmi/assert.h +++ b/include/kmi/assert.h @@ -26,6 +26,7 @@ /** * The kernel is in an irrepairable state, just give up. + * Should maybe call kernel_panic()? * * @param x Condition to check for. */ diff --git a/include/kmi/tcb.h b/include/kmi/tcb.h index b7211e8..4f2eb1b 100644 --- a/include/kmi/tcb.h +++ b/include/kmi/tcb.h @@ -9,6 +9,9 @@ * Process/thread handling. */ +/* forward declaration */ +struct tcb; + #include #include #include @@ -60,9 +63,6 @@ */ #define get_rproc(t) (get_tcb(t->rid)) -/* forward declaration */ -struct tcb; - /** Convenience structure for \ref tcb. */ struct tcb_ctx { /** Virtual address space of context. */ diff --git a/include/libfdt.h b/include/libfdt.h index 58173f9..c603840 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -35,15 +35,6 @@ struct cell_info { */ struct cell_info get_cellinfo(const void *fdt, const int offset); -/** - * Get information about a register. - * - * @param fdt Pointer to the global fdt. - * @param path Path to be searched. - * @return Register information. - */ -struct cell_info get_reginfo(const void *fdt, const char *path); - #if defined(DEBUG) /** * Print FDT node at specified location. @@ -89,7 +80,7 @@ void __dbg_fdt(const void *fdt, int node_offset, int depth); * Load int{32,64} from FDT at location specified by pointer. * * @param c Size of int, where 2 == int64 and everything else int32. Query int - * size from FDT with \ref get_cellinfo() and \ref get_reginfo(). + * size from FDT with \ref get_cellinfo(). * @param p Pointer to int{32,64} inside the global FDT. * @return Value of integer at location p. */ @@ -105,7 +96,8 @@ void __dbg_fdt(const void *fdt, int node_offset, int depth); * @param i Index of address to read. * @return Address in reg cell. */ -static inline fdt64_t fdt_load_reg_addr(struct cell_info ci, void *p, size_t i) +static inline fdt64_t fdt_load_reg_addr(struct cell_info ci, const void *p, + size_t i) { hard_assert(ci.addr_cells == 2 || ci.addr_cells == 1, 0); size_t offset = i * (ci.addr_cells + ci.size_cells) * sizeof(fdt32_t); @@ -121,7 +113,8 @@ static inline fdt64_t fdt_load_reg_addr(struct cell_info ci, void *p, size_t i) * @param i Index of size to read. * @return Size in reg cell. */ -static inline fdt64_t fdt_load_reg_size(struct cell_info ci, void *p, size_t i) +static inline fdt64_t fdt_load_reg_size(struct cell_info ci, const void *p, + size_t i) { hard_assert(ci.size_cells == 2 || ci.size_cells == 1, 0); size_t offset = i * (ci.addr_cells + ci.size_cells) * sizeof(fdt32_t); -- cgit v1.3