Ejemplo n.º 1
0
/*
 * Read memory statistics data
 */
static void get_paging_data(struct paging_data *pd)
{
	static const char *key_pgpgin = "pgpgin";
	static const char *key_nr_free_pages = "nr_free_pages";
	static const char parse_error_msg[] = "error parsing /proc/vmstat";
	char *cp, *xp;
	bool found_pgpgin = false;
	bool found_nr_free_pages = false;
	int nfound = 0;
	const int need_found = 2;

	pd->ts = getnow();

	pd->mem_pages = sysconf(_SC_PHYS_PAGES);
	if (pd->mem_pages <= 0)
		fatal_msg("unable to get system memory size");

	read_whole_file("/proc/vmstat", &vmstat, &vmstat_size, 4096);

	for (cp = vmstat; *cp != '\0';)
	{
		if (is_key(&cp, key_pgpgin))
		{
			if (!consume_umax(&cp, &pd->pgpgin))
				fatal_msg(parse_error_msg);

			if (!found_pgpgin)
			{
				found_pgpgin = true;
				if (need_found == ++nfound)
					break;
			}
		}
		else if (is_key(&cp, key_nr_free_pages))
		{
			if (!consume_umax(&cp, &pd->nr_free_pages))
				fatal_msg(parse_error_msg);

			if (!found_nr_free_pages)
			{
				found_nr_free_pages = true;
				if (need_found == ++nfound)
					break;
			}
		}
		else
		{
			xp = strchr(cp, '\n');
			if (!xp) break;
			cp = xp + 1;
		}
	}

	if (need_found != nfound)
		fatal_msg(parse_error_msg);
}
Ejemplo n.º 2
0
static void _handle_touch(struct cxl_afu_h *afu, uint64_t addr, uint8_t size)
{
	uint8_t buffer;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_handle_touch");
	if (!_testmemaddr((uint8_t *) addr)) {
		if (_handle_dsi(afu, addr) < 0) {
			perror("DSI Failure");
			return;
		}
		DPRINTF("TOUCH of invalid addr @ 0x%016" PRIx64 "\n", addr);
		buffer = (uint8_t) PSLSE_MEM_FAILURE;
		if (put_bytes_silent(afu->fd, 1, &buffer) != 1) {
			afu->opened = 0;
			afu->attached = 0;
		}
		return;
	}
	buffer = PSLSE_MEM_SUCCESS;
	if (put_bytes_silent(afu->fd, 1, &buffer) != 1) {
		afu->opened = 0;
		afu->attached = 0;
	}
	DPRINTF("TOUCH of addr @ 0x%016" PRIx64 "\n", addr);
}
Ejemplo n.º 3
0
static void _handle_read(struct cxl_afu_h *afu, uint64_t addr, uint8_t size)
{
	uint8_t buffer[MAX_LINE_CHARS];

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_handle_read");
	if (!_testmemaddr((uint8_t *) addr)) {
		if (_handle_dsi(afu, addr) < 0) {
			perror("DSI Failure");
			return;
		}
		DPRINTF("READ from invalid addr @ 0x%016" PRIx64 "\n", addr);
		buffer[0] = (uint8_t) PSLSE_MEM_FAILURE;
		if (put_bytes_silent(afu->fd, 1, buffer) != 1) {
			afu->opened = 0;
			afu->attached = 0;
		}
		return;
	}
	buffer[0] = PSLSE_MEM_SUCCESS;
	memcpy(&(buffer[1]), (void *)addr, size);
	if (put_bytes_silent(afu->fd, size + 1, buffer) != size + 1) {
		afu->opened = 0;
		afu->attached = 0;
	}
	DPRINTF("READ from addr @ 0x%016" PRIx64 "\n", addr);
}
Ejemplo n.º 4
0
static void _handle_ack(struct cxl_afu_h *afu)
{
	uint8_t data[sizeof(uint64_t)];

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_handle_ack");
	DPRINTF("MMIO ACK\n");
	if ((afu->mmio.type == PSLSE_MMIO_READ64)| (afu->mmio.type == PSLSE_MMIO_EBREAD)) {
		if (get_bytes_silent(afu->fd, sizeof(uint64_t), data, 1000, 0) <
		    0) {
			warn_msg("Socket failure getting MMIO Ack");
			_all_idle(afu);
			afu->mmio.data = 0xFEEDB00FFEEDB00FL;
		} else {
			memcpy(&(afu->mmio.data), data, sizeof(uint64_t));
			afu->mmio.data = ntohll(afu->mmio.data);
		}
	}
	if (afu->mmio.type == PSLSE_MMIO_READ32) {
		if (get_bytes_silent(afu->fd, sizeof(uint32_t), data, 1000, 0) <
		    0) {
			warn_msg("Socket failure getting MMIO Read 32 data");
			afu->mmio.data = 0xFEEDB00FL;
			_all_idle(afu);
		} else {
			memcpy(&(afu->mmio.data), data, sizeof(uint32_t));
			debug_msg("KEM:0x%08x", afu->mmio.data);
			afu->mmio.data = ntohl(afu->mmio.data);
			debug_msg("KEM:0x%08x", afu->mmio.data);
		}
	}
	afu->mmio.state = LIBCXL_REQ_IDLE;
}
Ejemplo n.º 5
0
static int _handle_dsi(struct cxl_afu_h *afu, uint64_t addr)
{
	uint16_t size;
	int i;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_handle_dsi");
	// Only track a single DSI at a time
	pthread_mutex_lock(&(afu->event_lock));
	i = 0;
	while (afu->events[i] != NULL) {
		if (afu->events[i]->header.type == CXL_EVENT_DATA_STORAGE) {
			pthread_mutex_unlock(&(afu->event_lock));
			return 0;
		}
		++i;
	}
	assert(i < EVENT_QUEUE_MAX);

	size = sizeof(struct cxl_event_header) +
	    sizeof(struct cxl_event_data_storage);
	afu->events[i] = (struct cxl_event *)calloc(1, size);
	afu->events[i]->header.type = CXL_EVENT_DATA_STORAGE;
	afu->events[i]->header.size = size;
	afu->events[i]->header.process_element = afu->context;
	afu->events[i]->fault.addr = addr & FOURK_MASK;
	afu->events[i]->fault.dsisr = DSISR;

	do {
		i = write(afu->pipe[1], &(afu->events[i]->header.type), 1);
	}
	while ((i == 0) || (errno == EINTR));
	pthread_mutex_unlock(&(afu->event_lock));
	return i;
}
Ejemplo n.º 6
0
static __inline__
void *safe_calloc(unsigned int size, char *file, unsigned int line)
{
  void *res = calloc(1, size);
  if (res == NULL) fatal_msg("CALLOC failed", file, line);
  return res;
}                                                                               
Ejemplo n.º 7
0
static void _mmio_read(struct cxl_afu_h *afu)
{
	uint8_t *buffer;
	uint32_t addr;
	int size, offset;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_mmio_read");
	size = 1 + sizeof(addr);
	buffer = (uint8_t *) malloc(size);
	buffer[0] = afu->mmio.type;
	offset = 1;
	addr = htonl(afu->mmio.addr);
	memcpy((char *)&(buffer[offset]), (char *)&addr, sizeof(addr));
	if (put_bytes_silent(afu->fd, size, buffer) != size) {
	        warn_msg("_mmio_read: put_bytes_silent failed");
		free(buffer);
		close_socket(&(afu->fd));
		afu->opened = 0;
		afu->attached = 0;
		afu->mmio.state = LIBCXL_REQ_IDLE;
		afu->mmio.data = 0xFEEDB00FFEEDB00FL;
		return;
	}
	free(buffer);
	afu->mmio.state = LIBCXL_REQ_PENDING;
}
Ejemplo n.º 8
0
/*
 * Commit current xenstore transaction.
 *
 * Returns:
 * 	XSTS_OK	       success
 * 	XSTS_RETRY     retry the transaction
 *	XSTS_NORETRY   out of retry limit (message logged)
 *	XSTS_FAIL      commit failed (message logged)
 */
