Example #1
0
static struct ptunit_result read_offset(struct section_fixture *sfix)
{
	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
	int status;

	sfix_write(sfix, bytes);

	sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
	ptu_ptr(sfix->section);

	status = pt_section_map(sfix->section);
	ptu_int_eq(status, 0);

	status = pt_section_read(sfix->section, buffer, 2, 0x1ull);
	ptu_int_eq(status, 2);
	ptu_uint_eq(buffer[0], bytes[2]);
	ptu_uint_eq(buffer[1], bytes[3]);
	ptu_uint_eq(buffer[2], 0xcc);

	status = pt_section_unmap(sfix->section);
	ptu_int_eq(status, 0);

	return ptu_passed();
}
Example #2
0
static int pt_sec_posix_map_success(struct pt_section *section)
{
	uint16_t mcount;
	int errcode, status;

	if (!section)
		return -pte_internal;

	mcount = section->mcount + 1;
	if (!mcount) {
		(void) pt_section_unlock(section);
		return -pte_overflow;
	}

	section->mcount = mcount;

	errcode = pt_section_unlock(section);
	if (errcode < 0)
		return errcode;

	status = pt_section_on_map(section);
	if (status < 0) {
		/* We had to release the section lock for pt_section_on_map() so
		 * @section may have meanwhile been mapped by other threads.
		 *
		 * We still want to return the error so we release our mapping.
		 * Our caller does not yet know whether pt_section_map()
		 * succeeded.
		 */
		(void) pt_section_unmap(section);
		return status;
	}

	return 0;
}
Example #3
0
static int worker(void *arg)
{
	struct section_fixture *sfix;
	int it, errcode;

	sfix = arg;
	if (!sfix)
		return -pte_internal;

	for (it = 0; it < num_work; ++it) {
		uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
		int read;

		errcode = pt_section_get(sfix->section);
		if (errcode < 0)
			return errcode;

		errcode = pt_section_map(sfix->section);
		if (errcode < 0)
			goto out_put;

		read = pt_section_read(sfix->section, buffer, 2, 0x0ull);
		if (read < 0)
			goto out_unmap;

		errcode = -pte_invalid;
		if ((read != 2) || (buffer[0] != 0x2) || (buffer[1] != 0x4))
			goto out_unmap;

		errcode = pt_section_unmap(sfix->section);
		if (errcode < 0)
			goto out_put;

		errcode = pt_section_put(sfix->section);
		if (errcode < 0)
			return errcode;
	}

	return 0;

out_unmap:
	(void) pt_section_unmap(sfix->section);

out_put:
	(void) pt_section_put(sfix->section);
	return errcode;
}
Example #4
0
static struct ptunit_result unmap_null(void)
{
	int errcode;

	errcode = pt_section_unmap(NULL);
	ptu_int_eq(errcode, -pte_internal);

	return ptu_passed();
}
Example #5
0
static int pt_image_read_cold(struct pt_image *image, int *isid,
			      uint8_t *buffer, uint16_t size,
			      const struct pt_asid *asid, uint64_t addr)
{
	struct pt_mapped_section *msec;
	struct pt_section_list *section;
	int errcode;

	if (!image || !isid)
		return -pte_internal;

	errcode = pt_image_fetch_section(image, asid, addr);
	if (errcode < 0) {
		if (errcode != -pte_nomap)
			return errcode;
	}

	section = image->sections;
	if (!section)
		return pt_image_read_callback(image, isid, buffer, size, asid,
					      addr);

	msec = &section->section;

	errcode = pt_image_check_msec(msec, asid, addr);
	if (errcode < 0) {
		if (errcode != -pte_nomap)
			return errcode;

		return pt_image_read_callback(image, isid, buffer, size, asid,
					      addr);
	}

	*isid = section->isid;

	if (section->mapped)
		return pt_image_read_msec(buffer, size, msec, addr);
	else {
		struct pt_section *sec;
		int status;

		sec = pt_msec_section(msec);

		errcode = pt_section_map(sec);
		if (errcode < 0)
			return errcode;

		status = pt_image_read_msec(buffer, size, msec, addr);

		errcode = pt_section_unmap(sec);
		if (errcode < 0)
			return errcode;

		return status;
	}
}
Example #6
0
static void pt_section_list_free(struct pt_section_list *list)
{
	if (!list)
		return;

	if (list->mapped)
		pt_section_unmap(list->section.section);
	pt_section_put(list->section.section);
	pt_msec_fini(&list->section);
	free(list);
}
Example #7
0
static struct ptunit_result map_unmap(struct section_fixture *sfix)
{
	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
	int errcode;

