aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/odp_ishmphy.c
blob: 046b254c3886572c7431b7ee6eac35ed73f4b5e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright (c) 2016-2018 Linaro Limited
 */

/*
 * This file handles the lower end of the ishm memory allocator:
 * It performs the physical mappings.
 */
#include <odp_posix_extensions.h>
#include <odp_config_internal.h>
#include <odp/api/align.h>
#include <odp/api/system_info.h>
#include <odp/api/debug.h>
#include <odp_debug_internal.h>
#include <odp_shm_internal.h>
#include <odp_ishmphy_internal.h>

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <inttypes.h>
#include <odp_ishmphy_internal.h>

static void *common_va_address;
static uint64_t common_va_len;

#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif

/* Reserve single VA memory
 * This function is called at odp_init_global() time to pre-reserve some memory
 * which is inherited by all odpthreads (i.e. descendant processes and threads).
 * This memory block is later used when memory is reserved with
 * _ODP_ISHM_SINGLE_VA flag.
 * returns the address of the mapping or NULL on error.
 */
void *_odp_ishmphy_reserve_single_va(uint64_t len, int fd)
{
	void *addr;

	addr = mmap(NULL, len, PROT_READ | PROT_WRITE,
		    MAP_SHARED | MAP_POPULATE, fd, 0);
	if (addr == MAP_FAILED) {
		_ODP_ERR("mmap failed: %s\n", strerror(errno));
		return NULL;
	}

	if (mprotect(addr, len, PROT_READ | PROT_WRITE))
		_ODP_ERR("mprotect failed: %s\n", strerror(errno));

	_ODP_DBG("VA Reserved: %p, len=%" PRIu64 "\n", addr, len);

	common_va_address = addr;
	common_va_len	  = len;

	return addr;
}

/* Free single VA memory
 * This function is called at odp_term_global() time to free the memory reserved
 * by _odp_ishmphy_reserve_single_va()
 */
int _odp_ishmphy_free_single_va(void)
{
	int ret;

	if (!common_va_address)
		return 0;

	ret = munmap(common_va_address, common_va_len);
	if (ret)
		_ODP_ERR("munmap failed: %s\n", strerror(errno));
	return ret;
}

/*
 * do a mapping:
 * Performs a mapping of the provided file descriptor to the process VA
 * space. Not to be used with _ODP_ISHM_SINGLE_VA blocks.
 * returns the address of the mapping or NULL on error.
 */
void *_odp_ishmphy_map(int fd, uint64_t size, uint64_t offset, int flags)
{
	void *mapped_addr;
	int mmap_flags = MAP_POPULATE;

	_ODP_ASSERT(!(flags & _ODP_ISHM_SINGLE_VA));

	/* do a new mapping in the VA space: */
	mapped_addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
			   MAP_SHARED | mmap_flags, fd, offset);
	if ((mapped_addr >= common_va_address) &&
	    ((char *)mapped_addr <
		(char *)common_va_address + common_va_len)) {
		_ODP_ERR("VA SPACE OVERLAP!\n");
	}

	if (mapped_addr == MAP_FAILED)
		return NULL;

	/* if locking is requested, lock it...*/
	if (flags & _ODP_ISHM_LOCK) {
		if (mlock(mapped_addr, size)) {
			_ODP_ERR("mlock failed: %s\n", strerror(errno));
			if (munmap(mapped_addr, size))
				_ODP_ERR("munmap failed: %s\n", strerror(errno));
			return NULL;
		}
	}
	return mapped_addr;
}

/* free a mapping:
 * _ODP_ISHM_SINGLE_VA memory is not returned back to linux until global
 * terminate. If the _ODP_ISHM_SINGLE_VA flag was not given, both physical
 * memory and virtual address space are released by calling the normal munmap.
 * return 0 on success or -1 on error.
 */
int _odp_ishmphy_unmap(void *start, uint64_t len, int flags)
{
	int ret;

	/* if locking was requested, unlock...*/
	if (flags & _ODP_ISHM_LOCK)
		munlock(start, len);

	if (flags & _ODP_ISHM_SINGLE_VA)
		return 0;

	/* just release the mapping */
	ret = munmap(start, len);
	if (ret)
		_ODP_ERR("munmap failed: %s\n", strerror(errno));
	return ret;
}