summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/atomic_helpers.h1
-rw-r--r--src/common/cache_management.cpp60
-rw-r--r--src/common/cache_management.h27
-rw-r--r--src/common/common_funcs.h4
-rw-r--r--src/common/host_memory.cpp6
-rw-r--r--src/common/settings.cpp1
-rw-r--r--src/common/x64/cpu_detect.cpp59
-rw-r--r--src/common/x64/cpu_detect.h4
9 files changed, 160 insertions, 4 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index c0555f840..b7c15c191 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -34,6 +34,8 @@ add_library(common STATIC
34 bit_util.h 34 bit_util.h
35 cityhash.cpp 35 cityhash.cpp
36 cityhash.h 36 cityhash.h
37 cache_management.cpp
38 cache_management.h
37 common_funcs.h 39 common_funcs.h
38 common_types.h 40 common_types.h
39 concepts.h 41 concepts.h
diff --git a/src/common/atomic_helpers.h b/src/common/atomic_helpers.h
index bef5015c1..aef3b66a4 100644
--- a/src/common/atomic_helpers.h
+++ b/src/common/atomic_helpers.h
@@ -156,6 +156,7 @@ AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN {
156 break; 156 break;
157 default: 157 default:
158 assert(false); 158 assert(false);
159 break;
159 } 160 }
160} 161}
161 162
diff --git a/src/common/cache_management.cpp b/src/common/cache_management.cpp
new file mode 100644
index 000000000..57810b76a
--- /dev/null
+++ b/src/common/cache_management.cpp
@@ -0,0 +1,60 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <cstring>
5
6#include "alignment.h"
7#include "cache_management.h"
8#include "common_types.h"
9
10namespace Common {
11
12#if defined(ARCHITECTURE_x86_64)
13
14// Most cache operations are no-ops on x86
15
16void DataCacheLineCleanByVAToPoU(void* start, size_t size) {}
17void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size) {}
18void DataCacheLineCleanByVAToPoC(void* start, size_t size) {}
19void DataCacheZeroByVA(void* start, size_t size) {
20 std::memset(start, 0, size);
21}
22
23#elif defined(ARCHITECTURE_arm64)
24
25// BS/DminLine is log2(cache size in words), we want size in bytes
26#define EXTRACT_DMINLINE(ctr_el0) (1 << ((((ctr_el0) >> 16) & 0xf) + 2))
27#define EXTRACT_BS(dczid_el0) (1 << (((dczid_el0)&0xf) + 2))
28
29#define DEFINE_DC_OP(op_name, function_name) \
30 void function_name(void* start, size_t size) { \
31 size_t ctr_el0; \
32 asm volatile("mrs %[ctr_el0], ctr_el0\n\t" : [ctr_el0] "=r"(ctr_el0)); \
33 size_t cacheline_size = EXTRACT_DMINLINE(ctr_el0); \
34 uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \
35 uintptr_t va_end = va_start + size; \
36 for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \
37 asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \
38 } \
39 }
40
41#define DEFINE_DC_OP_DCZID(op_name, function_name) \
42 void function_name(void* start, size_t size) { \
43 size_t dczid_el0; \
44 asm volatile("mrs %[dczid_el0], dczid_el0\n\t" : [dczid_el0] "=r"(dczid_el0)); \
45 size_t cacheline_size = EXTRACT_BS(dczid_el0); \
46 uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \
47 uintptr_t va_end = va_start + size; \
48 for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \
49 asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \
50 } \
51 }
52
53DEFINE_DC_OP(cvau, DataCacheLineCleanByVAToPoU);
54DEFINE_DC_OP(civac, DataCacheLineCleanAndInvalidateByVAToPoC);
55DEFINE_DC_OP(cvac, DataCacheLineCleanByVAToPoC);
56DEFINE_DC_OP_DCZID(zva, DataCacheZeroByVA);
57
58#endif
59
60} // namespace Common
diff --git a/src/common/cache_management.h b/src/common/cache_management.h
new file mode 100644
index 000000000..e467b87e4
--- /dev/null
+++ b/src/common/cache_management.h
@@ -0,0 +1,27 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "stdlib.h"
7
8namespace Common {
9
10// Data cache instructions enabled at EL0 by SCTLR_EL1.UCI.
11// VA = virtual address
12// PoC = point of coherency
13// PoU = point of unification
14
15// dc cvau
16void DataCacheLineCleanByVAToPoU(void* start, size_t size);
17
18// dc civac
19void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size);
20
21// dc cvac
22void DataCacheLineCleanByVAToPoC(void* start, size_t size);
23
24// dc zva
25void DataCacheZeroByVA(void* start, size_t size);
26
27} // namespace Common
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index e1e2a90fc..0dad9338a 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -31,8 +31,10 @@
31 31
32#ifndef _MSC_VER 32#ifndef _MSC_VER
33 33
34#ifdef ARCHITECTURE_x86_64 34#if defined(ARCHITECTURE_x86_64)
35#define Crash() __asm__ __volatile__("int $3") 35#define Crash() __asm__ __volatile__("int $3")
36#elif defined(ARCHITECTURE_arm64)
37#define Crash() __asm__ __volatile__("brk #0")
36#else 38#else
37#define Crash() exit(1) 39#define Crash() exit(1)
38#endif 40#endif
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 7f9659612..909f6cf3f 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -359,6 +359,12 @@ public:
359 } 359 }
360 }); 360 });
361 361
362 long page_size = sysconf(_SC_PAGESIZE);
363 if (page_size != 0x1000) {
364 LOG_CRITICAL(HW_Memory, "page size {:#x} is incompatible with 4K paging", page_size);
365 throw std::bad_alloc{};
366 }
367
362 // Backing memory initialization 368 // Backing memory initialization
363#if defined(__FreeBSD__) && __FreeBSD__ < 13 369#if defined(__FreeBSD__) && __FreeBSD__ < 13
364 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 370 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 0a560ebb7..8173462cb 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -151,6 +151,7 @@ void UpdateRescalingInfo() {
151 ASSERT(false); 151 ASSERT(false);
152 info.up_scale = 1; 152 info.up_scale = 1;
153 info.down_shift = 0; 153 info.down_shift = 0;
154 break;
154 } 155 }
155 info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift); 156 info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift);
156 info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale; 157 info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale;
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp
index 1a27532d4..e54383a4a 100644
--- a/src/common/x64/cpu_detect.cpp
+++ b/src/common/x64/cpu_detect.cpp
@@ -4,14 +4,27 @@
4 4
5#include <array> 5#include <array>
6#include <cstring> 6#include <cstring>
7#include <fstream>
7#include <iterator> 8#include <iterator>
9#include <optional>
8#include <string_view> 10#include <string_view>
11#include <thread>
12#include <vector>
9#include "common/bit_util.h" 13#include "common/bit_util.h"
10#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/logging/log.h"
11#include "common/x64/cpu_detect.h" 16#include "common/x64/cpu_detect.h"
12 17
18#ifdef _WIN32
19#include <windows.h>
20#endif
21
13#ifdef _MSC_VER 22#ifdef _MSC_VER
14#include <intrin.h> 23#include <intrin.h>
24
25static inline u64 xgetbv(u32 index) {
26 return _xgetbv(index);
27}
15#else 28#else
16 29
17#if defined(__DragonFly__) || defined(__FreeBSD__) 30#if defined(__DragonFly__) || defined(__FreeBSD__)
@@ -39,12 +52,11 @@ static inline void __cpuid(int info[4], u32 function_id) {
39} 52}
40 53
41#define _XCR_XFEATURE_ENABLED_MASK 0 54#define _XCR_XFEATURE_ENABLED_MASK 0
42static inline u64 _xgetbv(u32 index) { 55static inline u64 xgetbv(u32 index) {
43 u32 eax, edx; 56 u32 eax, edx;
44 __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); 57 __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
45 return ((u64)edx << 32) | eax; 58 return ((u64)edx << 32) | eax;
46} 59}
47
48#endif // _MSC_VER 60#endif // _MSC_VER
49 61
50namespace Common { 62namespace Common {
@@ -107,7 +119,7 @@ static CPUCaps Detect() {
107 // - Is the XSAVE bit set in CPUID? 119 // - Is the XSAVE bit set in CPUID?
108 // - XGETBV result has the XCR bit set. 120 // - XGETBV result has the XCR bit set.
109 if (Common::Bit<28>(cpu_id[2]) && Common::Bit<27>(cpu_id[2])) { 121 if (Common::Bit<28>(cpu_id[2]) && Common::Bit<27>(cpu_id[2])) {
110 if ((_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) { 122 if ((xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) {
111 caps.avx = true; 123 caps.avx = true;
112 if (Common::Bit<12>(cpu_id[2])) 124 if (Common::Bit<12>(cpu_id[2]))
113 caps.fma = true; 125 caps.fma = true;
@@ -192,4 +204,45 @@ const CPUCaps& GetCPUCaps() {
192 return caps; 204 return caps;
193} 205}
194 206
207std::optional<int> GetProcessorCount() {
208#if defined(_WIN32)
209 // Get the buffer length.
210 DWORD length = 0;
211 GetLogicalProcessorInformation(nullptr, &length);
212 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
213 LOG_ERROR(Frontend, "Failed to query core count.");
214 return std::nullopt;
215 }
216 std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
217 length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
218 // Now query the core count.
219 if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
220 LOG_ERROR(Frontend, "Failed to query core count.");
221 return std::nullopt;
222 }
223 return static_cast<int>(
224 std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
225 return proc_info.Relationship == RelationProcessorCore;
226 }));
227#elif defined(__unix__)
228 const int thread_count = std::thread::hardware_concurrency();
229 std::ifstream smt("/sys/devices/system/cpu/smt/active");
230 char state = '0';
231 if (smt) {
232 smt.read(&state, sizeof(state));
233 }
234 switch (state) {
235 case '0':
236 return thread_count;
237 case '1':
238 return thread_count / 2;
239 default:
240 return std::nullopt;
241 }
242#else
243 // Shame on you
244 return std::nullopt;
245#endif
246}
247
195} // namespace Common 248} // namespace Common
diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h
index 6830f3795..ca8db19d6 100644
--- a/src/common/x64/cpu_detect.h
+++ b/src/common/x64/cpu_detect.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <optional>
7#include <string_view> 8#include <string_view>
8#include "common/common_types.h" 9#include "common/common_types.h"
9 10
@@ -74,4 +75,7 @@ struct CPUCaps {
74 */ 75 */
75const CPUCaps& GetCPUCaps(); 76const CPUCaps& GetCPUCaps();
76 77
78/// Detects CPU core count
79std::optional<int> GetProcessorCount();
80
77} // namespace Common 81} // namespace Common