From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-bk0-x22d.google.com (mail-bk0-x22d.google.com [IPv6:2a00:1450:4008:c01::22d]) by dpdk.org (Postfix) with ESMTP id 0E703532D for ; Wed, 12 Jun 2013 09:50:15 +0200 (CEST) Received: by mail-bk0-f45.google.com with SMTP id je9so2841155bkc.4 for ; Wed, 12 Jun 2013 00:50:20 -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:x-gm-message-state; bh=85DCJqHiTT0ki2T4HX0xqmbMZvFyrH1hpt5wffxxFj8=; b=DzRe8D9zUeoHQjqJFke0Ke4bjEo25KTPp17JRrV6aoDzh0aSsnbQkbzAH67kKgp/c9 cOMe8QCOljlJebtpbYnKoCQfd0LgF6Vm34bVUNVVnQyoXOXqswZBhz9q6xT9cNkMvNmi rEnD2iztUQj/raePHhXQANZEoZIIVZA2mj1HPsoFCcazVejqQ2KZS1zjVvqBfZFQROev jcr1uldXi7bZXhkV7gGZ/16eOTjonqoDzVI2tcAeL1I0j0fB+ep3ng7YQ1MXzW0/SEfV Pw1rclsULudeuw2InlqS9q7PA4shT7+g+ZaOZoHw5nETE8Nb8uOyY4ZUc8lg+KCzCK0G uClw== X-Received: by 10.205.40.68 with SMTP id tp4mr2916007bkb.175.1371023420130; Wed, 12 Jun 2013 00:50:20 -0700 (PDT) Received: from 6wind.com (6wind.net2.nerim.net. [213.41.180.237]) by mx.google.com with ESMTPSA id so13sm6946601bkb.15.2013.06.12.00.50.17 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 12 Jun 2013 00:50:19 -0700 (PDT) Received: by 6wind.com (sSMTP sendmail emulation); Wed, 12 Jun 2013 09:50:20 +0200 From: Thomas Monjalon To: dev@dpdk.org Date: Wed, 12 Jun 2013 09:50:20 +0200 Message-Id: <1371023420-23195-1-git-send-email-thomas.monjalon@6wind.com> X-Mailer: git-send-email 1.7.10.4 X-Gm-Message-State: ALoCoQlymkjBu34mEdwTJkPJ2xqhxPNpiaTcEimNINR1LNOK5oYaUdjs3ceJnCQKXpwRB1bOrjVG 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 07:50:16 -0000 From: Damien Millescamps Extract rte_mem_virt2phy() from find_physaddr(). This function 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. Signed-off-by: Damien Millescamps Signed-off-by: Thomas Monjalon --- lib/librte_eal/common/include/rte_memory.h | 7 +++ lib/librte_eal/linuxapp/eal/eal_memory.c | 83 +++++++++++++++------------- 2 files changed, 52 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..eaf4cc9 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,12 @@ struct rte_memseg { uint32_t nrank; /**< Number of ranks. */ } __attribute__((__packed__)); +/** + * 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 won't be swappable anymore. + */ +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..f1dd2e9 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 @@ -266,53 +267,59 @@ unmap_all_hugepages_orig(struct hugepage *hugepg_tbl, struct hugepage_info *hpi) } /* - * 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(); + unsigned long aligned = (virtual & ~ (page_size - 1)); + + /* allocate page in physical memory and prevent from swapping */ + mlock((void*)aligned, page_size); + + 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