Commit b92e9fac authored by Jan Beulich's avatar Jan Beulich Committed by Andi Kleen
Browse files

[PATCH] x86: fix amd64-agp aperture validation



Under CONFIG_DISCONTIGMEM, assuming that a !pfn_valid() implies all
subsequent pfn-s are also invalid is wrong. Thus replace this by
explicitly checking against the E820 map.

AK: make e820 on x86-64 not initdata

Signed-off-by: default avatarJan Beulich <jbeulich@novell.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Acked-by: default avatarMark Langsdorf <mark.langsdorf@amd.com>
parent b00742d3
Loading
Loading
Loading
Loading
+20 −0
Original line number Original line Diff line number Diff line
@@ -825,6 +825,26 @@ void __init limit_regions(unsigned long long size)
	print_memory_map("limit_regions endfunc");
	print_memory_map("limit_regions endfunc");
}
}


/*
 * This function checks if any part of the range <start,end> is mapped
 * with type.
 */
int
e820_any_mapped(u64 start, u64 end, unsigned type)
{
	int i;
	for (i = 0; i < e820.nr_map; i++) {
		const struct e820entry *ei = &e820.map[i];
		if (type && ei->type != type)
			continue;
		if (ei->addr >= end || ei->addr + ei->size <= start)
			continue;
		return 1;
	}
	return 0;
}
EXPORT_SYMBOL_GPL(e820_any_mapped);

 /*
 /*
  * This function checks if the entire range <start,end> is mapped with type.
  * This function checks if the entire range <start,end> is mapped with type.
  *
  *
+3 −2
Original line number Original line Diff line number Diff line
@@ -25,7 +25,7 @@
#include <asm/bootsetup.h>
#include <asm/bootsetup.h>
#include <asm/sections.h>
#include <asm/sections.h>


struct e820map e820 __initdata;
struct e820map e820;


/* 
/* 
 * PFN of last memory page.
 * PFN of last memory page.
@@ -98,7 +98,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
 * This function checks if any part of the range <start,end> is mapped
 * This function checks if any part of the range <start,end> is mapped
 * with type.
 * with type.
 */
 */
int __meminit
int
e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
{ 
{ 
	int i;
	int i;
@@ -112,6 +112,7 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
	} 
	} 
	return 0;
	return 0;
}
}
EXPORT_SYMBOL_GPL(e820_any_mapped);


/*
/*
 * This function checks if the entire range <start,end> is mapped with type.
 * This function checks if the entire range <start,end> is mapped with type.
+4 −9
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/agp_backend.h>
#include <linux/agp_backend.h>
#include <linux/mmzone.h>
#include <linux/mmzone.h>
#include <asm/page.h>		/* PAGE_SIZE */
#include <asm/page.h>		/* PAGE_SIZE */
#include <asm/e820.h>
#include <asm/k8.h>
#include <asm/k8.h>
#include "agp.h"
#include "agp.h"


@@ -259,7 +260,6 @@ static const struct agp_bridge_driver amd_8151_driver = {
/* Some basic sanity checks for the aperture. */
/* Some basic sanity checks for the aperture. */
static int __devinit aperture_valid(u64 aper, u32 size)
static int __devinit aperture_valid(u64 aper, u32 size)
{
{
	u32 pfn, c;
	if (aper == 0) {
	if (aper == 0) {
		printk(KERN_ERR PFX "No aperture\n");
		printk(KERN_ERR PFX "No aperture\n");
		return 0;
		return 0;
@@ -272,15 +272,10 @@ static int __devinit aperture_valid(u64 aper, u32 size)
		printk(KERN_ERR PFX "Aperture out of bounds\n");
		printk(KERN_ERR PFX "Aperture out of bounds\n");
		return 0;
		return 0;
	}
	}
	pfn = aper >> PAGE_SHIFT;
	if (e820_any_mapped(aper, aper + size, E820_RAM)) {
	for (c = 0; c < size/PAGE_SIZE; c++) {
		if (!pfn_valid(pfn + c))
			break;
		if (!PageReserved(pfn_to_page(pfn + c))) {
		printk(KERN_ERR PFX "Aperture pointing to RAM\n");
		printk(KERN_ERR PFX "Aperture pointing to RAM\n");
		return 0;
		return 0;
	}
	}
	}


	/* Request the Aperture. This catches cases when someone else
	/* Request the Aperture. This catches cases when someone else
	   already put a mapping in there - happens with some very broken BIOS
	   already put a mapping in there - happens with some very broken BIOS
+1 −0
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ extern struct e820map e820;


extern int e820_all_mapped(unsigned long start, unsigned long end,
extern int e820_all_mapped(unsigned long start, unsigned long end,
			   unsigned type);
			   unsigned type);
extern int e820_any_mapped(u64 start, u64 end, unsigned type);
extern void find_max_pfn(void);
extern void find_max_pfn(void);
extern void register_bootmem_low_pages(unsigned long max_low_pfn);
extern void register_bootmem_low_pages(unsigned long max_low_pfn);
extern void e820_register_memory(void);
extern void e820_register_memory(void);