/* Find the section containing a given address in a given address space. * * On success, the found section is moved to the front of the section list. * If caching is enabled, maps the section. * * Returns zero on success, a negative error code otherwise. */ static int pt_image_fetch_section(struct pt_image *image, const struct pt_asid *asid, uint64_t vaddr) { struct pt_section_list **start, **list; if (!image) return -pte_internal; start = &image->sections; for (list = start; *list;) { struct pt_mapped_section *msec; struct pt_section_list *elem; int errcode; elem = *list; msec = &elem->section; errcode = pt_image_check_msec(msec, asid, vaddr); if (errcode < 0) { if (errcode != -pte_nomap) return errcode; list = &elem->next; continue; } /* Move the section to the front if it isn't already. */ if (list != start) { *list = elem->next; elem->next = *start; *start = elem; } /* Map the section if it isn't already - provided we do cache * recently used sections. */ if (!elem->mapped) { uint16_t cache, already; already = image->mapped; cache = image->cache; if (cache) { struct pt_section *section; section = pt_msec_section(msec); errcode = pt_section_map(section); if (errcode < 0) return errcode; elem->mapped = 1; already += 1; image->mapped = already; if (cache < already) return pt_image_prune_cache(image); } } return 0; } return -pte_nomap; }
static int pt_image_read_cold(struct pt_image *image, struct pt_section_list **list, uint8_t *buffer, uint16_t size, const struct pt_asid *asid, uint64_t addr) { struct pt_section_list **start; if (!image || !list) return -pte_internal; start = &image->sections; while (*list) { struct pt_mapped_section *msec; struct pt_section_list *elem; struct pt_section *sec; int mapped, errcode, status; elem = *list; msec = &elem->section; sec = msec->section; mapped = elem->mapped; if (!mapped) { errcode = pt_section_map(sec); if (errcode < 0) return errcode; } status = pt_msec_read_mapped(msec, buffer, size, asid, addr); if (status < 0) { if (!mapped) { errcode = pt_section_unmap(sec); if (errcode < 0) return errcode; } list = &elem->next; continue; } /* Move the section to the front if it isn't already. */ if (list != start) { *list = elem->next; elem->next = *start; *start = elem; } /* Keep the section mapped if it isn't already - provided we * do cache recently used sections. */ if (!mapped) { uint16_t cache, already; already = image->mapped; cache = image->cache; if (cache) { elem->mapped = 1; already += 1; image->mapped = already; if (cache < already) { errcode = pt_image_prune_cache(image); if (errcode < 0) return errcode; } } else { errcode = pt_section_unmap(sec); if (errcode < 0) return errcode; } } return status; } return pt_image_read_callback(image, buffer, size, asid, addr); }