Skip to contentSkip to conversation

hvm-stub for ia64: xen

RFC In review [email protected] 2 participants 2 messages Nov 22, 2007

lore
Share & tools
lore
#0 lore raw

RFC 2/3 hvm-stub for ia64: xen

xen/arch/ia64/vmx/Makefile +1 -0
diff -r 092232fa1fbd xen/arch/ia64/vmx/Makefile
@@ -21,3 +21,4 @@ obj-y += vacpi.o
 obj-y += vacpi.o
 obj-y += vmx_vcpu_save.o
 obj-y += save.o
+obj-y += hvm_stub.o
xen/arch/ia64/vmx/hvm_stub.c new file +160 -0

160 lines not on this page · raw message

xen/arch/ia64/vmx/mmio.c +39 -4

86 lines not on this page · raw message

xen/arch/ia64/vmx/vmx_fault.c +91 -80

218 lines not on this page · raw message

xen/arch/ia64/vmx/vmx_hypercall.c +20 -12
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_hypercall.c
@@ -47,15 +47,19 @@ static int hvmop_set_isa_irq_level(
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( op.isa_irq > 15 )
         return -EINVAL;
 
-    d = get_domain_by_id(op.domid);
-    if ( d == NULL )
-        return -ESRCH;
+    if ( op.domid == DOMID_SELF ) {
+        d = get_current_domain();
+    }
+    else {
+        if ( !IS_PRIV(current->domain) )
+            return -EPERM;
+        d = get_domain_by_id(op.domid);
+        if ( d == NULL )
+            return -ESRCH;
+    }
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
@@ -79,15 +83,19 @@ static int hvmop_set_pci_intx_level(
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) )
         return -EINVAL;
 
-    d = get_domain_by_id(op.domid);
-    if ( d == NULL )
-        return -ESRCH;
+    if ( op.domid == DOMID_SELF ) {
+        d = get_current_domain();
+    }
+    else {
+        if ( !IS_PRIV(current->domain) )
+            return -EPERM;
+        d = get_domain_by_id(op.domid);
+        if ( d == NULL )
+            return -ESRCH;
+    }
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
xen/arch/ia64/vmx/vmx_init.c +52 -38

117 lines not on this page · raw message

xen/arch/ia64/vmx/vmx_ivt.S +1 -1
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_ivt.S
@@ -472,7 +472,7 @@ ENTRY(vmx_break_fault)
     ;;
     ld4 r22=[r22]
     extr.u r24=r29,IA64_PSR_CPL0_BIT,2
-    cmp.eq p0,p6=r0,r0
+    cmp.ltu p6,p0=NR_hypercalls,r2
     ;;
     cmp.ne.or p6,p0=r22,r17
     cmp.ne.or p6,p0=r0,r24
xen/arch/ia64/vmx/vmx_phy_mode.c +3 -2
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_phy_mode.c
@@ -35,6 +35,7 @@
 #define SW_BAD    0   /* Bad mode transitition */
 #define SW_V2P_DT 1   /* Physical emulation is activated */
 #define SW_V2P_D  2   /* Physical emulation is activated (only for data) */
+#define SW_P2P_D  2   /* Physical emulation is activated (only for data) */
 #define SW_P2V    3   /* Exit physical mode emulation */
 #define SW_SELF   4   /* No mode transition */
 #define SW_NOP    5   /* Mode transition, but without action required */
@@ -60,7 +61,7 @@ static const unsigned char mm_switch_tab
      *  data access can be satisfied though itlb entry for physical
      *  emulation is hit.
      */
-    {SW_SELF,0,  0,  SW_NOP, 0,  0,  0,  SW_P2V},
+    {SW_SELF,0,  0,  SW_NOP, 0,  SW_P2P_D,  0,  SW_P2V},
     {0,  0,  0,  0,  0,  0,  0,  0},
     {0,  0,  0,  0,  0,  0,  0,  0},
     /*
@@ -79,7 +80,7 @@ static const unsigned char mm_switch_tab
      *  from the low level TLB miss handlers.
      *  (see "arch/ia64/kernel/ivt.S")
      */
