首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

缺页异常详解(10)

缺页异常详解(10)

    /*再获取下访问异常的地址addr对应的二级页表条目地址page_table*/         page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
         if (likely(pte_same(*page_table, orig_pte))) {
                   if (old_page) {
                            if (!PageAnon(old_page)) {
                                     dec_mm_counter(mm, file_rss);
                                     inc_mm_counter(mm, anon_rss);
                            }
                   } else
                            inc_mm_counter(mm, anon_rss);
                   flush_cache_page(vma, address, pte_pfn(orig_pte));
        /*写新页的二级页表条目内容为脏*/
                   entry = mk_pte(new_page, vma->vm_page_prot);
                   entry = maybe_mkwrite(pte_mkdirty(entry), vma);
                   /*
                    * Clear the pte entry and flush it first, before updating the
                    * pte with the new entry. This will avoid a race condition
                    * seen in the presence of one thread doing SMC and another
                    * thread doing COW.
                    */
                   ptep_clear_flush(vma, address, page_table);
                   page_add_new_anon_rmap(new_page, vma, address);
                   /*
                    * We call the notify macro here because, when using secondary
                    * mmu page tables (such as kvm shadow page tables), we want the
                    * new page to be mapped directly into the secondary page table.
                    */
                   set_pte_at_notify(mm, address, page_table, entry);
                   update_mmu_cache(vma, address, entry);
                   if (old_page) {
                            /*
                             * Only after switching the pte to the new page may
                             * we remove the mapcount here. Otherwise another
                             * process may come and find the rmap count decremented
                             * before the pte is switched to the new page, and
                             * "reuse" the old page writing into it while our pte
                             * here still points into it and can be read by other
                             * threads.
                             *
                             * The critical issue is to order this
                             * page_remove_rmap with the ptp_clear_flush above.
                             * Those stores are ordered by (if nothing else,)
                             * the barrier present in the atomic_add_negative
                             * in page_remove_rmap.
                             *
                             * Then the TLB flush in ptep_clear_flush ensures that
                             * no process can access the old page before the
                             * decremented mapcount is visible. And the old page
                             * cannot be reused until after the decremented
                             * mapcount is visible. So transitively, TLBs to
                             * old page will be flushed before it can be reused.
                             */
                            page_remove_rmap(old_page);
                   }
                   /* Free the old page.. */
                   new_page = old_page;
                   ret |= VM_FAULT_WRITE;
         }
继承事业,薪火相传
返回列表