static XsTransactionStatus commit_xs(int* p_nretries)
{
	if (xst == XS_TRANSACTION_NULL)
		fatal_msg("bug: commit_xs outside of a transaction");

	if (xs_transaction_end(xs, xst, FALSE))
	{
		debug_msg(15, "committed transaction");
		xst = XS_TRANSACTION_NULL;
		return XSTS_OK;
	}

	xst = XS_TRANSACTION_NULL;

	if (errno == EAGAIN)
	{
		if (++(*p_nretries) > max_xs_retries)
		{
			error_perror("unable to write xenstore (transaction retry limit exceeded)");
			return XSTS_NORETRY;
		}

		retry_wait(*p_nretries);

		debug_msg(2, "restarting xenstore transaction");
		return XSTS_RETRY;
	}
	else
	{
		error_perror("unable to write xenstore (xs_transaction_end)");
		return XSTS_FAIL;
	}
}
Ejemplo n.º 9
0
static void _pslse_attach(struct cxl_afu_h *afu)
{
	uint8_t *buffer;
	uint64_t *wed_ptr;
	int size, offset;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_pslse_attach");
	size = 1 + sizeof(uint64_t);
	buffer = (uint8_t *) malloc(size);
	buffer[0] = PSLSE_ATTACH;
	offset = 1;
	wed_ptr = (uint64_t *) & (buffer[offset]);
	*wed_ptr = htonll(afu->attach.wed);
	if (put_bytes_silent(afu->fd, size, buffer) != size) {
		free(buffer);
		close_socket(&(afu->fd));
		afu->opened = 0;
		afu->attached = 0;
		afu->attach.state = LIBCXL_REQ_IDLE;
		return;
	}
	free(buffer);
	afu->attach.state = LIBCXL_REQ_PENDING;
}
Ejemplo n.º 10
0
/*
 * Process expected signals
 */
