Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <string.h>
0003 #include <fcntl.h>
0004 #include "../kselftest.h"
0005 #include "vm_util.h"
0006 
0007 #define PMD_SIZE_FILE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size"
0008 #define SMAP_FILE_PATH "/proc/self/smaps"
0009 #define MAX_LINE_LENGTH 500
0010 
0011 uint64_t pagemap_get_entry(int fd, char *start)
0012 {
0013     const unsigned long pfn = (unsigned long)start / getpagesize();
0014     uint64_t entry;
0015     int ret;
0016 
0017     ret = pread(fd, &entry, sizeof(entry), pfn * sizeof(entry));
0018     if (ret != sizeof(entry))
0019         ksft_exit_fail_msg("reading pagemap failed\n");
0020     return entry;
0021 }
0022 
0023 bool pagemap_is_softdirty(int fd, char *start)
0024 {
0025     uint64_t entry = pagemap_get_entry(fd, start);
0026 
0027     // Check if dirty bit (55th bit) is set
0028     return entry & 0x0080000000000000ull;
0029 }
0030 
0031 void clear_softdirty(void)
0032 {
0033     int ret;
0034     const char *ctrl = "4";
0035     int fd = open("/proc/self/clear_refs", O_WRONLY);
0036 
0037     if (fd < 0)
0038         ksft_exit_fail_msg("opening clear_refs failed\n");
0039     ret = write(fd, ctrl, strlen(ctrl));
0040     close(fd);
0041     if (ret != strlen(ctrl))
0042         ksft_exit_fail_msg("writing clear_refs failed\n");
0043 }
0044 
0045 static bool check_for_pattern(FILE *fp, const char *pattern, char *buf)
0046 {
0047     while (fgets(buf, MAX_LINE_LENGTH, fp) != NULL) {
0048         if (!strncmp(buf, pattern, strlen(pattern)))
0049             return true;
0050     }
0051     return false;
0052 }
0053 
0054 uint64_t read_pmd_pagesize(void)
0055 {
0056     int fd;
0057     char buf[20];
0058     ssize_t num_read;
0059 
0060     fd = open(PMD_SIZE_FILE_PATH, O_RDONLY);
0061     if (fd == -1)
0062         ksft_exit_fail_msg("Open hpage_pmd_size failed\n");
0063 
0064     num_read = read(fd, buf, 19);
0065     if (num_read < 1) {
0066         close(fd);
0067         ksft_exit_fail_msg("Read hpage_pmd_size failed\n");
0068     }
0069     buf[num_read] = '\0';
0070     close(fd);
0071 
0072     return strtoul(buf, NULL, 10);
0073 }
0074 
0075 uint64_t check_huge(void *addr)
0076 {
0077     uint64_t thp = 0;
0078     int ret;
0079     FILE *fp;
0080     char buffer[MAX_LINE_LENGTH];
0081     char addr_pattern[MAX_LINE_LENGTH];
0082 
0083     ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "%08lx-",
0084                (unsigned long) addr);
0085     if (ret >= MAX_LINE_LENGTH)
0086         ksft_exit_fail_msg("%s: Pattern is too long\n", __func__);
0087 
0088     fp = fopen(SMAP_FILE_PATH, "r");
0089     if (!fp)
0090         ksft_exit_fail_msg("%s: Failed to open file %s\n", __func__, SMAP_FILE_PATH);
0091 
0092     if (!check_for_pattern(fp, addr_pattern, buffer))
0093         goto err_out;
0094 
0095     /*
0096      * Fetch the AnonHugePages: in the same block and check the number of
0097      * hugepages.
0098      */
0099     if (!check_for_pattern(fp, "AnonHugePages:", buffer))
0100         goto err_out;
0101 
0102     if (sscanf(buffer, "AnonHugePages:%10ld kB", &thp) != 1)
0103         ksft_exit_fail_msg("Reading smap error\n");
0104 
0105 err_out:
0106     fclose(fp);
0107     return thp;
0108 }