-    {0,  0,  0,  0,  0,  SW_SELF,0,  SW_P2V},
+    {SW_V2P_DT,  0,  0,  0,  0,  SW_SELF,0,  SW_P2V},
     {0,  0,  0,  0,  0,  0,  0,  0},
     /*
      *  (it,dt,rt): (1,1,1) -> (1,0,1)
xen/arch/ia64/xen/dom0_ops.c +5 -1
diff -r 092232fa1fbd xen/arch/ia64/xen/dom0_ops.c
@@ -104,13 +104,17 @@ long arch_do_domctl(xen_domctl_t *op, XE
                 ret = -EFAULT;
         }
         else {
-            if (ds->flags & XEN_DOMAINSETUP_hvm_guest) {
+            if (ds->flags & (XEN_DOMAINSETUP_hvm_guest
+                             | XEN_DOMAINSETUP_hvmstub_guest)) {
                 if (!vmx_enabled) {
                     printk("No VMX hardware feature for vmx domain.\n");
                     ret = -EINVAL;
                 } else {
                     d->arch.is_vti = 1;
+                    d->is_hvm = 1;
                     xen_ia64_set_convmem_end(d, ds->maxmem);
+                    if (ds->flags & XEN_DOMAINSETUP_hvmstub_guest)
+                        d->arch.is_hvmstub = 1;
                     ret = vmx_setup_platform(d);
                 }
             }
xen/arch/ia64/xen/hypercall.c +6 -1
diff -r 092232fa1fbd xen/arch/ia64/xen/hypercall.c
@@ -32,6 +32,7 @@
 #include <public/callback.h>
 #include <xen/event.h>
 #include <xen/perfc.h>
+#include <asm/hvm_stub.h>
 
 extern long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
 extern long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
@@ -224,7 +225,8 @@ ia64_hypercall(struct pt_regs *regs)
 		regs->r10 = fpswa_ret.err1;
 		regs->r11 = fpswa_ret.err2;
 		break;
-	case __HYPERVISOR_opt_feature: {
+	case __HYPERVISOR_opt_feature:
+	{
 		XEN_GUEST_HANDLE(void) arg;
 		struct xen_ia64_opt_feature optf;
 		set_xen_guest_handle(arg, (void*)(vcpu_get_gr(v, 32)));
@@ -234,6 +236,9 @@ ia64_hypercall(struct pt_regs *regs)
 			regs->r8 = -EFAULT;
 		break;
 	}
+	case FW_HYPERCALL_HVMSTUB:
+	        hvmstub_hypercall (regs);
+		break;
 	default:
 		printk("unknown ia64 fw hypercall %lx\n", regs->r2);
 		regs->r8 = do_ni_hypercall();
xen/include/asm-ia64/dom_fw.h +3 -0
diff -r 092232fa1fbd xen/include/asm-ia64/dom_fw.h
@@ -168,6 +168,9 @@
 /* Set the shared_info base virtual address.  */
 #define FW_HYPERCALL_SET_SHARED_INFO_VA			0x600UL
 
