[Crash-utility] Check _PAGE_PROTNONE bit in uvtop()

HATAYAMA Daisuke d.hatayama at jp.fujitsu.com
Thu Apr 28 08:51:33 UTC 2011


Currently, some of uvtop() functions on x86, x86_64 and ia64 lacks
checking whether in pte _PAGE_PROTNONE bit is set or not. The flag is
set to pte when specifying to the corresponding memory space PROT_NONE
using mprotect(), and then _PAGE_PRESENT bit in the pte is unset in
order to make hardware cause segmentation fault
intensionally. Important is the fact that besides _PAGE_PRESENT set,
_PAGE_PROTNONE indicates the page is present (not swapped out).

The architectures fixed are x86, x86_64 and ia64 except for Xen.

The patchset based on crash 5.1.4 consists of 5 patches, which are
divided into the ones extending machine dependent data on x86 and
x86_64, and the ones actually adding _PAGE_PROTNONE checking into each
uvtop().

 defs.h   |    6 ++++--
 ia64.c   |    6 +++---
 x86.c    |   10 ++++++++--
 x86_64.c |   11 +++++++++--
 4 files changed, 24 insertions(+), 9 deletions(-)

More two files attached are the programs I used in order to create
dumps for tests: testpro.c allocates 5 kinds of memory spaces in
combination with mprotect()ed, mlock()ed or hugepage; mempres.c can be
used to cause memory pressure to force pages to be swapped out.

By the way, the issue I faced but have yet fixed is that on ia64,
vtop() operation on mlock()ed hugepage memory space fails. The
situation can be reproduced using the attached program.

Thanks.
HATAYAMA, Daisuke
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-x86_64-Handle-_PAGE_PROTNONE-as-machine-specific-dat.patch
Type: text/x-patch
Size: 1613 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20110428/79341e7a/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-x86_64-Add-_PAGE_PROTNONE-check.patch
Type: text/x-patch
Size: 1289 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20110428/79341e7a/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-x86-Handle-_PAGE_PROTNONE-as-machine-specific-data.patch
Type: text/x-patch
Size: 1588 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20110428/79341e7a/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-x86-Add-_PAGE_PROTNONE-check.patch
Type: text/x-patch
Size: 955 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20110428/79341e7a/attachment-0003.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0005-ia64-Add-_PAGE_PROTNONE-check.patch
Type: text/x-patch
Size: 1529 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20110428/79341e7a/attachment-0004.bin>
-------------- next part --------------
/*
 * Take the following step before you run this program:
 *
 *   1. set up the environment to be able to use hugetlb feature.
 *
 *     $ echo 10 > /proc/sys/vm/nr_hugepages
 *
 *       - This operation is intended to change the number of
 *       hugepages that system can allocate from physical memory.
 *
 *       - You can check a single huge page size from /proc/meminfo
 *
 *         $ grep "Huge" /proc/meminfo
 *         HugePages_Total:   128
 *         HugePages_Free:    128
 *         HugePages_Rsvd:      0
 *         Hugepagesize:     2048 kB
 *
 *       - You need to set up the number of hugepages enough for required memory size.
 *
 *     $ mkdir -p /media/hugetlb
 *     $ mount -t hugetlbfs none /media/hugetlb -o uid=n,gid=m,mode=0777
 *     $ echo m > /proc/sys/vm/hugetlb_shm_group
 *
 *        - Both n and m are 0 for root user; so it's easy to specify this by
 *          doing as root user.
 *
 *   2. Use mmap or shmget to map hugepages via /media/hugetlb.
 *
 *     Reference
 *
 *       [1] linux-2.6/Documentation/vm/hugetlbpage.txt
 *
 */

#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static void pmapx(void);
static size_t get_hugepagesize(void);
static void *hugepage_alloc(size_t size);

int main(int argc, char **argv)
{
	unsigned long i;
	char *obj_swap, *obj_locked, *obj_huge_swap, *obj_huge_locked, *obj_huge_locked_nonprotect;
	long pagesize;
	size_t hugepagesize;

	if ((pagesize = sysconf(_SC_PAGESIZE)) < 0)
		goto error;

	if (!(hugepagesize = get_hugepagesize()))
		goto error;

	if (!(obj_swap = valloc(pagesize)))
		goto error;

	if (!(obj_locked = valloc(pagesize)))
		goto error;

	if (!(obj_huge_swap = hugepage_alloc(hugepagesize)))
		goto error;

	if (!(obj_huge_locked = hugepage_alloc(hugepagesize)))
		goto error;

	if (!(obj_huge_locked_nonprotect = hugepage_alloc(hugepagesize)))
		goto error;

	memset(obj_swap, 's', pagesize);
	memset(obj_locked, 'l', pagesize);

	memset(obj_huge_swap, 'S', hugepagesize);
	memset(obj_huge_locked, 'L', hugepagesize);
	memset(obj_huge_locked_nonprotect, 'N', hugepagesize);

	if (mlock(obj_locked, pagesize))
		goto error;

	if (mlock(obj_huge_locked, hugepagesize))
		goto error;

	if (mlock(obj_huge_locked_nonprotect, hugepagesize))
		goto error;

	if (mprotect(obj_locked, pagesize, PROT_NONE) < 0)
		goto error;

	if (mprotect(obj_swap, pagesize, PROT_NONE) < 0)
		goto error;

	if (mprotect(obj_huge_locked, hugepagesize, PROT_NONE) < 0)
		goto error;

	if (mprotect(obj_huge_swap, hugepagesize, PROT_NONE) < 0)
		goto error;

	for (;;) {
		sleep(100);
	}

	return EXIT_SUCCESS;

error:
	fprintf(stderr, "%s: %s\n", basename(argv[0]), strerror(errno));

	return EXIT_FAILURE;
}

static size_t get_hugepagesize(void)
{
	char buf[128];
	FILE *meminfo;
	size_t hugepagesize;

	meminfo = fopen("/proc/meminfo", "r");
	if (!meminfo)
		return 0;

	for (;;) {
		fgets(buf, sizeof(buf), meminfo);
		if (ferror(meminfo))
			return 0;
		if (strstr(buf, "Hugepagesize:"))
			break;
		if (feof(meminfo))
			return 0;
	}

	fclose(meminfo);

	sscanf(buf, "Hugepagesize: %lu kB", &hugepagesize);
	hugepagesize *= 1024; /* kB => B */

	return hugepagesize;
}

static void *hugepage_alloc(size_t size)
{
	int c, fd;
	void *obj;

	fd = open("/media/hugetlb/hugepage_protnone", O_CREAT | O_RDWR, 0755);
	if (fd < 0)
		return NULL;

	c = 'K';
	write(fd, &c, 1);
	obj = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (obj < 0)
		return NULL;

	return obj;
}
-------------- next part --------------
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	size_t memsize = (1UL << 30UL);
	long pagesize;
	int i;
	char *obj;

	pagesize = sysconf(_SC_PAGESIZE);

	obj = memalign(pagesize, memsize);
	if (!obj) {
		perror("malloc");
		exit(EXIT_FAILURE);
	}

	for (;;) {
		for (i = 0; i < memsize; ++i) {
			obj[i] = 'O';
		}
	}

	return 0;
}


More information about the Crash-utility mailing list