ia64/xen-unstable

changeset 17199:f40a07c00209

[IA64] Prepare sioemu for SMP and save & restore.

Use macros instead of constants.

Signed-off-by: Tristan Gingold <tgingold@free.fr>
author Alex Williamson <alex.williamson@hp.com>
date Mon Mar 10 11:08:11 2008 -0600 (2008-03-10)
parents d23487433911
children 16f6435a9d07
files xen/arch/ia64/vmx/sioemu.c xen/arch/ia64/vmx/vmx_fault.c xen/include/asm-ia64/sioemu.h xen/include/public/arch-ia64/sioemu.h
line diff
     1.1 --- a/xen/arch/ia64/vmx/sioemu.c	Mon Mar 10 10:58:45 2008 -0600
     1.2 +++ b/xen/arch/ia64/vmx/sioemu.c	Mon Mar 10 11:08:11 2008 -0600
     1.3 @@ -23,21 +23,14 @@
     1.4  #include <public/arch-ia64/sioemu.h>
     1.5  #include <asm/dom_fw.h>
     1.6  #include <asm/debugger.h>
     1.7 +#include <asm/sal.h>
     1.8 +#include <asm/vlsapic.h>
     1.9  
    1.10 -static REGS *
    1.11 -sioemu_deliver (void)
    1.12 +static void
    1.13 +sioemu_save_regs (VCPU *vcpu)
    1.14  {
    1.15 -    VCPU *vcpu = current;
    1.16      REGS *regs = vcpu_regs(vcpu);
    1.17 -    unsigned long psr = vmx_vcpu_get_psr(vcpu);
    1.18  
    1.19 -    if (vcpu->vcpu_info->evtchn_upcall_mask)
    1.20 -        panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
    1.21 -
    1.22 -    /* All cleared, but keep BN.  */
    1.23 -    vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
    1.24 -
    1.25 -    /* Save registers. */
    1.26      vcpu->arch.arch_vmx.stub_saved[0] = regs->r16;
    1.27      vcpu->arch.arch_vmx.stub_saved[1] = regs->r17;
    1.28      vcpu->arch.arch_vmx.stub_saved[2] = regs->r18;
    1.29 @@ -56,13 +49,62 @@ sioemu_deliver (void)
    1.30      vcpu->arch.arch_vmx.stub_saved[15] = regs->r31;
    1.31      vcpu->arch.arch_vmx.stub_nats =
    1.32          (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff;
    1.33 +}
    1.34 +
    1.35 +static void
    1.36 +sioemu_restore_regs (VCPU *vcpu)
    1.37 +{
    1.38 +    REGS *regs = vcpu_regs(vcpu);
    1.39 +
    1.40 +    /* First restore registers.  */
    1.41 +    regs->cr_iip = regs->r28;
    1.42 +    regs->cr_ifs = regs->r30;
    1.43 +    vmx_vcpu_set_psr (vcpu, regs->r29);
    1.44 +
    1.45 +    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
    1.46 +    regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
    1.47 +
    1.48 +    regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
    1.49 +    regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
    1.50 +    regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
    1.51 +    regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
    1.52 +    regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
    1.53 +    regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
    1.54 +    regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
    1.55 +    regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
    1.56 +    regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
    1.57 +    regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
    1.58 +    regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
    1.59 +    regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
    1.60 +    regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
    1.61 +    regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
    1.62 +    regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
    1.63 +    regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
    1.64 +
    1.65 +}
    1.66 +
    1.67 +static REGS *
    1.68 +sioemu_deliver (void)
    1.69 +{
    1.70 +    VCPU *vcpu = current;
    1.71 +    REGS *regs = vcpu_regs(vcpu);
    1.72 +    unsigned long psr = vmx_vcpu_get_psr(vcpu);
    1.73 +
    1.74 +    if (vcpu->vcpu_info->evtchn_upcall_mask)
    1.75 +        panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
    1.76 +
    1.77 +    /* All cleared, but keep BN.  */
    1.78 +    vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
    1.79 +
    1.80 +    /* Save registers. */
    1.81 +    sioemu_save_regs (vcpu);
    1.82  
    1.83      /* Context. */
    1.84      regs->r28 = regs->cr_iip;
    1.85      regs->r29 = psr;
    1.86      regs->r30 = regs->cr_ifs;
    1.87  
    1.88 -    regs->cr_ifs = 0;  // pre-cover
    1.89 +    regs->cr_ifs = 0;	// pre-cover
    1.90  
    1.91      regs->cr_iip = vcpu->arch.event_callback_ip;
    1.92      regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
    1.93 @@ -90,33 +132,15 @@ sioemu_callback_return (void)
    1.94      u64 arg3 = regs->r21;
    1.95  
    1.96      if ((cmd & ~0x1UL) != 0)
    1.97 -        panic_domain (NULL,
    1.98 -                      "sioemu_callback_return: bad operation (%lx)\n", cmd);
    1.99 +        panic_domain (NULL, "sioemu_callback_return: bad operation (%lx)\n",
   1.100 +                      cmd);
   1.101  
   1.102      /* First restore registers.  */
   1.103      regs->cr_iip = regs->r28;
   1.104      regs->cr_ifs = regs->r30;
   1.105      vmx_vcpu_set_psr (vcpu, regs->r29);
   1.106  
   1.107 -    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
   1.108 -    regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
   1.109 -
   1.110 -    regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
   1.111 -    regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
   1.112 -    regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
   1.113 -    regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
   1.114 -    regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
   1.115 -    regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
   1.116 -    regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
   1.117 -    regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
   1.118 -    regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
   1.119 -    regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
   1.120 -    regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
   1.121 -    regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
   1.122 -    regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
   1.123 -    regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
   1.124 -    regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
   1.125 -    regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
   1.126 +    sioemu_restore_regs (vcpu);
   1.127  
   1.128      /* Unmask events.  */
   1.129      vcpu->vcpu_info->evtchn_upcall_mask = 0;
   1.130 @@ -133,8 +157,7 @@ sioemu_deliver_event (void)
   1.131      REGS *regs;
   1.132  
   1.133      regs = sioemu_deliver ();
   1.134 -
   1.135 -    regs->r16 = 0;
   1.136 +    regs->r16 = SIOEMU_CB_EVENT;
   1.137  }
   1.138  
   1.139  void
   1.140 @@ -144,13 +167,32 @@ sioemu_io_emulate (unsigned long padr, u
   1.141      REGS *regs;
   1.142  
   1.143      regs = sioemu_deliver ();
   1.144 -    regs->r16 = 1;
   1.145 +    regs->r16 = SIOEMU_CB_IO_EMULATE;
   1.146      regs->r19 = padr;
   1.147      regs->r20 = data;
   1.148      regs->r21 = data1;
   1.149      regs->r22 = word;
   1.150  }
   1.151  
   1.152 +void
   1.153 +sioemu_wakeup_vcpu (int vcpu_id)
   1.154 +{
   1.155 +    REGS *regs;
   1.156 +
   1.157 +    regs = sioemu_deliver();
   1.158 +    regs->r16 = SIOEMU_CB_WAKEUP_VCPU;
   1.159 +    regs->r19 = vcpu_id;
   1.160 +}
   1.161 +
   1.162 +void
   1.163 +sioemu_sal_assist (struct vcpu *v)
   1.164 +{
   1.165 +    REGS *regs;
   1.166 +
   1.167 +    regs = sioemu_deliver();
   1.168 +    regs->r16 = SIOEMU_CB_SAL_ASSIST;
   1.169 +}
   1.170 +
   1.171  static int
   1.172  sioemu_add_io_physmap (struct domain *d, unsigned long start,
   1.173                        unsigned long size, unsigned long type)
   1.174 @@ -187,7 +229,7 @@ sioemu_hypercall (struct pt_regs *regs)
   1.175      //        regs->r2, regs->r8, regs->r9);
   1.176  
   1.177      if (current->vcpu_info->evtchn_upcall_mask == 0)
   1.178 -        panic_domain (NULL, "sioemu_hypercall: not in stub mode\n");
   1.179 +        panic_domain(NULL, "sioemu_hypercall: not in stub mode\n");
   1.180  
   1.181      switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW)
   1.182      {
   1.183 @@ -197,20 +239,40 @@ sioemu_hypercall (struct pt_regs *regs)
   1.184          break;
   1.185      case SIOEMU_HYPERCALL_START_FW:
   1.186          regs->cr_iip = regs->r8;
   1.187 -        vmx_vcpu_set_psr (current, regs->r9);
   1.188 +        vmx_vcpu_set_psr(current, regs->r9);
   1.189          current->vcpu_info->evtchn_upcall_mask = 0;
   1.190          break;
   1.191      case SIOEMU_HYPERCALL_ADD_IO_PHYSMAP:
   1.192 -        regs->r8 = sioemu_add_io_physmap (current->domain,
   1.193 -                                          regs->r8, regs->r9, regs->r10);
   1.194 +        regs->r8 = sioemu_add_io_physmap(current->domain,
   1.195 +                                         regs->r8, regs->r9, regs->r10);
   1.196          break;
   1.197      case SIOEMU_HYPERCALL_GET_TIME:
   1.198      {
   1.199          uint64_t sec, nsec;
   1.200 -        get_wallclock (&sec, &nsec);
   1.201 +        get_wallclock(&sec, &nsec);
   1.202          regs->r8 = (sec << 30) + nsec;
   1.203          break;
   1.204      }
   1.205 +    case SIOEMU_HYPERCALL_GET_REGS:
   1.206 +        sioemu_restore_regs(current);
   1.207 +        break;
   1.208 +    case SIOEMU_HYPERCALL_SET_REGS:
   1.209 +        sioemu_save_regs(current);
   1.210 +        break;
   1.211 +    case SIOEMU_HYPERCALL_FLUSH_CACHE:
   1.212 +        regs->r8 = ia64_sal_cache_flush(regs->r8);
   1.213 +        break;
   1.214 +    case SIOEMU_HYPERCALL_FREQ_BASE:
   1.215 +        regs->r8 = ia64_sal_freq_base(regs->r8, &regs->r9, &regs->r10);
   1.216 +        break;
   1.217 +    case SIOEMU_HYPERCALL_DELIVER_INT:
   1.218 +        regs->r8 = vlsapic_deliver_int(current->domain,
   1.219 +                                       regs->r8, regs->r9, regs->r10);
   1.220 +        break;
   1.221 +    case SIOEMU_HYPERCALL_CALLBACK_RETURN:
   1.222 +        regs->r2 = regs->r27;
   1.223 +        sioemu_callback_return ();
   1.224 +        break;
   1.225      default:
   1.226          panic_domain (NULL, "bad sioemu hypercall %lx\n", regs->r2);
   1.227          break;
     2.1 --- a/xen/arch/ia64/vmx/vmx_fault.c	Mon Mar 10 10:58:45 2008 -0600
     2.2 +++ b/xen/arch/ia64/vmx/vmx_fault.c	Mon Mar 10 11:08:11 2008 -0600
     2.3 @@ -208,8 +208,12 @@ vmx_ia64_handle_break (unsigned long ifa
     2.4              vcpu_increment_iip(v);
     2.5              return IA64_NO_FAULT;
     2.6          } else if (iim == DOMN_SAL_REQUEST) {
     2.7 -            sal_emul(v);
     2.8 -            vcpu_increment_iip(v);
     2.9 +            if (d->arch.is_sioemu)
    2.10 +                sioemu_sal_assist(v);
    2.11 +            else {
    2.12 +                sal_emul(v);
    2.13 +                vcpu_increment_iip(v);
    2.14 +            }
    2.15              return IA64_NO_FAULT;
    2.16          } else if (d->arch.is_sioemu
    2.17                     && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) {
     3.1 --- a/xen/include/asm-ia64/sioemu.h	Mon Mar 10 10:58:45 2008 -0600
     3.2 +++ b/xen/include/asm-ia64/sioemu.h	Mon Mar 10 11:08:11 2008 -0600
     3.3 @@ -26,5 +26,6 @@ extern void sioemu_deliver_event (void);
     3.4  extern void sioemu_callback_return (void);
     3.5  extern void sioemu_io_emulate (unsigned long padr, unsigned long data,
     3.6                                unsigned long data1, unsigned long word);
     3.7 -
     3.8 +extern void sioemu_wakeup_vcpu (int vcpu_id);
     3.9 +extern void sioemu_sal_assist (struct vcpu *v);
    3.10  #endif /* __ASM_SIOEMU_H_ */
     4.1 --- a/xen/include/public/arch-ia64/sioemu.h	Mon Mar 10 10:58:45 2008 -0600
     4.2 +++ b/xen/include/public/arch-ia64/sioemu.h	Mon Mar 10 11:08:11 2008 -0600
     4.3 @@ -22,6 +22,9 @@
     4.4  #ifndef __XEN_PUBLIC_IA64_SIOEMU_H__
     4.5  #define __XEN_PUBLIC_IA64_SIOEMU_H__
     4.6  
     4.7 +/* SIOEMU specific hypercalls.
     4.8 +   The numbers are the minor part of FW_HYPERCALL_SIOEMU.  */
     4.9 +
    4.10  /* Defines the callback entry point.  r8=ip, r9=data.
    4.11     Must be called per-vcpu.  */
    4.12  #define SIOEMU_HYPERCALL_SET_CALLBACK 0x01
    4.13 @@ -35,6 +38,39 @@
    4.14  /* Get wallclock time.  */
    4.15  #define SIOEMU_HYPERCALL_GET_TIME 0x04
    4.16  
    4.17 +/* Get/Set shadow registers.  */
    4.18 +#define SIOEMU_HYPERCALL_GET_REGS 0x05
    4.19 +#define SIOEMU_HYPERCALL_SET_REGS 0x06
    4.20 +
    4.21 +/* Flush cache.  */
    4.22 +#define SIOEMU_HYPERCALL_FLUSH_CACHE 0x07
    4.23 +
    4.24 +/* Get freq base.  */
    4.25 +#define SIOEMU_HYPERCALL_FREQ_BASE 0x08
    4.26 +
    4.27 +/* Return from callback.  */
    4.28 +#define SIOEMU_HYPERCALL_CALLBACK_RETURN 0x09
    4.29 +
    4.30 +/* Deliver an interrupt.  */
    4.31 +#define SIOEMU_HYPERCALL_DELIVER_INT 0x0a
    4.32 +
    4.33 +/* SIOEMU callback reason.  */
    4.34 +
    4.35 +/* An event (from event channel) has to be delivered.  */
    4.36 +#define SIOEMU_CB_EVENT       0x00
    4.37 +
    4.38 +/* Emulate an IO access.  */
    4.39 +#define SIOEMU_CB_IO_EMULATE  0x01
    4.40 +
    4.41 +/* An IPI is sent to a dead vcpu.  */
    4.42 +#define SIOEMU_CB_WAKEUP_VCPU 0x02
    4.43 +
    4.44 +/* A SAL hypercall is executed.  */
    4.45 +#define SIOEMU_CB_SAL_ASSIST  0x03
    4.46 +
    4.47 +
    4.48 +/* SIOEMU firmware mode hypercalls.  */
    4.49 +
    4.50  /* Return from callback.  r16=0.
    4.51     Unmask vcpu events.  */
    4.52  #define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01