+/* Hvmstub hypercalls.  See details in hvm_stub.h  */
+#define FW_HYPERCALL_HVMSTUB                            0x800UL
+
 /* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above
    are for the architecture.
    Note: this limit was defined by Xen/ia64 (and not by Xen).
xen/include/asm-ia64/domain.h +1 -0
diff -r 092232fa1fbd xen/include/asm-ia64/domain.h
@@ -126,6 +126,7 @@ struct arch_domain {
         unsigned long flags;
         struct {
             unsigned int is_vti : 1;
+            unsigned int is_hvmstub : 1;
 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
             unsigned int has_pervcpu_vhpt : 1;
             unsigned int vhpt_size_log2 : 6;
xen/include/asm-ia64/hvm_stub.h new file +23 -0
diff -r 092232fa1fbd xen/include/asm-ia64/hvm_stub.h
@@ -0,0 +1,23 @@
+/* Hvm stub hypercalls.  */
+
+/* Defines the callback entry point.  r8=ip, r9=data.
+   Must be called per-vcpu.  */
+#define HVMSTUB_HYPERCALL_SET_CALLBACK 0x01
+
+/* Finish stub initialization and start firmware.  r8=ip.  */
+#define HVMSTUB_HYPERCALL_START_FW 0x02
+
+/* Return from callback.  r16=0.
+   Unmask vcpu events.  */
+#define HVMSTUB_HYPERPRIVOP_CALLBACK_RETURN 0x01
+
+
+#ifdef __XEN__
+extern void hvmstub_hypercall (struct pt_regs *regs);
+extern void hvmstub_deliver_event (void);
+extern void hvmstub_callback_return (void);
+extern void hvmstub_io_emulate (unsigned long padr, unsigned long data,
+				unsigned long data1, unsigned long word);
+
+#endif
+
xen/include/asm-ia64/vmmu.h +1 -0
diff -r 092232fa1fbd xen/include/asm-ia64/vmmu.h
@@ -215,6 +215,7 @@ extern void machine_tlb_purge(u64 va, u6
 extern void machine_tlb_purge(u64 va, u64 ps);
 extern unsigned long fetch_code(struct vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle);
 extern void emulate_io_inst(struct vcpu *vcpu, u64 padr, u64 ma);
+extern void emulate_io_update (struct vcpu *vcpu, u64 word, u64 d, u64 d1);
 extern int vhpt_enabled(struct vcpu *vcpu, uint64_t vadr, vhpt_ref_t ref);
 extern u64 translate_phy_pte(struct vcpu *v, u64 *pte, u64 itir, u64 va);
 extern void thash_vhpt_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa,
xen/include/asm-ia64/vmx_vpd.h +3 -0
diff -r 092232fa1fbd xen/include/asm-ia64/vmx_vpd.h
@@ -64,6 +64,9 @@ struct arch_vmx_struct {
     unsigned long  ivt_current;
     struct ivt_debug ivt_debug[IVT_DEBUG_MAX];
 #endif
+    unsigned long stub_saved[16];
+    unsigned long stub_buffer;
+    unsigned int  stub_nats;
 };
 
 #define VMX_DOMAIN(v)   v->arch.arch_vmx.flags
xen/include/public/domctl.h +2 -0
diff -r 092232fa1fbd xen/include/public/domctl.h
@@ -373,6 +373,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_hyper
 #define XEN_DOMAINSETUP_hvm_guest  (1UL<<_XEN_DOMAINSETUP_hvm_guest)
 #define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save)  */
 #define XEN_DOMAINSETUP_query  (1UL<<_XEN_DOMAINSETUP_query)
+#define _XEN_DOMAINSETUP_hvmstub_guest 2
+#define XEN_DOMAINSETUP_hvmstub_guest  (1UL<<_XEN_DOMAINSETUP_hvmstub_guest)
 typedef struct xen_domctl_arch_setup {
     uint64_aligned_t flags;  /* XEN_DOMAINSETUP_* */
 #ifdef __ia64__
#1 lore raw
Quoted 1 line · On Thu, Nov 22, 2007 at 05:00:41AM +0100, [email protected] wrote:

diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_fault.c

...snip...

Quoted 105 lines
xen/arch/ia64/vmx/vmx_fault.c +52 -48
@@ -248,59 +256,62 @@ void leave_hypervisor_tail(void)
     struct domain *d = current->domain;
     struct vcpu *v = current;
 
+    /* FIXME: can this happen ?  */
+    if (is_idle_domain(current->domain))
+        return;
+
+    if (d->arch.is_hvmstub) {
+        if (local_events_need_delivery()) {
+            hvmstub_deliver_event ();
+        }
+    } else if (v->vcpu_id == 0) {
+        unsigned long callback_irq =
+            d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
+        
+        if ( v->arch.arch_vmx.pal_init_pending ) {
+            /*inject INIT interruption to guest pal*/
+            v->arch.arch_vmx.pal_init_pending = 0;
+            deliver_pal_init(v);
+            return;
+        }
+
+        /*
+         * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
+         *                  Domain = val[47:32], Bus  = val[31:16],
+         *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
+         * val[63:56] == 0: val[55:0] is a delivery as GSI
+         */
+        if (callback_irq != 0 && local_events_need_delivery()) {
+            /* change level for para-device callback irq */
+            /* use level irq to send discrete event */
+            if ((uint8_t)(callback_irq >> 56) == 1) {
+                /* case of using PCI INTx line as callback irq */
+                int pdev = (callback_irq >> 11) & 0x1f;
+                int pintx = callback_irq & 3;
+                viosapic_set_pci_irq(d, pdev, pintx, 1);
+                viosapic_set_pci_irq(d, pdev, pintx, 0);
+            } else {
+                /* case of using GSI as callback irq */
+                viosapic_set_irq(d, callback_irq, 1);
+                viosapic_set_irq(d, callback_irq, 0);
+            }
+        }
+    }
+
+    rmb();
+    if (xchg(&v->arch.irq_new_pending, 0)) {
+        v->arch.irq_new_condition = 0;
+        vmx_check_pending_irq(v);
+    }
+    else if (v->arch.irq_new_condition) {
+        v->arch.irq_new_condition = 0;
+        vhpi_detection(v);
+    }
+
     // FIXME: Will this work properly if doing an RFI???
-    if (!is_idle_domain(d) ) {	// always comes from guest
-//        struct pt_regs *user_regs = vcpu_regs(current);
-        local_irq_enable();
-        do_softirq();
-        local_irq_disable();
-
-        if (v->vcpu_id == 0) {
-            unsigned long callback_irq =
-                d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
-
-            if ( v->arch.arch_vmx.pal_init_pending ) {
-                /*inject INIT interruption to guest pal*/
-                v->arch.arch_vmx.pal_init_pending = 0;
-                deliver_pal_init(v);
-                return;
-            }
-
-            /*
-             * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
-             *                  Domain = val[47:32], Bus  = val[31:16],
-             *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
-             * val[63:56] == 0: val[55:0] is a delivery as GSI
-             */
-            if (callback_irq != 0 && local_events_need_delivery()) {
-                /* change level for para-device callback irq */
-                /* use level irq to send discrete event */
-                if ((uint8_t)(callback_irq >> 56) == 1) {
-                    /* case of using PCI INTx line as callback irq */
-                    int pdev = (callback_irq >> 11) & 0x1f;
-                    int pintx = callback_irq & 3;
-                    viosapic_set_pci_irq(d, pdev, pintx, 1);
-                    viosapic_set_pci_irq(d, pdev, pintx, 0);
-                } else {
-                    /* case of using GSI as callback irq */
-                    viosapic_set_irq(d, callback_irq, 1);
-                    viosapic_set_irq(d, callback_irq, 0);
-                }
-            }
-        }
-
-        rmb();
-        if (xchg(&v->arch.irq_new_pending, 0)) {
-            v->arch.irq_new_condition = 0;
-            vmx_check_pending_irq(v);
-            return;
-        }
-
-        if (v->arch.irq_new_condition) {

xen/arch/ia64/vmx/vmx_fault.c void leave_hypervisor_tail(void) · line 317

Quoted 10 lines
xen/arch/ia64/vmx/vmx_fault.c +3 -4
-            v->arch.irq_new_condition = 0;
-            vhpi_detection(v);
-        }
-    }
+    local_irq_enable();
+    do_softirq();
+    local_irq_disable();
 }
 
 static int vmx_handle_lds(REGS* regs)

do_softirq() should be called before the device emulation code. The device emulation code uses timer and the timer callbacks which are called by softirq may change the device status and trigger interrupts.

Signature · 1 line
yamahata