static void handle_signals(struct pollfd *pollfds, bool *p_recheck_time)
{
	struct signalfd_siginfo fdsi;
	ssize_t sz;

	/* SIGTERM - exit gracefully */
	if (pollfds[NPFD_SIGTERM].revents & (POLLIN|POLLPRI))
	{
		shutdown_xs();
		notice_msg("terminating...");
		exit(EXIT_SUCCESS);
	}

	/* SIGHUP - reload configuration */
	if (pollfds[NPFD_SIGHUP].revents & (POLLIN|POLLPRI))
	{
		sz = read(fd_sighup, &fdsi, sizeof(fdsi));
		if (sz < 0)
			fatal_perror("read signalfd");
		if (sz != sizeof(fdsi))
			fatal_msg("read signalfd");
		/* reload configuration -- currently none for memprobed */
		if (p_recheck_time)
			*p_recheck_time = true;
	}
}
Ejemplo n.º 11
0
static void _mmio_write32(struct cxl_afu_h *afu)
{
	uint8_t *buffer;
	uint32_t data;
	uint32_t addr;
	int size, offset;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_mmio_write32");
	size = 1 + sizeof(addr) + sizeof(data);
	buffer = (uint8_t *) malloc(size);
	buffer[0] = PSLSE_MMIO_WRITE32;
	offset = 1;
	addr = htonl(afu->mmio.addr);
	memcpy((char *)&(buffer[offset]), (char *)&addr, sizeof(addr));
	offset += sizeof(addr);
	data = htonl(afu->mmio.data);
	memcpy((char *)&(buffer[offset]), (char *)&data, sizeof(data));
	if (put_bytes_silent(afu->fd, size, buffer) != size) {
		free(buffer);
		close_socket(&(afu->fd));
		afu->opened = 0;
		afu->attached = 0;
		afu->mmio.state = LIBCXL_REQ_IDLE;
		return;
	}
	free(buffer);
	afu->mmio.state = LIBCXL_REQ_PENDING;
}
Ejemplo n.º 12
0
static void _mmio_map(struct cxl_afu_h *afu)
{
	uint8_t *buffer;
	uint32_t *flags_ptr;
	uint32_t flags;
	int size;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_mmio_map");
	size = 1 + sizeof(uint32_t);
	buffer = (uint8_t *) malloc(size);
	buffer[0] = PSLSE_MMIO_MAP;
	flags = (uint32_t) afu->mmio.data;
	flags_ptr = (uint32_t *) & (buffer[1]);
	*flags_ptr = htonl(flags);
	if (put_bytes_silent(afu->fd, size, buffer) != size) {
		free(buffer);
		close_socket(&(afu->fd));
		afu->opened = 0;
		afu->attached = 0;
		afu->mmio.state = LIBCXL_REQ_IDLE;
		return;
	}
	free(buffer);
	afu->mmio.state = LIBCXL_REQ_PENDING;
}
Ejemplo n.º 13
0
/*
 * Verify we are running under Xen,
 * and not in the root domain
 */
