예제 #1
0
/*
 * visorchannel_create() - creates the struct visorchannel abstraction for a
 *                         data area in memory, but does NOT modify this data
 *                         area
 * @physaddr:      physical address of start of channel
 * @gfp:           gfp_t to use when allocating memory for the data struct
 * @guid:          GUID that identifies channel type;
 * @needs_lock:    must specify true if you have multiple threads of execution
 *                 that will be calling visorchannel methods of this
 *                 visorchannel at the same time
 *
 * Return: pointer to visorchannel that was created if successful,
 *         otherwise NULL
 */
struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
					 const guid_t *guid, bool needs_lock)
{
	struct visorchannel *channel;
	int err;
	size_t size = sizeof(struct channel_header);

	if (physaddr == 0)
		return NULL;

	channel = kzalloc(sizeof(*channel), gfp);
	if (!channel)
		return NULL;
	channel->needs_lock = needs_lock;
	spin_lock_init(&channel->insert_lock);
	spin_lock_init(&channel->remove_lock);
	/*
	 * Video driver constains the efi framebuffer so it will get a conflict
	 * resource when requesting its full mem region. Since we are only
	 * using the efi framebuffer for video we can ignore this. Remember that
	 * we haven't requested it so we don't try to release later on.
	 */
	channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
	if (!channel->requested && !guid_equal(guid, &visor_video_guid))
		/* we only care about errors if this is not the video channel */
		goto err_destroy_channel;
	channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
	if (!channel->mapped) {
		release_mem_region(physaddr, size);
		goto err_destroy_channel;
	}
	channel->physaddr = physaddr;
	channel->nbytes = size;
	err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
	if (err)
		goto err_destroy_channel;
	size = (ulong)channel->chan_hdr.size;
	memunmap(channel->mapped);
	if (channel->requested)
		release_mem_region(channel->physaddr, channel->nbytes);
	channel->mapped = NULL;
	channel->requested = request_mem_region(channel->physaddr, size,
						VISOR_DRV_NAME);
	if (!channel->requested && !guid_equal(guid, &visor_video_guid))
		/* we only care about errors if this is not the video channel */
		goto err_destroy_channel;
	channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
	if (!channel->mapped) {
		release_mem_region(channel->physaddr, size);
		goto err_destroy_channel;
	}
	channel->nbytes = size;
	guid_copy(&channel->guid, guid);
	return channel;

err_destroy_channel:
	visorchannel_destroy(channel);
	return NULL;
}
예제 #2
0
static int
sig_read_data(struct visorchannel *channel, u32 queue,
	      struct signal_queue_header *sig_hdr, u32 slot, void *data)
{
	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
						 sig_hdr, slot);

	return visorchannel_read(channel, signal_data_offset,
				 data, sig_hdr->signal_size);
}
예제 #3
0
static int sig_read_header(struct visorchannel *channel, u32 queue,
			   struct signal_queue_header *sig_hdr)
{
	if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
		return -EINVAL;

	/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
	return visorchannel_read(channel,
				 sig_queue_offset(&channel->chan_hdr, queue),
				 sig_hdr, sizeof(struct signal_queue_header));
}
예제 #4
0
void
visorchannel_dump_section(VISORCHANNEL *chan, char *s,
			  int off, int len, struct seq_file *seq)
{
	char *buf, *tbuf, *fmtbuf;
	int fmtbufsize = 0;
	int i;
	int errcode = 0;

	fmtbufsize = 100 * COVQ(len, 16);
	buf = kmalloc(len, GFP_KERNEL|__GFP_NORETRY);
	fmtbuf = kmalloc(fmtbufsize, GFP_KERNEL|__GFP_NORETRY);
	if (buf == NULL || fmtbuf == NULL)
		goto Away;

	errcode = visorchannel_read(chan, off, buf, len);
	if (errcode < 0) {
		ERRDRV("%s failed to read %s from channel errcode=%d",
		       s, __func__, errcode);
		goto Away;
	}
	seq_printf(seq, "channel %s:\n", s);
	tbuf = buf;
	while (len > 0) {
		i = (len < 16) ? len : 16;
		hex_dump_to_buffer(tbuf, i, 16, 1, fmtbuf, fmtbufsize, TRUE);
		seq_printf(seq, "%s\n", fmtbuf);
		tbuf += 16;
		len -= 16;
	}

Away:
	if (buf != NULL) {
		kfree(buf);
		buf = NULL;
	}
	if (fmtbuf != NULL) {
		kfree(fmtbuf);
		fmtbuf = NULL;
	}
}
예제 #5
0
void
visorchannel_debug(VISORCHANNEL *channel, int nQueues,
		   struct seq_file *seq, U32 off)
{
	HOSTADDRESS addr = 0;
	ulong nbytes = 0, nbytes_region = 0;
	MEMREGION *memregion = NULL;
	CHANNEL_HEADER hdr;
	CHANNEL_HEADER *phdr = &hdr;
	int i = 0;
	int errcode = 0;

	if (channel == NULL) {
		ERRDRV("%s no channel", __func__);
		return;
	}
	memregion = channel->memregion;
	if (memregion == NULL) {
		ERRDRV("%s no memregion", __func__);
		return;
	}
	addr = visor_memregion_get_physaddr(memregion);
	nbytes_region = visor_memregion_get_nbytes(memregion);
	errcode = visorchannel_read(channel, off,
				    phdr, sizeof(CHANNEL_HEADER));
	if (errcode < 0) {
		seq_printf(seq,
			   "Read of channel header failed with errcode=%d)\n",
			   errcode);
		if (off == 0) {
			phdr = &channel->chan_hdr;
			seq_puts(seq, "(following data may be stale)\n");
		} else
			return;
	}
	nbytes = (ulong) (phdr->Size);
	seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
		   addr + off, nbytes, nbytes_region);
	seq_printf(seq, "Type            = %pUL\n", &phdr->Type);
	seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->ZoneGuid);
	seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
		   (long long) phdr->Signature);
	seq_printf(seq, "LegacyState     = %lu\n", (ulong) phdr->LegacyState);
	seq_printf(seq, "SrvState        = %lu\n", (ulong) phdr->SrvState);
	seq_printf(seq, "CliStateBoot    = %lu\n", (ulong) phdr->CliStateBoot);
	seq_printf(seq, "CliStateOS      = %lu\n", (ulong) phdr->CliStateOS);
	seq_printf(seq, "HeaderSize      = %lu\n", (ulong) phdr->HeaderSize);
	seq_printf(seq, "Size            = %llu\n", (long long) phdr->Size);
	seq_printf(seq, "Features        = 0x%-16.16llx\n",
		   (long long) phdr->Features);
	seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
		   (long long) phdr->PartitionHandle);
	seq_printf(seq, "Handle          = 0x%-16.16llx\n",
		   (long long) phdr->Handle);
	seq_printf(seq, "VersionId       = %lu\n", (ulong) phdr->VersionId);
	seq_printf(seq, "oChannelSpace   = %llu\n",
		   (long long) phdr->oChannelSpace);
	if ((phdr->oChannelSpace == 0) || (errcode < 0))
		;
	else
		for (i = 0; i < nQueues; i++) {
			SIGNAL_QUEUE_HEADER q;
			errcode = visorchannel_read(channel,
						    off + phdr->oChannelSpace +
						    (i * sizeof(q)),
						    &q, sizeof(q));
			if (errcode < 0) {
				seq_printf(seq,
					   "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
					   i, addr, errcode);
				continue;
			}
			sigqueue_debug(&q, i, seq);
		}
	seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
		   addr + off, nbytes);
}
예제 #6
0
/*
 * visorchannel_create_guts() - creates the struct visorchannel abstraction
 *                              for a data area in memory, but does NOT modify
 *                              this data area
 * @physaddr:      physical address of start of channel
 * @channel_bytes: size of the channel in bytes; this may 0 if the channel has
 *                 already been initialized in memory (which is true for all
 *                 channels provided to guest environments by the s-Par
 *                 back-end), in which case the actual channel size will be
 *                 read from the channel header in memory
 * @gfp:           gfp_t to use when allocating memory for the data struct
 * @guid:          uuid that identifies channel type; this may 0 if the channel
 *                 has already been initialized in memory (which is true for all
 *                 channels provided to guest environments by the s-Par
 *                 back-end), in which case the actual channel guid will be
 *                 read from the channel header in memory
 * @needs_lock:    must specify true if you have multiple threads of execution
 *                 that will be calling visorchannel methods of this
 *                 visorchannel at the same time
 *
 * Return: pointer to visorchannel that was created if successful,
 *         otherwise NULL
 */
