int __kinit__ devfs_init(void) { struct fs_superblock * sb; SUBSYS_DEP(ramfs_init); SUBSYS_INIT("devfs"); FS_GIANT_INIT(&devfs_fs.fs_giant); /* * Inherit ramfs and override what's needed. */ fs_inherit_vnops(&devfs_vnode_ops, &ramfs_vnode_ops); vn_devfs = fs_create_pseudofs_root(&devfs_fs, VDEV_MJNR_DEVFS); if (!vn_devfs) return -ENOMEM; /* * It's perfectly ok to set a new delete_vnode() function * as sb struct is always a fresh struct so altering it * doesn't really break functionality for anyone else than us. */ sb = vn_devfs->sb; sb->delete_vnode = devfs_delete_vnode; sb->umount = devfs_umount; /* * Finally register our creation with fs subsystem. */ fs_register(&devfs_fs); _devfs_create_specials(); return 0; }
void fb_init(void) { SUBSYS_INIT(); void ** p; SET_FOREACH(p, fb_init_funcs) { fbi_t fbi; fbi = *(fbi_t *)p; fbi(); }
int bcm_jtag_init(void) { SUBSYS_INIT("BCM2835 JTAG"); bcm2835_set_gpio_func(22, GPIO_FSEL_ALTFN4); bcm2835_set_gpio_func(4, GPIO_FSEL_ALTFN5); bcm2835_set_gpio_func(27, GPIO_FSEL_ALTFN4); bcm2835_set_gpio_func(25, GPIO_FSEL_ALTFN4); bcm2835_set_gpio_func(23, GPIO_FSEL_ALTFN4); bcm2835_set_gpio_func(24, GPIO_FSEL_ALTFN4); return 0; }
int __kinit__ bcm2835_info_init(void) { SUBSYS_DEP(bcm2835_prop_init); SUBSYS_INIT("BCM2835_info"); kputs("\n"); print_prop("firmware", 0x00000001, 1); print_prop("board model", 0x00010001, 1); print_prop("board rev", 0x00010002, 1); print_prop("board serial", 0x00010004, 2); return 0; }
void vralloc_init(void) { SUBSYS_INIT(); struct vregion * reg; vrlist = dllist_create(struct vregion, node); reg = vreg_alloc_node(256); if (!(vrlist && reg)) { panic("Can't initialize vralloc."); } last_vreg = reg; _bio_init(); SUBSYS_INITFINI("vralloc OK"); }
int __kinit__ procfs_init(void) { SUBSYS_DEP(ramfs_init); SUBSYS_INIT("procfs"); /* * This must be static as it's referenced and used in the file system via * the fs object system. */ static fs_t procfs_fs = { .fsname = PROCFS_FSNAME, .mount = procfs_mount, .sblist_head = SLIST_HEAD_INITIALIZER(), }; specinfo_pool = mempool_init(MEMPOOL_TYPE_NONBLOCKING, sizeof(struct procfs_info), configMAXPROC); if (!specinfo_pool) return -ENOMEM; FS_GIANT_INIT(&procfs_fs.fs_giant); /* * Inherit unimplemented vnops from ramfs. */ fs_inherit_vnops(&procfs_vnode_ops, &ramfs_vnode_ops); vn_procfs = fs_create_pseudofs_root(&procfs_fs, VDEV_MJNR_PROCFS); if (!vn_procfs) return -ENOMEM; struct fs_superblock * sb = vn_procfs->sb; sb->delete_vnode = procfs_delete_vnode; vn_procfs->sb->umount = procfs_umount; fs_register(&procfs_fs); int err = init_permanent_files(); if (err) return err; procfs_updatedir(vn_procfs); return 0; }
int __kinit__ devfs_init(void) { SUBSYS_DEP(ramfs_init); SUBSYS_INIT("devfs"); /* * This must be static as it's referenced and used in the file system via * the fs object system. */ static fs_t devfs_fs = { .fsname = DEVFS_FSNAME, .mount = devfs_mount, .sblist_head = SLIST_HEAD_INITIALIZER(), }; FS_GIANT_INIT(&devfs_fs.fs_giant); /* * Inherit ramfs and override what's needed. */ fs_inherit_vnops(&devfs_vnode_ops, &ramfs_vnode_ops); vn_devfs = fs_create_pseudofs_root(&devfs_fs, VDEV_MJNR_DEVFS); if (!vn_devfs) return -ENOMEM; /* * It's perfectly ok to set a new delete_vnode() function * as sb struct is always a fresh struct so altering it * doesn't really break functionality for anyone else than us. */ struct fs_superblock * sb = vn_devfs->sb; sb->delete_vnode = devfs_delete_vnode; sb->umount = devfs_umount; /* * Finally register our creation with fs subsystem. */ fs_register(&devfs_fs); _devfs_create_specials(); return 0; }
int __kinit__ fatfs_init(void) { int err; SUBSYS_DEP(fs_init); SUBSYS_DEP(proc_init); SUBSYS_INIT("fatfs"); fatfs_sb_arr = kcalloc(configFATFS_MAX_MOUNTS, sizeof(struct fatfs_sb *)); if (!fatfs_sb_arr) return -ENOMEM; fs_inherit_vnops(&fatfs_vnode_ops, &nofs_vnode_ops); err = ff_init(); if (err) return err; FS_GIANT_INIT(&fatfs_fs.fs_giant); fs_register(&fatfs_fs); return 0; }
/** * Page table mapper init function. * @note This function should be called by mmu init. */ void ptmapper_init(void) { SUBSYS_INIT(); KERROR(KERROR_INFO, "ptmapper init started"); /* Allocate memory for mmu_pagetable_master */ if (ptmapper_alloc(&mmu_pagetable_master)) { panic("Can't allocate memory for master page table."); } mmu_pagetable_system.master_pt_addr = mmu_pagetable_master.master_pt_addr; if (ptmapper_alloc(&mmu_pagetable_system)) { panic("Can't allocate memory for system page table."); } /* Initialize system page tables */ mmu_init_pagetable(&mmu_pagetable_master); mmu_init_pagetable(&mmu_pagetable_system); /* Init regions */ /* Kernel ro region */ mmu_region_kernel.num_pages = MMU_PAGE_CNT_BY_RANGE( MMU_VADDR_KERNEL_START, (intptr_t)(&_rodata_end) - 1, MMU_PGSIZE_COARSE); /* Kernel rw data region */ mmu_region_kdata.vaddr = (intptr_t)(&_data_start); mmu_region_kdata.num_pages = MMU_PAGE_CNT_BY_RANGE( (intptr_t)(&_data_start), MMU_VADDR_KERNEL_END, MMU_PGSIZE_COARSE); mmu_region_kdata.paddr = (intptr_t)(&_data_start); /* Fill page tables with translations & attributes */ { #if configDEBUG >= KERROR_DEBUG char buf[80]; const char str_type[2][9] = {"sections", "pages"}; #define PRINTMAPREG(region) \ ksprintf(buf, sizeof(buf), "Mapped %s: %u %s", \ #region, region.num_pages, \ (region.pt->type == MMU_PTT_MASTER) ? \ str_type[0] : str_type[1]); \ KERROR(KERROR_DEBUG, buf); #else #define PRINTMAPREG(region) #endif #define MAP_REGION(reg) \ mmu_map_region(®); \ PRINTMAPREG(reg) //MAP_REGION(mmu_region_tkstack); MAP_REGION(mmu_region_kstack); MAP_REGION(mmu_region_kernel); MAP_REGION(mmu_region_kdata); MAP_REGION(mmu_region_page_tables); MAP_REGION(mmu_region_rpihw); #undef MAP_REGION #undef PRINTMAPREG } /* Copy system page table to vm version of it, this is the only easy way to * solve some issues now. TODO Maybe we'd like to do some major refactoring * some day. */ vm_pagetable_system.pt = mmu_pagetable_system; vm_pagetable_system.linkcount = 1; /* Activate page tables */ mmu_attach_pagetable(&mmu_pagetable_master); /* Load L1 TTB */ #if configDEBUG >= KERROR_DEBUG KERROR(KERROR_DEBUG, "Attached TTB mmu_pagetable_master"); #endif mmu_attach_pagetable(&mmu_pagetable_system); /* Add L2 pte into L1 mpt */ #if configDEBUG >= KERROR_DEBUG KERROR(KERROR_DEBUG, "Attached mmu_pagetable_system"); #endif SUBSYS_INITFINI("ptmapper OK"); }
static pthread_t create_uinit_main(void * stack_addr) { struct _sched_pthread_create_args init_ds = { .param.sched_policy = SCHED_OTHER, .param.sched_priority = NZERO, .stack_addr = stack_addr, .stack_size = configUSRINIT_SSIZE, .flags = 0, .start = uinit, /* We have to first get into user space to use exec * and mount the rootfs. */ .arg1 = (uintptr_t)rootfs, .del_thread = (void (*)(void *))uinit_exit, }; return thread_create(&init_ds, THREAD_MODE_PRIV); } /** * Map vmstack to proc. */ static void map_vmstack2proc(struct proc_info * proc, struct buf * vmstack) { struct vm_pt * vpt; (*proc->mm.regions)[MM_STACK_REGION] = vmstack; vm_updateusr_ap(vmstack); vpt = ptlist_get_pt(&proc->mm, vmstack->b_mmu.vaddr, MMU_PGSIZE_COARSE, VM_PT_CREAT); if (vpt == 0) panic("Couldn't get vpt for init stack"); vmstack->b_mmu.pt = &(vpt->pt); vm_map_region(vmstack, vpt); } /** * Create init process. */ int __kinit__ kinit(void) { SUBSYS_DEP(sched_init); SUBSYS_DEP(proc_init); SUBSYS_DEP(ramfs_init); SUBSYS_DEP(sysctl_init); SUBSYS_INIT("kinit"); char strbuf[80]; /* Buffer for panic messages. */ struct buf * init_vmstack; pthread_t tid; pid_t pid; struct thread_info * init_thread; struct proc_info * init_proc; /* * FIXME Memory allocation, protection or manipulation bug! * There is a critical bug causing random crashes in userland. I suspect * something is overwriting user space allocation from the kernel space. * Allocating some memory before init is executed seems to fix this issue, * however naturally this is not the proper way to fix the bug. * Without the allocation here the issue is sometimes seen in init or * usually after couple of fork + exec + exit cycles. The usual symptom is * that the userland app first calls some 0:0 syscalls and then tries to * execute undefined instruction, which probably means that either some * jump table in the heap or some part of the executable code is modified * by a bad access in kernel mode just before this happens. */ (void)geteblk(MMU_PGSIZE_COARSE * 10); mount_tmp_rootfs(); /* * User stack for init */ init_vmstack = create_vmstack(); if (!init_vmstack) panic("Can't allocate a stack for init"); /* * Create a thread for init */ tid = create_uinit_main((void *)(init_vmstack->b_mmu.paddr)); if (tid < 0) { ksprintf(strbuf, sizeof(strbuf), "Can't create a thread for init. %i", tid); panic(strbuf); } /* * pid of init */ pid = proc_fork(); if (pid <= 0) { ksprintf(strbuf, sizeof(strbuf), "Can't fork a process for init. %i", pid); panic(strbuf); } init_thread = thread_lookup(tid); if (!init_thread) { panic("Can't get thread descriptor of init_thread!"); } init_proc = proc_ref(pid); if (!init_proc || (init_proc->state == PROC_STATE_INITIAL)) { panic("Failed to get proc struct or invalid struct"); } init_thread->pid_owner = pid; init_thread->curr_mpt = &init_proc->mm.mpt; /* * Map the previously created user stack with init process page table. */ map_vmstack2proc(init_proc, init_vmstack); /* * Map tkstack of init with vm_pagetable_system. */ mmu_map_region(&init_thread->kstack_region->b_mmu); init_proc->main_thread = init_thread; KERROR_DBG("Init created with pid: %u, tid: %u, stack: %p\n", pid, tid, (void *)init_vmstack->b_mmu.vaddr); proc_unref(init_proc); return 0; }
/** * Page table mapper init function. * @note This function should be called by mmu init. */ int ptmapper_init(void) { SUBSYS_INIT("ptmapper"); #if defined(configPTMAPPER_DEBUG) kputs("\n"); #endif /* Allocate memory for mmu_pagetable_master */ if (ptmapper_alloc(&mmu_pagetable_master)) { /* Critical failure */ panic("Can't allocate memory for master page table.\n"); } mmu_pagetable_system.master_pt_addr = mmu_pagetable_master.master_pt_addr; mmu_pagetable_system.nr_tables = (MMU_VADDR_KERNEL_END + 1) / MMU_PGSIZE_SECTION; if (ptmapper_alloc(&mmu_pagetable_system)) { /* Critical failure */ panic("Can't allocate memory for system page table.\n"); } /* Initialize system page tables */ mmu_init_pagetable(&mmu_pagetable_master); mmu_init_pagetable(&mmu_pagetable_system); /* * Init regions */ /* Kernel ro region */ mmu_region_kernel.num_pages = MMU_PAGE_CNT_BY_RANGE( MMU_VADDR_KERNEL_START, (intptr_t)(&_rodata_end) - 1, MMU_PGSIZE_COARSE); /* Kernel rw data region */ mmu_region_kdata.vaddr = (intptr_t)(&_data_start); mmu_region_kdata.num_pages = MMU_PAGE_CNT_BY_RANGE( (intptr_t)(&_data_start), MMU_VADDR_KERNEL_END, MMU_PGSIZE_COARSE); mmu_region_kdata.paddr = (intptr_t)(&_data_start); /* Fill page tables with translations & attributes */ { mmu_region_t ** regp; #if defined(configPTMAPPER_DEBUG) const char str_type[2][9] = {"sections", "pages"}; #define PRINTMAPREG(region) \ KERROR(KERROR_DEBUG, "Mapped %s: %u %s\n", \ #region, region.num_pages, \ (region.pt->pt_type == MMU_PTT_MASTER) ? \ str_type[0] : str_type[1]); #else #define PRINTMAPREG(region) #endif #define MAP_REGION(reg) \ mmu_map_region(®); \ PRINTMAPREG(reg) MAP_REGION(mmu_region_kstack); MAP_REGION(mmu_region_kernel); MAP_REGION(mmu_region_kdata); MAP_REGION(mmu_region_page_tables); #undef MAP_REGION #undef PRINTMAPREG SET_FOREACH(regp, ptmapper_fixed_regions) { mmu_map_region(*regp); } }