Bug 2750

Summary: MTRR linux setup failures.
Product: xorg Reporter: Thomas Hellström <thomas>
Component: Server/GeneralAssignee: Thomas Hellström <thomas>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: high CC: eich
Version: git   
Hardware: x86 (IA32)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments:
Description Flags
Patch to fix problems with Linux MTRR setup. none

Description Thomas Hellström 2005-03-16 13:07:21 UTC
When WC MTRR is set up, any previous MTRR region with offending size will block
correct MTRR setup.
Comment 1 Thomas Hellström 2005-03-16 13:11:12 UTC
Created attachment 2129 [details] [review]
Patch to fix problems with Linux MTRR setup.

This patch fixes the problem by removing any offending regions before trying to
set a new WC region. A region is considered offending if it partly overlapping
the  region we try to set.

It also fixes bugs related to the creation of the mtrr region linked list when
splitting has been active and final mtrr setting fails.
Comment 2 Thomas Hellström 2005-03-23 13:04:36 UTC
Commited now.
Comment 3 Egbert Eich 2005-05-11 09:07:52 UTC
Thomas,

Your code ends up in an endless loop if for some reason a range cannot be
unregistered.
You will need something like this in mtrr_remove_offending():
...
     if (gent.type == MTRR_TYPE_WRCOMB
            && ((gent.base >= base && gent.base + gent.size < base + size) ||
                (gent.base >  base && gent.base + gent.size <= base + size))
            && (*wcr
                = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from))){
            while(*wcr) {
                wcr = &((*wcr)->next);
            }
...
Could you please investigate this and apply a fix?
Comment 4 Thomas Hellström 2005-05-11 09:42:21 UTC
You're right. 

Do you have access to a machine where this actually happens? 
In that case could you try out this which is basically your fix but handled in a
way similar to what is done in mtrr_cull_region() for consistency?

    wcr = &wcreturn;
    for (gent.regnum = 0; 
	 ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++ ) {
	if (gent.type == MTRR_TYPE_WRCOMB
	    && ((gent.base >= base && gent.base + gent.size < base + size) || 
		(gent.base >  base && gent.base + gent.size <= base + size))) {
	    *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from);
	    if (*wcr) gent.regnum--;
	    while(*wcr) {
		wcr = &((*wcr)->next);
	    }
	}
    }
    return wcreturn;
}

/Thomas


Comment 5 Thomas Hellström 2005-05-17 13:41:53 UTC
Fixed and commited.
Comment 6 Egbert Eich 2005-05-18 00:37:33 UTC
Thomas, yes, your patch works. Thanks.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.