direct-io.hg

changeset 15134:96915ca8d5f2

[ACM] Simpler interface to hypercalls

Implement a simpler interface for the hypercalls to ACM. I put the
parameters to all hypercalls into a union. On top of this I have
implemented a shim layer for enabling ACM hypercalls on PPC.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kfraser@localhost.localdomain
date Thu May 24 10:18:55 2007 +0100 (2007-05-24)
parents 46095d5a59a9
children e49b110cbb4a 471478a1b89e
files tools/libxc/xc_acm.c tools/python/xen/lowlevel/acm/acm.c tools/security/secpol_tool.c xen/common/acm_ops.c xen/include/public/acm_ops.h xen/include/xen/hypercall.h
line diff
     1.1 --- a/tools/libxc/xc_acm.c	Thu May 24 10:14:05 2007 +0100
     1.2 +++ b/tools/libxc/xc_acm.c	Thu May 24 10:18:55 2007 +0100
     1.3 @@ -16,20 +16,96 @@
     1.4  
     1.5  int xc_acm_op(int xc_handle, int cmd, void *arg, unsigned long arg_size)
     1.6  {
     1.7 -    int ret = -1;
     1.8 +    int ret;
     1.9      DECLARE_HYPERCALL;
    1.10 +    struct xen_acmctl acmctl;
    1.11 +
    1.12 +    switch (cmd) {
    1.13 +        case ACMOP_setpolicy: {
    1.14 +            struct acm_setpolicy *setpolicy = (struct acm_setpolicy *)arg;
    1.15 +            memcpy(&acmctl.u.setpolicy,
    1.16 +                   setpolicy,
    1.17 +                   sizeof(struct acm_setpolicy));
    1.18 +        }
    1.19 +        break;
    1.20 +
    1.21 +        case ACMOP_getpolicy: {
    1.22 +            struct acm_getpolicy *getpolicy = (struct acm_getpolicy *)arg;
    1.23 +            memcpy(&acmctl.u.getpolicy,
    1.24 +                   getpolicy,
    1.25 +                   sizeof(struct acm_getpolicy));
    1.26 +        }
    1.27 +        break;
    1.28 +
    1.29 +        case ACMOP_dumpstats: {
    1.30 +            struct acm_dumpstats *dumpstats = (struct acm_dumpstats *)arg;
    1.31 +            memcpy(&acmctl.u.dumpstats,
    1.32 +                   dumpstats,
    1.33 +                   sizeof(struct acm_dumpstats));
    1.34 +        }
    1.35 +        break;
    1.36 +
    1.37 +        case ACMOP_getssid: {
    1.38 +            struct acm_getssid *getssid = (struct acm_getssid *)arg;
    1.39 +            memcpy(&acmctl.u.getssid,
    1.40 +                   getssid,
    1.41 +                   sizeof(struct acm_getssid));
    1.42 +        }
    1.43 +        break;
    1.44 +
    1.45 +        case ACMOP_getdecision: {
    1.46 +            struct acm_getdecision *getdecision = (struct acm_getdecision *)arg;
    1.47 +            memcpy(&acmctl.u.getdecision,
    1.48 +                   getdecision,
    1.49 +                   sizeof(struct acm_getdecision));
    1.50 +        }
    1.51 +        break;
    1.52 +
    1.53 +        case ACMOP_chgpolicy: {
    1.54 +            struct acm_change_policy *change_policy = (struct acm_change_policy *)arg;
    1.55 +            memcpy(&acmctl.u.change_policy,
    1.56 +                   change_policy,
    1.57 +                   sizeof(struct acm_change_policy));
    1.58 +        }
    1.59 +        break;
    1.60 +
    1.61 +        case ACMOP_relabeldoms: {
    1.62 +            struct acm_relabel_doms *relabel_doms = (struct acm_relabel_doms *)arg;
    1.63 +            memcpy(&acmctl.u.relabel_doms,
    1.64 +                   relabel_doms,
    1.65 +                   sizeof(struct acm_relabel_doms));
    1.66 +        }
    1.67 +        break;
    1.68 +    }
    1.69 +
    1.70 +    acmctl.cmd = cmd;
    1.71 +    acmctl.interface_version = ACM_INTERFACE_VERSION;
    1.72  
    1.73      hypercall.op = __HYPERVISOR_acm_op;
    1.74 -    hypercall.arg[0] = cmd;
    1.75 -    hypercall.arg[1] = (unsigned long) arg;
    1.76 +    hypercall.arg[0] = (unsigned long)&acmctl;
    1.77 +    if ( lock_pages(&acmctl, sizeof(acmctl)) != 0)
    1.78 +    {
    1.79 +        PERROR("Could not lock memory for Xen hypercall");
    1.80 +        return -EFAULT;
    1.81 +    }
    1.82 +    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
    1.83 +    {
    1.84 +        if ( errno == EACCES )
    1.85 +            DPRINTF("acmctl operation failed -- need to"
    1.86 +                    " rebuild the user-space tool set?\n");
    1.87 +    }
    1.88 +    unlock_pages(&acmctl, sizeof(acmctl));
    1.89  
    1.90 -    if (lock_pages(arg, arg_size) != 0) {
    1.91 -        PERROR("xc_acm_op: arg lock failed");
    1.92 -        goto out;
    1.93 +    switch (cmd) {
    1.94 +        case ACMOP_getdecision: {
    1.95 +            struct acm_getdecision *getdecision = (struct acm_getdecision *)arg;
    1.96 +            memcpy(getdecision,
    1.97 +                   &acmctl.u.getdecision,
    1.98 +                   sizeof(struct acm_getdecision));
    1.99 +            break;
   1.100 +        }
   1.101      }
   1.102 -    ret = do_xen_hypercall(xc_handle, &hypercall);
   1.103 -    unlock_pages(arg, arg_size);
   1.104 - out:
   1.105 +
   1.106      return ret;
   1.107  }
   1.108  
     2.1 --- a/tools/python/xen/lowlevel/acm/acm.c	Thu May 24 10:14:05 2007 +0100
     2.2 +++ b/tools/python/xen/lowlevel/acm/acm.c	Thu May 24 10:18:55 2007 +0100
     2.3 @@ -53,7 +53,6 @@ void * __getssid(int domid, uint32_t *bu
     2.4          goto out2;
     2.5      }
     2.6      memset(buf, 0, SSID_BUFFER_SIZE);
     2.7 -    getssid.interface_version = ACM_INTERFACE_VERSION;
     2.8      set_xen_guest_handle(getssid.ssidbuf, buf);
     2.9      getssid.ssidbuf_size = SSID_BUFFER_SIZE;
    2.10      getssid.get_ssid_by = ACM_GETBY_domainid;
    2.11 @@ -163,7 +162,6 @@ static PyObject *getdecision(PyObject * 
    2.12      (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
    2.13          return NULL;
    2.14  
    2.15 -    getdecision.interface_version = ACM_INTERFACE_VERSION;
    2.16      getdecision.hook = ACMHOOK_sharing;
    2.17      if (!strcmp(arg1_name, "domid")) {
    2.18          getdecision.get_decision_by1 = ACM_GETBY_domainid;
     3.1 --- a/tools/security/secpol_tool.c	Thu May 24 10:14:05 2007 +0100
     3.2 +++ b/tools/security/secpol_tool.c	Thu May 24 10:18:55 2007 +0100
     3.3 @@ -243,7 +243,6 @@ int acm_get_ssidref(int xc_handle, int d
     3.4      struct acm_getssid getssid;
     3.5      char buf[4096];
     3.6      struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)buf;
     3.7 -    getssid.interface_version = ACM_INTERFACE_VERSION;
     3.8      set_xen_guest_handle(getssid.ssidbuf, buf);
     3.9      getssid.ssidbuf_size = sizeof(buf);
    3.10      getssid.get_ssid_by = ACM_GETBY_domainid;
    3.11 @@ -268,7 +267,6 @@ int acm_domain_getpolicy(int xc_handle)
    3.12      uint16_t chwall_ref, ste_ref;
    3.13  
    3.14      memset(pull_buffer, 0x00, sizeof(pull_buffer));
    3.15 -    getpolicy.interface_version = ACM_INTERFACE_VERSION;
    3.16      set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
    3.17      getpolicy.pullcache_size = sizeof(pull_buffer);
    3.18      ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
    3.19 @@ -323,7 +321,6 @@ int acm_domain_loadpolicy(int xc_handle,
    3.20          struct acm_setpolicy setpolicy;
    3.21          /* dump it and then push it down into xen/acm */
    3.22          acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
    3.23 -        setpolicy.interface_version = ACM_INTERFACE_VERSION;
    3.24          set_xen_guest_handle(setpolicy.pushcache, buffer);
    3.25          setpolicy.pushcache_size = len;
    3.26          ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy));
    3.27 @@ -372,7 +369,6 @@ int acm_domain_dumpstats(int xc_handle)
    3.28      struct acm_stats_buffer *stats;
    3.29  
    3.30      memset(stats_buffer, 0x00, sizeof(stats_buffer));
    3.31 -    dumpstats.interface_version = ACM_INTERFACE_VERSION;
    3.32      set_xen_guest_handle(dumpstats.pullcache, stats_buffer);
    3.33      dumpstats.pullcache_size = sizeof(stats_buffer);
    3.34      ret = xc_acm_op(xc_handle, ACMOP_dumpstats, &dumpstats, sizeof(dumpstats));
     4.1 --- a/xen/common/acm_ops.c	Thu May 24 10:14:05 2007 +0100
     4.2 +++ b/xen/common/acm_ops.c	Thu May 24 10:18:55 2007 +0100
     4.3 @@ -38,69 +38,54 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
     4.4  
     4.5  int acm_authorize_acm_ops(struct domain *d)
     4.6  {
     4.7 +    /* currently, policy management functions are restricted to privileged domains */
     4.8      return (IS_PRIV(d) ? 0 : -EPERM);
     4.9  }
    4.10  
    4.11 -long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
    4.12 +
    4.13 +long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
    4.14  {
    4.15      long rc = -EFAULT;
    4.16 +    struct xen_acmctl curop, *op = &curop;
    4.17  
    4.18 -    if ( acm_authorize_acm_ops(current->domain) )
    4.19 +    if (acm_authorize_acm_ops(current->domain))
    4.20          return -EPERM;
    4.21  
    4.22 -    switch ( cmd )
    4.23 +    if ( copy_from_guest(op, u_acmctl, 1) )
    4.24 +        return -EFAULT;
    4.25 +
    4.26 +    if (op->interface_version != ACM_INTERFACE_VERSION)
    4.27 +        return -EACCES;
    4.28 +
    4.29 +    switch ( op->cmd )
    4.30      {
    4.31  
    4.32      case ACMOP_setpolicy: {
    4.33 -        struct acm_setpolicy setpolicy;
    4.34 -        if (copy_from_guest(&setpolicy, arg, 1) != 0)
    4.35 -            return -EFAULT;
    4.36 -        if (setpolicy.interface_version != ACM_INTERFACE_VERSION)
    4.37 -            return -EACCES;
    4.38 -
    4.39 -        rc = acm_set_policy(setpolicy.pushcache,
    4.40 -                            setpolicy.pushcache_size);
    4.41 +        rc = acm_set_policy(op->u.setpolicy.pushcache,
    4.42 +                            op->u.setpolicy.pushcache_size);
    4.43          break;
    4.44      }
    4.45  
    4.46      case ACMOP_getpolicy: {
    4.47 -        struct acm_getpolicy getpolicy;
    4.48 -        if (copy_from_guest(&getpolicy, arg, 1) != 0)
    4.49 -            return -EFAULT;
    4.50 -        if (getpolicy.interface_version != ACM_INTERFACE_VERSION)
    4.51 -            return -EACCES;
    4.52 -
    4.53 -        rc = acm_get_policy(getpolicy.pullcache,
    4.54 -                            getpolicy.pullcache_size);
    4.55 +        rc = acm_get_policy(op->u.getpolicy.pullcache,
    4.56 +                            op->u.getpolicy.pullcache_size);
    4.57          break;
    4.58      }
    4.59  
    4.60      case ACMOP_dumpstats: {
    4.61 -        struct acm_dumpstats dumpstats;
    4.62 -        if (copy_from_guest(&dumpstats, arg, 1) != 0)
    4.63 -            return -EFAULT;
    4.64 -        if (dumpstats.interface_version != ACM_INTERFACE_VERSION)
    4.65 -            return -EACCES;
    4.66 -
    4.67 -        rc = acm_dump_statistics(dumpstats.pullcache,
    4.68 -                                 dumpstats.pullcache_size);
    4.69 +        rc = acm_dump_statistics(op->u.dumpstats.pullcache,
    4.70 +                                 op->u.dumpstats.pullcache_size);
    4.71          break;
    4.72      }
    4.73  
    4.74      case ACMOP_getssid: {
    4.75 -        struct acm_getssid getssid;
    4.76          ssidref_t ssidref;
    4.77  
    4.78 -        if (copy_from_guest(&getssid, arg, 1) != 0)
    4.79 -            return -EFAULT;
    4.80 -        if (getssid.interface_version != ACM_INTERFACE_VERSION)
    4.81 -            return -EACCES;
    4.82 -
    4.83 -        if (getssid.get_ssid_by == ACM_GETBY_ssidref)
    4.84 -            ssidref = getssid.id.ssidref;
    4.85 -        else if (getssid.get_ssid_by == ACM_GETBY_domainid)
    4.86 +        if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
    4.87 +            ssidref = op->u.getssid.id.ssidref;
    4.88 +        else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
    4.89          {
    4.90 -            struct domain *subj = rcu_lock_domain_by_id(getssid.id.domainid);
    4.91 +            struct domain *subj = rcu_lock_domain_by_id(op->u.getssid.id.domainid);
    4.92              if (!subj)
    4.93              {
    4.94                  rc = -ESRCH; /* domain not found */
    4.95 @@ -120,24 +105,19 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
    4.96              rc = -ESRCH;
    4.97              break;
    4.98          }
    4.99 -        rc = acm_get_ssid(ssidref, getssid.ssidbuf, getssid.ssidbuf_size);
   4.100 +        rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
   4.101 +                          op->u.getssid.ssidbuf_size);
   4.102          break;
   4.103      }
   4.104  
   4.105      case ACMOP_getdecision: {
   4.106 -        struct acm_getdecision getdecision;
   4.107          ssidref_t ssidref1, ssidref2;
   4.108  
   4.109 -        if (copy_from_guest(&getdecision, arg, 1) != 0)
   4.110 -            return -EFAULT;
   4.111 -        if (getdecision.interface_version != ACM_INTERFACE_VERSION)
   4.112 -            return -EACCES;
   4.113 -
   4.114 -        if (getdecision.get_decision_by1 == ACM_GETBY_ssidref)
   4.115 -            ssidref1 = getdecision.id1.ssidref;
   4.116 -        else if (getdecision.get_decision_by1 == ACM_GETBY_domainid)
   4.117 +        if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
   4.118 +            ssidref1 = op->u.getdecision.id1.ssidref;
   4.119 +        else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
   4.120          {
   4.121 -            struct domain *subj = rcu_lock_domain_by_id(getdecision.id1.domainid);
   4.122 +            struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
   4.123              if (!subj)
   4.124              {
   4.125                  rc = -ESRCH; /* domain not found */
   4.126 @@ -157,11 +137,11 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
   4.127              rc = -ESRCH;
   4.128              break;
   4.129          }
   4.130 -        if (getdecision.get_decision_by2 == ACM_GETBY_ssidref)
   4.131 -            ssidref2 = getdecision.id2.ssidref;
   4.132 -        else if (getdecision.get_decision_by2 == ACM_GETBY_domainid)
   4.133 +        if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
   4.134 +            ssidref2 = op->u.getdecision.id2.ssidref;
   4.135 +        else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
   4.136          {
   4.137 -            struct domain *subj = rcu_lock_domain_by_id(getdecision.id2.domainid);
   4.138 +            struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
   4.139              if (!subj)
   4.140              {
   4.141                  rc = -ESRCH; /* domain not found */
   4.142 @@ -181,55 +161,33 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
   4.143              rc = -ESRCH;
   4.144              break;
   4.145          }
   4.146 -        rc = acm_get_decision(ssidref1, ssidref2, getdecision.hook);
   4.147 +        rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
   4.148  
   4.149          if (rc == ACM_ACCESS_PERMITTED)
   4.150          {
   4.151 -            getdecision.acm_decision = ACM_ACCESS_PERMITTED;
   4.152 +            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
   4.153              rc = 0;
   4.154          }
   4.155          else if  (rc == ACM_ACCESS_DENIED)
   4.156          {
   4.157 -            getdecision.acm_decision = ACM_ACCESS_DENIED;
   4.158 +            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
   4.159              rc = 0;
   4.160          }
   4.161          else
   4.162              rc = -ESRCH;
   4.163  
   4.164 -        if ( (rc == 0) && (copy_to_guest(arg, &getdecision, 1) != 0) )
   4.165 +        if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
   4.166              rc = -EFAULT;
   4.167          break;
   4.168      }
   4.169  
   4.170      case ACMOP_chgpolicy: {
   4.171 -        struct acm_change_policy chgpolicy;
   4.172 -
   4.173 -        if (copy_from_guest(&chgpolicy, arg, 1) != 0)
   4.174 -            return -EFAULT;
   4.175 -        if (chgpolicy.interface_version != ACM_INTERFACE_VERSION)
   4.176 -            return -EACCES;
   4.177 -
   4.178 -        rc = acm_change_policy(&chgpolicy);
   4.179 -
   4.180 -        if (rc == 0)
   4.181 -            if (copy_to_guest(arg, &chgpolicy, 1) != 0)
   4.182 -                rc = -EFAULT;
   4.183 +        rc = acm_change_policy(&op->u.change_policy);
   4.184          break;
   4.185      }
   4.186  
   4.187      case ACMOP_relabeldoms: {
   4.188 -        struct acm_relabel_doms relabeldoms;
   4.189 -
   4.190 -        if (copy_from_guest(&relabeldoms, arg, 1) != 0)
   4.191 -            return -EFAULT;
   4.192 -        if (relabeldoms.interface_version != ACM_INTERFACE_VERSION)
   4.193 -            return -EACCES;
   4.194 -
   4.195 -        rc = acm_relabel_domains(&relabeldoms);
   4.196 -
   4.197 -        if (rc == 0)
   4.198 -            if (copy_to_guest(arg, &relabeldoms, 1) != 0)
   4.199 -                rc = -EFAULT;
   4.200 +        rc = acm_relabel_domains(&op->u.relabel_doms);
   4.201          break;
   4.202      }
   4.203  
   4.204 @@ -241,7 +199,7 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
   4.205      return rc;
   4.206  }
   4.207  
   4.208 -#endif /* defined(ACM_SECURITY) */
   4.209 +#endif
   4.210  
   4.211  /*
   4.212   * Local variables:
     5.1 --- a/xen/include/public/acm_ops.h	Thu May 24 10:14:05 2007 +0100
     5.2 +++ b/xen/include/public/acm_ops.h	Thu May 24 10:18:55 2007 +0100
     5.3 @@ -34,7 +34,7 @@
     5.4   * This makes sure that old versions of acm tools will stop working in a
     5.5   * well-defined way (rather than crashing the machine, for instance).
     5.6   */
     5.7 -#define ACM_INTERFACE_VERSION   0xAAAA0009
     5.8 +#define ACM_INTERFACE_VERSION   0xAAAA000A
     5.9  
    5.10  /************************************************************************/
    5.11  
    5.12 @@ -49,7 +49,6 @@
    5.13  #define ACMOP_setpolicy         1
    5.14  struct acm_setpolicy {
    5.15      /* IN */
    5.16 -    uint32_t interface_version;
    5.17      XEN_GUEST_HANDLE_64(void) pushcache;
    5.18      uint32_t pushcache_size;
    5.19  };
    5.20 @@ -58,7 +57,6 @@ struct acm_setpolicy {
    5.21  #define ACMOP_getpolicy         2
    5.22  struct acm_getpolicy {
    5.23      /* IN */
    5.24 -    uint32_t interface_version;
    5.25      XEN_GUEST_HANDLE_64(void) pullcache;
    5.26      uint32_t pullcache_size;
    5.27  };
    5.28 @@ -67,7 +65,6 @@ struct acm_getpolicy {
    5.29  #define ACMOP_dumpstats         3
    5.30  struct acm_dumpstats {
    5.31      /* IN */
    5.32 -    uint32_t interface_version;
    5.33      XEN_GUEST_HANDLE_64(void) pullcache;
    5.34      uint32_t pullcache_size;
    5.35  };
    5.36 @@ -78,7 +75,6 @@ struct acm_dumpstats {
    5.37  #define ACM_GETBY_domainid 2
    5.38  struct acm_getssid {
    5.39      /* IN */
    5.40 -    uint32_t interface_version;
    5.41      uint32_t get_ssid_by; /* ACM_GETBY_* */
    5.42      union {
    5.43          domaintype_t domainid;
    5.44 @@ -91,7 +87,6 @@ struct acm_getssid {
    5.45  #define ACMOP_getdecision      5
    5.46  struct acm_getdecision {
    5.47      /* IN */
    5.48 -    uint32_t interface_version;
    5.49      uint32_t get_decision_by1; /* ACM_GETBY_* */
    5.50      uint32_t get_decision_by2; /* ACM_GETBY_* */
    5.51      union {
    5.52 @@ -111,7 +106,6 @@ struct acm_getdecision {
    5.53  #define ACMOP_chgpolicy        6
    5.54  struct acm_change_policy {
    5.55      /* IN */
    5.56 -    uint32_t interface_version;
    5.57      XEN_GUEST_HANDLE_64(void) policy_pushcache;
    5.58      uint32_t policy_pushcache_size;
    5.59      XEN_GUEST_HANDLE_64(void) del_array;
    5.60 @@ -127,7 +121,6 @@ struct acm_change_policy {
    5.61  #define ACMOP_relabeldoms       7
    5.62  struct acm_relabel_doms {
    5.63      /* IN */
    5.64 -    uint32_t interface_version;
    5.65      XEN_GUEST_HANDLE_64(void) relabel_map;
    5.66      uint32_t relabel_map_size;
    5.67      /* OUT */
     6.1 --- a/xen/include/xen/hypercall.h	Thu May 24 10:14:05 2007 +0100
     6.2 +++ b/xen/include/xen/hypercall.h	Thu May 24 10:18:55 2007 +0100
     6.3 @@ -98,7 +98,7 @@ do_vcpu_op(
     6.4  
     6.5  extern long
     6.6  do_acm_op(
     6.7 -    int cmd, XEN_GUEST_HANDLE(void) arg);
     6.8 +    XEN_GUEST_HANDLE(xen_acmctl_t) arg);
     6.9  
    6.10  extern long
    6.11  do_nmi_op(