amd64/138220: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Tue Sep 22 17:00:06 UTC 2009


The following reply was made to PR amd64/138220; it has been noted by GNATS.

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: amd64/138220: commit references a PR
Date: Tue, 22 Sep 2009 16:51:14 +0000 (UTC)

 Author: jhb
 Date: Tue Sep 22 16:51:00 2009
 New Revision: 197410
 URL: http://svn.freebsd.org/changeset/base/197410
 
 Log:
   - Split the logic to parse an SMAP entry out into a separate function on
     amd64 similar to i386.  This fixes a bug on amd64 where overlapping
     entries would not cause the SMAP parsing to stop.
   - Change the SMAP parsing code to do a sorted insertion into physmap[]
     instead of an append to support systems with out-of-order SMAP entries.
   
   PR:		amd64/138220
   Reported by:	James R. Van Artsdalen  james of jrv org
   MFC after:	3 days
 
 Modified:
   head/sys/amd64/amd64/machdep.c
   head/sys/i386/i386/machdep.c
 
 Modified: head/sys/amd64/amd64/machdep.c
 ==============================================================================
 --- head/sys/amd64/amd64/machdep.c	Tue Sep 22 16:28:07 2009	(r197409)
 +++ head/sys/amd64/amd64/machdep.c	Tue Sep 22 16:51:00 2009	(r197410)
 @@ -1192,6 +1192,77 @@ isa_irq_pending(void)
  
  u_int basemem;
  
 +static int
 +add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
 +{
 +	int i, insert_idx, physmap_idx;
 +
 +	physmap_idx = *physmap_idxp;
 +
 +	if (boothowto & RB_VERBOSE)
 +		printf("SMAP type=%02x base=%016lx len=%016lx\n",
 +		    smap->type, smap->base, smap->length);
 +
 +	if (smap->type != SMAP_TYPE_MEMORY)
 +		return (1);
 +
 +	if (smap->length == 0)
 +		return (0);
 +
 +	/*
 +	 * Find insertion point while checking for overlap.  Start off by
 +	 * assuming the new entry will be added to the end.
 +	 */
 +	insert_idx = physmap_idx + 2;
 +	for (i = 0; i <= physmap_idx; i += 2) {
 +		if (smap->base < physmap[i + 1]) {
 +			if (smap->base + smap->length <= physmap[i]) {
 +				insert_idx = i;
 +				break;
 +			}
 +			if (boothowto & RB_VERBOSE)
 +				printf(
 +		    "Overlapping memory regions, ignoring second region\n");
 +			return (1);
 +		}
 +	}
 +
 +	/* See if we can prepend to the next entry. */
 +	if (insert_idx <= physmap_idx &&
 +	    smap->base + smap->length == physmap[insert_idx]) {
 +		physmap[insert_idx] = smap->base;
 +		return (1);
 +	}
 +
 +	/* See if we can append to the previous entry. */
 +	if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) {
 +		physmap[insert_idx - 1] += smap->length;
 +		return (1);
 +	}
 +
 +	physmap_idx += 2;
 +	*physmap_idxp = physmap_idx;
 +	if (physmap_idx == PHYSMAP_SIZE) {
 +		printf(
 +		"Too many segments in the physical address map, giving up\n");
 +		return (0);
 +	}
 +
 +	/*
 +	 * Move the last 'N' entries down to make room for the new
 +	 * entry if needed.
 +	 */
 +	for (i = physmap_idx; i > insert_idx; i -= 2) {
 +		physmap[i] = physmap[i - 2];
 +		physmap[i + 1] = physmap[i - 1];
 +	}
 +
 +	/* Insert the new entry. */
 +	physmap[insert_idx] = smap->base;
 +	physmap[insert_idx + 1] = smap->base + smap->length;
 +	return (1);
 +}
 +
  /*
   * Populate the (physmap) array with base/bound pairs describing the
   * available physical memory in the system, then test this memory and
 @@ -1235,40 +1306,9 @@ getmemsize(caddr_t kmdp, u_int64_t first
  	smapsize = *((u_int32_t *)smapbase - 1);
  	smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
  
 -	for (smap = smapbase; smap < smapend; smap++) {
 -		if (boothowto & RB_VERBOSE)
 -			printf("SMAP type=%02x base=%016lx len=%016lx\n",
 -			    smap->type, smap->base, smap->length);
 -
 -		if (smap->type != SMAP_TYPE_MEMORY)
 -			continue;
 -
 -		if (smap->length == 0)
 -			continue;
 -
 -		for (i = 0; i <= physmap_idx; i += 2) {
 -			if (smap->base < physmap[i + 1]) {
 -				if (boothowto & RB_VERBOSE)
 -					printf(
 -	"Overlapping or non-monotonic memory region, ignoring second region\n");
 -				continue;
 -			}
 -		}
 -
 -		if (smap->base == physmap[physmap_idx + 1]) {
 -			physmap[physmap_idx + 1] += smap->length;
 -			continue;
 -		}
 -
 -		physmap_idx += 2;
 -		if (physmap_idx == PHYSMAP_SIZE) {
 -			printf(
 -		"Too many segments in the physical address map, giving up\n");
 +	for (smap = smapbase; smap < smapend; smap++)
 +		if (!add_smap_entry(smap, physmap, &physmap_idx))
  			break;
 -		}
 -		physmap[physmap_idx] = smap->base;
 -		physmap[physmap_idx + 1] = smap->base + smap->length;
 -	}
  
  	/*
  	 * Find the 'base memory' segment for SMP
 
 Modified: head/sys/i386/i386/machdep.c
 ==============================================================================
 --- head/sys/i386/i386/machdep.c	Tue Sep 22 16:28:07 2009	(r197409)
 +++ head/sys/i386/i386/machdep.c	Tue Sep 22 16:51:00 2009	(r197410)
 @@ -1946,7 +1946,7 @@ sdtossd(sd, ssd)
  static int
  add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp)
  {
 -	int i, physmap_idx;
 +	int i, insert_idx, physmap_idx;
  
  	physmap_idx = *physmap_idxp;
  	
 @@ -1968,17 +1968,34 @@ add_smap_entry(struct bios_smap *smap, v
  	}
  #endif
  
 +	/*
 +	 * Find insertion point while checking for overlap.  Start off by
 +	 * assuming the new entry will be added to the end.
 +	 */
 +	insert_idx = physmap_idx + 2;
  	for (i = 0; i <= physmap_idx; i += 2) {
  		if (smap->base < physmap[i + 1]) {
 +			if (smap->base + smap->length <= physmap[i]) {
 +				insert_idx = i;
 +				break;
 +			}
  			if (boothowto & RB_VERBOSE)
  				printf(
 -	"Overlapping or non-monotonic memory region, ignoring second region\n");
 +		    "Overlapping memory regions, ignoring second region\n");
  			return (1);
  		}
  	}
  
 -	if (smap->base == physmap[physmap_idx + 1]) {
 -		physmap[physmap_idx + 1] += smap->length;
 +	/* See if we can prepend to the next entry. */
 +	if (insert_idx <= physmap_idx &&
 +	    smap->base + smap->length == physmap[insert_idx]) {
 +		physmap[insert_idx] = smap->base;
 +		return (1);
 +	}
 +
 +	/* See if we can append to the previous entry. */
 +	if (insert_idx > 0 && smap->base == physmap[insert_idx - 1]) {
 +		physmap[insert_idx - 1] += smap->length;
  		return (1);
  	}
  
 @@ -1989,8 +2006,19 @@ add_smap_entry(struct bios_smap *smap, v
  		"Too many segments in the physical address map, giving up\n");
  		return (0);
  	}
 -	physmap[physmap_idx] = smap->base;
 -	physmap[physmap_idx + 1] = smap->base + smap->length;
 +
 +	/*
 +	 * Move the last 'N' entries down to make room for the new
 +	 * entry if needed.
 +	 */
 +	for (i = physmap_idx; i > insert_idx; i -= 2) {
 +		physmap[i] = physmap[i - 2];
 +		physmap[i + 1] = physmap[i - 1];
 +	}
 +
 +	/* Insert the new entry. */
 +	physmap[insert_idx] = smap->base;
 +	physmap[insert_idx + 1] = smap->base + smap->length;
  	return (1);
  }
  
 _______________________________________________
 svn-src-all at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-amd64 mailing list