static void sys_ipa_to_pa(vm_t* vm, seL4_UserContext* regs) { seL4_ARM_Page_GetAddress_t ret; uint32_t ipa; seL4_CPtr cap; ipa = regs->r0; cap = vspace_get_cap(vm_get_vspace(vm), (void*)ipa); if (cap == seL4_CapNull) { void* mapped_address; mapped_address = map_vm_ram(vm, ipa); if (mapped_address == NULL) { printf("Could not map address for IPA translation\n"); return; } cap = vspace_get_cap(vm_get_vspace(vm), (void*)ipa); assert(cap != seL4_CapNull); } ret = seL4_ARM_Page_GetAddress(cap); assert(!ret.error); DSTRACE("IPA translation syscall from [%s]: 0x%08x->0x%08x\n", vm->name, ipa, ret.paddr); regs->r0 = ret.paddr; }
int vm_install_tk1_usb_passthrough_device(vm_t* vm) { /* Add the device */ void *addr = map_vm_device(vm, dev_usb.pstart, dev_usb.pstart, seL4_AllRights); if (addr == NULL) { ZF_LOGE("map_vm_device returned NULL"); return -1; } void *vmm_addr = vspace_share_mem(vm_get_vspace(vm), vm_get_vmm_vspace(vm), addr, 1, seL4_PageBits, seL4_AllRights, 0); if (vmm_addr == NULL) { ZF_LOGE("vspace_share_mem returned NULL"); return -1; } int err = vm_add_device(vm, &dev_usb); if (err) { ZF_LOGE("vm_add_device returned error: %d", err); return -1; } err = vm_register_reboot_callback(vm, usb_vm_reboot_hook, vmm_addr); if (err) { ZF_LOGE("vm_register_reboot_callback returned error: %d", err); return -1; } return 0; }
uintptr_t vm_ipa_to_pa(vm_t* vm, uintptr_t ipa_base, size_t size) { seL4_ARM_Page_GetAddress_t ret; uintptr_t pa_base = 0; uintptr_t ipa; vspace_t *vspace; vspace = vm_get_vspace(vm); ipa = ipa_base; do { seL4_CPtr cap; int bits; /* Find the cap */ cap = vspace_get_cap(vspace, (void*)ipa); if (cap == seL4_CapNull) { return 0; } /* Find mapping size */ bits = vspace_get_cookie(vspace, (void*)ipa); assert(bits == 12 || bits == 21); /* Find the physical address */ ret = seL4_ARM_Page_GetAddress(cap); if (ret.error) { return 0; } if (ipa == ipa_base) { /* Record the result */ pa_base = ret.paddr + (ipa & MASK(bits)); /* From here on, ipa and ret.paddr will be aligned */ ipa &= ~MASK(bits); } else { /* Check for a contiguous mapping */ if (ret.paddr - pa_base != ipa - ipa_base) { return 0; } } ipa += BIT(bits); } while (ipa - ipa_base < size); return pa_base; }
int vm_copyout_atags(vm_t* vm, struct atag_list* atags, uint32_t addr) { vspace_t *vm_vspace, *vmm_vspace; void* vm_addr, *vmm_addr, *buf; reservation_t res; vka_t* vka; vka_object_t frame; size_t size; struct atag_list* atag_cur; int err; vka = vm->vka; vm_addr = (void*)(addr & ~0xfff); vm_vspace = vm_get_vspace(vm); vmm_vspace = vm->vmm_vspace; /* Make sure we don't cross a page boundary * NOTE: the next page will usually be used by linux for PT! */ for (size = 0, atag_cur = atags; atag_cur != NULL; atag_cur = atag_cur->next) { size += atags_size_bytes(atag_cur); } size += 8; /* NULL tag */ assert((addr & 0xfff) + size < 0x1000); /* Create a frame (and a copy for the VMM) */ err = vka_alloc_frame(vka, 12, &frame); assert(!err); if (err) { return -1; } /* Map the frame to the VMM */ vmm_addr = vspace_map_pages(vmm_vspace, &frame.cptr, NULL, seL4_AllRights, 1, 12, 0); assert(vmm_addr); /* Copy in the atags */ buf = vmm_addr + (addr & 0xfff); for (atag_cur = atags; atag_cur != NULL; atag_cur = atag_cur->next) { int tag_size = atags_size_bytes(atag_cur); DVM("ATAG copy 0x%x<-0x%x %d\n", (uint32_t)buf, (uint32_t)atag_cur->hdr, tag_size); memcpy(buf, atag_cur->hdr, tag_size); buf += tag_size; } /* NULL tag terminator */ memset(buf, 0, 8); /* Unmap the page and map it into the VM */ vspace_unmap_pages(vmm_vspace, vmm_addr, 1, 12, NULL); res = vspace_reserve_range_at(vm_vspace, vm_addr, 0x1000, seL4_AllRights, 0); assert(res.res); if (!res.res) { vka_free_object(vka, &frame); return -1; } err = vspace_map_pages_at_vaddr(vm_vspace, &frame.cptr, NULL, vm_addr, 1, 12, res); vspace_free_reservation(vm_vspace, res); assert(!err); if (err) { printf("Failed to provide memory\n"); vka_free_object(vka, &frame); return -1; } return 0; }