tools/testing/selftests/powerpc/mm/stack_expansion_ldst.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/powerpc/mm/stack_expansion_ldst.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/powerpc/mm/stack_expansion_ldst.c
Extension
.c
Size
4480 bytes
Lines
203
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rc != 3) {
			printf("sscanf errored\n");
			rc = -1;
			break;
		}

		if (strstr(name, needle)) {
			*low = start;
			*high = end - 1;
			rc = 0;
			break;
		}
	}

	fclose(f);

	return rc;
}

int child(unsigned int stack_used, int delta, enum access_type type)
{
	unsigned long low, stack_high;

	assert(search_proc_maps("[stack]", &low, &stack_high) == 0);

	assert(consume_stack(stack_high - stack_used, stack_high, delta, type) == 0);

	printf("Access OK: %s delta %-7d used size 0x%06x stack high 0x%lx top_ptr %p top sp 0x%lx actual used 0x%lx\n",
	       type == LOAD ? "load" : "store", delta, stack_used, stack_high,
	       stack_top_ptr, stack_top_sp, stack_high - stack_top_sp + 1);

	return 0;
}

static int test_one(unsigned int stack_used, int delta, enum access_type type)
{
	pid_t pid;
	int rc;

	pid = fork();
	if (pid == 0)
		exit(child(stack_used, delta, type));

	assert(waitpid(pid, &rc, 0) != -1);

	if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
		return 0;

	// We don't expect a non-zero exit that's not a signal
	assert(!WIFEXITED(rc));

	printf("Faulted:   %s delta %-7d used size 0x%06x signal %d\n",
	       type == LOAD ? "load" : "store", delta, stack_used,
	       WTERMSIG(rc));

	return 1;
}

// This is fairly arbitrary but is well below any of the targets below,
// so that the delta between the stack pointer and the target is large.
#define DEFAULT_SIZE	(32 * _KB)

static void test_one_type(enum access_type type, unsigned long page_size, unsigned long rlim_cur)
{
	unsigned long delta;

	// We should be able to access anywhere within the rlimit
	for (delta = page_size; delta <= rlim_cur; delta += page_size)
		assert(test_one(DEFAULT_SIZE, delta, type) == 0);

	assert(test_one(DEFAULT_SIZE, rlim_cur, type) == 0);

	// But if we go past the rlimit it should fail
	assert(test_one(DEFAULT_SIZE, rlim_cur + 1, type) != 0);
}

static int test(void)
{
	unsigned long page_size;
	struct rlimit rlimit;

	page_size = getpagesize();
	getrlimit(RLIMIT_STACK, &rlimit);
	printf("Stack rlimit is 0x%llx\n", (unsigned long long)rlimit.rlim_cur);

	printf("Testing loads ...\n");
	test_one_type(LOAD, page_size, rlimit.rlim_cur);
	printf("Testing stores ...\n");
	test_one_type(STORE, page_size, rlimit.rlim_cur);

Annotation

Implementation Notes