Hi, reading the source code of kmap_atomic() and kunmap_atomic() as
below, I would like to ask:
a. noticed that pagefault_disable() and pagefault_enable() is called
across two different function - why is that necessary?
b. basically, I would like to create a new page, and assign the PTE
to point to that page, and change the page attributes in the PTE - so
all these operation MUST ALWAYS BE done with pagefault disabled?
c. Since within an interrupt, the interrupt is disabled, therefore,
I can always do these above operation inside the pagefault handler
context as well?
d. After I get a new page with __get_free_page(__GFP_HIGHMEM), and
returned value is not null, it means that PTE mapping has already been
allocated to it, right?
e. So if I want to change the page attributes inside the PTE from
(d), it should be done within pagefault_disabled mode?
f. After I set the _PAGE_PRESENT bit of the PTE to invalid, and
since __get_free_page() derive the page from a free_list, will the
page ever be reused by the kernel, either for another allocation, or
for some other purposes?
Sorry, if these questions are confusing.....
==============================================================================
/*
* kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
* no global lock is needed and because the kmap code must perform a global TLB
* invalidation when the kmap pool wraps.
*
* However when holding an atomic kmap is is not legal to sleep, so atomic
* kmaps are appropriate for short, tight code paths only.
*/
void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
{
enum fixed_addresses idx;
unsigned long vaddr;
/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
pagefault_disable();
if (!PageHighMem(page))
return page_address(page);
debug_kmap_atomic_prot(type);
idx = type + KM_TYPE_NR*smp_processor_id();
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
BUG_ON(!pte_none(*(kmap_pte-idx)));
set_pte(kmap_pte-idx, mk_pte(page, prot));
arch_flush_lazy_mmu_mode();
return (void *)vaddr;
}
void *kmap_atomic(struct page *page, enum km_type type)
{
return kmap_atomic_prot(page, type, kmap_prot);
}
void kunmap_atomic(void *kvaddr, enum km_type type)
{
unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
/*
* Force other mappings to Oops if they'll try to access this pte
* without first remap it. Keeping stale mappings around is a bad idea
* also, in case the page changes cacheability attributes or becomes
* a protected page in a hypervisor.
*/
if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
kpte_clear_flush(kmap_pte-idx, vaddr);
else {
#ifdef CONFIG_DEBUG_HIGHMEM
BUG_ON(vaddr < PAGE_OFFSET);
BUG_ON(vaddr >= (unsigned long)high_memory);
#endif
}
arch_flush_lazy_mmu_mode();
pagefault_enable();
}
--
Regards,
Peter Teoh
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [EMAIL PROTECTED]
Please read the FAQ at http://kernelnewbies.org/FAQ