About pmap_mapdev() & pmap_unmapdev()
Kohji Okuno
okuno.kohji at jp.panasonic.com
Sat Oct 4 08:00:40 UTC 2014
Hi, Konstantin,
Thank you for your comment.
And, your change is better than mine.
> Do you mean that this panic is related to missed pmap_remove() ?
> I doubt it, since pmap_mapdev() does not establish managed mappings.
Yes, pmap_mapdev() does not establish managed mappings. But, if
kernel_pmap.pm_stats.resident_count is zero, then any managed pages
(for example pipe_map, exec_map, or etc.) are not able to change
unmanaged status, because pmap_remove() returns without calling
pmap_remove_pte().
In this result, I encounterd the panic. Could you refer the following?
Regards,
Kohji Okuno
int
vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
{
>> SNIP <<
/** this pmap_remove() does not change for mappings! **/
pmap_remove(map->pmap, entry->start, entry->end);
/*
* Delete the entry only after removing all pmap
* entries pointing to its pages. (Otherwise, its
* page frames may be reallocated, and any modify bits
* will be set in the wrong object!)
*/
/** this calls vm_page_free_toq() and causes panic! **/
vm_map_entry_delete(map, entry);
entry = next;
}
return (KERN_SUCCESS);
}
> On Fri, Oct 03, 2014 at 05:25:33PM +0900, Kohji Okuno wrote:
>> Hi,
>>
>> At least in i386 && 9-stable, when we call pmap_mapdev() and
>> pmap_unmapdev(), kernel_pmap.pm_stats.resident_count is decreased
>> incorrectly.
>>
>> pmap_mapdev_attr()->pmap_kenter_attr():
>> In this path, kernel_pmap.pm_stats.resident_count is not increlmented.
>>
>> pmap_unmapdev()->kmem_free(kernel_map)->vm_map_remove()->pmap_remove():
>> But, in this path, kernel_pmap.pm_stats.resident_count is decreased in
>> pmap_remove_pte().
>>
>> While I called pmap_mapdev() and pmap_unmapdev() repeatedly and
>> kernel_pmap.pm_stats.resident_count became `0', since pmap_remove()
>> returned without removing ptes, I encountered various kernel panics.
> I think you are right.
>
> The problem seems to be fixed in HEAD and 10, since mapdev was switched
> to use kva_alloc/kva_free. I added stable@ to Cc:.
>
>>
>> And, when I enabled INVARIANTS, I looked the following panic message.
>> panic: vm_page_free_toq: freeing mapped page 0xXXXXXXXX.
> Do you mean that this panic is related to missed pmap_remove() ?
> I doubt it, since pmap_mapdev() does not establish managed mappings.
>
>>
>> I think, I should change the following.
>> What do you think about this?
>>
>>
>> diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
>> index 2adc6f8..a0998e8 100644
>> --- a/sys/i386/i386/pmap.c
>> +++ b/sys/i386/i386/pmap.c
>> @@ -5061,6 +5061,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
>> {
>> vm_offset_t va, offset;
>> vm_size_t tmpsize;
>> + int kmem_allocated = 0;
>>
>> offset = pa & PAGE_MASK;
>> size = roundup(offset + size, PAGE_SIZE);
>> @@ -5068,13 +5069,18 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
>>
>> if (pa < KERNLOAD && pa + size <= KERNLOAD)
>> va = KERNBASE + pa;
>> - else
>> + else {
>> va = kmem_alloc_nofault(kernel_map, size);
>> + kmem_allocated = 1;
>
> You could just do
> PMAP_LOCK(kernel_pmap);
> kernel_pmap.pm_stats.resident_count += OFF_TO_IDX(size);
> PMAP_UNLOCK(kernel_pmap);
> there. And, the same fix is needed for amd64.
>
>> + }
>> if (!va)
>> panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
>>
>> - for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE)
>> + for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE) {
>> pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
>> + if (kmem_allocated)
>> + kernel_pmap.pm_stats.resident_count++;
>> + }
>> pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
>> pmap_invalidate_cache_range(va, va + size);
>> return ((void *)(va + offset));
>> _______________________________________________
>> freebsd-current at freebsd.org mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-current
>> To unsubscribe, send any mail to "freebsd-current-unsubscribe at freebsd.org"
> _______________________________________________
> freebsd-current at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to "freebsd-current-unsubscribe at freebsd.org"
More information about the freebsd-stable
mailing list