void *phys_map(phys_addr_t addr, size_t size, int mmflag) { phys_addr_t base; phys_addr_t end; void *ret = NULL; if (!size) { /* What do you want to do??? */ ASSERT(0); goto out; } /* Use the physical map area if the range lies within it. For more * information please refer to the memory layout of our system. */ if (PMAP_CONTAINS(addr, size)) { ret = (void *)addr; goto out; } base = ROUND_DOWN(addr, PAGE_SIZE); end = ROUND_UP(addr + size, PAGE_SIZE); ASSERT(end > base); /* Map pages from kernel memory */ ret = kmem_map(base, end - base, mmflag); if (ret) { ret = (char *)ret + (addr - base); // Don't miss the offset } DEBUG(DL_DBG, ("addr(%x), size(%x), ret(%p).\n", addr, size, ret)); out: return ret; }
void kmain(s64 magic, s64 info) { //vga_clear(COLOR_BLACK); idt_init(); isr_init(); serial_init(); set_debug_traps(); BREAKPOINT(); cpuid_print(); multiboot(magic, info); kmem_map(); page_init(); kmalloc_init(); //vesa_init(); root_init(); pci_init(); vm_init(); syscall_init(); timer_init(); kbd_init(); //mouse_init(); console_init(); create_kthread(NULL, idle_thread, THREAD_PRI_LOW, NULL, NULL); create_kthread(NULL, init_thread, THREAD_PRI_NORMAL, NULL, NULL); thread_schedule(); }
/** Map physical memory into the kernel address space. * @param addr Physical address to map. * @param size Size of range to map. * @param mmflag Allocation flags. * @return Pointer to mapped data. */ void *phys_map(phys_ptr_t addr, size_t size, unsigned mmflag) { phys_ptr_t base, end; if(unlikely(!size)) return NULL; /* Use the physical map area if the range lies within it. */ if(PMAP_CONTAINS(addr, size)) return (void *)(KERNEL_PMAP_BASE + (addr - KERNEL_PMAP_OFFSET)); /* Outside the physical map area. Must instead allocate some kernel * memory space and map there. */ base = round_down(addr, PAGE_SIZE); end = round_up(addr + size, PAGE_SIZE); return kmem_map(base, end - base, mmflag); }
/* * Send a message. * * The current thread will be blocked until any other thread * receives and reply the message. A thread can send a * message to any object if it knows the object id. */ int msg_send(object_t obj, void *msg, size_t size) { struct msg_header *hdr; thread_t t; void *kmsg; int rc; if (!user_area(msg)) return EFAULT; if (size < sizeof(struct msg_header)) return EINVAL; sched_lock(); if (!object_valid(obj)) { sched_unlock(); return EINVAL; } /* * A thread can not send a message when it is * already receiving from the target object. * It will obviously cause a deadlock. */ if (obj == curthread->recvobj) { sched_unlock(); return EDEADLK; } /* * Translate message address to the kernel linear * address. So that a receiver thread can access * the message via kernel pointer. We can catch * the page fault here. */ if ((kmsg = kmem_map(msg, size)) == NULL) { sched_unlock(); return EFAULT; } curthread->msgaddr = kmsg; curthread->msgsize = size; /* * The sender ID is filled in the message header * by the kernel. So, the receiver can trust it. */ hdr = (struct msg_header *)kmsg; hdr->task = curtask; /* * If receiver already exists, wake it up. * The highest priority thread can get the message. */ if (!queue_empty(&obj->recvq)) { t = msg_dequeue(&obj->recvq); sched_unsleep(t, 0); } /* * Sleep until we get a reply message. * Note: Do not touch any data in the object * structure after we wakeup. This is because the * target object may be deleted while we are sleeping. */ curthread->sendobj = obj; msg_enqueue(&obj->sendq, curthread); rc = sched_sleep(&ipc_event); if (rc == SLP_INTR) queue_remove(&curthread->ipc_link); curthread->sendobj = NULL; sched_unlock(); /* * Check sleep result. */ switch (rc) { case SLP_BREAK: return EAGAIN; /* Receiver has been terminated */ case SLP_INVAL: return EINVAL; /* Object has been deleted */ case SLP_INTR: return EINTR; /* Exception */ default: /* DO NOTHING */ break; } return 0; }
/* * Send a message. * * The current thread will be blocked until any other thread * receives the message and calls msg_reply() for the target * object. When new message has been reached to the object, it * will be received by highest priority thread waiting for * that message. A thread can send a message to any object if * it knows the object id. */ int msg_send(object_t obj, void *msg, size_t size, u_long timeout) { struct msg_header *hdr; thread_t th; void *kmsg; int rc; if (!user_area(msg)) return EFAULT; if (size < sizeof(struct msg_header)) return EINVAL; sched_lock(); if (!object_valid(obj)) { sched_unlock(); return EINVAL; } if (obj->owner != cur_task() && !task_capable(CAP_IPC)) { sched_unlock(); return EPERM; } /* * A thread can not send a message when the * thread is already receiving from the target * object. This will obviously cause a deadlock. */ if (obj == cur_thread->recvobj) { sched_unlock(); return EDEADLK; } /* * Translate message address to the kernel linear * address. So that a receiver thread can access * the message via kernel pointer. We can catch * the page fault here. */ if ((kmsg = kmem_map(msg, size)) == NULL) { /* Error - no physical address for the message */ sched_unlock(); return EFAULT; } /* * The sender ID in the message header is filled * by the kernel. So, the receiver can trust it. */ hdr = (struct msg_header *)kmsg; hdr->task = cur_task(); /* Save information about the message block. */ cur_thread->msgaddr = kmsg; cur_thread->msgsize = size; /* * If receiver already exists, wake it up. * Highest priority thread will get this message. */ if (!queue_empty(&obj->recvq)) { th = msg_dequeue(&obj->recvq); sched_unsleep(th, 0); } /* * Sleep until we get a reply message. * Note: Do not touch any data in the object * structure after we wakeup. This is because the * target object may be deleted during we were * sleeping. */ cur_thread->sendobj = obj; msg_enqueue(&obj->sendq, cur_thread); rc = sched_tsleep(&ipc_event, timeout); if (rc == SLP_INTR) queue_remove(&cur_thread->ipc_link); cur_thread->sendobj = NULL; sched_unlock(); /* * Check sleep result. */ switch (rc) { case SLP_BREAK: return EAGAIN; /* Receiver has been terminated */ case SLP_INVAL: return EINVAL; /* Object has been deleted */ case SLP_INTR: return EINTR; /* Exception */ case SLP_TIMEOUT: return ETIMEDOUT; /* Timeout */ default: /* DO NOTHING */ break; } return 0; }