Print this page
remove xhat
The xhat infrastructure was added to support hardware such as the zulu
graphics card - hardware which had on-board MMUs.  The VM used the xhat code
to keep the CPU's and Zulu's page tables in-sync.  Since the only xhat user
was zulu (which is gone), we can safely remove it simplifying the whole VM
subsystem.
Assorted notes:
- AS_BUSY flag was used solely by xhat

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  851          int holding_wpage = 0;
 885      -        extern struct seg_ops   segdev_ops;
 886  852  
 887  853  
 888  854  
 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  855  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++;
      856 +        /*
      857 +         * Indicate that the lwp is not to be stopped while waiting for a
      858 +         * pagefault.  This is to avoid deadlock while debugging a process
      859 +         * via /proc over NFS (in particular).
      860 +         */
      861 +        if (lwp != NULL)
      862 +                lwp->lwp_nostop++;
 906  863  
 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) {
      864 +        /*
      865 +         * same length must be used when we softlock and softunlock.  We
      866 +         * don't support softunlocking lengths less than the original length
      867 +         * when there is largepage support.  See seg_dev.c for more
      868 +         * comments.
      869 +         */
      870 +        switch (type) {
 914  871  
 915      -                case F_SOFTLOCK:
 916      -                        CPU_STATS_ADD_K(vm, softlock, 1);
 917      -                        break;
      872 +        case F_SOFTLOCK:
      873 +                CPU_STATS_ADD_K(vm, softlock, 1);
      874 +                break;
 918  875  
 919      -                case F_SOFTUNLOCK:
 920      -                        break;
      876 +        case F_SOFTUNLOCK:
      877 +                break;
 921  878  
 922      -                case F_PROT:
 923      -                        CPU_STATS_ADD_K(vm, prot_fault, 1);
 924      -                        break;
      879 +        case F_PROT:
      880 +                CPU_STATS_ADD_K(vm, prot_fault, 1);
      881 +                break;
 925  882  
 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      -                }
      883 +        case F_INVAL:
      884 +                CPU_STATS_ENTER_K();
      885 +                CPU_STATS_ADDQ(CPU, vm, as_fault, 1);
      886 +                if (as == &kas)
      887 +                        CPU_STATS_ADDQ(CPU, vm, kernel_asflt, 1);
      888 +                CPU_STATS_EXIT_K();
      889 +                break;
 934  890          }
 935  891  
 936  892          /* Kernel probe */
 937  893          TNF_PROBE_3(address_fault, "vm pagefault", /* CSTYLED */,
 938  894              tnf_opaque, address,        addr,
 939  895              tnf_fault_type,     fault_type,     type,
 940  896              tnf_seg_access,     access,         rw);
 941  897  
 942  898          raddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
 943  899          rsize = (((size_t)(addr + size) + PAGEOFFSET) & PAGEMASK) -
↓ open down ↓ 1 lines elided ↑ open up ↑
 945  901  
 946  902          /*
 947  903           * XXX -- Don't grab the as lock for segkmap. We should grab it for
 948  904           * correctness, but then we could be stuck holding this lock for
 949  905           * a LONG time if the fault needs to be resolved on a slow
 950  906           * filesystem, and then no-one will be able to exec new commands,
 951  907           * as exec'ing requires the write lock on the as.
 952  908           */
 953  909          if (as == &kas && segkmap && segkmap->s_base <= raddr &&
 954  910              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  911                  seg = segkmap;
 960  912                  as_lock_held = 0;
 961  913          } else {
 962  914                  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  915  
 980  916                  seg = as_segat(as, raddr);
 981  917                  if (seg == NULL) {
 982  918                          AS_LOCK_EXIT(as, &as->a_lock);
 983      -                        if ((lwp != NULL) && (!is_xhat))
      919 +                        if (lwp != NULL)
 984  920                                  lwp->lwp_nostop--;
 985  921                          return (FC_NOMAP);
 986  922                  }
 987  923  
 988  924                  as_lock_held = 1;
 989  925          }
 990  926  
 991  927          addrsav = raddr;
 992  928          segsav = seg;
 993  929  
