[PATCH] DMA 4GB boundary protection

Jake Moilanen moilanen at austin.ibm.com
Fri Mar 23 04:47:45 EST 2007


On Thu, 2007-03-22 at 12:53 -0500, Olof Johansson wrote:
> On Wed, Mar 21, 2007 at 04:05:48PM -0500, Jake Moilanen wrote:
> 
> > @@ -480,6 +495,21 @@ struct iommu_table *iommu_init_table(str
> >  	ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
> >  #endif
> >  
> > +	/*
> > +	 * DMA cannot cross 4 GB boundary.  Mark first entry of each 4
> > +	 * GB chunk as reserved.
> > +	 */
> > +	if (protect4gb) {
> > +		start_addr = tbl->it_offset << IOMMU_PAGE_SHIFT;
> > +		/* go up to next 4GB boundary */
> > +		start_addr = (start_addr + 0x00000000ffffffffl) >> 32;
> > +		end_addr = (tbl->it_offset + tbl->it_size) << IOMMU_PAGE_SHIFT;
> > +		for (index = start_addr; index < end_addr; index += (1l << 32)) {
> > +			/* Reserve 4GB entry */
> > +			__set_bit((index >> IOMMU_PAGE_SHIFT) - tbl->it_offset,
> > tbl->it_map);
> > +		}
> > +	}
> > +
> 
> 
> This is done a bit more complicated than it has to be. The >> 32 is a
> red flag as well.
> 
> I would also like it to be the last page in the range, not the first
> (since otherwise you'll reserve even if the window is less than 4GB.
> 
> Something like (untested):
> 
> 	entries_per_4g = 0x100000000 >> IOMMU_PAGE_SHIFT;
> 
> 	/* Mark the last bit before a 4GB boundary as used */
> 	start_index = tbl->it_offset | (entries_per_4g - 1);
> 	end_index = tbl->it_offset + tbl->it_size;
> 
> 	for (index = start_index; index < end_index; index += entries_per_4g)
> 		__set_bit(index, tbl->it_map);
> 
> Is easier to follow.

Yup, I like that better.  I'll give it a run.

Jake




More information about the Linuxppc-dev mailing list