Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux system internal refactoring #288

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions lib/system/linux/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,8 +592,6 @@ static int metal_linux_probe_driver(struct linux_bus *lbus,
return ldrv->sdrv ? 0 : -ENODEV;
}

static void metal_linux_bus_close(struct metal_bus *bus);

static int metal_linux_probe_bus(struct linux_bus *lbus)
{
struct linux_driver *ldrv;
Expand Down
12 changes: 1 addition & 11 deletions lib/system/linux/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static int metal_init_page_sizes(void)
sizes[0] = getpagesize();
if (sizes[0] <= 0) {
metal_log(METAL_LOG_ERROR, "failed to get page size\n");
return -ENOSYS;
return -EINVAL;
}
_metal.page_size = sizes[0];
_metal.page_shift = metal_log2(sizes[0]);
Expand Down Expand Up @@ -109,21 +109,11 @@ static int metal_init_page_sizes(void)

int metal_sys_init(const struct metal_init_params *params)
{
static char sysfs_path[SYSFS_PATH_MAX];
const char *tmp_path;
unsigned int seed;
FILE *urandom;
int result;

/* Determine sysfs mount point. */
result = sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path));
if (result) {
metal_log(METAL_LOG_ERROR, "failed to get sysfs path (%s)\n",
strerror(-result));
return result;
}
_metal.sysfs_path = sysfs_path;

/* Find the temporary directory location. */
tmp_path = getenv("TMPDIR");
if (!tmp_path)
Expand Down
32 changes: 30 additions & 2 deletions lib/system/linux/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@ static const struct metal_io_ops metal_shmem_io_ops = {
NULL, NULL, NULL, NULL, NULL, metal_shmem_io_close, NULL, NULL
};

static int metal_virt2phys(void *addr, unsigned long *phys)
{
off_t offset;
uint64_t entry;
int error;

if (_metal.pagemap_fd < 0)
return -EINVAL;

offset = ((uintptr_t)addr >> _metal.page_shift) * sizeof(entry);
error = pread(_metal.pagemap_fd, &entry, sizeof(entry), offset);
if (error < 0) {
metal_log(METAL_LOG_ERROR, "failed pagemap pread (offset %llx) - %s\n",
(unsigned long long)offset, strerror(errno));
return -errno;
}

/* Check page present and not swapped. */
if ((entry >> 62) != 2) {
metal_log(METAL_LOG_ERROR, "pagemap page not present, %llx -> %llx\n",
(unsigned long long)offset, (unsigned long long)entry);
return -ENOENT;
}

*phys = (entry & ((1ULL << 54) - 1)) << _metal.page_shift;
return 0;
}

static int metal_shmem_try_map(struct metal_page_size *ps, int fd, size_t size,
struct metal_io_region **result)
{
Expand All @@ -49,10 +77,10 @@ static int metal_shmem_try_map(struct metal_page_size *ps, int fd, size_t size,
return error;
}

error = metal_mlock(mem, size);
error = mlock(mem, size);
if (error) {
metal_log(METAL_LOG_WARNING, "failed to mlock shmem - %s\n",
strerror(-error));
strerror(errno));
}