static void verify_hypervisor(void)
{
	FILE *fp = NULL;
	char buf[256];
	char *p;
	const static char root_uuid[] = "00000000-0000-0000-0000-000000000000";
	const char *rp;

	/*
	 * Check that file /sys/hypervisor/type is present
	 * and contains "xen"
	 */
	if (access("/sys/hypervisor/type", F_OK) == -1 &&
	    (errno == ENOENT || errno == ENOTDIR))
		fatal_msg("not running under a hypervisor");

	fp = fopen("/sys/hypervisor/type", "r");
	if (fp == NULL || NULL == fgets(buf, countof(buf), fp))
		fatal_msg("unable to read /sys/hypervisor/type");

	buf[countof(buf) - 1] = '\0';
	p = strchr(buf, '\n');
	if (p)  *p = '\0';
	if (0 != strcasecmp(buf, "xen"))
		fatal_msg("hypervisor is not Xen");

	fclose(fp);

	/*
	 * Read Xen domain UUID from /sys/hypervisor/uuid
	 * and check it is not the root domain
	 */
	fp = fopen("/sys/hypervisor/uuid", "r");
	if (fp == NULL || NULL == fgets(buf, countof(buf), fp))
		fatal_msg("unable to read /sys/hypervisor/uuid");

	buf[countof(buf) - 1] = '\0';
	p = strchr(buf, '\n');
	if (p)  *p = '\0';
	if (0 == strcmp(buf, root_uuid))
		fatal_msg("may run only in a VM, not root domain");

	fclose(fp);

	if (strlen(buf) != strlen(root_uuid) /* ||
	    strlen(buf) != UUID_STRING_SIZE - 1 */)
		fatal_msg("unexpected domain uuid");

	for (p = buf, rp = root_uuid; *rp;  p++, rp++)
	{
		if (*rp == '-' && *p == '-')  continue;
		if (isxdigit(*rp) && isxdigit(*p))  continue;
		fatal_msg("unexpected domain uuid");
	}

	// strcpy(vm_uuid, buf);
}
Ejemplo n.º 14
0
static void _all_idle(struct cxl_afu_h *afu)
{
	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_all_idle");
	afu->int_req.state = LIBCXL_REQ_IDLE;
	afu->open.state = LIBCXL_REQ_IDLE;
	afu->attach.state = LIBCXL_REQ_IDLE;
	afu->mmio.state = LIBCXL_REQ_IDLE;
	afu->mapped = 0;
	afu->attached = 0;
	afu->opened = 0;
}
Ejemplo n.º 15
0
static int _handle_afu_error(struct cxl_afu_h *afu)
{
	uint64_t error;
	uint16_t size;
	uint8_t data[sizeof(error)];
	int i;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_handle_afu_error");
	DPRINTF("AFU ERROR\n");
	if (get_bytes_silent(afu->fd, sizeof(error), data, 1000, 0) < 0) {
		warn_msg("Socket failure getting AFU ERROR");
		_all_idle(afu);
		return -1;
	}
	memcpy(&error, data, sizeof(error));
	error = ntohll(error);

	// Only track a single AFU error at a time
	pthread_mutex_lock(&(afu->event_lock));
	i = 0;
	while (afu->events[i] != NULL) {
		if (afu->events[i]->header.type == CXL_EVENT_AFU_ERROR) {
			pthread_mutex_unlock(&(afu->event_lock));
			return 0;
		}
		++i;
	}
	assert(i < EVENT_QUEUE_MAX);

	size = sizeof(struct cxl_event_header) +
	    sizeof(struct cxl_event_afu_error);
	afu->events[i] = (struct cxl_event *)calloc(1, size);
	afu->events[i]->header.type = CXL_EVENT_AFU_ERROR;
	afu->events[i]->header.size = size;
	afu->events[i]->header.process_element = afu->context;
	afu->events[i]->afu_error.error = error;

	do {
		i = write(afu->pipe[1], &(afu->events[i]->header.type), 1);
	}
	while ((i == 0) || (errno == EINTR));
	pthread_mutex_unlock(&(afu->event_lock));
	return i;
}
Ejemplo n.º 16
0
/*
 * Select preferred interval clock among available ones
 */
static void select_clk_id(void)
{
	struct timespec ts;

	clk_id = CLOCK_BOOTTIME;
	if (0 == clock_gettime(clk_id, &ts))
		return;

	clk_id = CLOCK_MONOTONIC_RAW;
	if (0 == clock_gettime(clk_id, &ts))
		return;

	clk_id = CLOCK_MONOTONIC;
	if (0 == clock_gettime(clk_id, &ts))
		return;

	fatal_msg("unable to select clk_id");
}
Ejemplo n.º 17
0
static int _handle_interrupt(struct cxl_afu_h *afu)
{
	uint16_t size, irq;
	uint8_t data[sizeof(irq)];
	int i;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_handle_interrupt");
	DPRINTF("AFU INTERRUPT\n");
	if (get_bytes_silent(afu->fd, sizeof(irq), data, 1000, 0) < 0) {
		warn_msg("Socket failure getting IRQ");
		_all_idle(afu);
		return -1;
	}
	memcpy(&irq, data, sizeof(irq));
	irq = ntohs(irq);

	// Only track a single interrupt at a time
	pthread_mutex_lock(&(afu->event_lock));
	i = 0;
	while (afu->events[i] != NULL) {
		if (afu->events[i]->header.type == CXL_EVENT_AFU_INTERRUPT) {
			pthread_mutex_unlock(&(afu->event_lock));
			return 0;
		}
		++i;
	}
	assert(i < EVENT_QUEUE_MAX);

	size = sizeof(struct cxl_event_header) +
	    sizeof(struct cxl_event_afu_interrupt);
	afu->events[i] = (struct cxl_event *)calloc(1, size);
	afu->events[i]->header.type = CXL_EVENT_AFU_INTERRUPT;
	afu->events[i]->header.size = size;
	afu->events[i]->header.process_element = afu->context;
	afu->events[i]->irq.irq = irq;

	do {
		i = write(afu->pipe[1], &(afu->events[i]->header.type), 1);
	}
	while ((i == 0) || (errno == EINTR));
	pthread_mutex_unlock(&(afu->event_lock));
	return i;
}
Ejemplo n.º 18
0
/*
 * Start XenStore transaction.
 * If successful, return @true.
 * On error, return @false and log error message.     		      .
 */
