(Android) Define LIGHTREC_CUSTOM_MAP
[pcsx_rearmed.git] / libpcsxcore / lightrec / mem.c
CommitLineData
a093e81f
PC
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * Copyright (C) 2022 Paul Cercueil <paul@crapouillou.net>
4 */
5
6#include <errno.h>
7#include <fcntl.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <sys/mman.h>
12#include <sys/shm.h>
13#include <sys/stat.h>
14#include <unistd.h>
15
16#include "../psxhw.h"
17#include "../psxmem.h"
18#include "../r3000a.h"
19
20#include "mem.h"
21
22#define ARRAY_SIZE(a) (sizeof(a) ? (sizeof(a) / sizeof((a)[0])) : 0)
23
24#ifndef MAP_FIXED_NOREPLACE
25#define MAP_FIXED_NOREPLACE 0x100000
26#endif
27
2f609094
PC
28#ifndef MFD_HUGETLB
29#define MFD_HUGETLB 0x0004
30#endif
31
a093e81f
PC
32static const uintptr_t supported_io_bases[] = {
33 0x0,
34 0x10000000,
35 0x40000000,
36 0x80000000,
37};
38
39static void * mmap_huge(void *addr, size_t length, int prot, int flags,
40 int fd, off_t offset)
41{
42 void *map = MAP_FAILED;
43
44 if (length >= 0x200000) {
45 map = mmap(addr, length, prot,
46 flags | MAP_HUGETLB | (21 << MAP_HUGE_SHIFT),
47 fd, offset);
48 if (map != MAP_FAILED)
49 printf("Hugetlb mmap to address 0x%lx succeeded\n", (uintptr_t) addr);
50 }
51
52 if (map == MAP_FAILED) {
53 map = mmap(addr, length, prot, flags, fd, offset);
54 if (map != MAP_FAILED)
55 printf("Regular mmap to address 0x%lx succeeded\n", (uintptr_t) addr);
56 }
57
58 return map;
59}
60
61static int lightrec_mmap_ram(bool hugetlb)
62{
63 unsigned int i, j;
64 int err, memfd, flags = 0;
65 uintptr_t base;
66 void *map;
67
68 if (hugetlb)
69 flags |= MFD_HUGETLB;
70
71 memfd = memfd_create("/lightrec_memfd", flags);
72 if (memfd < 0) {
73 err = -errno;
74 fprintf(stderr, "Failed to create memfd: %d\n", err);
75 return err;
76 }
77
78 err = ftruncate(memfd, 0x200000);
79 if (err < 0) {
80 err = -errno;
81 fprintf(stderr, "Could not trim memfd: %d\n", err);
82 goto err_close_memfd;
83 }
84
85 for (i = 0; i < ARRAY_SIZE(supported_io_bases); i++) {
86 base = supported_io_bases[i];
87
88 for (j = 0; j < 4; j++) {
89 map = mmap_huge((void *)(base + j * 0x200000),
90 0x200000, PROT_READ | PROT_WRITE,
91 MAP_SHARED | MAP_FIXED, memfd, 0);
92 if (map == MAP_FAILED)
93 break;
94 }
95
96 /* Impossible to map using this base */
97 if (j == 0)
98 continue;
99
100 /* All mirrors mapped - we got a match! */
101 if (j == 4)
102 break;
103
104 /* Only some mirrors mapped - clean the mess and try again */
105 for (; j > 0; j--)
106 munmap((void *)(base + (j - 1) * 0x200000), 0x200000);
107 }
108
109 if (i == ARRAY_SIZE(supported_io_bases)) {
110 err = -EINVAL;
111 goto err_close_memfd;
112 }
113
114 err = 0;
115 psxM = (s8 *)base;
116
117err_close_memfd:
118 close(memfd);
119 return err;
120}
121
122int lightrec_init_mmap(void)
123{
124 unsigned int i;
125 uintptr_t base;
126 void *map;
127 int err;
128
129 err = lightrec_mmap_ram(true);
130 if (err) {
131 err = lightrec_mmap_ram(false);
132 if (err) {
133 fprintf(stderr, "Unable to mmap RAM and mirrors\n");
134 return err;
135 }
136 }
137
138 base = (uintptr_t) psxM;
139
140 map = mmap((void *)(base + 0x1f000000), 0x10000,
141 PROT_READ | PROT_WRITE,
142 MAP_PRIVATE | MAP_FIXED_NOREPLACE | MAP_ANONYMOUS, 0, 0);
143 if (map == MAP_FAILED) {
144 err = -EINVAL;
145 fprintf(stderr, "Unable to mmap parallel port\n");
146 goto err_unmap;
147 }
148
149 psxP = (s8 *)map;
150
151 map = mmap_huge((void *)(base + 0x1fc00000), 0x200000,
152 PROT_READ | PROT_WRITE,
153 MAP_PRIVATE | MAP_FIXED_NOREPLACE | MAP_ANONYMOUS, 0, 0);
154 if (map == MAP_FAILED) {
155 err = -EINVAL;
156 fprintf(stderr, "Unable to mmap BIOS\n");
157 goto err_unmap_parallel;
158 }
159
160 psxR = (s8 *)map;
161
162 map = mmap((void *)(base + 0x1f800000), 0x10000,
163 PROT_READ | PROT_WRITE,
164 MAP_PRIVATE | MAP_FIXED_NOREPLACE | MAP_ANONYMOUS, 0, 0);
165 if (map == MAP_FAILED) {
166 err = -EINVAL;
167 fprintf(stderr, "Unable to mmap scratchpad\n");
168 goto err_unmap_bios;
169 }
170
171 psxH = (s8 *)map;
172
173 return 0;
174
175err_unmap_bios:
176 munmap(psxR, 0x80000);
177err_unmap_parallel:
178 munmap(psxP, 0x10000);
179err_unmap:
180 for (i = 0; i < 4; i++)
181 munmap((void *)((uintptr_t)psxM + i * 0x200000), 0x200000);
182 return err;
183}
184
185void lightrec_free_mmap(void)
186{
187 unsigned int i;
188
189 munmap(psxH, 0x10000);
190 munmap(psxR, 0x80000);
191 munmap(psxP, 0x10000);
192 for (i = 0; i < 4; i++)
193 munmap((void *)((uintptr_t)psxM + i * 0x200000), 0x200000);
194}