When WC MTRR is set up, any previous MTRR region with offending size will block correct MTRR setup.
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.
Commited now.
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?
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
Fixed and commited.
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.