static bool begin_xs(void)
{
	int nretries = 0;

	if (xst != XS_TRANSACTION_NULL)
		fatal_msg("bug: begin_xs inside a transaction");

	for (;;)
	{
		xst = xs_transaction_start(xs);
		if (xst != XS_TRANSACTION_NULL)
			break;

		/*
		 * ENOSPC means too many concurrent transactions from the domain
		 */
		if (errno == ENOSPC)
		{
			if (++nretries > max_xs_retries)
			{
				error_perror("unable to start xenstore transaction (retry limit exceeded)");
				break;
			}

			retry_wait(nretries);
			debug_msg(2, "retrying to start xenstore transaction");
		}
		else
		{
			error_perror("unable to start xenstore transaction");
			break;
		}
	}

	if (xst != XS_TRANSACTION_NULL)
	{
		debug_msg(15, "started transaction");
		return true;
	}
	else
	{
		return false;
	}
}
Ejemplo n.º 19
0
/*
 * Socket file with the same name already exists.
 * If another instance of membalanced is already running, abort.
 * Otherwise delete leftover file, and let the caller retry again.
 */
static void on_addrinuse(const struct sockaddr_un& addr)
{
	int fd;
	int rc;

	DO_RESTARTABLE(fd, socket(AF_UNIX, SOCK_STREAM, 0));
	if (fd == -1)
		fatal_perror("unable to create RPC socket");

	DO_RESTARTABLE(rc, connect(fd, (struct sockaddr*)&addr, sizeof addr));
	if (rc == 0)
		fatal_msg("membalanced is already running and owns RPC socket");
	if (errno != ECONNREFUSED)
		fatal_perror("socket file %s in a bad state", socket_path);

	/* socket exists, but no one is lisening on it */
	if (unlink(socket_path) && errno != ENOENT)
		fatal_perror("unable to delete socket file %s", socket_path);
}
Ejemplo n.º 20
0
static void _release_adapters(struct cxl_adapter_h *adapter)
{
	struct cxl_adapter_h *current;
	uint8_t rc = PSLSE_DETACH;

	if (!adapter)
		fatal_msg("NULL adapter passed to libcxl.c:_release_adapters");
	_release_afus(adapter->afu_list);
	current = adapter;
	while (current != NULL) {
		adapter = current;
		current = current->_next;
		// Disconnect from PSLSE
		if (adapter->fd) {
			put_bytes_silent(adapter->fd, 1, &rc);
			close_socket(&(adapter->fd));
		}
		free(adapter->id);
		free(adapter);
	}
}
Ejemplo n.º 21
0
/*
 * Log/print error message (incl. errno) and terminate
 */
