/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
/* Copyright (C) 2014 OSCAR lab, Stony Brook University
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
/*
* db_ipc.c
*
* This file contains APIs for physical memory bulk copy across processes.
*/
#include "pal_defs.h"
#include "pal_linux_defs.h"
#include "pal.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_error.h"
#include "pal_security.h"
#include "graphene-ipc.h"
#include "api.h"
#include
#include
int gipc_open (PAL_HANDLE * handle, const char * type, const char * uri,
int access, int share, int create, int options)
{
int64_t token;
int rv;
int fd = INLINE_SYSCALL(open, 3, GIPC_FILE, O_RDONLY|O_CLOEXEC, 0);
if (IS_ERR(fd))
return -PAL_ERROR_DENIED;
token = atoi(uri);
rv = INLINE_SYSCALL(ioctl, 3, fd, GIPC_JOIN, token);
if (rv < 0) {
INLINE_SYSCALL(close, 1, fd);
return -PAL_ERROR_DENIED;
}
PAL_HANDLE hdl = malloc(HANDLE_SIZE(gipc));
SET_HANDLE_TYPE(hdl, gipc);
hdl->gipc.fd = fd;
*handle = hdl;
return 0;
}
int gipc_close (PAL_HANDLE handle)
{
int ret = INLINE_SYSCALL(close, 1, handle->gipc.fd);
if (IS_ERR(ret))
return -PAL_ERROR_BADHANDLE;
return 0;
}
const char * gipc_getrealpath (PAL_HANDLE handle)
{
return GIPC_FILE;
}
struct handle_ops gipc_ops = {
.getrealpath = &gipc_getrealpath,
.open = &gipc_open,
.close = &gipc_close,
};
int _DkCreatePhysicalMemoryChannel (PAL_HANDLE * handle, unsigned long * key)
{
store_frame(CreatePhysicalMemoryChannel);
unsigned long token = 0;
int fd = INLINE_SYSCALL(open, 3, GIPC_FILE, O_RDONLY|O_CLOEXEC, 0);
if (IS_ERR(fd))
goto err;
PAL_HANDLE hdl = malloc(HANDLE_SIZE(gipc));
SET_HANDLE_TYPE(hdl, gipc);
hdl->gipc.fd = fd;
// ioctl to create a new queue
token = INLINE_SYSCALL(ioctl, 3, fd, GIPC_CREATE, 0);
if (token < 0)
goto err_fd;
*handle = hdl;
*key = token;
return 0;
err_fd:
INLINE_SYSCALL(close, 1, fd);
err:
return -PAL_ERROR_DENIED;
}
int _DkPhysicalMemoryCommit (PAL_HANDLE channel, int entries, void ** addrs,
unsigned long * sizes, int flags)
{
int fd = channel->gipc.fd;
struct gipc_send gs;
int nsent = 0, n;
unsigned long npagesent = 0;
while (nsent < entries) {
n = entries - nsent;
if (n > ADDR_ENTS)
n = ADDR_ENTS;
gs.entries = n;
gs.addr = (unsigned long *) (addrs + nsent);
gs.len = (unsigned long *) (sizes + nsent);
int ret = INLINE_SYSCALL(ioctl, 3, fd, GIPC_SEND, &gs);
if (IS_ERR(ret)) {
if (!npagesent)
return -PAL_ERROR_DENIED;
return npagesent;
}
npagesent += ret;
nsent += n;
}
return npagesent;
}
int _DkPhysicalMemoryMap (PAL_HANDLE channel, int entries, void ** addrs,
unsigned long * sizes, unsigned int * prots)
{
int fd = channel->gipc.fd;
struct gipc_recv gr;
int nrecv = 0, n;
unsigned long npagerecv = 0;
while (nrecv < entries) {
n = entries - nrecv;
if (n > ADDR_ENTS)
n = ADDR_ENTS;
gr.entries = n;
gr.addr = (unsigned long *) (addrs + nrecv);
gr.len = (unsigned long *) (sizes + nrecv);
gr.prot = (int *) (prots + nrecv);
int ret = INLINE_SYSCALL(ioctl, 3, fd, GIPC_RECV, &gr);
if (IS_ERR(ret)) {
if (!npagerecv)
return -PAL_ERROR_DENIED;
return npagerecv;
}
npagerecv += ret;
nrecv += n;
}
return npagerecv;
}