forked from OSchip/llvm-project
[BOLT] Hugify: check for THP support via sysfs
Summary: Remove dependence on kernel version check, query sysfs directly instead. (cherry picked from FBD28858208)
This commit is contained in:
parent
7bccf8d25d
commit
2da5b12a3d
|
@ -86,6 +86,20 @@ constexpr uint32_t BufSize = 10240;
|
|||
#define _STRINGIFY(x) #x
|
||||
#define STRINGIFY(x) _STRINGIFY(x)
|
||||
|
||||
uint64_t __read(uint64_t fd, const void *buf, uint64_t count) {
|
||||
uint64_t ret;
|
||||
#if defined(__APPLE__)
|
||||
#define READ_SYSCALL 0x2000003
|
||||
#else
|
||||
#define READ_SYSCALL 0
|
||||
#endif
|
||||
__asm__ __volatile__("movq $" STRINGIFY(READ_SYSCALL) ", %%rax\n"
|
||||
"syscall\n"
|
||||
: "=a"(ret)
|
||||
: "D"(fd), "S"(buf), "d"(count)
|
||||
: "cc", "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t __write(uint64_t fd, const void *buf, uint64_t count) {
|
||||
uint64_t ret;
|
||||
|
@ -102,7 +116,6 @@ uint64_t __write(uint64_t fd, const void *buf, uint64_t count) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void *__mmap(uint64_t addr, uint64_t size, uint64_t prot, uint64_t flags,
|
||||
uint64_t fd, uint64_t offset) {
|
||||
#if defined(__APPLE__)
|
||||
|
@ -186,6 +199,18 @@ char *strCopy(char *OutBuf, const char *Str, int32_t Size = BufSize) {
|
|||
return OutBuf;
|
||||
}
|
||||
|
||||
/// Compare two strings, at most Num bytes.
|
||||
int strnCmp(const char *Str1, const char *Str2, size_t Num) {
|
||||
while (Num && *Str1 && (*Str1 == *Str2)) {
|
||||
Num--;
|
||||
Str1++;
|
||||
Str2++;
|
||||
}
|
||||
if (Num == 0)
|
||||
return 0;
|
||||
return *(unsigned char *)Str1 - *(unsigned char *)Str2;
|
||||
}
|
||||
|
||||
void memSet(char *Buf, char C, uint32_t Size) {
|
||||
for (int I = 0; I < Size; ++I)
|
||||
*Buf++ = C;
|
||||
|
@ -265,29 +290,6 @@ int __madvise(void *addr, size_t length, int advice) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Length of the entries in `struct utsname' is 65. */
|
||||
#define _UTSNAME_LENGTH 65
|
||||
|
||||
struct utsname {
|
||||
char sysname[_UTSNAME_LENGTH]; /* Operating system name (e.g., "Linux") */
|
||||
char nodename[_UTSNAME_LENGTH]; /* Name within "some implementation-defined
|
||||
network" */
|
||||
char release[_UTSNAME_LENGTH]; /* Operating system release (e.g., "2.6.28") */
|
||||
char version[_UTSNAME_LENGTH]; /* Operating system version */
|
||||
char machine[_UTSNAME_LENGTH]; /* Hardware identifier */
|
||||
char domainname[_UTSNAME_LENGTH]; /* NIS or YP domain name */
|
||||
};
|
||||
|
||||
int __uname(struct utsname *buf) {
|
||||
int ret;
|
||||
__asm__ __volatile__("movq $63, %%rax\n"
|
||||
"syscall\n"
|
||||
: "=a"(ret)
|
||||
: "D"(buf)
|
||||
: "cc", "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct timespec {
|
||||
uint64_t tv_sec; /* seconds */
|
||||
uint64_t tv_nsec; /* nanoseconds */
|
||||
|
|
|
@ -24,70 +24,22 @@ extern uint64_t __hot_start;
|
|||
extern uint64_t __hot_end;
|
||||
|
||||
#ifdef MADV_HUGEPAGE
|
||||
/// Starting from character at \p buf, find the longest consecutive sequence
|
||||
/// of digits (0-9) and convert it to uint32_t. The converted value
|
||||
/// is put into \p ret. \p end marks the end of the buffer to avoid buffer
|
||||
/// overflow. The function \returns whether a valid uint32_t value is found.
|
||||
/// \p buf will be updated to the next character right after the digits.
|
||||
static bool scanUInt32(const char *&buf, const char *end, uint32_t &ret) {
|
||||
uint64_t result = 0;
|
||||
const char *oldBuf = buf;
|
||||
while (buf < end && ((*buf) >= '0' && (*buf) <= '9')) {
|
||||
result = result * 10 + (*buf) - '0';
|
||||
++buf;
|
||||
}
|
||||
if (oldBuf != buf && result <= 0xFFFFFFFFu) {
|
||||
ret = static_cast<uint32_t>(result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check whether the kernel supports THP by checking the kernel version.
|
||||
/// Only fb kernel 5.2 and latter supports it.
|
||||
/// Check whether the kernel supports THP via corresponding sysfs entry.
|
||||
static bool has_pagecache_thp_support() {
|
||||
struct utsname u;
|
||||
int ret = __uname(&u);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
char buf[256] = {0};
|
||||
const char *madviseStr = "always [madvise] never";
|
||||
|
||||
const char *buf = u.release;
|
||||
#ifdef ENABLE_DEBUG
|
||||
report("[hugify] uname release: ");
|
||||
report(buf);
|
||||
report("\n");
|
||||
#endif
|
||||
const char *end = buf + strLen(buf);
|
||||
uint32_t nums[5];
|
||||
char delims[4][5] = {".", ".", "-", "_fbk"};
|
||||
// release should be in the format: %d.%d.%d-%d_fbk%d
|
||||
// they represent: major, minor, release, build, fbk.
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (!scanUInt32(buf, end, nums[i])) {
|
||||
return false;
|
||||
}
|
||||
if (i < 4) {
|
||||
const char *ptr = delims[i];
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr != *buf) {
|
||||
return false;
|
||||
}
|
||||
++ptr;
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nums[0] > 5) {
|
||||
// Major is > 5.
|
||||
return true;
|
||||
}
|
||||
if (nums[0] < 5) {
|
||||
// Major is < 5.
|
||||
int fd = __open("/sys/kernel/mm/transparent_hugepage/enabled",
|
||||
0 /* O_RDONLY */, 0);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
}
|
||||
// minor > 2 || fbk >= 5.
|
||||
return nums[1] > 2 || nums[4] >= 5;
|
||||
|
||||
size_t res = __read(fd, buf, 256);
|
||||
if (res < 0)
|
||||
return false;
|
||||
|
||||
int cmp = strnCmp(buf, madviseStr, strLen(madviseStr));
|
||||
return cmp == 0;
|
||||
}
|
||||
|
||||
static void hugify_for_old_kernel(uint8_t *from, uint8_t *to) {
|
||||
|
|
Loading…
Reference in New Issue