summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli.c77
-rw-r--r--driver/common.h1
-rw-r--r--driver/kmem.c36
-rw-r--r--driver/pciDriver.h1
-rw-r--r--driver/sysfs.c5
-rw-r--r--kmem.c9
-rw-r--r--kmem.h3
7 files changed, 106 insertions, 26 deletions
diff --git a/cli.c b/cli.c
index 7ac4a09..ea8325c 100644
--- a/cli.c
+++ b/cli.c
@@ -60,6 +60,7 @@ typedef enum {
MODE_STOP_DMA,
MODE_WAIT_IRQ,
MODE_LIST_KMEM,
+ MODE_READ_KMEM,
MODE_FREE_KMEM
} MODE;
@@ -79,8 +80,8 @@ typedef enum {
OPT_OUTPUT = 'o',
OPT_TIMEOUT = 't',
OPT_INFO = 'i',
- OPT_BENCHMARK = 'p',
OPT_LIST = 'l',
+ OPT_BENCHMARK = 'p',
OPT_READ = 'r',
OPT_WRITE = 'w',
OPT_GRAB = 'g',
@@ -92,6 +93,7 @@ typedef enum {
OPT_ITERATIONS,
OPT_LIST_KMEM,
OPT_FREE_KMEM,
+ OPT_READ_KMEM,
OPT_FORCE,
OPT_HELP = 'h',
} OPTIONS;
@@ -117,6 +119,7 @@ static struct option long_options[] = {
{"stop-dma", optional_argument, 0, OPT_STOP_DMA },
{"wait-irq", optional_argument, 0, OPT_WAIT_IRQ },
{"list-kernel-memory", no_argument, 0, OPT_LIST_KMEM },
+ {"read-kernel-memory", required_argument, 0, OPT_READ_KMEM },
{"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM },
{"quiete", no_argument, 0, OPT_QUIETE },
{"force", no_argument, 0, OPT_FORCE },
@@ -159,6 +162,8 @@ void Usage(int argc, char *argv[], const char *format, ...) {
"\n"
" Kernel Modes:\n"
" --list-kernel-memory - List kernel buffers\n"
+" --read-kernel-memory <blk> - Read the specified block of the kernel memory,\n"
+" block is specified as: use:block_number\n"
" --free-kernel-memory <use> - Cleans lost kernel space buffers (DANGEROUS)\n"
" dma - Remove all buffers allocated by DMA subsystem\n"
" #number - Remove all buffers with the specified use id\n"
@@ -1085,7 +1090,7 @@ int ListKMEM(pcilib_t *handle, const char *device) {
return 0;
}
- printf("Use Type Count Total Size REF Mode \n");
+ printf("Use Type Count Total Size REF Mode \n");
printf("--------------------------------------------------------------------------------\n");
for (useid = 0; useid < n_uses; useid++) {
if (useid + 1 == n_uses) {
@@ -1093,20 +1098,21 @@ int ListKMEM(pcilib_t *handle, const char *device) {
i = 0;
} else i = useid + 1;
- if (!i) printf("0x%08lx Others", 0);
- else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"C2S":"S2C"));
- else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"C2S":"S2C"));
- else printf("0x%08lx ", uses[i].use);
- printf(" ");
- printf("% 9lu", uses[i].count);
+ printf("%08lx ", uses[i].use);
+ if (!i) printf("All Others ");
+ else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_RING) printf("DMA%u %s Ring ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
+ else if ((uses[i].use >> 16) == PCILIB_KMEM_USE_DMA_PAGES) printf("DMA%u %s Pages ", uses[i].use&0x7F, ((uses[i].use&0x80)?"S2C":"C2S"));
+ else printf (" ", uses[i].use);
+ printf(" ");
+ printf("% 6lu", uses[i].count);
printf(" ");
- printf("% 12s", PrintSize(stmp, uses[i].size));
- printf(" ");
+ printf("% 10s", PrintSize(stmp, uses[i].size));
+ printf(" ");
if (uses[i].referenced&&uses[i].hw_lock) printf("HW+SW");
else if (uses[i].referenced) printf(" SW");
else if (uses[i].hw_lock) printf("HW ");
else printf(" - ");
- printf(" ");
+ printf(" ");
if (uses[i].persistent) printf("Persistent");
else if (uses[i].open) printf("Open ");
else if (uses[i].reusable) printf("Reusable ");
@@ -1120,6 +1126,28 @@ int ListKMEM(pcilib_t *handle, const char *device) {
return 0;
}
+int ReadKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t use, size_t block, FILE *o) {
+ void *data;
+ size_t size;
+ pcilib_kmem_handle_t *kbuf;
+
+ kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, use, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
+ if (!kbuf) {
+ printf("The specified kernel buffer is not allocated\n");
+ return 0;
+ }
+
+ data = pcilib_kmem_get_block_ua(handle, kbuf, block);
+ if (data) {
+ size = pcilib_kmem_get_block_size(handle, kbuf, block);
+ fwrite(data, 1, size, o?o:stdout);
+ } else {
+ printf("The specified block is not existing\n");
+ }
+
+ pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
+}
+
int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) {
int err;
int i;
@@ -1172,6 +1200,7 @@ int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq
int main(int argc, char **argv) {
int i;
long itmp;
+ unsigned long utmp;
unsigned char c;
const char *num_offset;
@@ -1194,6 +1223,8 @@ int main(int argc, char **argv) {
const char *event = NULL;
const char *dma_channel = NULL;
const char *use = NULL;
+ pcilib_kmem_use_t use_id;
+ size_t block = 0;
pcilib_irq_hw_source_t irq_source;
pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL;
@@ -1294,6 +1325,27 @@ int main(int argc, char **argv) {
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
mode = MODE_LIST_KMEM;
break;
+ case OPT_READ_KMEM:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+ mode = MODE_READ_KMEM;
+
+ num_offset = strchr(optarg, ':');
+
+ if (num_offset) {
+ if (sscanf(num_offset + 1, "%zu", &block) != 1)
+ Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1);
+
+ *(char*)num_offset = 0;
+ }
+
+ if (sscanf(optarg, "%lx", &utmp) != 1)
+ Usage(argc, argv, "Invalid USE number is specified (%s)", optarg);
+
+ if (!utmp)
+ Usage(argc, argv, "Can't read buffer with the unspecific use (use number is 0)");
+
+ use_id = utmp;
+ break;
case OPT_FREE_KMEM:
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
mode = MODE_FREE_KMEM;
@@ -1570,6 +1622,9 @@ int main(int argc, char **argv) {
case MODE_LIST_KMEM:
ListKMEM(handle, fpga_device);
break;
+ case MODE_READ_KMEM:
+ ReadKMEM(handle, fpga_device, use_id, block, ofile);
+ break;
case MODE_FREE_KMEM:
FreeKMEM(handle, fpga_device, use, force);
break;
diff --git a/driver/common.h b/driver/common.h
index 5de501c..e6dea5f 100644
--- a/driver/common.h
+++ b/driver/common.h
@@ -16,6 +16,7 @@ typedef struct {
unsigned long cpua;
unsigned long size;
unsigned long type;
+ unsigned long align;
unsigned long use;
unsigned long item;
diff --git a/driver/kmem.c b/driver/kmem.c
index 274ab9f..afe3889 100644
--- a/driver/kmem.c
+++ b/driver/kmem.c
@@ -40,28 +40,41 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
if (kmem_entry) {
unsigned long flags = kmem_handle->flags;
- if (kmem_handle->type != kmem_entry->type) {
- mod_info("Invalid type of reusable kmem_entry\n");
+ if (flags&KMEM_FLAG_TRY) {
+ kmem_handle->type = kmem_entry->type;
+ kmem_handle->size = kmem_entry->size;
+ kmem_handle->align = kmem_entry->align;
+ } else {
+ if (kmem_handle->type != kmem_entry->type) {
+ mod_info("Invalid type of reusable kmem_entry\n");
return -EINVAL;
- }
+ }
- if (kmem_handle->type == PCILIB_KMEM_TYPE_PAGE) {
- kmem_handle->size = kmem_entry->size;
- } else if (kmem_handle->size != kmem_entry->size) {
+ if (kmem_handle->type == PCILIB_KMEM_TYPE_PAGE) {
+ kmem_handle->size = kmem_entry->size;
+ } else if (kmem_handle->size != kmem_entry->size) {
mod_info("Invalid size of reusable kmem_entry\n");
return -EINVAL;
- }
-
- if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) {
+ }
+
+ if (kmem_handle->align != kmem_entry->align) {
+ mod_info("Invalid alignment of reusable kmem_entry\n");
+ return -EINVAL;
+ }
+
+ if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) {
mod_info("Invalid mode of reusable kmem_entry\n");
return -EINVAL;
+ }
}
+
if ((kmem_entry->mode&KMEM_MODE_COUNT)==KMEM_MODE_COUNT) {
mod_info("Reuse counter of kmem_entry is overflown");
return -EBUSY;
}
+
kmem_handle->handle_id = kmem_entry->id;
kmem_handle->pa = (unsigned long)(kmem_entry->dma_handle);
@@ -79,9 +92,11 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
if (flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT;
privdata->kmem_cur_id = kmem_entry->id;
-
+
return 0;
}
+
+ if (kmem_handle->flags&KMEM_FLAG_TRY) return -ENOENT;
}
/* First, allocate zeroed memory for the kmem_entry */
@@ -96,6 +111,7 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
kmem_entry->use = kmem_handle->use;
kmem_entry->item = kmem_handle->item;
kmem_entry->type = kmem_handle->type;
+ kmem_entry->align = kmem_handle->align;
/* Initialize sysfs if possible */
if (pcidriver_sysfs_initialize_kmem(privdata, kmem_entry->id, &(kmem_entry->sysfs_attr)) != 0)
diff --git a/driver/pciDriver.h b/driver/pciDriver.h
index fc92b11..3ffe8b7 100644
--- a/driver/pciDriver.h
+++ b/driver/pciDriver.h
@@ -106,6 +106,7 @@
#define KMEM_FLAG_HW 8 /**< The buffer may be accessed by hardware, the hardware access will not occur any more if passed to _free function */
#define KMEM_FLAG_FORCE 16 /**< Force memory cleanup even if references are present */
#define KMEM_FLAG_MASS 32 /**< Apply to all buffers of selected use */
+#define KMEM_FLAG_TRY 64 /**< Do not allocate buffers, try to reuse and fail if not possible */
#define KMEM_FLAG_REUSED 1 /**< Indicates if buffer with specified use & item was already allocated and reused */
#define KMEM_FLAG_REUSED_PERSISTENT 4 /**< Indicates that reused buffer was persistent before the call */
diff --git a/driver/sysfs.c b/driver/sysfs.c
index 47e4395..b10157b 100644
--- a/driver/sysfs.c
+++ b/driver/sysfs.c
@@ -101,7 +101,10 @@ static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10);
pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id);
if (entry)
- return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode);
+ if (entry->size >= 16)
+ return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n data: %8x %8x %8x %8x\n", id, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4), *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12));
+ else
+ return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode);
else
return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
#else
diff --git a/kmem.c b/kmem.c
index cc84e8c..b94b628 100644
--- a/kmem.c
+++ b/kmem.c
@@ -144,9 +144,9 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type
break;
}
- if ((alignment)&&(type != PCILIB_KMEM_TYPE_PAGE)) {
- if (kh.pa % alignment) kbuf->buf.blocks[i].alignment_offset = alignment - kh.pa % alignment;
- kbuf->buf.blocks[i].size -= alignment;
+ if ((kh.align)&&(type != PCILIB_KMEM_TYPE_PAGE)) {
+ if (kh.pa % kh.align) kbuf->buf.blocks[i].alignment_offset = kh.align - kh.pa % kh.align;
+ kbuf->buf.blocks[i].size -= kh.align;
}
addr = mmap( 0, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset, PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 );
@@ -157,6 +157,9 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type
}
kbuf->buf.blocks[i].ua = addr;
+// if (use == PCILIB_KMEM_USE_DMA_PAGES) {
+// memset(addr, 10, kbuf->buf.blocks[i].size + kbuf->buf.blocks[i].alignment_offset);
+// }
kbuf->buf.blocks[i].mmap_offset = kh.pa & ctx->page_mask;
}
diff --git a/kmem.h b/kmem.h
index 0f76025..ea806a1 100644
--- a/kmem.h
+++ b/kmem.h
@@ -9,7 +9,8 @@ typedef enum {
PCILIB_KMEM_FLAG_EXCLUSIVE = KMEM_FLAG_EXCLUSIVE,
PCILIB_KMEM_FLAG_PERSISTENT = KMEM_FLAG_PERSISTENT,
PCILIB_KMEM_FLAG_HARDWARE = KMEM_FLAG_HW,
- PCILIB_KMEM_FLAG_FORCE = KMEM_FLAG_FORCE
+ PCILIB_KMEM_FLAG_FORCE = KMEM_FLAG_FORCE,
+ PCILIB_KMEM_FLAG_TRY = KMEM_FLAG_TRY
} pcilib_kmem_flags_t;