hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
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
/*
 * Copyright (C) 2009 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <rtdm/rtdm.h>
#include <cobalt/uapi/kernel/heap.h>
#include <asm/xenomai/syscall.h>
#include "current.h"
#include "umm.h"
#include "internal.h"
 
struct xnvdso *cobalt_vdso;
 
void *cobalt_umm_private = NULL;
 
void *cobalt_umm_shared = NULL;
 
static pthread_once_t init_bind_once = PTHREAD_ONCE_INIT;
 
static uint32_t private_size;
 
static void *__map_umm(const char *name, uint32_t *size_r)
{
   struct cobalt_memdev_stat statbuf;
   int fd, ret;
   void *addr;
 
   fd = __RT(open(name, O_RDWR));
   if (fd < 0) {
       early_warning("cannot open RTDM device %s: %s", name,
                 strerror(errno));
       return MAP_FAILED;
   }
 
   ret = __RT(ioctl(fd, MEMDEV_RTIOC_STAT, &statbuf));
   if (ret) {
       __RT(close(fd));
       early_warning("failed getting status of %s: %s",
                 name, strerror(errno));
       return MAP_FAILED;
   }
 
   addr = __RT(mmap(NULL, statbuf.size, PROT_READ|PROT_WRITE,
            MAP_SHARED, fd, 0));
   __RT(close(fd));
 
   *size_r = statbuf.size;
 
   return addr;
}
 
#define map_umm(__name, __size_r)  __map_umm("/dev/rtdm/" __name, __size_r)
 
void cobalt_unmap_umm(void)
{
   void *addr;
 
   /*
    * Remapping the private heap must be done after the process
    * has re-attached to the Cobalt core, in order to reinstate a
    * proper private heap, Otherwise the global heap would be
    * used instead, leading to unwanted effects.
    *
    * On machines without an MMU, there is no such thing as fork.
    *
    * We replace former mappings with an invalid one, to detect
    * any spurious late access.
    */
   addr = __STD(mmap(cobalt_umm_private,
             private_size, PROT_NONE,
             MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0));
 
   if (addr != cobalt_umm_private)
       munmap(cobalt_umm_private, private_size);
 
   cobalt_umm_private = NULL;
   init_bind_once = PTHREAD_ONCE_INIT;
}
 
/*
 * Will be called once on behalf of xenomai_init(), and when
 * re-binding after a fork.
 */
static void init_bind(void)
{
   cobalt_umm_private = map_umm(COBALT_MEMDEV_PRIVATE, &private_size);
   if (cobalt_umm_private == MAP_FAILED) {
       early_warning("cannot map private umm area: %s",
                 strerror(errno));
       early_panic("(CONFIG_DEVTMPFS_MOUNT not enabled?)");
   }
}
 
/* Will be called only once, upon call to xenomai_init(). */
static void init_loadup(__u32 vdso_offset)
{
   uint32_t size;
 
   cobalt_umm_shared = map_umm(COBALT_MEMDEV_SHARED, &size);
   if (cobalt_umm_shared == MAP_FAILED)
       early_panic("cannot map shared umm area: %s",
               strerror(errno));
 
   cobalt_vdso = (struct xnvdso *)(cobalt_umm_shared + vdso_offset);
}
 
void cobalt_init_umm(__u32 vdso_offset)
{
   pthread_once(&init_bind_once, init_bind);
   init_loadup(vdso_offset);
}