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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/powerpc/mm/subpage_prot.c
Extension
.c
Size
4749 bytes
Lines
237
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 (dar != addr) {
			printf("Fault expected at %p and happened at %p !\n",
			       addr, dar);
		}
		faulted = 0;
		asm volatile("sync" : : : "memory");
	}
}

static int run_test(void *addr, unsigned long size)
{
	unsigned int *map;
	long i, j, pages, err;

	pages = size / 0x10000;
	map = malloc(pages * 4);
	assert(map);

	/*
	 * for each page, mark subpage i % 16 read only and subpage
	 * (i + 3) % 16 inaccessible
	 */
	for (i = 0; i < pages; i++) {
		map[i] = (0x40000000 >> (((i + 1) * 2) % 32)) |
			(0xc0000000 >> (((i + 3) * 2) % 32));
	}

	err = syscall(__NR_subpage_prot, addr, size, map);
	if (err) {
		perror("subpage_perm");
		return 1;
	}
	free(map);

	in_test = 1;
	errors = 0;
	for (i = 0; i < pages; i++) {
		for (j = 0; j < 16; j++, addr += 0x1000) {
			do_read(addr);
			check_faulted(addr, i, j, 0);
			do_write(addr);
			check_faulted(addr, i, j, 1);
		}
	}

	in_test = 0;
	if (errors) {
		printf("%d errors detected\n", errors);
		return 1;
	}

	return 0;
}

static int syscall_available(void)
{
	int rc;

	errno = 0;
	rc = syscall(__NR_subpage_prot, 0, 0, 0);

	return rc == 0 || (errno != ENOENT && errno != ENOSYS);
}

int test_anon(void)
{
	unsigned long align;
	struct sigaction act = {
		.sa_sigaction = segv,
		.sa_flags = SA_SIGINFO
	};
	void *mallocblock;
	unsigned long mallocsize;

	SKIP_IF(!syscall_available());

	if (getpagesize() != 0x10000) {
		fprintf(stderr, "Kernel page size must be 64K!\n");
		return 1;
	}

	sigaction(SIGSEGV, &act, NULL);

	mallocsize = 4 * 16 * 1024 * 1024;

	FAIL_IF(posix_memalign(&mallocblock, 64 * 1024, mallocsize));

	align = (unsigned long)mallocblock;
	if (align & 0xffff)
		align = (align | 0xffff) + 1;

Annotation

Implementation Notes