status_t vmi_translate_uv2p (vmi_instance_t vmi, addr_t virt_address, vmi_pid_t pid, addr_t *paddr) { status_t ret = VMI_FAILURE; addr_t dtb = 0; if ( VMI_FAILURE == vmi_pid_to_dtb(vmi, pid, &dtb) || !dtb ) { dbprint(VMI_DEBUG_PTLOOKUP, "--early bail on v2p lookup because dtb not found\n"); return VMI_FAILURE; } ret = vmi_pagetable_lookup_cache(vmi, dtb, virt_address, paddr); if ( VMI_FAILURE == ret) { if ( VMI_FAILURE == pid_cache_del(vmi, pid) ) return VMI_FAILURE; ret = vmi_pid_to_dtb(vmi, pid, &dtb); if (VMI_SUCCESS == ret) { page_info_t info = {0}; /* _extended() skips the v2p_cache lookup that must have already failed */ ret = vmi_pagetable_lookup_extended(vmi, dtb, virt_address, &info); if ( VMI_SUCCESS == ret ) *paddr = info.paddr; } } return ret; }
addr_t vmi_translate_uv2p (vmi_instance_t vmi, addr_t virt_address, vmi_pid_t pid) { addr_t paddr = 0; addr_t dtb = vmi_pid_to_dtb(vmi, pid); if (!dtb) { dbprint(VMI_DEBUG_PTLOOKUP, "--early bail on v2p lookup because dtb is zero\n"); return 0; } if (VMI_SUCCESS != vmi_pagetable_lookup_cache(vmi, dtb, virt_address, &paddr)) { if ( VMI_FAILURE == pid_cache_del(vmi, pid) ) return 0; dtb = vmi_pid_to_dtb(vmi, pid); if (dtb) { page_info_t info = {0}; /* _extended() skips the v2p_cache lookup that must have already failed */ if (VMI_SUCCESS == vmi_pagetable_lookup_extended(vmi, dtb, virt_address, &info)) { paddr = info.paddr; } } } return paddr; }
addr_t vmi_pagetable_lookup (vmi_instance_t vmi, addr_t dtb, addr_t vaddr) { addr_t paddr = 0; status_t status = vmi_pagetable_lookup_cache(vmi, dtb, vaddr, &paddr); if (status != VMI_SUCCESS) { return 0; } return paddr; }
status_t vmi_pagetable_lookup (vmi_instance_t vmi, addr_t dtb, addr_t vaddr, addr_t *paddr) { return vmi_pagetable_lookup_cache(vmi, dtb, vaddr, paddr); }
/////////////////////////////////////////////////////////// // Classic read functions for access to memory status_t vmi_read( vmi_instance_t vmi, const access_context_t *ctx, size_t count, void *buf, size_t *bytes_read) { status_t ret = VMI_FAILURE; unsigned char *memory = NULL; addr_t start_addr = 0; addr_t paddr = 0; addr_t pfn = 0; addr_t offset = 0; addr_t dtb = 0; size_t buf_offset = 0; #ifdef ENABLE_SAFETY_CHECKS if (NULL == vmi) { dbprint(VMI_DEBUG_READ, "--%s: vmi passed as NULL, returning without read\n", __FUNCTION__); goto done; } if (NULL == ctx) { dbprint(VMI_DEBUG_READ, "--%s: ctx passed as NULL, returning without read\n", __FUNCTION__); goto done; } if (NULL == buf) { dbprint(VMI_DEBUG_READ, "--%s: buf passed as NULL, returning without read\n", __FUNCTION__); goto done; } #endif switch (ctx->translate_mechanism) { case VMI_TM_NONE: start_addr = ctx->addr; break; case VMI_TM_KERNEL_SYMBOL: #ifdef ENABLE_SAFETY_CHECKS if (!vmi->arch_interface || !vmi->os_interface || !vmi->kpgd) goto done; #endif dtb = vmi->kpgd; if ( VMI_FAILURE == vmi_translate_ksym2v(vmi, ctx->ksym, &start_addr) ) goto done; break; case VMI_TM_PROCESS_PID: #ifdef ENABLE_SAFETY_CHECKS if (!vmi->arch_interface || !vmi->os_interface) goto done; #endif if ( !ctx->pid ) dtb = vmi->kpgd; else if (ctx->pid > 0) { if ( VMI_FAILURE == vmi_pid_to_dtb(vmi, ctx->pid, &dtb) ) goto done; } if (!dtb) goto done; start_addr = ctx->addr; break; case VMI_TM_PROCESS_DTB: #ifdef ENABLE_SAFETY_CHECKS if (!vmi->arch_interface) goto done; #endif dtb = ctx->dtb; start_addr = ctx->addr; break; default: errprint("%s error: translation mechanism is not defined.\n", __FUNCTION__); goto done; } while (count > 0) { size_t read_len = 0; if (dtb) { if (VMI_SUCCESS != vmi_pagetable_lookup_cache(vmi, dtb, start_addr + buf_offset, &paddr)) goto done; } else { paddr = start_addr + buf_offset; } /* access the memory */ pfn = paddr >> vmi->page_shift; offset = (vmi->page_size - 1) & paddr; memory = vmi_read_page(vmi, pfn); if (NULL == memory) goto done; /* determine how much we can read */ if ((offset + count) > vmi->page_size) { read_len = vmi->page_size - offset; } else { read_len = count; } /* do the read */ memcpy(((char *) buf) + (addr_t) buf_offset, memory + (addr_t) offset, read_len); /* set variables for next loop */ count -= read_len; buf_offset += read_len; } ret = VMI_SUCCESS; done: if ( bytes_read ) *bytes_read = buf_offset; return ret; }
/////////////////////////////////////////////////////////// // Classic write functions for access to memory size_t vmi_write( vmi_instance_t vmi, const access_context_t *ctx, void *buf, size_t count) { addr_t start_addr = 0; addr_t dtb = 0; addr_t paddr = 0; addr_t offset = 0; size_t buf_offset = 0; if (NULL == buf) { dbprint(VMI_DEBUG_WRITE, "--%s: buf passed as NULL, returning without write\n", __FUNCTION__); return 0; } if (NULL == ctx) { dbprint(VMI_DEBUG_WRITE, "--%s: ctx passed as NULL, returning without write\n", __FUNCTION__); return 0; } switch (ctx->translate_mechanism) { case VMI_TM_NONE: start_addr = ctx->addr; break; case VMI_TM_KERNEL_SYMBOL: if (!vmi->arch_interface || !vmi->os_interface || !vmi->kpgd) return 0; dtb = vmi->kpgd; start_addr = vmi_translate_ksym2v(vmi, ctx->ksym); break; case VMI_TM_PROCESS_PID: if (!vmi->arch_interface || !vmi->os_interface) { return 0; } if(ctx->pid) { dtb = vmi_pid_to_dtb(vmi, ctx->pid); } else { dtb = vmi->kpgd; } if (!dtb) { return 0; } start_addr = ctx->addr; break; case VMI_TM_PROCESS_DTB: if (!vmi->arch_interface) { return 0; } dtb = ctx->dtb; start_addr = ctx->addr; break; default: errprint("%s error: translation mechanism is not defined.\n", __FUNCTION__); return 0; } while (count > 0) { size_t write_len = 0; if(dtb) { if (VMI_SUCCESS != vmi_pagetable_lookup_cache(vmi, dtb, start_addr + buf_offset, &paddr)) { return buf_offset; } } else { paddr = start_addr + buf_offset; } /* determine how much we can write to this page */ offset = (vmi->page_size - 1) & paddr; if ((offset + count) > vmi->page_size) { write_len = vmi->page_size - offset; } else { write_len = count; } /* do the write */ if (VMI_FAILURE == driver_write(vmi, paddr, ((char *) buf + (addr_t) buf_offset), write_len)) { return buf_offset; } /* set variables for next loop */ count -= write_len; buf_offset += write_len; } return buf_offset; }