↓ open down ↓ 3 lines elided ↑ open up ↑
 997  933                          if (seg == NULL || raddr != seg->s_base) {
 998  934                                  res = FC_NOMAP;
 999  935                                  break;
1000  936                          }
1001  937                  }
1002  938                  if (raddr + rsize > seg->s_base + seg->s_size)
1003  939                          ssize = seg->s_base + seg->s_size - raddr;
1004  940                  else
1005  941                          ssize = rsize;
1006  942  
1007      -                if (!is_xhat || (seg->s_ops != &segdev_ops)) {
      943 +                res = SEGOP_FAULT(hat, seg, raddr, ssize, type, rw);
1008  944  
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      -                        }
      945 +                /* Restore watchpoints */
      946 +                if (holding_wpage) {
      947 +                        as_setwatch(as);
      948 +                        holding_wpage = 0;
      949 +                }
1028  950  
1029      -                        if (res != 0)
1030      -                                break;
1031      -                } else {
1032      -                        /* XHAT does not support seg_dev */
1033      -                        res = FC_NOSUPPORT;
      951 +                if (res != 0)
1034  952                          break;
1035      -                }
1036  953          }
1037  954  
1038  955          /*
1039  956           * If we were SOFTLOCKing and encountered a failure,
1040  957           * we must SOFTUNLOCK the range we already did. (Maybe we
1041  958           * should just panic if we are SOFTLOCKing or even SOFTUNLOCKing
1042  959           * right here...)
1043  960           */
1044  961          if (res != 0 && type == F_SOFTLOCK) {
1045  962                  for (seg = segsav; addrsav < raddr; addrsav += ssize) {
↓ open down ↓ 8 lines elided ↑ open up ↑
1054  971                          if (raddr > seg->s_base + seg->s_size)
1055  972                                  ssize = seg->s_base + seg->s_size - addrsav;
1056  973                          else
1057  974                                  ssize = raddr - addrsav;
1058  975                          (void) SEGOP_FAULT(hat, seg, addrsav, ssize,
1059  976                              F_SOFTUNLOCK, S_OTHER);
1060  977                  }
1061  978          }
1062  979          if (as_lock_held)
1063  980                  AS_LOCK_EXIT(as, &as->a_lock);
1064      -        if ((lwp != NULL) && (!is_xhat))
      981 +        if (lwp != NULL)
1065  982                  lwp->lwp_nostop--;
1066  983  
1067  984          /*
1068  985           * If the lower levels returned EDEADLK for a fault,
1069  986           * It means that we should retry the fault.  Let's wait
1070  987           * a bit also to let the deadlock causing condition clear.
1071  988           * This is part of a gross hack to work around a design flaw
1072  989           * in the ufs/sds logging code and should go away when the
1073  990           * logging code is re-designed to fix the problem. See bug
1074  991           * 4125102 for details of the problem.
↓ open down ↓ 1084 lines elided ↑ open up ↑
2159 2076          /*
2160 2077           * Kernel-only processes have given up their address
2161 2078           * spaces.  Of course, we shouldn't be attempting to
2162 2079           * swap out such processes in the first place...
2163 2080           */
2164 2081          if (as == NULL)
2165 2082                  return (0);
2166 2083  
2167 2084          AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
2168 2085  
2169      -        /* Prevent XHATs from attaching */
2170      -        mutex_enter(&as->a_contents);
2171      -        AS_SETBUSY(as);
2172      -        mutex_exit(&as->a_contents);
2173      -
2174      -
2175 2086          /*
2176 2087           * Free all mapping resources associated with the address
2177 2088           * space.  The segment-level swapout routines capitalize
2178 2089           * on this unmapping by scavanging pages that have become
2179 2090           * unmapped here.
2180 2091           */
2181 2092          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 2093  
2189 2094          /*
2190 2095           * Call the swapout routines of all segments in the address
2191 2096           * space to do the actual work, accumulating the amount of
2192 2097           * space reclaimed.
2193 2098           */
2194 2099          for (seg = AS_SEGFIRST(as); seg != NULL; seg = AS_SEGNEXT(as, seg)) {
2195 2100                  struct seg_ops *ov = seg->s_ops;
2196 2101  
2197 2102                  /*
↓ open down ↓ 1495 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX