mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-28 12:34:26 +01:00
Factor common userland and baremetal C functions
This allows add.c to run unmodified on both! For that to work, use int main on baremetal, and pass the return value to the final exit.
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <fcntl.h> /* open */
|
||||
#include <math.h> /* fabs */
|
||||
#include <stdint.h> /* uint64_t */
|
||||
#include <stdlib.h> /* size_t */
|
||||
#include <stdio.h> /* snprintf */
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h> /* pread, sysconf */
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Format documented at:
|
||||
* https://github.com/torvalds/linux/blob/v4.9/Documentation/vm/pagemap.txt
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t pfn : 54;
|
||||
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,
|
||||
&data,
|
||||
sizeof(data) - nread,
|
||||
vpn * sizeof(data) + nread
|
||||
);
|
||||
nread += ret;
|
||||
if (ret <= 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
entry->pfn = data & (((uint64_t)1 << 54) - 1);
|
||||
entry->soft_dirty = (data >> 54) & 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, pid_t pid, uintptr_t vaddr)
|
||||
{
|
||||
char pagemap_file[BUFSIZ];
|
||||
int pagemap_fd;
|
||||
|
||||
snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%ju/pagemap", (uintmax_t)pid);
|
||||
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;
|
||||
}
|
||||
|
||||
bool common_vector_equal(size_t n, double * v1, double * v2, double max_err)
|
||||
{
|
||||
double sum = 0.0;
|
||||
double diff;
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
diff = v1[i] - v2[i];
|
||||
sum += diff * diff;
|
||||
}
|
||||
if (sqrt(sum)/n > max_err)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user