Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
virt2phys.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2019 Paparazzi Team
3 *
4 * This file is part of Paparazzi.
5 *
6 * Paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
36/* Will make the 64 bit interfaces available (off64_t, lseek64(), etc...). See feature_test_macros(7) */
37#define _LARGEFILE64_SOURCE
38
39#include <stdio.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include "virt2phys.h"
43
44#define BIT(i) ((unsigned long long) 1 << i)
45#define FILENAME_SIZE 30
46#define PAGE_SHIFT 12
47#define PAGE_SIZE (1<<PAGE_SHIFT)
48#define PAGE_MASK (((unsigned long long)1<< PAGE_SHIFT) -1)
49
50#define PAGE_PRESENT BIT(63)
51#define PAGE_SWAPPED BIT(62)
52#define PAGE_PFN_MASK (((unsigned long long)1<< 55) -1)
53
54/*
55 * open_pagemap - open pagemap
56 * @param[in] pid: process id of program with pagemap to access
57 * @return file descriptor of pagemap, -1 if unable to open
58 */
59static int open_pagemap(pid_t pid)
60{
62
63 if (snprintf(filename, FILENAME_SIZE, "/proc/%d/pagemap", pid) < 0) {
64 fprintf(stderr, "Cant create file name\n");
65 return -1;
66 }
67
68 return open(filename, O_RDONLY);
69}
70
71/*
72 * virt2phys - Get physical address of virtual memory
73 * @param[in] fd : file descriptor of pagemap
74 * @param[in] vaddr : virtual address
75 * @param[in] *paddr: physical address
76 * @return 0 if successful, -1 otherwise
77 */
78static int virt2phys(int fd, unsigned long vaddr, unsigned long *paddr)
79{
80 unsigned long long pm_info, index;
81
82 index = (vaddr >> PAGE_SHIFT) * sizeof(unsigned long long);
83
84 if ((off64_t)index != lseek64(fd, index, SEEK_SET)) {
85 return -1;
86 }
87
88 /* This read can return 0 if address is not in userspace */
89 if (sizeof(unsigned long long) != read(fd, &pm_info, sizeof(unsigned long long))) {
90 return -1;
91 }
92
93 if ((pm_info & PAGE_PRESENT) && (!(pm_info & PAGE_SWAPPED))) {
94 *paddr = ((pm_info & PAGE_PFN_MASK) << PAGE_SHIFT) + (vaddr & PAGE_MASK);
95 }
96
97 return 0;
98}
99
100/* checkcontiguity - Get information on physical memory associated with virtual address.
101 *
102 * @param[in] vaddr : the virtual address in the context of process pid
103 * @param[in] pid : a valid pid
104 * @param[in] *pmem : Valid only if fonction returns 0.
105 * pmem->paddr contains physical address of the first byte.
106 * pmem->size contains the number of contiguous bytes checked. If size is not zero, buffer is contiguous if pmem->size >= size.
107 * @param[in] size : if size>0 contiguity is checked as far as possible.
108 * : if size=0, check contiguity until at least size bytes had been checked as contiguous.
109 * @return 0 if vaddr can be converted in physical address and -1 otherwise.
110 */
111int check_contiguity(unsigned long vaddr, pid_t pid, struct physmem *pmem, size_t size)
112{
113 int fd;
114 unsigned long vcurrent, pcurrent = 0, pnext;
115
116 pmem->paddr = 0;
117 pmem->size = 0;
118
119 fd = open_pagemap(pid);
120 if (fd < 0) {
121 return -1;
122 }
123
124 /* Get first physical address, it may not be aligned on a page */
125 if (virt2phys(fd, vaddr, &pmem->paddr)) {
126 close(fd);
127 return -1;
128 }
129
130 pmem->size = PAGE_SIZE - (pmem->paddr & PAGE_MASK);
131 /* We aligned addresses on pages */
133 pnext = (pmem->paddr & ~PAGE_MASK) + PAGE_SIZE;
134
135 while (1) {
136 /* exit if we had checked the requested bytes */
137 if (size && (pmem->size >= size)) {
138 break;
139 }
140
142 if (virt2phys(fd, vcurrent, &pcurrent)) {
143 break;
144 }
145
146 /* Test if memory is still contiguous */
147 if (pcurrent == pnext) {
148 pmem->size += PAGE_SIZE;
149 pnext += PAGE_SIZE;
150 } else {
151 break;
152 }
153 }
154 close(fd);
155
156 return 0;
157}
uint16_t foo
Definition main_demo5.c:58
int fd
Definition serial.c:26
#define FILENAME_SIZE
Definition virt2phys.c:45
#define PAGE_PRESENT
Definition virt2phys.c:50
#define PAGE_PFN_MASK
Definition virt2phys.c:52
static int virt2phys(int fd, unsigned long vaddr, unsigned long *paddr)
Definition virt2phys.c:78
#define PAGE_SIZE
Definition virt2phys.c:47
#define PAGE_SHIFT
Definition virt2phys.c:46
#define PAGE_SWAPPED
Definition virt2phys.c:51
int check_contiguity(unsigned long vaddr, pid_t pid, struct physmem *pmem, size_t size)
Definition virt2phys.c:111
static int open_pagemap(pid_t pid)
Definition virt2phys.c:59
#define PAGE_MASK
Definition virt2phys.c:48