void l4x_evict_tasks(struct task_struct *exclude) { struct task_struct *p; int cnt = 0; rcu_read_lock(); for_each_process(p) { l4_cap_idx_t t; struct mm_struct *mm; if (p == exclude) continue; task_lock(p); mm = p->mm; if (!mm) { task_unlock(p); continue; } t = ACCESS_ONCE(mm->context.task); if (l4_is_invalid_cap(t)) { task_unlock(p); continue; } if (down_read_trylock(&mm->mmap_sem)) { struct vm_area_struct *vma; for (vma = mm->mmap; vma; vma = vma->vm_next) if (vma->vm_flags & VM_LOCKED) { t = L4_INVALID_CAP; break; } up_read(&mm->mmap_sem); if (!vma) if (cmpxchg(&mm->context.task, t, L4_INVALID_CAP) != t) t = L4_INVALID_CAP; } else t = L4_INVALID_CAP; task_unlock(p); if (!l4_is_invalid_cap(t)) { l4lx_task_delete_task(t); l4lx_task_number_free(t); if (++cnt > 10) break; } } rcu_read_unlock(); if (cnt == 0) pr_info_ratelimited("l4x-evict: Found no process to free.\n"); }
static ssize_t onda_pwm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { ssize_t status; l4_msgtag_t tag; l4_umword_t label; l4_cap_idx_t comm_cap; int value = 0; int ipc_error; mutex_lock(&sysfs_lock); comm_cap = l4re_get_env_cap("comm"); /* Get a free capability slot for the comm capability */ if (l4_is_invalid_cap(comm_cap)) { printk("Did not find an comm\n"); mutex_unlock(&sysfs_lock); return 0; } /* To an L4 IPC call, i.e. send a message to thread2 and wait for a * reply from thread2. The '1' in the msgtag denotes that we want to * transfer one word of our message registers (i.e. MR0). No timeout. */ if (sscanf(buf,"%d\n", &value) > 0) { l4_utcb_mr()->mr[0] = 0x67; l4_utcb_mr()->mr[1] = value; tag = l4_ipc_call(comm_cap, l4_utcb(), l4_msgtag(0x67, 2, 0, 0), L4_IPC_NEVER); } mutex_unlock(&sysfs_lock); return size; }
static int __init l4vpci_init(void) { int err; vbus = l4re_env_get_cap("vbus"); if (l4_is_invalid_cap(vbus)) return -ENOENT; err = L4XV_FN_i(l4vbus_get_device_by_hid(vbus, 0, &root_bridge, "PNP0A03", 0, 0)); if (err < 0) { printk(KERN_INFO "l4vPCI: no root bridge found, no PCI\n"); return err; } printk(KERN_INFO "l4vPCI: L4 root bridge is device %lx\n", root_bridge); #ifdef CONFIG_X86 return l4vpci_x86_init(); #endif #ifdef CONFIG_ARM pci_common_init(&l4vpci_pci); return 0; #endif }
static int allocate_memory(void ** virt_addr, unsigned long virt_base, unsigned long size_in_bytes, unsigned long flags) { int r; l4re_ds_t ds; /* Allocate a free capability index for our data space */ ds = l4re_util_cap_alloc(); if (l4_is_invalid_cap(ds)) return -L4_ENOMEM; /* Allocate memory via a dataspace */ if ((r = l4re_ma_alloc(size_in_bytes, ds, flags))) { printf("Memory allocation failed.\n"); return r; } /* Make the dataspace visible in our address space */ *virt_addr = (void *)virt_base; if ((r = l4re_rm_attach(virt_addr, size_in_bytes, L4RE_RM_SEARCH_ADDR, ds, 0, L4_PAGESHIFT))) { printf("Memory mapping failed.\n"); return r; } /* Done, virtual address is in virt_addr */ return 0; }
void l4x_exit_thread(void) { #ifndef CONFIG_L4_VCPU int i; if (unlikely(current->thread.is_hybrid)) { l4_cap_idx_t hybgate; l4_msgtag_t tag; l4_umword_t o = 0; hybgate = L4LX_KERN_CAP_HYBRID_BASE + (current->pid << L4_CAP_SHIFT); tag = l4_ipc_gate_get_infos(hybgate, &o); if (l4_error(tag)) printk("hybrid: Could not get gate info, leaking mem.\n"); else kfree((void *)o); tag = l4_task_unmap(L4_BASE_TASK_CAP, l4_obj_fpage(hybgate, 0, L4_FPAGE_RWX), L4_FP_ALL_SPACES); if (l4_error(tag)) printk("hybrid: Delete of gate failed.\n"); } for (i = 0; i < NR_CPUS; i++) { l4_cap_idx_t thread_id = current->thread.user_thread_ids[i]; /* check if we were a non-user thread (i.e., have no user-space partner) */ if (unlikely(l4_is_invalid_cap(thread_id) || !thread_id)) continue; #ifdef DEBUG LOG_printf("exit_thread: trying to delete %s(%d, " PRINTF_L4TASK_FORM ")\n", current->comm, current->pid, PRINTF_L4TASK_ARG(thread_id)); #endif /* If task_delete fails we don't free the task number so that it * won't be used again. */ if (likely(!l4lx_task_delete_thread(thread_id))) { l4x_hybrid_remove(current); current->thread.user_thread_ids[i] = L4_INVALID_CAP; l4lx_task_number_free(thread_id); current->thread.started = 0; } else printk("%s: failed to delete task " PRINTF_L4TASK_FORM "\n", __func__, PRINTF_L4TASK_ARG(thread_id)); } #endif #ifdef CONFIG_X86_DS ds_exit_thread(current); #endif }
int kthreads_seq_show(struct seq_file *m, void *v) { int i = *(int *)v; if (!l4_is_invalid_cap(l4lx_thread_names[i].id)) seq_printf(m, PRINTF_L4TASK_FORM ": %s\n", PRINTF_L4TASK_ARG(l4lx_thread_names[i].id), l4lx_thread_names[i].name); return 0; }
/* kernel-internal execve() */ asmlinkage int l4_kernelinternal_execve(const char * file, const char * const * argv, const char * const * envp) { int ret; struct thread_struct *t = ¤t->thread; ASSERT(l4_is_invalid_cap(t->user_thread_id)); /* we are going to become a real user task now, so prepare a real * pt_regs structure. */ /* Enable Interrupts, Set IOPL (needed for X, hwclock etc.) */ t->regs.flags = 0x3200; /* XXX hardcoded */ /* do_execve() will create the user task for us in start_thread() and call set_fs(USER_DS) in flush_thread. I know this sounds strange but there are places in the kernel (kernel/kmod.c) which call execve with parameters inside the kernel. They set fs to KERNEL_DS before calling execve so we can't set it back to USER_DS before execve had a chance to look at the name of the executable. */ ASSERT(segment_eq(get_fs(), KERNEL_DS)); ret = do_execve(file, argv, envp, &t->regs); if (ret < 0) { /* we failed -- become a kernel thread again */ if (!l4_is_invalid_cap(t->user_thread_id)) l4lx_task_number_free(t->user_thread_id); set_fs(KERNEL_DS); t->user_thread_id = L4_INVALID_CAP; return -1; } l4x_user_dispatcher(); /* not reached */ return 0; }
/* Delete a key */ int pthread_key_delete(pthread_key_t key) { pthread_descr self = thread_self(); pthread_mutex_lock(&pthread_keys_mutex); if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { pthread_mutex_unlock(&pthread_keys_mutex); return EINVAL; } pthread_keys[key].in_use = 0; pthread_keys[key].destr = NULL; /* Set the value of the key to NULL in all running threads, so that if the key is reallocated later by pthread_key_create, its associated values will be NULL in all threads. If no threads have been created yet, or if we are exiting, clear it just in the current thread. */ struct pthread_key_delete_helper_args args; args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; if (!l4_is_invalid_cap(__pthread_manager_request) && !(__builtin_expect (__pthread_exit_requested, 0))) { struct pthread_request request; args.self = 0; request.req_thread = self; request.req_kind = REQ_FOR_EACH_THREAD; request.req_args.for_each.arg = &args; request.req_args.for_each.fn = pthread_key_delete_helper; #if 1 __pthread_send_manager_rq(&request, 1); #else TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, (char *) &request, sizeof(request))); #endif suspend(self); } else { if (self->p_specific[args.idx1st] != NULL) self->p_specific[args.idx1st][args.idx2nd] = NULL; } pthread_mutex_unlock(&pthread_keys_mutex); return 0; }
static void setup_memory(void) { int ret; l4_size_t phys_size; if (fb_vaddr) return; ret = l4io_request_iomem(0x48050000, 0x1000, 0, &omap_dss_virt_base); if (ret) { printf("[LCD] Error: Could not map device memory\n"); return; } // get some frame buffer l4re_ds_t mem = l4re_util_cap_alloc(); if (l4_is_invalid_cap(mem)) return; if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED)) { printf("[LCD] Error: Could not allocate memory\n"); return; } fb_vaddr = 0; if (l4re_rm_attach(&fb_vaddr, fbmem_size(), L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP, mem, 0, L4_PAGESHIFT)) { printf("[LCD] Error: Could not attach memory\n"); return; } printf("[LCD] Info: Video memory is at virtual %p (size: 0x%x Bytes)\n", fb_vaddr, fbmem_size()); // get physical address if (l4re_ds_phys(mem, 0, &fb_paddr, &phys_size) || phys_size != fbmem_size()) { printf("[LCD] Error: Could not get physical address\n"); return; } printf("[LCD] Info: Physical video memory is at %p\n", (void *)fb_paddr); }
void destroy_context(struct mm_struct *mm) { l4_cap_idx_t task_id; destroy_context_origarch(mm); if (!mm || !mm->context.task || l4_is_invalid_cap(task_id = mm->context.task)) return; if (l4lx_task_delete_task(task_id)) do_exit(9); mm->context.task = L4_INVALID_CAP; l4lx_task_number_free(task_id); }
static int __init l4vpci_init(void) { struct pci_dev *dev = NULL; #ifdef CONFIG_ARM struct pci_sys_data *sd; #else struct pci_sysdata *sd; #endif int err; L4XV_V(f); vbus = l4re_get_env_cap("vbus"); if (l4_is_invalid_cap(vbus)) return -ENOENT; L4XV_L(f); err = l4vbus_get_device_by_hid(vbus, 0, &root_bridge, "PNP0A03", 0, 0); if (err < 0) { printk(KERN_INFO "PCI: no root bridge found, no PCI\n"); L4XV_U(f); return err; } L4XV_U(f); printk(KERN_INFO "PCI: L4 root bridge is device %lx\n", root_bridge); sd = kzalloc(sizeof(*sd), GFP_KERNEL); if (!sd) return -ENOMEM; pci_scan_bus(0, &l4vpci_ops, sd); printk(KERN_INFO "PCI: Using L4-IO for IRQ routing\n"); for_each_pci_dev(dev) l4vpci_irq_enable(dev); #ifdef CONFIG_X86 pcibios_resource_survey(); #endif return 0; }
static ssize_t onda_interval_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t status; l4_msgtag_t tag; l4_umword_t label; l4_cap_idx_t comm_cap; int value = 0; int ipc_error; mutex_lock(&sysfs_lock); comm_cap = l4re_get_env_cap("comm"); /* Get a free capability slot for the comm capability */ if (l4_is_invalid_cap(comm_cap)) { printk("Did not find an comm\n"); mutex_unlock(&sysfs_lock); return 0; } /* To an L4 IPC call, i.e. send a message to thread2 and wait for a * reply from thread2. The '1' in the msgtag denotes that we want to * transfer one word of our message registers (i.e. MR0). No timeout. */ l4_utcb_mr()->mr[0] = 0x56; tag = l4_ipc_call(comm_cap, l4_utcb(), l4_msgtag(0x56, 1, 0, 0), L4_IPC_NEVER); /* Check for IPC error, if yes, print out the IPC error code, if not, * print the received result. */ ipc_error = l4_ipc_error(tag, l4_utcb()); if (ipc_error) { printk("IPC error: %x\n", ipc_error); return 0; buf[0] = '\n'; buf[1] = '\0'; status = 1; } else { value = (int)(l4_utcb_mr()->mr[0]); status = sprintf(buf, "%d\n", value); } mutex_unlock(&sysfs_lock); return status; }
static int kp_init(void) { vbus = l4re_get_env_cap("vbus"); if (l4_is_invalid_cap(vbus)) { printf("[KEYP] Failed to query vbus\n"); return -1; } if (l4vbus_get_device_by_hid(vbus, 0, &i2c_handle, "i2c", 0, 0)) { printf("[KEYP] ##### Cannot find I2C\n"); } return init_keypad(); }
static void l4x_flush_page(struct mm_struct *mm, unsigned long address, unsigned long vaddr, int size, unsigned long flush_rights, unsigned long caller) { l4_msgtag_t tag; if (IS_ENABLED(CONFIG_ARM)) return; if (mm && mm->context.l4x_unmap_mode == L4X_UNMAP_MODE_SKIP) return; if ((address & PAGE_MASK) == 0) address = PAGE0_PAGE_ADDRESS; if (likely(mm)) { unmap_log_add(mm, vaddr, size, flush_rights, caller); return; } /* do the real flush */ if (mm && !l4_is_invalid_cap(mm->context.task)) { /* Direct flush in the child, use virtual address in the * child address space */ tag = L4XV_FN(l4_msgtag_t, l4_task_unmap(mm->context.task, l4_fpage(vaddr & PAGE_MASK, size, flush_rights), L4_FP_ALL_SPACES)); } else { /* Flush all pages in all childs using the 'physical' * address known in the Linux server */ tag = L4XV_FN(l4_msgtag_t, l4_task_unmap(L4RE_THIS_TASK_CAP, l4_fpage(address & PAGE_MASK, size, flush_rights), L4_FP_OTHER_SPACES)); } if (l4_error(tag)) l4x_printf("l4_task_unmap error %ld\n", l4_error(tag)); }
int l4x_register_irq(l4_cap_idx_t irqcap) { unsigned long flags; int i, ret = -1; if (!init_done) init_array(); spin_lock_irqsave(&lock, flags); for (i = 0; i < NR_REQUESTABLE; ++i) { if (l4_is_invalid_cap(caps[i])) { caps[i] = irqcap; ret = i + BASE; break; } } spin_unlock_irqrestore(&lock, flags); return ret; }
void l4x_unmap_log_flush(void) { unsigned i; struct unmap_log_t *log; unsigned long flags; local_irq_save(flags); log = this_cpu_ptr(&unmap_log); for (i = 0; i < log->cnt; ++i) { l4_msgtag_t tag; struct mm_struct *mm = log->log[i].mm; if (unlikely(l4_is_invalid_cap(mm->context.task))) continue; tag = L4XV_FN(l4_msgtag_t, l4_task_unmap(mm->context.task, l4_fpage(log->log[i].addr, log->log[i].size, log->log[i].rights), L4_FP_ALL_SPACES)); if (unlikely(l4_error(tag))) { l4x_printf("l4_task_unmap error %ld: t=%lx\n", l4_error(tag), mm->context.task); WARN_ON(1); } else if (0) l4x_printf("flushing(%d) %lx:%08lx[%d,%x]\n", i, mm->context.task, log->log[i].addr, log->log[i].size, log->log[i].rights); } log->cnt = 0; local_irq_restore(flags); }
static int clcd_init_overo(void) { vbus = l4re_get_env_cap("vbus"); if (l4_is_invalid_cap(vbus)) { printf("[LCD] Error: Could not query <vbus> capability\n"); return -1; } if (l4vbus_get_device_by_hid(vbus, 0, &i2c_handle, "i2c", 0, 0)) { printf("[LCD] Error: Could not find <i2c> vbus device\n"); return -1; } if (l4vbus_get_device_by_hid(vbus, 0, &gpio_handle, "gpio", 0, 0)) { printf("[LCD] Error: Could not find <gpio> vbus device\n"); return -L4_ENODEV; } return 0; }
static void l4x_flush_page(struct mm_struct *mm, unsigned long address, unsigned long vaddr, int size, unsigned long flush_rights) { l4_msgtag_t tag; if (mm && mm->context.l4x_unmap_mode == L4X_UNMAP_MODE_SKIP) return; /* some checks: */ if (address > 0x80000000UL) { unsigned long remap; remap = find_ioremap_entry(address); /* VU: it may happen, that memory is not remapped but mapped in * user space, if a task mmaps /dev/mem but never accesses it. * Therefore, we fail silently... */ if (!remap) return; address = remap; } else if ((address & PAGE_MASK) == 0) address = PAGE0_PAGE_ADDRESS; #if 0 /* only for debugging */ else { if ((address >= (unsigned long)high_memory) && (address < 0x80000000UL)) { printk("flushing non physical page (0x%lx)\n", address); enter_kdebug("flush_page: non physical page"); } } #endif /* do the real flush */ if (mm && !l4_is_invalid_cap(mm->context.task)) { L4XV_V(f); if (!mm->context.task) l4x_printf("%s: Ups, task == 0\n", __func__); /* Direct flush in the child, use virtual address in the * child address space */ L4XV_L(f); tag = l4_task_unmap(mm->context.task, l4_fpage(vaddr & PAGE_MASK, size, flush_rights), L4_FP_ALL_SPACES); L4XV_U(f); } else { L4XV_V(f); /* Flush all pages in all childs using the 'physical' * address known in the Linux server */ L4XV_L(f); tag = l4_task_unmap(L4RE_THIS_TASK_CAP, l4_fpage(address & PAGE_MASK, size, flush_rights), L4_FP_OTHER_SPACES); L4XV_U(f); } if (l4_error(tag)) l4x_printf("l4_task_unmap error %ld\n", l4_error(tag)); }
int main(void) { l4_msgtag_t tag; #ifdef MEASURE l4_cpu_time_t s, e; #endif l4_utcb_t *u = l4_utcb(); l4_exc_regs_t exc; l4_umword_t mr0, mr1; printf("Alien feature testing\n"); l4_debugger_set_object_name(l4re_env()->main_thread, "alientest"); /* Start alien thread */ if (l4_is_invalid_cap(alien = l4re_util_cap_alloc())) return 1; l4_touch_rw(alien_thread_stack, sizeof(alien_thread_stack)); tag = l4_factory_create_thread(l4re_env()->factory, alien); if (l4_error(tag)) return 1; l4_debugger_set_object_name(alien, "alienth"); l4_thread_control_start(); l4_thread_control_pager(l4re_env()->main_thread); l4_thread_control_exc_handler(l4re_env()->main_thread); l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, L4RE_THIS_TASK_CAP); l4_thread_control_alien(1); tag = l4_thread_control_commit(alien); if (l4_error(tag)) return 2; tag = l4_thread_ex_regs(alien, (l4_umword_t)alien_thread, (l4_umword_t)alien_thread_stack + sizeof(alien_thread_stack), 0); if (l4_error(tag)) return 3; l4_sched_param_t sp = l4_sched_param(1, 0); tag = l4_scheduler_run_thread(l4re_env()->scheduler, alien, &sp); if (l4_error(tag)) return 4; #ifdef MEASURE l4_calibrate_tsc(l4re_kip()); #endif /* Pager/Exception loop */ if (l4_msgtag_has_error(tag = l4_ipc_receive(alien, u, L4_IPC_NEVER))) { printf("l4_ipc_receive failed"); return 1; } memcpy(&exc, l4_utcb_exc(), sizeof(exc)); mr0 = l4_utcb_mr()->mr[0]; mr1 = l4_utcb_mr()->mr[1]; for (;;) { #ifdef MEASURE s = l4_rdtsc(); #endif if (l4_msgtag_is_exception(tag)) { #ifndef MEASURE printf("PC=%08lx SP=%08lx Err=%08lx Trap=%lx, %s syscall, SC-Nr: %lx\n", l4_utcb_exc_pc(&exc), exc.sp, exc.err, exc.trapno, (exc.err & 4) ? " after" : "before", exc.err >> 3); #endif tag = l4_msgtag((exc.err & 4) ? 0 : L4_PROTO_ALLOW_SYSCALL, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0); } else printf("Umm, non-handled request (like PF): %lx %lx\n", mr0, mr1); memcpy(l4_utcb_exc(), &exc, sizeof(exc)); /* Reply and wait */ if (l4_msgtag_has_error(tag = l4_ipc_call(alien, u, tag, L4_IPC_NEVER))) { printf("l4_ipc_call failed\n"); return 1; } memcpy(&exc, l4_utcb_exc(), sizeof(exc)); mr0 = l4_utcb_mr()->mr[0]; mr1 = l4_utcb_mr()->mr[1]; #ifdef MEASURE e = l4_rdtsc(); printf("time %lld\n", l4_tsc_to_ns(e - s)); #endif }
static int l4x_rtc_platform_probe(struct platform_device *pdev) { int r; if (l4x_re_resolve_name("rtc", &rtc_server)) { pr_err("l4x-rtc: Could not find 'rtc' cap.\n"); return -ENOENT; } irq_cap = l4x_cap_alloc(); if (l4_is_invalid_cap(irq_cap)) { pr_err("l4x-rtc: Could not allocate irq cap.\n"); return -ENOMEM; } if (L4XV_FN_e(l4_factory_create_irq(l4re_env()->factory, irq_cap))) { pr_err("l4x-rtc: Could not create user irq.\n"); r = -ENOMEM; goto free_cap; } if (L4XV_FN_e(l4_icu_bind(rtc_server, 0, irq_cap))) { pr_err("l4x-rtc: Error registering for time updates.\n"); r = -ENOSYS; goto free_irq_cap; } irq = l4x_register_irq(irq_cap); if (irq < 0) { pr_err("l4x-rtc: Error registering IRQ with L4Linux.\n"); r = irq; goto free_irq_cap; } r = request_irq(irq, l4x_rtc_int, IRQF_TRIGGER_RISING, "l4x_rtc", NULL); if (r) { pr_err("l4x-rtc: Could not register IRQ.\n"); goto unregister_irq; } if (l4x_rtc_update_offset()) { pr_err("l4x-rtc: Could not get the time offset to real time.\n"); r = -ENOSYS; goto free_irq; } rtc_dev = rtc_device_register(driver_name, &(pdev->dev), &l4x_rtc_ops, THIS_MODULE); if (IS_ERR(rtc_dev)) { pr_err("l4x-rtc: Could not register as rtc device.\n"); r = PTR_ERR(rtc_dev); goto free_irq; } INIT_WORK(&w_update_time, l4x_rtc_update_time); return 0; free_irq: free_irq(irq, NULL); unregister_irq: l4x_unregister_irq(irq); free_irq_cap: L4XV_FN_v(l4_task_release_cap(L4RE_THIS_TASK_CAP, irq_cap)); free_cap: l4x_cap_free(irq_cap); return r; }
static void setup_memory(void) { l4_size_t phys_size; l4io_device_handle_t dh; l4io_resource_handle_t hdl; if (fb_vaddr) return; if (l4io_lookup_device("System Control", &dh, 0, &hdl)) { printf("Could not get system controller space\n"); return; } /* System controller -- XXX Wrong Place XXX */ amba_pl110_sys_base_virt = l4io_request_resource_iomem(dh, &hdl); if (amba_pl110_sys_base_virt == 0) { printf("Could not map system controller space\n"); return; } if (l4io_lookup_device("AMBA PL110", &dh, 0, &hdl)) { printf("Could not get PL110 LCD device\n"); return; } amba_pl110_lcd_control_virt_base = l4io_request_resource_iomem(dh, &hdl); if (amba_pl110_lcd_control_virt_base == 0) { printf("Could not map controller space for '%s'\n", arm_lcd_get_info()); return; } setup_type(); if ((read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask) == 0x1000) { is_qemu = 1; // remember if we run on qemu because of the different // handling of the bpp16 mode with PL110: my hardware has // 5551 mode, qemu does 565 type = PL111; // also set the type to PL111 because qemu only // announces a PL110 but can do the 1024 resolution too printf("Running on QEmu (assuming PL111).\n"); } if (config_request_xga && type == PL111) use_xga = 1; // get some frame buffer l4re_ds_t mem = l4re_util_cap_alloc(); if (l4_is_invalid_cap(mem)) return; if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED)) { printf("Error allocating memory\n"); return; } fb_vaddr = 0; if (l4re_rm_attach(&fb_vaddr, fbmem_size(), L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP, mem, 0, L4_PAGESHIFT)) { printf("Error getting memory\n"); return; } printf("Video memory is at virtual %p (size: 0x%x Bytes)\n", fb_vaddr, fbmem_size()); // get physical address if (l4re_ds_phys(mem, 0, &fb_paddr, &phys_size) || phys_size != fbmem_size()) { printf("Getting the physical address failed or not contiguous\n"); return; } printf("Physical video memory is at %p\n", (void *)fb_paddr); }
/* Our main function */ int main(void) { /* Get a capability slot for our new thread. */ l4_cap_idx_t t1 = l4re_util_cap_alloc(); l4_utcb_t *u = l4_utcb(); l4_exc_regs_t *e = l4_utcb_exc_u(u); l4_msgtag_t tag; int err; extern char _start[], _end[], _etext[]; if (l4_is_invalid_cap(t1)) return 1; /* Prevent pagefaults of our new thread because we do not want to * implement a pager as well. */ l4_touch_ro(_start, _end - _start + 1); l4_touch_rw(_etext, _end - _etext); /* Create the thread using our default factory */ tag = l4_factory_create_thread(l4re_env()->factory, t1); if (l4_msgtag_has_error(tag)) return 1; /* Setup the thread by setting the pager and task. */ l4_thread_control_start(); l4_thread_control_pager(l4re_env()->main_thread); l4_thread_control_exc_handler(l4re_env()->main_thread); l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, L4RE_THIS_TASK_CAP); tag = l4_thread_control_commit(t1); if (l4_msgtag_has_error(tag)) return 2; /* Start the thread by finally setting instruction and stack pointer */ tag = l4_thread_ex_regs(t1, (l4_umword_t)thread, (l4_umword_t)thread_stack + sizeof(thread_stack), L4_THREAD_EX_REGS_TRIGGER_EXCEPTION); if (l4_msgtag_has_error(tag)) return 3; /* Receive initial exception from just started thread */ tag = l4_ipc_receive(t1, u, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) { printf("Umm, ipc error: %x\n", err); return 1; } /* We expect an exception IPC */ if (!l4_msgtag_is_exception(tag)) { printf("PF?: %lx %lx (not prepared to handle this) %ld\n", l4_utcb_mr_u(u)->mr[0], l4_utcb_mr_u(u)->mr[1], l4_msgtag_label(tag)); return 1; } /* Fill out the complete register set of the new thread */ e->ip = (l4_umword_t)thread; e->sp = (l4_umword_t)(thread_stack + sizeof(thread_stack)); e->eax = 1; e->ebx = 4; e->ecx = 2; e->edx = 3; e->esi = 6; e->edi = 7; e->ebp = 5; /* Send a complete exception */ tag = l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0); /* Send reply and start the thread with the defined CPU register set */ tag = l4_ipc_send(t1, u, tag, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) printf("Error sending IPC: %x\n", err); /* Idle around */ while (1) l4_sleep(10000); return 0; }
SDL_Surface *L4FB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { char* apptitle = APPTITLE; char* wintitle = WINTITLE; printf("L4FB_SetVideoMode: %dx%d@%d:\n", width, height, bpp); /* * is requested resolution higher than the framebuffer's one? */ if( width > (int)this->hidden->vvi.width || height > (int)this->hidden->vvi.height) { return (NULL); } /* * calc the offsets for current resolution the center the image */ this->hidden->x_offset = (this->hidden->vvi.width - width ) / 2; this->hidden->y_offset = (this->hidden->vvi.height - height) / 2; // make sure to have correct scale if (L4FB_video_scale_factor<=0) L4FB_video_scale_factor = 1.0; // reject unsupported bpp if (bpp != 16) return NULL; // reject unsupported flags if (flags & SDL_OPENGL) return NULL; /* Allocate the new pixel format for the screen */ if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { SDL_SetError("Couldn't allocate new pixel format for requested mode"); return(NULL); } // if we were double buffered clear shadow buffer if (current->flags & SDL_DOUBLEBUF) { FreeAndNull(current->pixels); } // init new window if (this->wm_title) wintitle = this->wm_title; if (this->wm_icon) apptitle = this->wm_icon; // L4FB_SetCaption(this, wintitle, apptitle); if (l4_is_invalid_cap(this->hidden->ev_ds) || !this->hidden->ev_ds) L4FB_InstallEventHandler(this); /* Set up the new mode framebuffer */ current->w = width; current->h = height; current->pitch = SDL_CalculatePitch(current); this->hidden->pitch = current->pitch; current->flags = SDL_PREALLOC | SDL_ASYNCBLIT; // if (current->pixels) // { // /* TODO: ERROR HANDLING */ // } // memset(current->pixels, 0, current->h*current->pitch); /* since we want to center image in fb we allway have to use doublebuf... */ this->hidden->fb_start = this->hidden->fbmem_vaddr + this->hidden->vvi.buffer_offset; current->pixels = malloc(current->h*current->pitch); if (current->pixels) { // success! printf("allocated shadow buffer\n"); this->hidden->pixels = current->pixels; memset(current->pixels, 0, current->h*current->pitch); } else return NULL; if (flags&SDL_DOUBLEBUF) { current->flags |= SDL_DOUBLEBUF|SDL_HWSURFACE; // try to alloc shadow buffer } /* We're done */ return(current); }
/* Our main function */ int main(void) { /* Get a capability slot for our new thread. */ l4_cap_idx_t t1 = l4re_util_cap_alloc(); l4_utcb_t *u = l4_utcb(); l4_exc_regs_t *e = l4_utcb_exc_u(u); l4_msgtag_t tag; int err; printf("Example showing how to start a thread with an exception.\n"); /* We do not want to implement a pager here, take the shortcut. */ printf("Make sure to start this program with ldr-flags=eager_map\n"); if (l4_is_invalid_cap(t1)) return 1; /* Create the thread using our default factory */ tag = l4_factory_create_thread(l4re_env()->factory, t1); if (l4_error(tag)) return 1; /* Setup the thread by setting the pager and task. */ l4_thread_control_start(); l4_thread_control_pager(l4re_env()->main_thread); l4_thread_control_exc_handler(l4re_env()->main_thread); l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, L4RE_THIS_TASK_CAP); tag = l4_thread_control_commit(t1); if (l4_error(tag)) return 2; /* Start the thread by finally setting instruction and stack pointer */ tag = l4_thread_ex_regs(t1, (l4_umword_t)thread, (l4_umword_t)thread_stack + sizeof(thread_stack), L4_THREAD_EX_REGS_TRIGGER_EXCEPTION); if (l4_error(tag)) return 3; l4_sched_param_t sp = l4_sched_param(1, 0); tag = l4_scheduler_run_thread(l4re_env()->scheduler, t1, &sp); if (l4_error(tag)) return 4; /* Receive initial exception from just started thread */ tag = l4_ipc_receive(t1, u, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) { printf("Umm, ipc error: %x\n", err); return 1; } /* We expect an exception IPC */ if (!l4_msgtag_is_exception(tag)) { printf("PF?: %lx %lx (not prepared to handle this) %ld\n", l4_utcb_mr_u(u)->mr[0], l4_utcb_mr_u(u)->mr[1], l4_msgtag_label(tag)); return 1; } /* Fill out the complete register set of the new thread */ e->sp = (l4_umword_t)(thread_stack + sizeof(thread_stack)); #ifdef ARCH_x86 e->ip = (l4_umword_t)thread; e->eax = 1; e->ebx = 4; e->ecx = 2; e->edx = 3; e->esi = 6; e->edi = 7; e->ebp = 5; #endif #ifdef ARCH_arm e->pc = (l4_umword_t)thread; e->r[0] = 0; e->r[1] = 1; e->r[2] = 2; e->r[3] = 3; e->r[4] = 4; e->r[5] = 5; e->r[6] = 6; e->r[7] = 7; #endif /* Send a complete exception */ tag = l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0); /* Send reply and start the thread with the defined CPU register set */ tag = l4_ipc_send(t1, u, tag, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) printf("Error sending IPC: %x\n", err); /* Idle around */ while (1) l4_sleep(10000); return 0; }
static int __init l4x_timer_init_ret(void) { int r; l4lx_thread_t thread; int irq; L4XV_V(f); timer_irq_cap = l4x_cap_alloc(); if (l4_is_invalid_cap(timer_irq_cap)) { printk(KERN_ERR "l4timer: Failed to alloc\n"); return -ENOMEM; } r = L4XV_FN_i(l4_error(l4_factory_create_irq(l4re_env()->factory, timer_irq_cap))); if (r) { printk(KERN_ERR "l4timer: Failed to create irq: %d\n", r); goto out1; } if ((irq = l4x_register_irq(timer_irq_cap)) < 0) { r = -ENOMEM; goto out2; } printk("l4timer: Using IRQ%d\n", irq); setup_irq(irq, &l4timer_irq); L4XV_L(f); thread = l4lx_thread_create (timer_thread, /* thread function */ smp_processor_id(), /* cpu */ NULL, /* stack */ &timer_irq_cap, sizeof(timer_irq_cap), /* data */ l4x_cap_alloc(), /* cap */ PRIO_TIMER, /* prio */ 0, /* vcpup */ "timer", /* name */ NULL); L4XV_U(f); timer_srv = l4lx_thread_get_cap(thread); if (!l4lx_thread_is_valid(thread)) { printk(KERN_ERR "l4timer: Failed to create thread\n"); r = -ENOMEM; goto out3; } l4timer_clockevent.irq = irq; l4timer_clockevent.mult = div_sc(1000000, NSEC_PER_SEC, l4timer_clockevent.shift); l4timer_clockevent.max_delta_ns = clockevent_delta2ns(0xffffffff, &l4timer_clockevent); l4timer_clockevent.min_delta_ns = clockevent_delta2ns(0xf, &l4timer_clockevent); l4timer_clockevent.cpumask = cpumask_of(0); clockevents_register_device(&l4timer_clockevent); return 0; out3: l4x_unregister_irq(irq); out2: L4XV_FN_v(l4_task_delete_obj(L4RE_THIS_TASK_CAP, timer_irq_cap)); out1: l4x_cap_free(timer_irq_cap); return r; }