1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/platform/os.h"
17
18#include <malloc.h>
19#include <sched.h>
20#include <sys/mman.h>
21#include <sys/prctl.h>
22#include <sys/ptrace.h>
23#include <sys/sysinfo.h>
24#include <sys/types.h>
25#include <sys/xattr.h>
26#include <unistd.h>
27
28#include "ecmascript/log_wrapper.h"
29
30#ifndef PR_SET_VMA
31#define PR_SET_VMA 0x53564d41
32#endif
33
34#ifndef PR_SET_VMA_ANON_NAME
35#define PR_SET_VMA_ANON_NAME 0
36#endif
37
38namespace panda::ecmascript {
39size_t MallocUsableSize(void *p)
40{
41    return malloc_usable_size(p);
42}
43
44uint32_t NumberOfCpuCore()
45{
46    return static_cast<uint32_t>(sysconf(_SC_NPROCESSORS_ONLN));
47}
48
49size_t PhysicalSize()
50{
51    auto pages = sysconf(_SC_PHYS_PAGES);
52    auto pageSize = sysconf(_SC_PAGE_SIZE);
53    return pages * pageSize;
54}
55
56int PrctlSetVMA(const void *p, const size_t size, const char *tag)
57{
58    return prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, size, tag);
59}
60
61long PtracePeektext(int pid, uintptr_t addr)
62{
63    return ptrace(PTRACE_PEEKTEXT, pid, addr, NULL);
64}
65
66void BindSmallCpuCore()
67{
68    cpu_set_t cpuset;
69
70    CPU_ZERO(&cpuset);
71    CPU_SET(0, &cpuset); // 0: bind this process to cpu0
72    CPU_SET(1, &cpuset); // 1: bind this process to cpu1
73    CPU_SET(2, &cpuset); // 2: bind this process to cpu2
74    CPU_SET(3, &cpuset); // 3: bind this process to cpu3
75
76    if (sched_setaffinity(0, sizeof(cpuset), &cpuset) == -1) {
77        LOG_ECMA(ERROR) << "Set CPU affinity failed";
78    }
79}
80
81void BindMidCpuCore()
82{
83    cpu_set_t cpuset;
84
85    CPU_ZERO(&cpuset);
86    for (size_t i = 0; i < 7; i++) { // 7: 0-3 little core, 4-6 mid core
87        CPU_SET(i, &cpuset);
88    }
89
90    if (sched_setaffinity(0, sizeof(cpuset), &cpuset) == -1) {
91        LOG_ECMA(ERROR) << "Set CPU affinity failed";
92    }
93}
94
95void *PageMapExecFortSpace(void *addr, size_t size, int prot)
96{
97    void *res = mmap(addr, size, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_EXECUTABLE, -1, 0);
98    if (res == MAP_FAILED) {
99        LOG_ECMA(ERROR) << "PageMapExecFortSpace mmap failed, addr = " << addr << ", size = " << size <<
100            ", prot = " << prot << ", error code is " << errno;
101    }
102    return res;
103}
104
105void SetSecurityLabel(const std::string& path)
106{
107    auto xattrValueSize = getxattr(path.c_str(), XATTR_KEY, nullptr, 0);
108    if (xattrValueSize == static_cast<ssize_t>(DEFAULT_DATA_LENGTH)) {
109        char xattrValue[DEFAULT_DATA_LENGTH + 1];
110        xattrValueSize = getxattr(path.c_str(), XATTR_KEY, xattrValue, xattrValueSize);
111        xattrValue[DEFAULT_DATA_LENGTH] = '\0';
112    }
113
114    if (setxattr(path.c_str(), XATTR_KEY, DEFAULT_DATA_LEVEL.data(), DEFAULT_DATA_LEVEL.size(), 0) < 0) {
115        LOG_ECMA(WARN) << "set label failed! level: " << DEFAULT_DATA_LEVEL << ", file: " << path;
116    }
117}
118}  // namespace panda::ecmascript
119