X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fx86%2Fmm%2Fpat.c;h=d4585077977a0bd1c6c7234b09051d671851a6aa;hb=751851af7aae9b8bd5a60b3897209081fbc18b2b;hp=c996a3641200c101266f07708e337861ab9ffd6f;hpb=69e26be9b1d0c83d3581475095ce2a1ccc578215;p=linux-2.6 diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index c996a36412..d458507797 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -178,6 +178,33 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type) return req_type; } +static int chk_conflict(struct memtype *new, struct memtype *entry, + unsigned long *type) +{ + if (new->type != entry->type) { + if (type) { + new->type = entry->type; + *type = entry->type; + } else + goto conflict; + } + + /* check overlaps with more than one entry in the list */ + list_for_each_entry_continue(entry, &memtype_list, nd) { + if (new->end <= entry->start) + break; + else if (new->type != entry->type) + goto conflict; + } + return 0; + + conflict: + printk(KERN_INFO "%s:%d conflicting memory types " + "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start, + new->end, cattr_name(new->type), cattr_name(entry->type)); + return -EBUSY; +} + /* * req_type typically has one of the: * - _PAGE_CACHE_WB @@ -198,6 +225,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, { struct memtype *new, *entry; unsigned long actual_type; + struct list_head *where; int err = 0; BUG_ON(start >= end); /* end is exclusive */ @@ -251,150 +279,50 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, spin_lock(&memtype_lock); /* Search for existing mapping that overlaps the current range */ + where = NULL; list_for_each_entry(entry, &memtype_list, nd) { - struct memtype *saved_ptr; - - if (entry->start >= end) { - dprintk("New Entry\n"); - list_add(&new->nd, entry->nd.prev); - new = NULL; + if (end <= entry->start) { + where = entry->nd.prev; break; - } - - if (start <= entry->start && end >= entry->start) { - if (actual_type != entry->type && new_type) { - actual_type = entry->type; - *new_type = actual_type; - new->type = actual_type; - } - - if (actual_type != entry->type) { - printk( - KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n", - current->comm, current->pid, - start, end, - cattr_name(actual_type), - cattr_name(entry->type)); - err = -EBUSY; - break; - } - - saved_ptr = entry; - /* - * Check to see whether the request overlaps more - * than one entry in the list - */ - list_for_each_entry_continue(entry, &memtype_list, nd) { - if (end <= entry->start) { - break; - } - - if (actual_type != entry->type) { - printk( - KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n", - current->comm, current->pid, - start, end, - cattr_name(actual_type), - cattr_name(entry->type)); - err = -EBUSY; - break; - } - } - - if (err) { - break; + } else if (start <= entry->start) { /* end > entry->start */ + err = chk_conflict(new, entry, new_type); + if (!err) { + dprintk("Overlap at 0x%Lx-0x%Lx\n", + entry->start, entry->end); + where = entry->nd.prev; } - - dprintk("Overlap at 0x%Lx-0x%Lx\n", - saved_ptr->start, saved_ptr->end); - /* No conflict. Go ahead and add this new entry */ - list_add(&new->nd, saved_ptr->nd.prev); - new = NULL; break; - } - - if (start < entry->end) { - if (actual_type != entry->type && new_type) { - actual_type = entry->type; - *new_type = actual_type; - new->type = actual_type; - } - - if (actual_type != entry->type) { - printk( - KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n", - current->comm, current->pid, - start, end, - cattr_name(actual_type), - cattr_name(entry->type)); - err = -EBUSY; - break; - } - - saved_ptr = entry; - /* - * Check to see whether the request overlaps more - * than one entry in the list - */ - list_for_each_entry_continue(entry, &memtype_list, nd) { - if (end <= entry->start) { - break; - } - - if (actual_type != entry->type) { - printk( - KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n", - current->comm, current->pid, - start, end, - cattr_name(actual_type), - cattr_name(entry->type)); - err = -EBUSY; - break; - } - } - - if (err) { - break; + } else if (start < entry->end) { /* start > entry->start */ + err = chk_conflict(new, entry, new_type); + if (!err) { + dprintk("Overlap at 0x%Lx-0x%Lx\n", + entry->start, entry->end); + where = &entry->nd; } - - dprintk("Overlap at 0x%Lx-0x%Lx\n", - saved_ptr->start, saved_ptr->end); - /* No conflict. Go ahead and add this new entry */ - list_add(&new->nd, &saved_ptr->nd); - new = NULL; break; } } if (err) { - printk(KERN_INFO - "reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n", - start, end, cattr_name(new->type), - cattr_name(req_type)); + printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, " + "track %s, req %s\n", + start, end, cattr_name(new->type), cattr_name(req_type)); kfree(new); spin_unlock(&memtype_lock); return err; } - if (new) { - /* No conflict. Not yet added to the list. Add to the tail */ + if (where) + list_add(&new->nd, where); + else list_add_tail(&new->nd, &memtype_list); - dprintk("New Entry\n"); - } - - if (new_type) { - dprintk( - "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n", - start, end, cattr_name(actual_type), - cattr_name(req_type), cattr_name(*new_type)); - } else { - dprintk( - "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n", - start, end, cattr_name(actual_type), - cattr_name(req_type)); - } spin_unlock(&memtype_lock); + + dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n", + start, end, cattr_name(new->type), cattr_name(req_type), + new_type ? cattr_name(*new_type) : "-"); + return err; } @@ -521,7 +449,8 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, if (retval < 0) return 0; - if (pfn <= max_pfn_mapped && + if (((pfn < max_low_pfn_mapped) || + (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn < max_pfn_mapped)) && ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) { free_memtype(offset, offset + size); printk(KERN_INFO