????????????????????????????--

????1???????????????????????????vma?У?????δ?????????????????????OK??????????????????????????

????2?????????????????????????????vma?У???????????ж????????????????????????????????????????????????????????????????????????????????????????????????????????η??????????????????????????

????????????do_page_fault()?????????????????????

dotraplinkage void __kprobes
do_page_fault(struct pt_regs *regs?? unsigned long error_code)
{
 struct vm_area_struct *vma;
 struct task_struct *tsk;
 unsigned long address;
 struct mm_struct *mm;
 int write;
 int fault;

 tsk = current; //??????????
 mm = tsk->mm;  //????????????????

 /* Get the faulting address: */
 address = read_cr2(); //???CR2?????????????????????

 ...
         ...
         ...
         ...

 vma = find_vma(mm?? address);//????????????address????vma??vma????address????address???

 /*????????????vma?????address?????????????????????address???????Ч???
   ???bad_area()·?????????bad_area()????????__bad_area()-->bad_area_nosemaphore()*/
 if (unlikely(!vma)) {
  bad_area(regs?? error_code?? address);
  return;
 }
 /*?????????????vma??У????????good_area?????д???*/
 if (likely(vma->vm_start <= address))
  goto good_area;

 /*??????????????????????ж?????????????????????????????????????PUSH???
   ???????????δ????????????????????μ?????????????????????????????VM_GROWSDOWNλ
   ????λ*/
 if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
  bad_area(regs?? error_code?? address);//??????????????bad_area()??????
  return;
 }
 if (error_code & PF_USER) {//????????????
  /*
   * Accessing the stack below %sp is always a bug.
   * The large cushion allows instructions like enter
   * and pusha to work. ("enter $65535?? $31" pushes
   * 32 pointers and then decrements %sp by 65535.)
   */
   /*??????address????и???????(?????????????65536+32*sizeof(unsigned long))??
     ??????????????????????????????????bad_area()????*/
  if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
   bad_area(regs?? error_code?? address);
   return;
  }
 }
 if (unlikely(expand_stack(vma?? address))) {//????????????????bad_area()????
  bad_area(regs?? error_code?? address);
  return;
 }