/* * 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; }
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); }
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)); }
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; } }
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); }
/* * 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; }
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); }