blob: e4b0b319d03b1d5b694da2da04d94975bc219227 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define TLOG_TAG "coverage-common-shm"
#include <assert.h>
#include <lib/coverage/common/shm.h>
#include <lk/macros.h>
#include <memref.h>
#include <stdlib.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <trusty_log.h>
#include <uapi/err.h>
#define PAGE_SIZE getauxval(AT_PAGESZ)
#define MMAP_FLAG_PROT_RW (MMAP_FLAG_PROT_READ | MMAP_FLAG_PROT_WRITE)
int shm_alloc(struct shm* shm, size_t len) {
int rc;
void* base;
size_t shm_len;
shm_len = round_up(len, PAGE_SIZE);
base = memalign(PAGE_SIZE, shm_len);
if (!base) {
TLOGE("failed to allocate %zu bytes of shared memory\n", shm_len);
return ERR_NO_MEMORY;
}
rc = memref_create(base, shm_len, MMAP_FLAG_PROT_RW);
if (rc < 0) {
TLOGE("failed (%d) to create memref\n", rc);
free(shm);
return rc;
}
shm->memref = (handle_t)rc;
shm->base = base;
shm->len = shm_len;
shm_clear(shm);
return NO_ERROR;
}
void shm_free(struct shm* shm) {
/*
* TODO: HACK: No way to safely deallocate memory that has already been
* shared, but works in practice.
*/
free(shm->base);
close(shm->memref);
shm->memref = INVALID_IPC_HANDLE;
shm->base = NULL;
shm->len = 0;
}
int shm_mmap(struct shm* shm, handle_t memref, size_t len) {
void* base = mmap(0, len, MMAP_FLAG_PROT_RW, 0, memref, 0);
if (base == MAP_FAILED) {
TLOGE("failed to mmap() shared memory\n");
return ERR_BAD_HANDLE;
}
shm->memref = memref;
shm->base = base;
shm->len = len;
return NO_ERROR;
}
void shm_munmap(struct shm* shm) {
assert(shm_is_mapped(shm));
munmap(shm->base, shm->len);
close(shm->memref);
shm->memref = INVALID_IPC_HANDLE;
shm->base = NULL;
shm->len = 0;
}
void shm_clear(struct shm* shm) {
assert(shm_is_mapped(shm));
for (size_t i = 0; i < shm->len; i++) {
WRITE_ONCE(*((uint8_t*)(shm->base) + i), 0);
}
}