Print this page
patch fixes
6345 remove xhat support

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/vm/vm_as.c
          +++ new/usr/src/uts/common/vm/vm_as.c
↓ open down ↓ 51 lines elided ↑ open up ↑
  52   52  #include <sys/sysinfo.h>
  53   53  #include <sys/kmem.h>
  54   54  #include <sys/vnode.h>
  55   55  #include <sys/vmsystm.h>
  56   56  #include <sys/cmn_err.h>
  57   57  #include <sys/debug.h>
  58   58  #include <sys/tnf_probe.h>
  59   59  #include <sys/vtrace.h>
  60   60  
  61   61  #include <vm/hat.h>
  62      -#include <vm/xhat.h>
  63   62  #include <vm/as.h>
  64   63  #include <vm/seg.h>
  65   64  #include <vm/seg_vn.h>
  66   65  #include <vm/seg_dev.h>
  67   66  #include <vm/seg_kmem.h>
  68   67  #include <vm/seg_map.h>
  69   68  #include <vm/seg_spt.h>
  70   69  #include <vm/page.h>
  71   70  
  72   71  clock_t deadlk_wait = 1; /* number of ticks to wait before retrying */
↓ open down ↓ 591 lines elided ↑ open up ↑
 664  663          as->a_sizedir           = 0;
 665  664          as->a_userlimit         = (caddr_t)USERLIMIT;
 666  665          as->a_lastgap           = NULL;
 667  666          as->a_lastgaphl         = NULL;
 668  667          as->a_callbacks         = NULL;
 669  668  
 670  669          AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 671  670          as->a_hat = hat_alloc(as);      /* create hat for default system mmu */
 672  671          AS_LOCK_EXIT(as, &as->a_lock);
 673  672  
 674      -        as->a_xhat = NULL;
 675      -
 676  673          return (as);
 677  674  }
 678  675  
 679  676  /*
 680  677   * Free an address space data structure.
 681  678   * Need to free the hat first and then
 682  679   * all the segments on this as and finally
 683  680   * the space for the as struct itself.
 684  681   */
 685  682  void
 686  683  as_free(struct as *as)
 687  684  {
 688  685          struct hat *hat = as->a_hat;
 689  686          struct seg *seg, *next;
 690      -        int called = 0;
      687 +        boolean_t free_started = B_FALSE;
 691  688  
 692  689  top:
 693  690          /*
 694  691           * Invoke ALL callbacks. as_do_callbacks will do one callback
 695  692           * per call, and not return (-1) until the callback has completed.
 696  693           * When as_do_callbacks returns zero, all callbacks have completed.
 697  694           */
 698  695          mutex_enter(&as->a_contents);
 699  696          while (as->a_callbacks && as_do_callbacks(as, AS_ALL_EVENT, 0, 0))
 700  697                  ;
 701  698  
 702      -        /* This will prevent new XHATs from attaching to as */
 703      -        if (!called)
 704      -                AS_SETBUSY(as);
 705  699          mutex_exit(&as->a_contents);
 706  700          AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 707  701  
 708      -        if (!called) {
 709      -                called = 1;
      702 +        if (!free_started) {
      703 +                free_started = B_TRUE;
 710  704                  hat_free_start(hat);
 711      -                if (as->a_xhat != NULL)
 712      -                        xhat_free_start_all(as);
 713  705          }
 714  706          for (seg = AS_SEGFIRST(as); seg != NULL; seg = next) {
 715  707                  int err;
 716  708  
 717  709                  next = AS_SEGNEXT(as, seg);
 718  710  retry:
 719  711                  err = SEGOP_UNMAP(seg, seg->s_base, seg->s_size);
 720  712                  if (err == EAGAIN) {
 721  713                          mutex_enter(&as->a_contents);
 722  714                          if (as->a_callbacks) {
↓ open down ↓ 29 lines elided ↑ open up ↑
 752  744                          goto top;
 753  745                  } else {
 754  746                          /*
 755  747                           * We do not expect any other error return at this
 756  748                           * time. This is similar to an ASSERT in seg_unmap()
 757  749                           */
 758  750                          ASSERT(err == 0);
 759  751                  }
 760  752          }
 761  753          hat_free_end(hat);
 762      -        if (as->a_xhat != NULL)
 763      -                xhat_free_end_all(as);
 764  754          AS_LOCK_EXIT(as, &as->a_lock);
 765  755  
 766  756          /* /proc stuff */
 767  757          ASSERT(avl_numnodes(&as->a_wpage) == 0);
 768  758          if (as->a_objectdir) {
 769  759                  kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
 770  760                  as->a_objectdir = NULL;
 771  761                  as->a_sizedir = 0;
 772  762          }
 773  763  
↓ open down ↓ 13 lines elided ↑ open up ↑
 787  777          int error;
 788  778  
 789  779          AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 790  780          as_clearwatch(as);
 791  781          newas = as_alloc();
 792  782          newas->a_userlimit = as->a_userlimit;
 793  783          newas->a_proc = forkedproc;
 794  784  
 795  785          AS_LOCK_ENTER(newas, &newas->a_lock, RW_WRITER);
 796  786  
 797      -        /* This will prevent new XHATs from attaching */
 798      -        mutex_enter(&as->a_contents);
 799      -        AS_SETBUSY(as);
 800      -        mutex_exit(&as->a_contents);
 801      -        mutex_enter(&newas->a_contents);
 802      -        AS_SETBUSY(newas);
 803      -        mutex_exit(&newas->a_contents);
 804      -
 805  787          (void) hat_dup(as->a_hat, newas->a_hat, NULL, 0, HAT_DUP_SRD);
 806  788  
 807  789          for (seg = AS_SEGFIRST(as); seg != NULL; seg = AS_SEGNEXT(as, seg)) {
 808  790  
 809  791                  if (seg->s_flags & S_PURGE) {
 810  792                          purgesize += seg->s_size;
 811  793                          continue;
 812  794                  }
 813  795  
 814  796                  newseg = seg_alloc(newas, seg->s_base, seg->s_size);
 815  797                  if (newseg == NULL) {
 816  798                          AS_LOCK_EXIT(newas, &newas->a_lock);
 817  799                          as_setwatch(as);
 818      -                        mutex_enter(&as->a_contents);
 819      -                        AS_CLRBUSY(as);
 820      -                        mutex_exit(&as->a_contents);
 821  800                          AS_LOCK_EXIT(as, &as->a_lock);
 822  801                          as_free(newas);
 823  802                          return (-1);
 824  803                  }
 825  804                  if ((error = SEGOP_DUP(seg, newseg)) != 0) {
 826  805                          /*
 827  806                           * We call seg_free() on the new seg
 828  807                           * because the segment is not set up
 829  808                           * completely; i.e. it has no ops.
 830  809                           */
 831  810                          as_setwatch(as);
 832      -                        mutex_enter(&as->a_contents);
 833      -                        AS_CLRBUSY(as);
 834      -                        mutex_exit(&as->a_contents);
 835  811                          AS_LOCK_EXIT(as, &as->a_lock);
 836  812                          seg_free(newseg);
 837  813                          AS_LOCK_EXIT(newas, &newas->a_lock);
 838  814                          as_free(newas);
 839  815                          return (error);
 840  816                  }
 841  817                  newas->a_size += seg->s_size;
 842  818          }
 843  819          newas->a_resvsize = as->a_resvsize - purgesize;
 844  820  
 845  821          error = hat_dup(as->a_hat, newas->a_hat, NULL, 0, HAT_DUP_ALL);
 846      -        if (as->a_xhat != NULL)
 847      -                error |= xhat_dup_all(as, newas, NULL, 0, HAT_DUP_ALL);
 848  822  
 849      -        mutex_enter(&newas->a_contents);
 850      -        AS_CLRBUSY(newas);
 851      -        mutex_exit(&newas->a_contents);
 852  823          AS_LOCK_EXIT(newas, &newas->a_lock);
 853  824  
 854  825          as_setwatch(as);
 855      -        mutex_enter(&as->a_contents);
 856      -        AS_CLRBUSY(as);
 857      -        mutex_exit(&as->a_contents);
 858  826          AS_LOCK_EXIT(as, &as->a_lock);
 859  827          if (error != 0) {
 860  828                  as_free(newas);
 861  829                  return (error);
 862  830          }
 863  831          forkedproc->p_as = newas;
 864  832          return (0);
 865  833  }
 866  834  
 867  835  /*
↓ open down ↓ 5 lines elided ↑ open up ↑
 873  841  {
 874  842          struct seg *seg;
 875  843          caddr_t raddr;                  /* rounded down addr */
 876  844          size_t rsize;                   /* rounded up size */
 877  845          size_t ssize;
 878  846          faultcode_t res = 0;
 879  847          caddr_t addrsav;
 880  848          struct seg *segsav;
 881  849          int as_lock_held;
 882  850          klwp_t *lwp = ttolwp(curthread);
 883      -        int is_xhat = 0;
 884      -        int holding_wpage = 0;
 885      -        extern struct seg_ops   segdev_ops;
 886  851  
 887  852  
 888  853  
 889      -        if (as->a_hat != hat) {
 890      -                /* This must be an XHAT then */
 891      -                is_xhat = 1;
 892      -
 893      -                if ((type != F_INVAL) || (as == &kas))
 894      -                        return (FC_NOSUPPORT);
 895      -        }
 896      -
 897  854  retry:
 898      -        if (!is_xhat) {
 899      -                /*
 900      -                 * Indicate that the lwp is not to be stopped while waiting
 901      -                 * for a pagefault.  This is to avoid deadlock while debugging
 902      -                 * a process via /proc over NFS (in particular).
 903      -                 */
 904      -                if (lwp != NULL)
 905      -                        lwp->lwp_nostop++;
      855 +        /*
      856 +         * Indicate that the lwp is not to be stopped while waiting for a
      857 +         * pagefault.  This is to avoid deadlock while debugging a process
      858 +         * via /proc over NFS (in particular).
      859 +         */
      860 +        if (lwp != NULL)
      861 +                lwp->lwp_nostop++;
 906  862  
 907      -                /*
 908      -                 * same length must be used when we softlock and softunlock.
 909      -                 * We don't support softunlocking lengths less than
 910      -                 * the original length when there is largepage support.
 911      -                 * See seg_dev.c for more comments.
 912      -                 */
 913      -                switch (type) {
      863 +        /*
      864 +         * same length must be used when we softlock and softunlock.  We
      865 +         * don't support softunlocking lengths less than the original length
      866 +         * when there is largepage support.  See seg_dev.c for more
      867 +         * comments.
      868 +         */
      869 +        switch (type) {
 914  870  
 915      -                case F_SOFTLOCK:
 916      -                        CPU_STATS_ADD_K(vm, softlock, 1);
 917      -                        break;
      871 +        case F_SOFTLOCK:
      872 +                CPU_STATS_ADD_K(vm, softlock, 1);
      873 +                break;
 918  874  
 919      -                case F_SOFTUNLOCK:
 920      -                        break;
      875 +        case F_SOFTUNLOCK:
      876 +                break;
 921  877  
 922      -                case F_PROT:
 923      -                        CPU_STATS_ADD_K(vm, prot_fault, 1);
 924      -                        break;
      878 +        case F_PROT:
      879 +                CPU_STATS_ADD_K(vm, prot_fault, 1);
      880 +                break;
 925  881  
 926      -                case F_INVAL:
 927      -                        CPU_STATS_ENTER_K();
 928      -                        CPU_STATS_ADDQ(CPU, vm, as_fault, 1);
 929      -                        if (as == &kas)
 930      -                                CPU_STATS_ADDQ(CPU, vm, kernel_asflt, 1);
 931      -                        CPU_STATS_EXIT_K();
 932      -                        break;
 933      -                }
      882 +        case F_INVAL:
      883 +                CPU_STATS_ENTER_K();
      884 +                CPU_STATS_ADDQ(CPU, vm, as_fault, 1);
      885 +                if (as == &kas)
      886 +                        CPU_STATS_ADDQ(CPU, vm, kernel_asflt, 1);
      887 +                CPU_STATS_EXIT_K();
      888 +                break;
 934  889          }
 935  890  
 936  891          /* Kernel probe */
 937  892          TNF_PROBE_3(address_fault, "vm pagefault", /* CSTYLED */,
 938  893              tnf_opaque, address,        addr,
 939  894              tnf_fault_type,     fault_type,     type,
 940  895              tnf_seg_access,     access,         rw);
 941  896  
 942  897          raddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
 943  898          rsize = (((size_t)(addr + size) + PAGEOFFSET) & PAGEMASK) -
↓ open down ↓ 1 lines elided ↑ open up ↑
 945  900  
 946  901          /*
 947  902           * XXX -- Don't grab the as lock for segkmap. We should grab it for
 948  903           * correctness, but then we could be stuck holding this lock for
 949  904           * a LONG time if the fault needs to be resolved on a slow
 950  905           * filesystem, and then no-one will be able to exec new commands,
 951  906           * as exec'ing requires the write lock on the as.
 952  907           */
 953  908          if (as == &kas && segkmap && segkmap->s_base <= raddr &&
 954  909              raddr + size < segkmap->s_base + segkmap->s_size) {
 955      -                /*
 956      -                 * if (as==&kas), this can't be XHAT: we've already returned
 957      -                 * FC_NOSUPPORT.
 958      -                 */
 959  910                  seg = segkmap;
 960  911                  as_lock_held = 0;
 961  912          } else {
 962  913                  AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
 963      -                if (is_xhat && avl_numnodes(&as->a_wpage) != 0) {
 964      -                        /*
 965      -                         * Grab and hold the writers' lock on the as
 966      -                         * if the fault is to a watched page.
 967      -                         * This will keep CPUs from "peeking" at the
 968      -                         * address range while we're temporarily boosting
 969      -                         * the permissions for the XHAT device to
 970      -                         * resolve the fault in the segment layer.
 971      -                         *
 972      -                         * We could check whether faulted address
 973      -                         * is within a watched page and only then grab
 974      -                         * the writer lock, but this is simpler.
 975      -                         */
 976      -                        AS_LOCK_EXIT(as, &as->a_lock);
 977      -                        AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 978      -                }
 979  914  
 980  915                  seg = as_segat(as, raddr);
 981  916                  if (seg == NULL) {
 982  917                          AS_LOCK_EXIT(as, &as->a_lock);
 983      -                        if ((lwp != NULL) && (!is_xhat))
      918 +                        if (lwp != NULL)
 984  919                                  lwp->lwp_nostop--;
 985  920                          return (FC_NOMAP);
 986  921                  }
 987  922  
 988  923                  as_lock_held = 1;
 989  924          }
 990  925  
 991  926          addrsav = raddr;
 992  927          segsav = seg;
 993  928  
↓ open down ↓ 3 lines elided ↑ open up ↑
 997  932                          if (seg == NULL || raddr != seg->s_base) {
 998  933                                  res = FC_NOMAP;
 999  934                                  break;
1000  935                          }
1001  936                  }
1002  937                  if (raddr + rsize > seg->s_base + seg->s_size)
1003  938                          ssize = seg->s_base + seg->s_size - raddr;
1004  939                  else
1005  940                          ssize = rsize;
1006  941  
1007      -                if (!is_xhat || (seg->s_ops != &segdev_ops)) {
1008      -
1009      -                        if (is_xhat && avl_numnodes(&as->a_wpage) != 0 &&
1010      -                            pr_is_watchpage_as(raddr, rw, as)) {
1011      -                                /*
1012      -                                 * Handle watch pages.  If we're faulting on a
1013      -                                 * watched page from an X-hat, we have to
1014      -                                 * restore the original permissions while we
1015      -                                 * handle the fault.
1016      -                                 */
1017      -                                as_clearwatch(as);
1018      -                                holding_wpage = 1;
1019      -                        }
1020      -
1021      -                        res = SEGOP_FAULT(hat, seg, raddr, ssize, type, rw);
1022      -
1023      -                        /* Restore watchpoints */
1024      -                        if (holding_wpage) {
1025      -                                as_setwatch(as);
1026      -                                holding_wpage = 0;
1027      -                        }
1028      -
1029      -                        if (res != 0)
1030      -                                break;
1031      -                } else {
1032      -                        /* XHAT does not support seg_dev */
1033      -                        res = FC_NOSUPPORT;
      942 +                res = SEGOP_FAULT(hat, seg, raddr, ssize, type, rw);
      943 +                if (res != 0)
1034  944                          break;
1035      -                }
1036  945          }
1037  946  
1038  947          /*
1039  948           * If we were SOFTLOCKing and encountered a failure,
1040  949           * we must SOFTUNLOCK the range we already did. (Maybe we
1041  950           * should just panic if we are SOFTLOCKing or even SOFTUNLOCKing
1042  951           * right here...)
1043  952           */
1044  953          if (res != 0 && type == F_SOFTLOCK) {
1045  954                  for (seg = segsav; addrsav < raddr; addrsav += ssize) {
↓ open down ↓ 8 lines elided ↑ open up ↑
1054  963                          if (raddr > seg->s_base + seg->s_size)
1055  964                                  ssize = seg->s_base + seg->s_size - addrsav;
1056  965                          else
1057  966                                  ssize = raddr - addrsav;
1058  967                          (void) SEGOP_FAULT(hat, seg, addrsav, ssize,
1059  968                              F_SOFTUNLOCK, S_OTHER);
1060  969                  }
1061  970          }
1062  971          if (as_lock_held)
1063  972                  AS_LOCK_EXIT(as, &as->a_lock);
1064      -        if ((lwp != NULL) && (!is_xhat))
      973 +        if (lwp != NULL)
1065  974                  lwp->lwp_nostop--;
1066  975  
1067  976          /*
1068  977           * If the lower levels returned EDEADLK for a fault,
1069  978           * It means that we should retry the fault.  Let's wait
1070  979           * a bit also to let the deadlock causing condition clear.
1071  980           * This is part of a gross hack to work around a design flaw
1072  981           * in the ufs/sds logging code and should go away when the
1073  982           * logging code is re-designed to fix the problem. See bug
1074  983           * 4125102 for details of the problem.
↓ open down ↓ 1084 lines elided ↑ open up ↑
2159 2068          /*
2160 2069           * Kernel-only processes have given up their address
2161 2070           * spaces.  Of course, we shouldn't be attempting to
2162 2071           * swap out such processes in the first place...
2163 2072           */
2164 2073          if (as == NULL)
2165 2074                  return (0);
2166 2075  
2167 2076          AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
2168 2077  
2169      -        /* Prevent XHATs from attaching */
2170      -        mutex_enter(&as->a_contents);
2171      -        AS_SETBUSY(as);
2172      -        mutex_exit(&as->a_contents);
2173      -
2174      -
2175 2078          /*
2176 2079           * Free all mapping resources associated with the address
2177 2080           * space.  The segment-level swapout routines capitalize
2178 2081           * on this unmapping by scavanging pages that have become
2179 2082           * unmapped here.
2180 2083           */
2181 2084          hat_swapout(as->a_hat);
2182      -        if (as->a_xhat != NULL)
2183      -                xhat_swapout_all(as);
2184      -
2185      -        mutex_enter(&as->a_contents);
2186      -        AS_CLRBUSY(as);
2187      -        mutex_exit(&as->a_contents);
2188 2085  
2189 2086          /*
2190 2087           * Call the swapout routines of all segments in the address
2191 2088           * space to do the actual work, accumulating the amount of
2192 2089           * space reclaimed.
2193 2090           */
2194 2091          for (seg = AS_SEGFIRST(as); seg != NULL; seg = AS_SEGNEXT(as, seg)) {
2195 2092                  struct seg_ops *ov = seg->s_ops;
2196 2093  
2197 2094                  /*
↓ open down ↓ 1495 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX