예제 #1
0
/* 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;
}
예제 #2
0
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);
}