	sfix_write(sfix, bytes);

	sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
	ptu_ptr(sfix->section);

	errcode = pt_section_map(sfix->section);
	ptu_int_eq(errcode, 0);

	errcode = pt_section_map(sfix->section);
	ptu_int_eq(errcode, 0);

	errcode = pt_section_unmap(sfix->section);
	ptu_int_eq(errcode, 0);

	errcode = pt_section_unmap(sfix->section);
	ptu_int_eq(errcode, 0);

	return ptu_passed();
}
Example #8
0
int pt_iscache_read(struct pt_image_section_cache *iscache, uint8_t *buffer,
		    uint64_t size, int isid, uint64_t vaddr)
{
	struct pt_section *section;
	uint64_t laddr;
	int errcode, status;

	if (!iscache || !buffer || !size)
		return -pte_invalid;

	errcode = pt_iscache_lookup(iscache, &section, &laddr, isid);
	if (errcode < 0)
		return errcode;

	if (vaddr < laddr) {
		(void) pt_section_put(section);
		return -pte_nomap;
	}

	vaddr -= laddr;

	errcode = pt_section_map(section);
	if (errcode < 0) {
		(void) pt_section_put(section);
		return errcode;
	}

	/* We truncate the read if it gets too big.  The user is expected to
	 * issue further reads for the remaining part.
	 */
	if (UINT16_MAX < size)
		size = UINT16_MAX;

	status = pt_section_read(section, buffer, (uint16_t) size, vaddr);

	errcode = pt_section_unmap(section);
	if (errcode < 0) {
		(void) pt_section_put(section);
		return errcode;
	}

	errcode = pt_section_put(section);
	if (errcode < 0)
		return errcode;

	return status;
}
Example #9
0
static int pt_image_prune_cache(struct pt_image *image)
{
	struct pt_section_list *list;
	uint16_t cache, mapped;
	int status;

	if (!image)
		return -pte_internal;

	cache = image->cache;
	status = 0;
	mapped = 0;
	for (list = image->sections; list; list = list->next) {
		int errcode;

		/* Let's traverse the entire list.  It isn't very long and
		 * this allows us to fix up any previous unmap errors.
		 */
		if (!list->mapped)
			continue;

		mapped += 1;
		if (mapped <= cache)
			continue;

		errcode = pt_section_unmap(list->section.section);
		if (errcode < 0) {
			status = errcode;
			continue;
		}

		list->mapped = 0;
		mapped -= 1;
	}

	image->mapped = mapped;
	return status;
}
Example #10
0
int pt_msec_read(const struct pt_mapped_section *msec, uint8_t *buffer,
		 uint16_t size, const struct pt_asid *asid, uint64_t addr)
{
	struct pt_section *sec;
	int errcode, status;

	if (!msec)
		return -pte_internal;

	sec = msec->section;

	errcode = pt_section_map(sec);
	if (errcode < 0)
		return errcode;

	status = pt_msec_read_mapped(msec, buffer, size, asid, addr);

	errcode = pt_section_unmap(sec);
	if (errcode < 0)
		return errcode;

	return status;
}
Example #11
0
static struct ptunit_result read_overflow_32bit(struct section_fixture *sfix)
{
	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
	int status;

	sfix_write(sfix, bytes);

	sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
	ptu_ptr(sfix->section);

