示例#1
0
文件: psl.c 项目: open-cpu/pslse
// Handle events from AFU
static void _handle_afu(struct psl *psl)
{
	struct client *client;
	uint64_t error;
	uint8_t *buffer;
	int reset_done;
	size_t size;

	reset_done = handle_aux2(psl->job, &(psl->parity_enabled),
				 &(psl->latency), &error);
	if (error && !directed_mode_support(psl->mmio)) {
		client = psl->client[0];
		size = 1 + sizeof(uint64_t);
		buffer = (uint8_t *) malloc(size);
		buffer[0] = PSLSE_AFU_ERROR;
		error = htonll(error);
		memcpy((char *)&(buffer[1]), (char *)&error, sizeof(error));
		if (put_bytes
		    (client->fd, size, buffer, psl->dbg_fp, psl->dbg_id,
		     0) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
		}
	}
	handle_mmio_ack(psl->mmio, psl->parity_enabled);
	if (psl->cmd != NULL) {
		if (reset_done)
			psl->cmd->credits = psl->cmd->parms->credits;
		handle_response(psl->cmd);
		handle_buffer_write(psl->cmd);
		handle_buffer_read(psl->cmd);
		handle_buffer_data(psl->cmd, psl->parity_enabled);
		handle_mem_write(psl->cmd);
		handle_touch(psl->cmd);
		handle_cmd(psl->cmd, psl->parity_enabled, psl->latency);
		handle_interrupt(psl->cmd);
	}
}
示例#2
0
文件: psl.c 项目: ibm-capi/pslse
// Client is detaching from the AFU
static void _detach(struct psl *psl, struct client *client)
{
	uint64_t wed;

	debug_msg("DETACH from client context 0x%02x", client->context);
	// if dedicated mode just drop the client
	// if afu-directed mode
	//   add llcmd terminate to psl->job->pe
	//   add llcmd remove to psl->job->pe
	// comment - check to see if send pe is called if the client state is CLIENT_NONE
	// allow the socket to close and the client struct to be freed.
	if (client->type == 'm' || client->type == 's') {
	        wed = PSL_LLCMD_TERMINATE;
		wed = wed | (uint64_t)client->context;
	        if (add_pe(psl->job, PSL_JOB_LLCMD, wed) == NULL) {
		  // error
		  error_msg( "%s:_detach failed to add llcmd terminate for context=%d"PRIx64, psl->name, client->context );
		}
	        wed = PSL_LLCMD_REMOVE;
		wed = wed | (uint64_t)client->context;
	        if (add_pe(psl->job, PSL_JOB_LLCMD, wed) == NULL) {
		  // error
		  error_msg( "%s:_detach failed to add llcmd remove for context=%d"PRIx64, psl->name, client->context );
		}
	} else {
	  if (client->type == 'd' ) {
	    client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
	  }
	}

	// we will let _psl_loop call send_pe to issue the llcmds
	// when the jcack's come back, we will 
	//   send the detach response to the client and 
	//   free the client structure

	
}
示例#3
0
文件: psl.c 项目: open-cpu/pslse
static void _handle_client(struct psl *psl, struct client *client)
{
	struct mmio_event *mmio;
	struct cmd_event *cmd;
	uint8_t buffer[MAX_LINE_CHARS];
	int dw = 0;

	// Handle MMIO done
	if (client->mmio_access != NULL) {
		client->idle_cycles = PSL_IDLE_CYCLES;
		client->mmio_access = handle_mmio_done(psl->mmio, client);
	}
	// Client disconnected
	if (client->state == CLIENT_NONE)
		return;

	// Check for event from application
	cmd = (struct cmd_event *)client->mem_access;
	mmio = NULL;
	if (bytes_ready(client->fd, 1, &(client->abort))) {
		if (get_bytes(client->fd, 1, buffer, psl->timeout,
			      &(client->abort), psl->dbg_fp, psl->dbg_id,
			      client->context) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
			return;
		}
		switch (buffer[0]) {
		case PSLSE_DETACH:
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
			break;
		case PSLSE_ATTACH:
			_attach(psl, client);
			break;
		case PSLSE_MEM_FAILURE:
			if (client->mem_access != NULL)
				handle_aerror(psl->cmd, cmd);
			client->mem_access = NULL;
			break;
		case PSLSE_MEM_SUCCESS:
			if (client->mem_access != NULL)
				handle_mem_return(psl->cmd, cmd, client->fd);
			client->mem_access = NULL;
			break;
		case PSLSE_MMIO_MAP:
			handle_mmio_map(psl->mmio, client);
			break;
		case PSLSE_MMIO_WRITE64:
			dw = 1;
		case PSLSE_MMIO_WRITE32:	/*fall through */
			mmio = handle_mmio(psl->mmio, client, 0, dw);
			break;
		case PSLSE_MMIO_READ64:
			dw = 1;
		case PSLSE_MMIO_READ32:	/*fall through */
			mmio = handle_mmio(psl->mmio, client, 1, dw);
			break;
		default:
			error_msg("Unexpected 0x%02x from client", buffer[0]);
		}

		if (mmio)
			client->mmio_access = (void *)mmio;

		if (client->state == CLIENT_VALID)
			client->idle_cycles = PSL_IDLE_CYCLES;
	}
}
示例#4
0
static void *_client_loop(void *ptr)
{
    struct client *client = (struct client *)ptr;
    uint8_t data[2];
    int rc;

    pthread_mutex_lock(&lock);
    while (client->pending) {
        rc = bytes_ready(client->fd, client->timeout, &(client->abort));
        if (rc == 0) {
            lock_delay(&lock);
            continue;
        }
        if ((rc < 0) || get_bytes(client->fd, 1, data, 10,
                                  &(client->abort), fp, -1, -1) < 0) {
            client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
            break;
        }
        if (data[0] == PSLSE_QUERY) {
            if (get_bytes_silent(client->fd, 1, data, timeout,
                                 &(client->abort)) < 0) {
                debug_msg("_client_loop failed PSLSE_QUERY");
                client_drop(client, PSL_IDLE_CYCLES,
                            CLIENT_NONE);
                break;
            }
            _query(client, data[0]);
            lock_delay(&lock);
            continue;
        }
        if (data[0] == PSLSE_MAX_INT) {
            if (get_bytes(client->fd, 2, data, timeout,
                          &(client->abort), fp, -1, -1) < 0) {
                client_drop(client, PSL_IDLE_CYCLES,
                            CLIENT_NONE);
                break;
            }
            _max_irqs(client, data[0]);
            lock_delay(&lock);
            continue;
        }
        if (data[0] == PSLSE_OPEN) {
            if (get_bytes_silent(client->fd, 2, data, timeout,
                                 &(client->abort)) < 0) {
                client_drop(client, PSL_IDLE_CYCLES,
                            CLIENT_NONE);
                debug_msg("_client_loop: client associate failed; could not communicate with socket");
                break;
            }
            _client_associate(client, data[0], (char)data[1]);
            debug_msg("_client_loop: client associated");
            break;
        }
        client->pending = 0;
        break;
        lock_delay(&lock);
    }
    pthread_mutex_unlock(&lock);

    // Terminate thread
    pthread_exit(NULL);
}
示例#5
0
文件: cmd.c 项目: open-cpu/pslse
// Handle randomly selected pending read by either generating early buffer
// write with bogus data, send request to client for real data or do final
// buffer write with valid data after it has been received from client.
void handle_buffer_write(struct cmd *cmd)
{
	struct cmd_event *event;
	struct client *client;
	uint8_t buffer[10];
	uint64_t *addr;
	int quadrant, byte;

	// Make sure cmd structure is valid
	if (cmd == NULL)
		return;

	// Randomly select a pending read (or none)
	event = cmd->list;
	while (event != NULL) {
		if ((event->type == CMD_READ) &&
		    (event->state != MEM_DONE) &&
		    ((event->client_state != CLIENT_VALID) ||
		     !allow_reorder(cmd->parms))) {
			break;
		}
		event = event->_next;
	}

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// After the client returns data with a call to the function
	// _handle_mem_read() issue buffer write with valid data and
	// prepare for response.
	if (event->state == MEM_RECEIVED) {
		if (psl_buffer_write(cmd->afu_event, event->tag, event->addr,
				     CACHELINE_BYTES, event->data,
				     event->parity) == PSL_SUCCESS) {
			debug_msg("%s:BUFFER WRITE tag=0x%02x", cmd->afu_name,
				  event->tag);
			for (quadrant = 0; quadrant < 4; quadrant++) {
				DPRINTF("DEBUG: Q%d 0x", quadrant);
				for (byte = 0; byte < CACHELINE_BYTES / 4;
				     byte++) {
					DPRINTF("%02x", event->data[byte]);
				}
				DPRINTF("\n");
			}
			event->resp = PSL_RESPONSE_DONE;
			event->state = MEM_DONE;
			debug_cmd_buffer_write(cmd->dbg_fp, cmd->dbg_id,
					       event->tag);
			debug_cmd_update(cmd->dbg_fp, cmd->dbg_id, event->tag,
					 event->context, event->resp);
		}
	}

	if (event->state != MEM_IDLE)
		return;

	if (!event->buffer_activity && allow_buffer(cmd->parms)) {
		// Buffer write with bogus data, but only once
		debug_cmd_buffer_write(cmd->dbg_fp, cmd->dbg_id, event->tag);
		psl_buffer_write(cmd->afu_event, event->tag, event->addr,
				 CACHELINE_BYTES, event->data, event->parity);
		event->buffer_activity = 1;
	} else if (client->mem_access == NULL) {
		// Send read request to client, set client->mem_access
		// to point to this event blocking any other memory
		// accesses to client until data is returned by call
		// to the _handle_mem_read() function.
		buffer[0] = (uint8_t) PSLSE_MEMORY_READ;
		buffer[1] = (uint8_t) event->size;
		addr = (uint64_t *) & (buffer[2]);
		*addr = htonll(event->addr);
		event->abort = &(client->abort);
		if (put_bytes(client->fd, 10, buffer, cmd->dbg_fp,
			      cmd->dbg_id, event->context) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
		}
		event->state = MEM_REQUEST;
		debug_cmd_client(cmd->dbg_fp, cmd->dbg_id, event->tag,
				 event->context);
		client->mem_access = (void *)event;
	}
}
示例#6
0
文件: psl.c 项目: ibm-capi/pslse
// Attach to AFU
static void _attach(struct psl *psl, struct client *client)
{
	uint64_t wed;
	uint8_t ack;
	uint8_t buffer[MAX_LINE_CHARS];
	size_t size;

	// FIXME: This only works for dedicate mode
	// might work for afu-directed now - lgt

	// Get wed value from application
	// always do the get
        // pass the wed only for dedicated
	ack = PSLSE_DETACH;
	size = sizeof(uint64_t);
	if (get_bytes_silent(client->fd, size, buffer, psl->timeout,
			     &(client->abort)) < 0) {
	  warn_msg("Failed to get WED value from client");
	  client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
	  goto attach_done;
	}

	// but need to save wed if master|slave for future consumption
	// interestingly, I can always save it
	// add to client type.
	memcpy((char *)&wed, (char *)buffer, sizeof(uint64_t));
	// wed came over in be format
	// since we are modeling the psl register here, we should leave it be
#if defined PSL9lite || defined PSL9
	client->wed = wed; // ntohll(wed);
#else
	client->wed = ntohll(wed);
#endif 

	// Send start to AFU
	// only add PSL_JOB_START for dedicated and master clients.
	// send an empty wed in the case of master
	// lgt - new idea:
	// track number of clients in psl
	// if number of clients = 0, then add the start job
	// add llcmd add to client  (loop through clients in send_com)
	// increment number of clients (decrement where we handle the completion of the detach)
	switch (client->type) {
	case 'd':
	  if (psl->attached_clients == 0) {
	    if (add_job(psl->job, PSL_JOB_START, client->wed) != NULL) {
	      // if dedicated, we can ack PSLSE_ATTACH
	      // if master, we might want to wait until after the llcmd add is complete
	      // can I wait here for the START to finish?
	      psl->idle_cycles = PSL_IDLE_CYCLES;
	      ack = PSLSE_ATTACH;
	    }
	  }
	  break;
	case 'm':
	case 's':
	  if (psl->attached_clients < psl->max_clients) {
	    if (psl->attached_clients == 0) {
	      if (add_job(psl->job, PSL_JOB_START, 0L) != NULL) {
		// if master, we might want to wait until after the llcmd add is complete
		// can I wait here for the START to finish?
	      }
	    }
	    psl->idle_cycles = PSL_IDLE_CYCLES;
	    ack = PSLSE_ATTACH;
	  }
	  // running will be set by send/handle_aux2 routines
	  break;
	default:
	  // error?
	  break;
	}

	psl->attached_clients++;
	info_msg( "Attached client context %d: current attached clients = %d: client type = %c\n", client->context, psl->attached_clients, client->type );
	
	// for master and slave send llcmd add
        // master "wed" is 0x0005000000000000 can actually use client->context here as well since context = 0
	// slave "wed" is 0x000500000000hhhh where hhhh is the "handle" from client->context
	// now - about those llcmds :-)
	// put these in a separate list associated with the job?  psl->pe maybe...  or another call to add_job?
	// new routine to job.c?  add_cmd?
	// should a slave know their master?
	if (client->type == 'm' || client->type == 's') {
	        wed = PSL_LLCMD_ADD;
		wed = wed | (uint64_t)client->context;
		// add_pe adds to the client
	        if (add_pe(psl->job, PSL_JOB_LLCMD, wed) != NULL) {
		}
	}

 attach_done:
	if (put_bytes(client->fd, 1, &ack, psl->dbg_fp, psl->dbg_id,
		      client->context) < 0) {
		client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
	}
}
示例#7
0
文件: psl.c 项目: ibm-capi/pslse
// Handle events from AFU
static void _handle_afu(struct psl *psl)
{
	struct client *client;
	uint64_t error;
	uint8_t *buffer;
	int reset_done;
	int i;
	size_t size;

	reset_done = _handle_aux2(psl, &(psl->parity_enabled),
				 &(psl->latency), &error);
//printf("after reset_done in handle_afu \n");
	if (error) {
	  if (dedicated_mode_support(psl->mmio)) {
		client = psl->client[0];
		size = 1 + sizeof(uint64_t);
		buffer = (uint8_t *) malloc(size);
		buffer[0] = PSLSE_AFU_ERROR;
		error = htonll(error);
		memcpy((char *)&(buffer[1]), (char *)&error, sizeof(error));
	        warn_msg("%s: Received JERROR: 0x%016"PRIx64" in afu-dedicated mode", psl->name, error);
		if (put_bytes
		    (client->fd, size, buffer, psl->dbg_fp, psl->dbg_id,
		     0) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
		}
	  }
	  if (directed_mode_support(psl->mmio)) {
	        // afu error gets logged by OS. - print warning message
                // no interrupt/event is sent up to the application - don't "put_bytes" back to client(s)
	        // all clients lose connection to afu but how is this observered by the client?
	        warn_msg("%s: Received JERROR: 0x%016"PRIx64" in afu-directed mode", psl->name, error);
		for (i = 0; i < psl->max_clients; i++) {
			if (psl->client[i] == NULL)
				continue;
			client_drop(psl->client[i], PSL_IDLE_CYCLES, CLIENT_NONE);
		}
	  }
	}
	handle_mmio_ack(psl->mmio, psl->parity_enabled);
	if (psl->cmd != NULL) {
		if (reset_done)
			psl->cmd->credits = psl->cmd->parms->credits;
#if defined PSL9lite || defined PSL9
		handle_caia2_cmds(psl->cmd);
#endif /* ifdef PSL9 or PSL9lite */
#ifdef PSL9
		handle_dma0_port(psl->cmd);
		handle_dma0_write(psl->cmd);
		handle_dma0_sent_sts(psl->cmd);
		handle_dma0_read(psl->cmd);
#endif /* ifdef PSL9 */

		handle_response(psl->cmd);
		handle_buffer_write(psl->cmd);
		handle_buffer_read(psl->cmd);
		handle_buffer_data(psl->cmd, psl->parity_enabled);
		handle_mem_write(psl->cmd);
		handle_touch(psl->cmd);
		handle_cmd(psl->cmd, psl->parity_enabled, psl->latency);
		handle_interrupt(psl->cmd);

	}
}