static void fatal_perror(const char *fmt, ...) /* __noreturn__  __format_printf__ */
{
	char *errno_msg;
	char errno_msg_buf[128];
	char msg[512];
	int size = 0;
	va_list ap;

	errno_msg = strerror_r(errno, errno_msg_buf, countof(errno_msg_buf));

	strcpy(msg, "fatal error: ");

	size = strlen(msg);
	va_start(ap, fmt);
	vsnprintf(msg + size, countof(msg) - size, fmt, ap);
	va_end(ap);

	size = strlen(msg);
	snprintf(msg + size, countof(msg) - size, ": %s", errno_msg);

	fatal_msg("%s", msg);
}
Ejemplo n.º 22
0
static void _req_max_int(struct cxl_afu_h *afu)
{
	uint8_t *buffer;
	int size;
	uint16_t value;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_req_max_int");
	size = 1 + sizeof(uint16_t);
	buffer = (uint8_t *) malloc(size);
	buffer[0] = PSLSE_MAX_INT;
	value = htons(afu->int_req.max);
	memcpy((char *)&(buffer[1]), (char *)&value, sizeof(uint16_t));
	if (put_bytes_silent(afu->fd, size, buffer) != size) {
		free(buffer);
		close_socket(&(afu->fd));
		afu->int_req.max = 0;
		_all_idle(afu);
		return;
	}
	free(buffer);
	afu->int_req.state = LIBCXL_REQ_PENDING;
}
Ejemplo n.º 23
0
Archivo: cmd.c Proyecto: open-cpu/pslse
// Send a randomly selected pending response back to AFU
void handle_response(struct cmd *cmd)
{
	struct cmd_event **head;
	struct cmd_event *event;
	struct client *client;
	int rc;

	// Select a random pending response (or none)
	client = NULL;
	head = &cmd->list;
	while (*head != NULL) {
		// Fast track error responses
		if (((*head)->resp == PSL_RESPONSE_PAGED) ||
		    ((*head)->resp == PSL_RESPONSE_NRES) ||
		    ((*head)->resp == PSL_RESPONSE_NLOCK) ||
		    ((*head)->resp == PSL_RESPONSE_FAILED) ||
		    ((*head)->resp == PSL_RESPONSE_FLUSHED)) {
			event = *head;
			goto drive_resp;
		}
		if (((*head)->state == MEM_DONE) && !allow_reorder(cmd->parms)) {
			break;
		}
		head = &((*head)->_next);
	}

	// Randomly decide not to drive response yet
	event = *head;
	if ((event == NULL) || ((event->client_state == CLIENT_VALID)
				&& !allow_resp(cmd->parms))) {
		return;
	}
	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// Send response, remove command from list and free memory
	if ((event->resp == PSL_RESPONSE_PAGED) ||
	    (event->resp == PSL_RESPONSE_AERROR) ||
	    (event->resp == PSL_RESPONSE_DERROR)) {
		client->flushing = FLUSH_FLUSHING;
		_update_pending_resps(cmd, PSL_RESPONSE_FLUSHED);
	}

 drive_resp:
	// Check for pending buffer activity
	if (event == cmd->buffer_read) {
		fatal_msg("Driving response when buffer read still active");
		_print_event(event);
		assert(event != cmd->buffer_read);
	}

	rc = psl_response(cmd->afu_event, event->tag, event->resp, 1, 0, 0);
	if (rc == PSL_SUCCESS) {
		debug_msg("%s:RESPONSE tag=0x%02x code=0x%x", cmd->afu_name,
			  event->tag, event->resp);
		debug_cmd_response(cmd->dbg_fp, cmd->dbg_id, event->tag);
		if ((client != NULL) && (event->command == PSL_COMMAND_RESTART))
			client->flushing = FLUSH_NONE;
		*head = event->_next;
		free(event->data);
		free(event->parity);
		free(event);
		cmd->credits++;
	}
}
Ejemplo n.º 24
0
static void *_psl_loop(void *ptr)
{
	struct cxl_afu_h *afu = (struct cxl_afu_h *)ptr;
	uint8_t buffer[MAX_LINE_CHARS];
	uint8_t size;
	uint64_t addr;
	uint16_t value;
	uint32_t lvalue;
	int rc;

	if (!afu)
		fatal_msg("NULL afu passed to libcxl.c:_psl_loop");
	afu->opened = 1;
	while (afu->opened) {
		_delay_1ms();
		// Send any requests to PSLSE over socket
		if (afu->int_req.state == LIBCXL_REQ_REQUEST)
			_req_max_int(afu);
		if (afu->attach.state == LIBCXL_REQ_REQUEST)
			_pslse_attach(afu);
		if (afu->mmio.state == LIBCXL_REQ_REQUEST) {
			switch (afu->mmio.type) {
			case PSLSE_MMIO_MAP:
				_mmio_map(afu);
				break;
			case PSLSE_MMIO_WRITE64:
				_mmio_write64(afu);
				break;
			case PSLSE_MMIO_WRITE32:
				_mmio_write32(afu);
				break;
			case PSLSE_MMIO_EBREAD:
			case PSLSE_MMIO_READ64:
			case PSLSE_MMIO_READ32:	/*fall through */
				_mmio_read(afu);
				break;
			default:
				break;
			}
		}
		// Process socket input from PSLSE
		rc = bytes_ready(afu->fd, 1000, 0);
		if (rc == 0)
			continue;
		if (rc < 0) {
			warn_msg("Socket failure testing bytes_ready");
			_all_idle(afu);
			break;
		}
		if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) {
			warn_msg("Socket failure getting PSL event");
			_all_idle(afu);
			break;
		}
		DPRINTF("PSL EVENT\n");
		switch (buffer[0]) {
		case PSLSE_OPEN:
			if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) {
				warn_msg("Socket failure getting OPEN context");
				_all_idle(afu);
				break;
			}
			afu->context = (uint16_t) buffer[0];
			afu->open.state = LIBCXL_REQ_IDLE;
			break;
		case PSLSE_ATTACH:
			afu->attach.state = LIBCXL_REQ_IDLE;
			break;
		case PSLSE_DETACH:
		        info_msg("detach response from from pslse");
			afu->mapped = 0;
			afu->attached = 0;
			afu->opened = 0;
			afu->open.state = LIBCXL_REQ_IDLE;
			afu->attach.state = LIBCXL_REQ_IDLE;
			afu->mmio.state = LIBCXL_REQ_IDLE;
			afu->int_req.state = LIBCXL_REQ_IDLE;
			break;
		case PSLSE_MAX_INT:
			size = sizeof(uint16_t);
			if (get_bytes_silent(afu->fd, size, buffer, 1000, 0) <
			    0) {
				warn_msg
				    ("Socket failure getting max interrupt acknowledge");
				_all_idle(afu);
				break;
			}
			memcpy((char *)&value, (char *)buffer,
			       sizeof(uint16_t));
			afu->irqs_max = ntohs(value);
			afu->int_req.state = LIBCXL_REQ_IDLE;
			break;
		case PSLSE_QUERY: {
			size = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) +
			    sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) +  
                            sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t);
			if (get_bytes_silent(afu->fd, size, buffer, 1000, 0) <
			    0) {
				warn_msg("Socket failure getting PSLSE query");
				_all_idle(afu);
				break;
			}
			memcpy((char *)&value, (char *)&(buffer[0]), 2);
			afu->irqs_min = (long)(value);
			memcpy((char *)&value, (char *)&(buffer[2]), 2);
			afu->irqs_max = (long)(value);
                	memcpy((char *)&value, (char *)&(buffer[4]), 2);
			afu->modes_supported = (long)(value);
                	memcpy((char *)&value, (char *)&(buffer[6]), 8);
			afu->mmio_len = (long)(value);
                	memcpy((char *)&value, (char *)&(buffer[14]), 8);
			afu->mmio_off = (long)(value);
                	memcpy((char *)&value, (char *)&(buffer[22]), 8);
			//afu->eb_len = (long)ntohll(value);
			afu->eb_len = (long)(value);
                	memcpy((char *)&value, (char *)&(buffer[30]), 2);
			afu->cr_device = (long)ntohs(value);
                        memcpy((char *)&value, (char *)&(buffer[32]), 2);
			afu->cr_vendor = (long)ntohs(value);
                        memcpy((char *)&lvalue, (char *)&(buffer[34]), 4);
			afu->cr_class = ntohl(lvalue);
			//no better place to put this right now
			afu->prefault_mode = CXL_PREFAULT_MODE_NONE;
			break;
		}
		case PSLSE_MEMORY_READ:
			DPRINTF("AFU MEMORY READ\n");
			if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) {
				warn_msg
				    ("Socket failure getting memory read size");
				_all_idle(afu);
				break;
			}
			size = (uint8_t) buffer[0];
			if (get_bytes_silent(afu->fd, sizeof(uint64_t), buffer,
					     -1, 0) < 0) {
				warn_msg
				    ("Socket failure getting memory read addr");
				_all_idle(afu);
				break;
			}
			memcpy((char *)&addr, (char *)buffer, sizeof(uint64_t));
			addr = ntohll(addr);
			_handle_read(afu, addr, size);
			break;
		case PSLSE_MEMORY_WRITE:
			DPRINTF("AFU MEMORY WRITE\n");
			if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) {
				warn_msg
				    ("Socket failure getting memory write size");
				_all_idle(afu);
				break;
			}
			size = (uint8_t) buffer[0];
			if (get_bytes_silent(afu->fd, sizeof(uint64_t), buffer,
					     -1, 0) < 0) {
				_all_idle(afu);
				break;
			}
			memcpy((char *)&addr, (char *)buffer, sizeof(uint64_t));
			addr = ntohll(addr);
			if (get_bytes_silent(afu->fd, size, buffer, 1000, 0) <
			    0) {
				warn_msg
				    ("Socket failure getting memory write data");
				_all_idle(afu);
				break;
			}
			_handle_write(afu, addr, size, buffer);
			break;
		case PSLSE_MEMORY_TOUCH:
			DPRINTF("AFU MEMORY TOUCH\n");
			if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) {
				warn_msg
				    ("Socket failure getting memory touch size");
				_all_idle(afu);
				break;
			}
			size = buffer[0];
			if (get_bytes_silent(afu->fd, sizeof(uint64_t), buffer,
					     -1, 0) < 0) {
				warn_msg
				    ("Socket failure getting memory touch addr");
				_all_idle(afu);
				break;
			}
			memcpy((char *)&addr, (char *)buffer, sizeof(uint64_t));
			addr = ntohll(addr);
			_handle_touch(afu, addr, size);
			break;
		case PSLSE_MMIO_ACK:
			_handle_ack(afu);
			break;
		case PSLSE_INTERRUPT:
			if (_handle_interrupt(afu) < 0) {
				perror("Interrupt Failure");
				goto psl_fail;
			}
			break;
		case PSLSE_AFU_ERROR:
			if (_handle_afu_error(afu) < 0) {
				perror("AFU ERROR Failure");
				goto psl_fail;
			}
			break;
		default:
			break;
		}
	}

 psl_fail:
	afu->attached = 0;
	pthread_exit(NULL);
}
Ejemplo n.º 25
0
/*
 * Start built-in RPC server
 */