static struct visorchannel *
visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
			 gfp_t gfp, uuid_le guid, bool needs_lock)
{
	struct visorchannel *channel;
	int err;
	size_t size = sizeof(struct channel_header);

	if (physaddr == 0)
		return NULL;

	channel = kzalloc(sizeof(*channel), gfp);
	if (!channel)
		return NULL;

	channel->needs_lock = needs_lock;
	spin_lock_init(&channel->insert_lock);
	spin_lock_init(&channel->remove_lock);

	/*
	 * Video driver constains the efi framebuffer so it will get a
	 * conflict resource when requesting its full mem region. Since
	 * we are only using the efi framebuffer for video we can ignore
	 * this. Remember that we haven't requested it so we don't try to
	 * release later on.
	 */
	channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
	if (!channel->requested && uuid_le_cmp(guid, spar_video_guid))
		/* we only care about errors if this is not the video channel */
		goto err_destroy_channel;

	channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
	if (!channel->mapped) {
		release_mem_region(physaddr, size);
		goto err_destroy_channel;
	}

	channel->physaddr = physaddr;
	channel->nbytes = size;

	err = visorchannel_read(channel, 0, &channel->chan_hdr,
				sizeof(struct channel_header));
	if (err)
		goto err_destroy_channel;

	/* we had better be a CLIENT of this channel */
	if (channel_bytes == 0)
		channel_bytes = (ulong)channel->chan_hdr.size;
	if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
		guid = channel->chan_hdr.chtype;

	memunmap(channel->mapped);
	if (channel->requested)
		release_mem_region(channel->physaddr, channel->nbytes);
	channel->mapped = NULL;
	channel->requested = request_mem_region(channel->physaddr,
						channel_bytes, MYDRVNAME);
	if (!channel->requested && uuid_le_cmp(guid, spar_video_guid))
		/* we only care about errors if this is not the video channel */
		goto err_destroy_channel;

	channel->mapped = memremap(channel->physaddr, channel_bytes,
			MEMREMAP_WB);
	if (!channel->mapped) {
		release_mem_region(channel->physaddr, channel_bytes);
		goto err_destroy_channel;
	}

	channel->nbytes = channel_bytes;
	channel->guid = guid;
	return channel;

err_destroy_channel:
	visorchannel_destroy(channel);
	return NULL;
}
예제 #7
0
void
visorchannel_debug(VISORCHANNEL *channel, int nQueues,
		   struct seq_file *seq, u32 off)
{
	HOSTADDRESS addr = 0;
	ulong nbytes = 0, nbytes_region = 0;
	struct memregion *memregion = NULL;
	struct channel_header hdr;
	struct channel_header *phdr = &hdr;
	int i = 0;
	int errcode = 0;

	if (channel == NULL) {
		ERRDRV("%s no channel", __func__);
		return;
	}
	memregion = channel->memregion;
	if (memregion == NULL) {
		ERRDRV("%s no memregion", __func__);
		return;
	}
	addr = visor_memregion_get_physaddr(memregion);
	nbytes_region = visor_memregion_get_nbytes(memregion);
	errcode = visorchannel_read(channel, off,
				    phdr, sizeof(struct channel_header));
	if (errcode < 0) {
		seq_printf(seq,
			   "Read of channel header failed with errcode=%d)\n",
			   errcode);
		if (off == 0) {
			phdr = &channel->chan_hdr;
			seq_puts(seq, "(following data may be stale)\n");
		} else {
			return;
		}
	}
	nbytes = (ulong)(phdr->size);
	seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
		   addr + off, nbytes, nbytes_region);
	seq_printf(seq, "Type            = %pUL\n", &phdr->chtype);
	seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
	seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
		   (long long)phdr->signature);
	seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
	seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
	seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
	seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
	seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
	seq_printf(seq, "Size            = %llu\n", (long long)phdr->size);
	seq_printf(seq, "Features        = 0x%-16.16llx\n",
		   (long long)phdr->features);
	seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
		   (long long)phdr->partition_handle);
	seq_printf(seq, "Handle          = 0x%-16.16llx\n",
		   (long long)phdr->handle);
	seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
	seq_printf(seq, "oChannelSpace   = %llu\n",
		   (long long)phdr->ch_space_offset);
	if ((phdr->ch_space_offset == 0) || (errcode < 0))
		;
	else
		for (i = 0; i < nQueues; i++) {
			struct signal_queue_header q;

			errcode = visorchannel_read(channel,
						    off +
						    phdr->ch_space_offset +
						    (i * sizeof(q)),
						    &q, sizeof(q));
			if (errcode < 0) {
				seq_printf(seq,
					   "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
					   i, addr, errcode);
				continue;
			}
			sigqueue_debug(&q, i, seq);
		}
	seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
		   addr + off, nbytes);
}