#define __rte_cache_aligned __attribute__((__aligned__(CACHE_LINE_SIZE)))
typedef uint64_t phys_addr_t; /**< Physical address definition. */
+#define RTE_BAD_PHYS_ADDR ((phys_addr_t)-1)
/**
* Physical memory segment descriptor.
#endif
} __attribute__((__packed__));
+/**
+ * Lock page in physical memory and prevent from swapping.
+ *
+ * @param virt
+ * The virtual address.
+ * @return
+ * 0 on success, negative on error.
+ */
+int rte_mem_lock_page(const void *virt);
+
+/**
+ * Get physical address of any mapped virtual address in the current process.
+ * It is found by browsing the /proc/self/pagemap special file.
+ * The page must be locked.
+ *
+ * @param virt
+ * The virtual address.
+ * @return
+ * The physical address or RTE_BAD_PHYS_ADDR on error.
+ */
+phys_addr_t rte_mem_virt2phy(const void *virt);
/**
* Get the layout of the available physical memory.
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#define RANDOMIZE_VA_SPACE_FILE "/proc/sys/kernel/randomize_va_space"
-static uint64_t
-get_physaddr(void * virtaddr)
+/* Lock page in physical memory and prevent from swapping. */
+int
+rte_mem_lock_page(const void *virt)
+{
+ unsigned long virtual = (unsigned long)virt;
+ int page_size = getpagesize();
+ unsigned long aligned = (virtual & ~ (page_size - 1));
+ return mlock((void*)aligned, page_size);
+}
+
+/*
+ * Get physical address of any mapped virtual address in the current process.
+ */
+phys_addr_t
+rte_mem_virt2phy(const void *virtaddr)
{
int fd;
uint64_t page, physaddr;
if (fd < 0) {
RTE_LOG(ERR, EAL, "%s(): cannot open /proc/self/pagemap: %s\n",
__func__, strerror(errno));
- return (uint64_t) -1;
+ return RTE_BAD_PHYS_ADDR;
}
off_t offset;
RTE_LOG(ERR, EAL, "%s(): seek error in /proc/self/pagemap: %s\n",
__func__, strerror(errno));
close(fd);
- return (uint64_t) -1;
+ return RTE_BAD_PHYS_ADDR;
}
if (read(fd, &page, sizeof(uint64_t)) < 0) {
RTE_LOG(ERR, EAL, "%s(): cannot read /proc/self/pagemap: %s\n",
__func__, strerror(errno));
close(fd);
- return (uint64_t) -1;
+ return RTE_BAD_PHYS_ADDR;
}
/*
* the pfn (page frame number) are bits 0-54 (see
* pagemap.txt in linux Documentation)
*/
- physaddr = ((page & 0x7fffffffffffffULL) * page_size);
+ physaddr = ((page & 0x7fffffffffffffULL) * page_size)
+ + ((unsigned long)virtaddr % page_size);
close(fd);
return physaddr;
}
phys_addr_t addr;
for (i = 0; i < hpi->num_pages[0]; i++) {
- addr = get_physaddr(hugepg_tbl[i].orig_va);
- if (addr == (phys_addr_t) -1)
+ addr = rte_mem_virt2phy(hugepg_tbl[i].orig_va);
+ if (addr == RTE_BAD_PHYS_ADDR)
return -1;
hugepg_tbl[i].physaddr = addr;
}
rte_snprintf(hugepg_tbl[page_idx].filepath, MAX_HUGEPAGE_PATH, "%s",
filepath);
- physaddr = get_physaddr(vma_addr);
+ physaddr = rte_mem_virt2phy(vma_addr);
- if (physaddr == (phys_addr_t) -1)
+ if (physaddr == RTE_BAD_PHYS_ADDR)
return -1;
hugepg_tbl[page_idx].final_va = vma_addr;
expected_physaddr = hugepg_tbl[page_idx].physaddr + offset;
page_addr = RTE_PTR_ADD(vma_addr, offset);
- physaddr = get_physaddr(page_addr);
+ physaddr = rte_mem_virt2phy(page_addr);
if (physaddr != expected_physaddr) {
RTE_LOG(ERR, EAL, "Segment sanity check failed: wrong physaddr "