/*
 * Copyright (c) 2013-2019, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  * Neither the name of Intel Corporation nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "pt_sync.h"
#include "pt_packet.h"
#include "pt_opcodes.h"

#include "intel-pt.h"


/* A psb packet contains a unique 2-byte repeating pattern.
 *
 * There are only two ways to fill up a 64bit work with such a pattern.
 */
static const uint64_t psb_pattern[] = {
	((uint64_t) pt_psb_lohi		| (uint64_t) pt_psb_lohi << 16 |
	 (uint64_t) pt_psb_lohi << 32	| (uint64_t) pt_psb_lohi << 48),
	((uint64_t) pt_psb_hilo		| (uint64_t) pt_psb_hilo << 16 |
	 (uint64_t) pt_psb_hilo << 32	| (uint64_t) pt_psb_hilo << 48)
};

static const uint8_t *truncate(const uint8_t *pointer, size_t alignment)
{
	uintptr_t raw = (uintptr_t) pointer;

	raw /= alignment;
	raw *= alignment;

	return (const uint8_t *) raw;
}

static const uint8_t *align(const uint8_t *pointer, size_t alignment)
{
	return truncate(pointer + alignment - 1, alignment);
}

/* Find a psb packet given a position somewhere in the payload.
 *
 * Return the position of the psb packet.
 * Return NULL, if this is not a psb packet.
 */
static const uint8_t *pt_find_psb(const uint8_t *pos,
				  const struct pt_config *config)
{
	const uint8_t *begin, *end;
	int errcode;

	if (!pos || !config)
		return NULL;

	begin = config->begin;
	end = config->end;

	/* Navigate to the end of the psb payload pattern.
	 *
	 * Beware that PSB is an extended opcode. We must not confuse the extend
	 * opcode of the following packet as belonging to the PSB.
	 */
	if (*pos != pt_psb_hi)
		pos++;

	for (; (pos + 1) < end; pos += 2) {
		uint8_t hi, lo;

		hi = pos[0];
		lo = pos[1];

		if (hi != pt_psb_hi)
			break;

		if (lo != pt_psb_lo)
			break;
	}
	/*
	 * We're right after the psb payload and within the buffer.
	 * Navigate to the expected beginning of the psb packet.
	 */
	pos -= ptps_psb;

	/* Check if we're still inside the buffer. */
	if (pos < begin)
		return NULL;

	/* Check that this is indeed a psb packet we're at. */
	if (pos[0] != pt_opc_psb || pos[1] != pt_ext_psb)
		return NULL;

	errcode = pt_pkt_read_psb(pos, config);
	if (errcode < 0)
		return NULL;

	return pos;
}

static int pt_sync_within_bounds(const uint8_t *pos, const uint8_t *begin,
				 const uint8_t *end)
{
	/* We allow @pos == @end representing the very end of the trace.
	 *
	 * This will result in -pte_eos when we actually try to read from @pos.
	 */
	return (begin <= pos) && (pos <= end);
}

int pt_sync_set(const uint8_t **sync, const uint8_t *pos,
		const struct pt_config *config)
{
	const uint8_t *begin, *end;
	int errcode;

	if (!sync || !pos || !config)
		return -pte_internal;

	begin = config->begin;
	end = config->end;

	if (!pt_sync_within_bounds(pos, begin, end))
		return -pte_eos;

	if (end < pos + 2)
		return -pte_eos;

	/* Check that this is indeed a psb packet we're at. */
	if (pos[0] != pt_opc_psb || pos[1] != pt_ext_psb)
		return -pte_nosync;

	errcode = pt_pkt_read_psb(pos, config);
	if (errcode < 0)
		return errcode;

	*sync = pos;

	return 0;
}

int pt_sync_forward(const uint8_t **sync, const uint8_t *pos,
		    const struct pt_config *config)
{
	const uint8_t *begin, *end, *start;

	if (!sync || !pos || !config)
		return -pte_internal;

	start = pos;
	begin = config->begin;
	end = config->end;

	if (!pt_sync_within_bounds(pos, begin, end))
		return -pte_internal;

	/* We search for a full 64bit word. It's OK to skip the current one. */
	pos = align(pos, sizeof(*psb_pattern));

	/* Search for the psb payload pattern in the buffer. */
	for (;;) {
		const uint8_t *current = pos;
		uint64_t val;

		pos += sizeof(uint64_t);
		if (end < pos)
			return -pte_eos;

		val = * (const uint64_t *) current;

		if ((val != psb_pattern[0]) && (val != psb_pattern[1]))
			continue;

		/* We found a 64bit word's worth of psb payload pattern. */
		current = pt_find_psb(pos, config);
		if (!current)
			continue;

		/* If @start points inside a PSB, we may find that one.  Ignore
		 * it unless @start points to its beginning.
		 */
		if (current < start)
			continue;

		*sync = current;
		return 0;
	}
}

int pt_sync_backward(const uint8_t **sync, const uint8_t *pos,
		    const struct pt_config *config)
{
	const uint8_t *begin, *end;

	if (!sync || !pos || !config)
		return -pte_internal;

	begin = config->begin;
	end = config->end;

	if (!pt_sync_within_bounds(pos, begin, end))
		return -pte_internal;

	/* We search for a full 64bit word. It's OK to skip the current one. */
	pos = truncate(pos, sizeof(*psb_pattern));

	/* Search for the psb payload pattern in the buffer. */
	for (;;) {
		const uint8_t *next = pos;
		uint64_t val;

		pos -= sizeof(uint64_t);
		if (pos < begin)
			return -pte_eos;

		val = * (const uint64_t *) pos;

		if ((val != psb_pattern[0]) && (val != psb_pattern[1]))
			continue;

		/* We found a 64bit word's worth of psb payload pattern. */
		next = pt_find_psb(next, config);
		if (!next)
			continue;

		*sync = next;
		return 0;
	}
}
