From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wg0-x22d.google.com (mail-wg0-x22d.google.com [IPv6:2a00:1450:400c:c00::22d]) by dpdk.org (Postfix) with ESMTP id 37097532D for ; Wed, 12 Jun 2013 17:24:42 +0200 (CEST) Received: by mail-wg0-f45.google.com with SMTP id j13so1701210wgh.0 for ; Wed, 12 Jun 2013 08:24:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=5jVbodGCnvJ1NVF2jof+qXgc3p74z/m7xJxTCi8OQc0=; b=o4Me9tb+E0fGK496V8TW7yiO1zpmbR+y6wyuemnNTEvrLtoao0lu8ok2l4QRPXWguy AMu8yewV6ldiAFIy0Hzn9mO+r8UZRBtK386swSWhgfutNJKh8WSKV62LcdH9fvaQIfBC 3PajG1WV4UCAD0X1IvvNLMsVDUmkbiI+oXqZDnWPH1xpK/GcZD/v8hIxh9Vhr1DA4j4n iQsSnNbJzps6n0+1Pq12agR5Me7yTr0qGR+zSSfLKJD/5kNl2smerrA2vATK8lNKPB7q pguXFaVscxIhUPp6rACKlPftDPV08M8WIqFVD3TYzzF7iReF/UGPBPCNOl3y8YN8hdrA 1YOA== X-Received: by 10.194.123.69 with SMTP id ly5mr12337194wjb.29.1371050692011; Wed, 12 Jun 2013 08:24:52 -0700 (PDT) Received: from 6wind.com (6wind.net2.nerim.net. [213.41.180.237]) by mx.google.com with ESMTPSA id fu14sm25338650wic.0.2013.06.12.08.24.49 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 12 Jun 2013 08:24:51 -0700 (PDT) Received: by 6wind.com (sSMTP sendmail emulation); Wed, 12 Jun 2013 17:24:52 +0200 From: Thomas Monjalon To: dev@dpdk.org Date: Wed, 12 Jun 2013 17:24:52 +0200 Message-Id: <1371050692-16945-1-git-send-email-thomas.monjalon@6wind.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <51B8617B.7000009@6wind.com> References: <51B8617B.7000009@6wind.com> X-Gm-Message-State: ALoCoQn3WqkAgQyeNOQhPrVakfiFZeSiK6G7QMs5T4f77DiFF+IJT0tQWrPsEF6PCag5OTbCUk3s Subject: [dpdk-dev] [PATCH] mem: get physical address of any pointer X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Jun 2013 15:24:42 -0000 From: Damien Millescamps Extract rte_mem_virt2phy() from find_physaddr(). rte_mem_virt2phy() permits to obtain the physical address of any virtual address mapped to the current process calling this function. Note that this function is very slow and shouldn't be called after initialization to avoid a performance bottleneck. The memory must be locked with mlock(). The function rte_mem_lock_page() is a mlock() helper that lock the whole page. A better name would be rte_mem_virt2phys but rte_mem_virt2phy is more consistent with rte_mempool_virt2phy. Signed-off-by: Damien Millescamps Signed-off-by: Thomas Monjalon --- lib/librte_eal/common/include/rte_memory.h | 22 +++++++ lib/librte_eal/linuxapp/eal/eal_memory.c | 89 ++++++++++++++++------------ 2 files changed, 73 insertions(+), 38 deletions(-) diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h index bf843dc..d9d368b 100644 --- a/lib/librte_eal/common/include/rte_memory.h +++ b/lib/librte_eal/common/include/rte_memory.h @@ -70,6 +70,7 @@ enum rte_page_sizes { #ifndef __KERNEL__ /* so we can include this header in kernel modules */ typedef uint64_t phys_addr_t; /**< Physical address definition. */ #endif +#define RTE_BAD_PHYS_ADDR ((phys_addr_t)-1) /** * Physical memory segment descriptor. @@ -87,6 +88,27 @@ struct rte_memseg { uint32_t nrank; /**< Number of ranks. */ } __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. diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c index 30a955f..82467f3 100644 --- a/lib/librte_eal/linuxapp/eal/eal_memory.c +++ b/lib/librte_eal/linuxapp/eal/eal_memory.c @@ -34,6 +34,7 @@ * version: DPDK.L.1.2.3-3 */ +#define _FILE_OFFSET_BITS 64 #include #include #include @@ -265,54 +266,66 @@ unmap_all_hugepages_orig(struct hugepage *hugepg_tbl, struct hugepage_info *hpi) return 0; } +/* 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); +} + /* - * For each hugepage in hugepg_tbl, fill the physaddr value. We find - * it by browsing the /proc/self/pagemap special file. + * Get physical address of any mapped virtual address in the current process. */ -static int -find_physaddr(struct hugepage *hugepg_tbl, struct hugepage_info *hpi) +phys_addr_t +rte_mem_virt2phy(const void *virt) { - int fd; - unsigned i; + int fdmem; uint64_t page; - unsigned long virt_pfn; - int page_size; + off_t offset; + unsigned long virtual = (unsigned long)virt; + int page_size = getpagesize(); + + fdmem = open("/proc/self/pagemap", O_RDONLY); + if (fdmem < 0) { + RTE_LOG(ERR, EAL, "%s(): cannot open /proc/self/pagemap: %s\n", + __func__, strerror(errno)); + return RTE_BAD_PHYS_ADDR; + } + offset = (off_t) (virtual / page_size) * sizeof(uint64_t); + if (lseek(fdmem, offset, SEEK_SET) == (off_t) -1) { + RTE_LOG(ERR, EAL, "%s(): seek error in /proc/self/pagemap: %s\n", + __func__, strerror(errno)); + close(fdmem); + return RTE_BAD_PHYS_ADDR; + } + if (read(fdmem, &page, sizeof(uint64_t)) <= 0) { + RTE_LOG(ERR, EAL, "%s(): cannot read /proc/self/pagemap: %s\n", + __func__, strerror(errno)); + close(fdmem); + return RTE_BAD_PHYS_ADDR; + } + close (fdmem); - /* standard page size */ - page_size = getpagesize(); + /* pfn (page frame number) are bits 0-54 (see pagemap.txt in Linux doc) */ + return ((page & 0x7fffffffffffffULL) * page_size) + (virtual % page_size); +} - fd = open("/proc/self/pagemap", O_RDONLY); - if (fd < 0) { - RTE_LOG(ERR, EAL, "%s(): cannot open /proc/self/pagemap: %s", - __func__, strerror(errno)); - return -1; - } +/* + * For each hugepage in hugepg_tbl, fill the physaddr value. + */ +static int +find_physaddr(struct hugepage *hugepg_tbl, struct hugepage_info *hpi) +{ + unsigned i; for (i = 0; i < hpi->num_pages; i++) { - off_t offset; - virt_pfn = (unsigned long)hugepg_tbl[i].orig_va / - page_size; - offset = sizeof(uint64_t) * virt_pfn; - if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { - RTE_LOG(ERR, EAL, "%s(): seek error in /proc/self/pagemap: %s", - __func__, strerror(errno)); - close(fd); - return -1; - } - if (read(fd, &page, sizeof(uint64_t)) < 0) { - RTE_LOG(ERR, EAL, "%s(): cannot read /proc/self/pagemap: %s", - __func__, strerror(errno)); - close(fd); + hugepg_tbl[i].physaddr = rte_mem_virt2phy(hugepg_tbl[i].orig_va); + if (hugepg_tbl[i].physaddr == RTE_BAD_PHYS_ADDR) return -1; - } - - /* - * the pfn (page frame number) are bits 0-54 (see - * pagemap.txt in linux Documentation) - */ - hugepg_tbl[i].physaddr = ((page & 0x7fffffffffffffULL) * page_size); } - close(fd); return 0; } -- 1.7.10.4