void start_rcmd_server(void)
{
	struct sockaddr_un addr;
	int rc;

	if (sock != -1)
		return;

	/* ensure socket directory exists */
	make_membalance_rundir();

	for (;;)
	{
		/* create socket */
		if (sock == -1)
		{
			DO_RESTARTABLE(sock, socket(AF_UNIX, SOCK_STREAM, 0));
			if (sock == -1)
				fatal_perror("unable to create RPC socket");
		}

		/* build address block */
		if (strlen(socket_path) >= sizeof(addr.sun_path))
			fatal_msg("RPC socket path is too long");

		memset(&addr, 0, sizeof(addr));
		addr.sun_family = AF_UNIX;
		strcpy(addr.sun_path, socket_path);

		/* try to bind socket to a name (and create socket file in file system) */
		DO_RESTARTABLE(rc, bind(sock, (struct sockaddr*)&addr, sizeof addr));
		if (rc != 0)
		{
			/* socket file already exists? */
			if (errno == EADDRINUSE)
			{
				on_addrinuse(addr);
				continue;
			}
			else
			{
				fatal_perror("unable to bind RPC socket to %s", socket_path);
			}
		}

		/* successfully created socket file */
		sock_unlink = true;
		if (chmod(socket_path, S_IRWXU))
		{
			stop_rcmd_server();
			fatal_perror("unable to set protection on socket file %s", socket_path);
		}

		DO_RESTARTABLE(rc, listen(sock, SOMAXCONN));
		if (rc == 0)
			break;

		stop_rcmd_server();

		if (errno == EADDRINUSE)
		{
			on_addrinuse(addr);
			continue;
		}
		else
		{
			fatal_perror("unable to listen on socket file %s", socket_path);
		}
	}

	if (!svc_registered)
	{
		if (!svc_register(NULL, RCMD_MEMBALANCED, RCMD_MEMBALANCED_V1, rcmd_membalanced_1, 0))
			fatal_msg("unable to register RPC server (svc_register)");
		svc_registered = true;
	}

	debug_msg(7, "registered RPC server");
}
Ejemplo n.º 26
0
static struct cxl_afu_h *_pslse_open(int *fd, uint16_t afu_map, uint8_t major,
				     uint8_t minor, char afu_type)
{
	struct cxl_afu_h *afu;
	uint8_t *buffer;
	uint16_t position;

	if (!fd)
		fatal_msg("NULL fd passed to libcxl.c:_pslse_open");
	position = 0x8000;
	position >>= 4 * major;
	position >>= minor;
	if ((afu_map & position) != position) {
		warn_msg("open:AFU not in system");
		close_socket(fd);
		errno = ENODEV;
		return NULL;
	}
	// Create struct for AFU
	afu = _new_afu(afu_map, position, *fd);
	if (afu == NULL)
		return NULL;

	buffer = (uint8_t *) calloc(1, MAX_LINE_CHARS);
	buffer[0] = (uint8_t) PSLSE_OPEN;
	buffer[1] = afu->dbg_id;
	buffer[2] = afu_type;
	afu->fd = *fd;
	if (put_bytes_silent(afu->fd, 3, buffer) != 3) {
		warn_msg("open:Failed to write to socket");
		free(buffer);
		goto open_fail;
	}
	free(buffer);

	afu->_head = afu;
	afu->adapter = major;
	afu->id = (char *)malloc(7);
	afu->open.state = LIBCXL_REQ_PENDING;

	// Start thread
	if (pthread_create(&(afu->thread), NULL, _psl_loop, afu)) {
		perror("pthread_create");
		close_socket(&(afu->fd));
		goto open_fail;
	}
	// Wait for open acknowledgement
	while (afu->open.state != LIBCXL_REQ_IDLE)	/*infinite loop */
		_delay_1ms();

	if (!afu->opened) {
		pthread_join(afu->thread, NULL);
		goto open_fail;
	}

	sprintf(afu->id, "afu%d.%d", major, minor);

	return afu;

 open_fail:
	pthread_mutex_destroy(&(afu->event_lock));
	free(afu);
	errno = ENODEV;
	return NULL;
}
Ejemplo n.º 27
0
/*
 * Commit a pseudo-transaction that involves just one read or write operation
 */
static XsTransactionStatus commit_singleop_xs(int* p_nretries)
{
	if (xst != XS_TRANSACTION_NULL)
		fatal_msg("bug: commit_singleop_xs inside a real transaction");
	return XSTS_OK;
}
Ejemplo n.º 28
0
/*
 * Abort a pseudo-transaction that involves just one read or write operation
 */
static void abort_singleop_xs(void)
{
	if (xst != XS_TRANSACTION_NULL)
		fatal_msg("bug: abort_singleop_xs inside a real transaction");
}
Ejemplo n.º 29
0
/*
 * Begin a pseudo-transaction that involves just one read or write operation
 */
static bool begin_singleop_xs(void)
{
	if (xst != XS_TRANSACTION_NULL)
		fatal_msg("bug: begin_singleop_xs inside a transaction");
	return true;
}
Ejemplo n.º 30
0
/*
 * Log/print "out of memory" message and terminate
 */
static void out_of_memory(void) /* __noreturn__  __format_printf__ */
{
	fatal_msg("out of memory");
}