phys_size = sizeof(*phys) * pages;
Expand Down
12 changes: 0 additions & 12 deletions lib/system/linux/sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ struct metal_state {
/** system page shift. */
unsigned long page_shift;

/** sysfs mount point. */
const char *sysfs_path;

/** sysfs mount point. */
const char *tmp_path;

Expand All @@ -99,19 +96,10 @@ int metal_linux_bus_init(void);
void metal_linux_bus_finish(void);

int metal_open(const char *path, int shm);
int metal_open_unlinked(const char *path, int shm);
int metal_mktemp(char *template, int fifo);
int metal_mktemp_unlinked(char *template);

int metal_map(int fd, off_t offset, size_t size, int expand,
int flags, void **result);
int metal_unmap(void *mem, size_t size);
int metal_mlock(void *mem, size_t size);

void metal_randomize_string(char *template);
void metal_mktemp_template(char template[PATH_MAX],
const char *name);
int metal_virt2phys(void *addr, unsigned long *phys);

/**
* @brief Read a device tree property of a device
Expand Down
189 changes: 0 additions & 189 deletions lib/system/linux/utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,155 +35,6 @@ int metal_open(const char *path, int shm)
return fd < 0 ? -errno : fd;
}

/**
* @brief Open (or create) and unlink a file.
*
* This function opens or creates a file with read/write permissions and the
* O_CLOEXEC flag set. This file is then unlinked to ensure that it is removed
* when the last reference to the file is dropped. This ensures that libmetal
* shared maps are released appropriately once all users of the shared data
* exit.
*
* @param[in] path File path to open.
* @param[in] shm Open shared memory (via shm_open) if non-zero.
* @return File descriptor.
*/
int metal_open_unlinked(const char *path, int shm)
{
int fd, error;

fd = metal_open(path, shm);
if (fd < 0)
return fd;

error = shm ? shm_unlink(path) : unlink(path);
error = error < 0 ? -errno : 0;
if (error)
close(fd);

return error ? error : fd;
}

/**
* @brief Randomize a string.
*
* This function randomizes the contents of a string.
*
* @param[in] template String to be randomized.
*/
void metal_randomize_string(char *template)
{
const char *chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-=";
while (*template) {
*template++ = chars[rand() % 64];
}
}

/**
* @brief Create a file name template suitable for use with metal_mktemp.
*
* @param[out] template Template string to be filled in.
* @param[in] name Module/user identifier used as part of the
* generated template.
*/
void metal_mktemp_template(char template[PATH_MAX], const char *name)
{
snprintf(template, PATH_MAX, "%s/metal-%s-XXXXXX",
_metal.tmp_path, name);
}

/**
* @brief Create a temporary file or fifo.
*
* This function creates a temporary file or fifo, and sets the O_CLOEXEC flag
* on it.
*
* @param[in] template File name template (the last 6 characters must
* be XXXXXX per mkstemp requirements).
* @param[in] fifo Non-zero to create a FIFO instead of a regular
* file.
* @return File descriptor.
*/
int metal_mktemp(char *template, int fifo)
{
const int mode = S_IRUSR | S_IWUSR;
int result, len, flags;
char *suffix;

if (!template)
return -EINVAL;

len = strlen(template);
suffix = &template[len - 6];
if (len < 6 || strcmp(suffix, "XXXXXX")) {
metal_log(METAL_LOG_ERROR, "template %s has no trailing pattern\n",
template);
return -EINVAL;
}

flags = (fifo
? O_RDONLY | O_NONBLOCK | O_CLOEXEC
: O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC);

for (;;) {
metal_randomize_string(suffix);
if (fifo) {
result = mkfifo(template, mode);
if (result < 0) {
if (errno == EEXIST)
continue;
metal_log(METAL_LOG_ERROR,
"mkfifo(%s) failed (%s)\n",
template, strerror(errno));
return -errno;
}
}

result = open(template, flags, mode);
if (result < 0) {
if (fifo)
unlink(template);
if (errno == EEXIST)
continue;
metal_log(METAL_LOG_ERROR, "open() failed (%s)\n",
strerror(errno));
return -errno;
}

return result;
}
}

/**
* @brief Open (or create) and unlink a temporary file.
*
* This function creates a temporary file, and sets the O_CLOEXEC flag on it.
* O_CLOEXEC flag set. This file is then unlinked to ensure that it is removed
* when the last reference to the file is dropped. This ensures that libmetal
* shared maps are released appropriately once all users of the shared data
* exit.
*
* @param[in] template File name template (the last 6 characters must
* be XXXXXX per mkstemp requirements).
* @return File descriptor.
*/
int metal_mktemp_unlinked(char *template)
{
int fd, error;

fd = metal_mktemp(template, 0);
if (fd < 0)
return fd;

error = unlink(template) < 0 ? -errno : 0;
if (error)
close(fd);

return error ? error : fd;
}

/**
* @brief Map a segment of a file/device.
*
Expand Down Expand Up @@ -247,43 +98,3 @@ int metal_unmap(void *mem, size_t size)
{
return munmap(mem, size) < 0 ? -errno : 0;
}

/**
* @brief Lock in a region of the process address space.
*
* @param[in] mem Pointer to start of region.
* @param[in] size Size of region.
* @return 0 on success, or -errno on error.
*/
int metal_mlock(void *mem, size_t size)
{
return mlock(mem, size) ? -errno : 0;
}

int metal_virt2phys(void *addr, unsigned long *phys)
{
off_t offset;
uint64_t entry;
int error;

if (_metal.pagemap_fd < 0)
return -ENOSYS;

offset = ((uintptr_t)addr >> _metal.page_shift) * sizeof(entry);
error = pread(_metal.pagemap_fd, &entry, sizeof(entry), offset);
if (error < 0) {
metal_log(METAL_LOG_ERROR, "failed pagemap pread (offset %llx) - %s\n",
(unsigned long long)offset, strerror(errno));
return -errno;
}

/* Check page present and not swapped. */
if ((entry >> 62) != 2) {
metal_log(METAL_LOG_ERROR, "pagemap page not present, %llx -> %llx\n",
(unsigned long long)offset, (unsigned long long)entry);
return -ENOENT;
}

*phys = (entry & ((1ULL << 54) - 1)) << _metal.page_shift;
return 0;
}
Loading