Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75bb8835 authored by Pekka Paalanen's avatar Pekka Paalanen Committed by Thomas Gleixner
Browse files

x86 mmiotrace: use lookup_address()



Use lookup_address() from pageattr.c instead of doing the same
manually. Also had to EXPORT_SYMBOL_GPL(lookup_address) to make this
work for modules. This also fixes "undefined symbol 'init_mm'"
compile error for x86_32.

Signed-off-by: default avatarPekka Paalanen <pq@iki.fi>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 8b7d89d0
Loading
Loading
Loading
Loading
+31 −15
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <asm/cacheflush.h>
#include <asm/errno.h>
#include <asm/tlbflush.h>
#include <asm/pgtable.h>

#include "kmmio.h"

@@ -117,40 +118,55 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
	return NULL;
}

static void arm_kmmio_fault_page(unsigned long page, int *large)
static void arm_kmmio_fault_page(unsigned long page, int *page_level)
{
	unsigned long address = page & PAGE_MASK;
	pgd_t *pgd = pgd_offset_k(address);
	pud_t *pud = pud_offset(pgd, address);
	pmd_t *pmd = pmd_offset(pud, address);
	pte_t *pte = pte_offset_kernel(pmd, address);
	int level;
	pte_t *pte = lookup_address(address, &level);

	if (pmd_large(*pmd)) {
	if (!pte) {
		printk(KERN_ERR "Error in %s: no pte for page 0x%08lx\n",
						__FUNCTION__, page);
		return;
	}

	if (level == PG_LEVEL_2M) {
		pmd_t *pmd = (pmd_t *)pte;
		set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_PRESENT));
		if (large)
			*large = 1;
	} else {
		/* PG_LEVEL_4K */
		set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
	}

	if (page_level)
		*page_level = level;

	__flush_tlb_one(page);
}

static void disarm_kmmio_fault_page(unsigned long page, int *large)
static void disarm_kmmio_fault_page(unsigned long page, int *page_level)
{
	unsigned long address = page & PAGE_MASK;
	pgd_t *pgd = pgd_offset_k(address);
	pud_t *pud = pud_offset(pgd, address);
	pmd_t *pmd = pmd_offset(pud, address);
	pte_t *pte = pte_offset_kernel(pmd, address);
	int level;
	pte_t *pte = lookup_address(address, &level);

	if (large && *large) {
	if (!pte) {
		printk(KERN_ERR "Error in %s: no pte for page 0x%08lx\n",
						__FUNCTION__, page);
		return;
	}

	if (level == PG_LEVEL_2M) {
		pmd_t *pmd = (pmd_t *)pte;
		set_pmd(pmd, __pmd(pmd_val(*pmd) | _PAGE_PRESENT));
		*large = 0;
	} else {
		/* PG_LEVEL_4K */
		set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
	}

	if (page_level)
		*page_level = level;

	__flush_tlb_one(page);
}

+12 −7
Original line number Diff line number Diff line
@@ -120,19 +120,24 @@ static int write_marker(struct file *file, const char __user *buffer,

static void print_pte(unsigned long address)
{
	pgd_t *pgd = pgd_offset_k(address);
	pud_t *pud = pud_offset(pgd, address);
	pmd_t *pmd = pmd_offset(pud, address);
	if (pmd_large(*pmd)) {
	int level;
	pte_t *pte = lookup_address(address, &level);

	if (!pte) {
		printk(KERN_ERR "Error in %s: no pte for page 0x%08lx\n",
						__FUNCTION__, address);
		return;
	}

	if (level == PG_LEVEL_2M) {
		printk(KERN_EMERG MODULE_NAME ": 4MB pages are not "
						"currently supported: %lx\n",
						address);
		BUG();
	}
	printk(KERN_DEBUG MODULE_NAME ": pte for 0x%lx: 0x%lx 0x%lx\n",
		address,
		pte_val(*pte_offset_kernel(pmd, address)),
		pte_val(*pte_offset_kernel(pmd, address)) & _PAGE_PRESENT);
					address, pte_val(*pte),
					pte_val(*pte) & _PAGE_PRESENT);
}

/*
+1 −0
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ pte_t *lookup_address(unsigned long address, unsigned int *level)

	return pte_offset_kernel(pmd, address);
}
EXPORT_SYMBOL_GPL(lookup_address);

/*
 * Set the new pmd in all the pgds we know about: