Add some dumb test code
This commit is contained in:
18
sw/test/Makefile
Normal file
18
sw/test/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
BIN=pcie_dma_test
|
||||
|
||||
SRCS=$(wildcard *.c)
|
||||
OBJS=$(SRCS:.c=.o)
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
gcc -o $@ $(CFLAGS) $(LDFLAGS) $^
|
||||
|
||||
%.o: %.c
|
||||
gcc -c -o $@ $(CFLAGS) $<
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(OBJS)
|
||||
rm -rf $(BIN)
|
||||
2
sw/test/enable_bus_mastering.sh
Normal file
2
sw/test/enable_bus_mastering.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
# Enable bus mastering
|
||||
sudo setpci -d 10EE:9038 COMMAND=7
|
||||
102
sw/test/pcie_dma_test.c
Normal file
102
sw/test/pcie_dma_test.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <fcntl.h> /* open */
|
||||
#include <stdint.h> /* uint64_t */
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdlib.h> /* size_t */
|
||||
#include <unistd.h> /* pread, sysconf */
|
||||
#include <sys/mman.h>
|
||||
|
||||
typedef struct {
|
||||
uint64_t pfn : 55;
|
||||
unsigned int soft_dirty : 1;
|
||||
unsigned int file_page : 1;
|
||||
unsigned int swapped : 1;
|
||||
unsigned int present : 1;
|
||||
} PagemapEntry;
|
||||
|
||||
/* Parse the pagemap entry for the given virtual address.
|
||||
*
|
||||
* @param[out] entry the parsed entry
|
||||
* @param[in] pagemap_fd file descriptor to an open /proc/pid/pagemap file
|
||||
* @param[in] vaddr virtual address to get entry for
|
||||
* @return 0 for success, 1 for failure
|
||||
*/
|
||||
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr)
|
||||
{
|
||||
size_t nread;
|
||||
ssize_t ret;
|
||||
uint64_t data;
|
||||
uintptr_t vpn;
|
||||
|
||||
vpn = vaddr / sysconf(_SC_PAGE_SIZE);
|
||||
nread = 0;
|
||||
while (nread < sizeof(data)) {
|
||||
ret = pread(pagemap_fd, ((uint8_t*)&data) + nread, sizeof(data) - nread,
|
||||
vpn * sizeof(data) + nread);
|
||||
nread += ret;
|
||||
if (ret <= 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
entry->pfn = data & (((uint64_t)1 << 55) - 1);
|
||||
entry->soft_dirty = (data >> 55) & 1;
|
||||
entry->file_page = (data >> 61) & 1;
|
||||
entry->swapped = (data >> 62) & 1;
|
||||
entry->present = (data >> 63) & 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert the given virtual address to physical using /proc/PID/pagemap.
|
||||
*
|
||||
* @param[out] paddr physical address
|
||||
* @param[in] pid process to convert for
|
||||
* @param[in] vaddr virtual address to get entry for
|
||||
* @return 0 for success, 1 for failure
|
||||
*/
|
||||
int virt_to_phys_user(uintptr_t *paddr, uintptr_t vaddr)
|
||||
{
|
||||
char pagemap_file[BUFSIZ];
|
||||
int pagemap_fd;
|
||||
|
||||
snprintf(pagemap_file, sizeof(pagemap_file), "/proc/self/pagemap");
|
||||
pagemap_fd = open(pagemap_file, O_RDONLY);
|
||||
if (pagemap_fd < 0) {
|
||||
return 1;
|
||||
}
|
||||
PagemapEntry entry;
|
||||
if (pagemap_get_entry(&entry, pagemap_fd, vaddr)) {
|
||||
return 1;
|
||||
}
|
||||
close(pagemap_fd);
|
||||
*paddr = (entry.pfn * sysconf(_SC_PAGE_SIZE)) + (vaddr % sysconf(_SC_PAGE_SIZE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Allocating 1024 bytes as source\n");
|
||||
uintptr_t src = (uintptr_t)malloc(1024);
|
||||
printf("Virtual address: %lx\n", src);
|
||||
uintptr_t src_phys;
|
||||
virt_to_phys_user(&src_phys, src);
|
||||
printf("Physical address: %lx\n", src_phys);
|
||||
printf("\n\n");
|
||||
|
||||
printf("Allocating 1024 bytes as destination\n");
|
||||
uintptr_t dst = (uintptr_t)malloc(1024);
|
||||
printf("Virtual address: %lx\n", dst);
|
||||
uintptr_t dst_phys;
|
||||
virt_to_phys_user(&dst_phys, dst);
|
||||
printf("Physical address: %lx\n", dst_phys);
|
||||
printf("\n\n");
|
||||
|
||||
printf("mmaping PCIe space\n");
|
||||
// this is hardcoded, seems to be deterministic.
|
||||
uint32_t pcie_physical_base_offset = 0xfe800000;
|
||||
int fd = open("/dev/mem", O_RDWR|O_SYNC);
|
||||
uint32_t* pcie_base = (uint32_t*)mmap(0, 64, PROT_READ|PROT_WRITE, MAP_SHARED, fd, pcie_physical_base_offset);
|
||||
uintptr_t pcie_physical_sanity_check;
|
||||
virt_to_phys_user(&pcie_physical_sanity_check, (uintptr_t)pcie_base);
|
||||
printf("Virtual PCIe Base: %p\n", pcie_base);
|
||||
printf("Physical PCIe Base: %lx\n", pcie_physical_sanity_check);
|
||||
}
|
||||
Reference in New Issue
Block a user