	status = pt_section_map(sfix->section);
	ptu_int_eq(status, 0);

	status = pt_section_read(sfix->section, buffer, 1,
				 0xff00000000ull);
	ptu_int_eq(status, -pte_nomap);
	ptu_uint_eq(buffer[0], 0xcc);

	status = pt_section_unmap(sfix->section);
	ptu_int_eq(status, 0);

	return ptu_passed();
}
Example #12
0
int pt_image_add(struct pt_image *image, struct pt_section *section,
		 const struct pt_asid *asid, uint64_t vaddr, int isid)
{
	struct pt_section_list **list, *next, *removed;
	uint64_t begin, end;
	int errcode;

	if (!image || !section)
		return -pte_internal;

	next = pt_mk_section_list(section, asid, vaddr, isid);
	if (!next)
		return -pte_nomem;

	removed = NULL;
	errcode = 0;

	begin = vaddr;
	end = begin + pt_section_size(section);

	/* Check for overlaps while we move to the end of the list. */
	list = &(image->sections);
	while (*list) {
		const struct pt_mapped_section *msec;
		const struct pt_asid *masid;
		struct pt_section_list *current;
		struct pt_section *lsec;
		uint64_t lbegin, lend;

		current = *list;
		msec = &current->section;
		masid = pt_msec_asid(msec);

		errcode = pt_asid_match(masid, asid);
		if (errcode < 0)
			break;

		if (!errcode) {
			list = &((*list)->next);
			continue;
		}

		lbegin = pt_msec_begin(msec);
		lend = pt_msec_end(msec);

		if ((end <= lbegin) || (lend <= begin)) {
			list = &((*list)->next);
			continue;
		}

		/* The new section overlaps with @msec's section. */
		lsec = pt_msec_section(msec);

		/* Let's check for an identical overlap that may be the result
		 * of repeatedly copying images or repeatedly adding the same
		 * file.
		 */
		if ((begin == lbegin) && (end == lend) &&
		    (isid == current->isid)) {
			const char *fname, *lfname;

			fname = pt_section_filename(section);
			lfname = pt_section_filename(lsec);

			if (!fname || !lfname) {
				errcode = -pte_internal;
				break;
			}

			if (strcmp(fname, lfname) == 0) {
				/* There should not have been any removals or
				 * additions.
				 */
				if (removed || next->next) {
					errcode = -pte_internal;
					break;
				}

				pt_section_list_free(next);
				return 0;
			}
		}

		/* We remove @msec and insert new sections for the remaining
		 * parts, if any.  Those new sections are not mapped initially
		 * and need to be added to the end of the section list.
		 */
		*list = current->next;

		/* Keep a list of removed sections so we can re-add them in case
		 * of errors.
		 */
		current->next = removed;
		removed = current;

		/* Unmap the removed section.  If we need to re-add it, it will
		 * be moved to the end of the section list where the unmapped
		 * sections are.
		 */
		if (current->mapped) {
			pt_section_unmap(lsec);
			current->mapped = 0;
		}

		/* Add a section covering the remaining bytes at the front.
		 *
		 * We preserve the section identifier to indicate that the new
		 * section originated from the original section.
		 */
		if (lbegin < begin) {
			errcode = pt_image_clone(&next, msec, lbegin, begin,
						 current->isid);
			if (errcode < 0)
				break;
		}

		/* Add a section covering the remaining bytes at the back.
		 *
		 * We preserve the section identifier to indicate that the new
		 * section originated from the original section.
		 */
		if (end < lend) {
			errcode = pt_image_clone(&next, msec, end, lend,
						 current->isid);
			if (errcode < 0)
				break;
		}
	}

	if (errcode < 0) {
		pt_section_list_free_tail(next);

		/* Re-add removed sections to the tail of the section list. */
		for (; *list; list = &((*list)->next))
			;

		*list = removed;
		return errcode;
	}

	pt_section_list_free_tail(removed);

	*list = next;
	return 0;
}
Example #13
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);
}