1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci
3f08c3bdfSopenharmony_ci/*
4f08c3bdfSopenharmony_ci * Copyright (c) Zilogic Systems Pvt. Ltd. <code@zilogic.com>, 2018
5f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2019-2023
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Validating memfd_create() with MFD_HUGETLB and MFD_HUGE_x flags.
12f08c3bdfSopenharmony_ci *
13f08c3bdfSopenharmony_ci * Attempt to create files in the hugetlbfs filesystem using different huge page
14f08c3bdfSopenharmony_ci * sizes.
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * [Algorithm]
17f08c3bdfSopenharmony_ci *
18f08c3bdfSopenharmony_ci * memfd_create() should return non-negative value (fd) if the system supports
19f08c3bdfSopenharmony_ci * that particular huge page size.
20f08c3bdfSopenharmony_ci * On success, fd is returned. On failure, -1 is returned with ENODEV error.
21f08c3bdfSopenharmony_ci */
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_ci#define _GNU_SOURCE
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci#include "tst_test.h"
26f08c3bdfSopenharmony_ci#include "memfd_create_common.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#include <errno.h>
29f08c3bdfSopenharmony_ci#include <stdio.h>
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_cistatic  struct test_flag {
32f08c3bdfSopenharmony_ci	int flag;
33f08c3bdfSopenharmony_ci	char *h_size;
34f08c3bdfSopenharmony_ci	int exp_err;
35f08c3bdfSopenharmony_ci} test_flags[] =  {
36f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_64KB,         .h_size = "64kB"},
37f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_512KB,       .h_size = "512kB"},
38f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_2MB,        .h_size = "2048kB"},
39f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_8MB,        .h_size = "8192kB"},
40f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_16MB,      .h_size = "16384kB"},
41f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_256MB,    .h_size = "262144kB"},
42f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_1GB,     .h_size = "1048576kB"},
43f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_2GB,     .h_size = "2097152kB"},
44f08c3bdfSopenharmony_ci	{.flag = MFD_HUGE_16GB,   .h_size = "16777216kB"},
45f08c3bdfSopenharmony_ci};
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_cistatic void check_hugepage_support(struct test_flag *test_flags)
48f08c3bdfSopenharmony_ci{
49f08c3bdfSopenharmony_ci	char pattern[64];
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ci	sprintf(pattern, PATH_HUGEPAGES);
52f08c3bdfSopenharmony_ci	strcat(pattern, "hugepages-");
53f08c3bdfSopenharmony_ci	strcat(pattern, test_flags->h_size);
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	if (access(pattern, F_OK))
56f08c3bdfSopenharmony_ci		test_flags->exp_err = ENODEV;
57f08c3bdfSopenharmony_ci}
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_cistatic void memfd_huge_x_controller(unsigned int n)
60f08c3bdfSopenharmony_ci{
61f08c3bdfSopenharmony_ci	int fd;
62f08c3bdfSopenharmony_ci	struct test_flag tflag;
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci	tflag = test_flags[n];
65f08c3bdfSopenharmony_ci	check_hugepage_support(&tflag);
66f08c3bdfSopenharmony_ci	tst_res(TINFO,
67f08c3bdfSopenharmony_ci		"Attempt to create file using %s huge page size",
68f08c3bdfSopenharmony_ci		tflag.h_size);
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci	fd = sys_memfd_create("tfile", MFD_HUGETLB | tflag.flag);
71f08c3bdfSopenharmony_ci	if (fd < 0) {
72f08c3bdfSopenharmony_ci		if (errno == tflag.exp_err)
73f08c3bdfSopenharmony_ci			tst_res(TPASS, "Test failed as expected");
74f08c3bdfSopenharmony_ci		else
75f08c3bdfSopenharmony_ci			tst_brk(TFAIL | TERRNO,
76f08c3bdfSopenharmony_ci				"memfd_create() failed unexpectedly");
77f08c3bdfSopenharmony_ci		return;
78f08c3bdfSopenharmony_ci	}
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	tst_res(TPASS,
81f08c3bdfSopenharmony_ci		"memfd_create succeeded for %s page size",
82f08c3bdfSopenharmony_ci		tflag.h_size);
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
85f08c3bdfSopenharmony_ci}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_cistatic void setup(void)
88f08c3bdfSopenharmony_ci{
89f08c3bdfSopenharmony_ci	if (access(PATH_HUGEPAGES, F_OK))
90f08c3bdfSopenharmony_ci		tst_brk(TCONF, "Huge page is not supported");
91f08c3bdfSopenharmony_ci}
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_cistatic struct tst_test test = {
94f08c3bdfSopenharmony_ci	.setup = setup,
95f08c3bdfSopenharmony_ci	.test = memfd_huge_x_controller,
96f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(test_flags),
97f08c3bdfSopenharmony_ci	.min_kver = "4.14",
98f08c3bdfSopenharmony_ci};
99