# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID c1a7ed266c7ee01b31f4908e6283539d014e5e54
# Parent 95f14bb8d22004bc11eb5bf61348c93c93f3c08e
# Parent 215d8b2f3d94e3ad623cd219d4371cd04a84fb70
Catch up to xen-unstable.hg tip
diff -r 95f14bb8d220 -r c1a7ed266c7e
linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
Thu Jul 7 17:12:52 2005
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
Sat Jul 9 13:54:10 2005
@@ -126,8 +126,8 @@
/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
extern int bind_virq_to_irq(int virq);
extern void unbind_virq_from_irq(int virq);
-extern int bind_ipi_on_cpu_to_irq(int cpu, int ipi);
-extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
+extern int bind_ipi_to_irq(int ipi);
+extern void unbind_ipi_from_irq(int ipi);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
diff -r 95f14bb8d220 -r c1a7ed266c7e Makefile
--- a/Makefile Thu Jul 7 17:12:52 2005
+++ b/Makefile Sat Jul 9 13:54:10 2005
@@ -177,10 +177,10 @@
# Legacy targets for compatibility
linux24:
- $(MAKE) 'KERNELS=linux-2.4*' dist
+ $(MAKE) 'KERNELS=linux-2.4*' kernels
linux26:
- $(MAKE) 'KERNELS=linux-2.6*' dist
+ $(MAKE) 'KERNELS=linux-2.6*' kernels
netbsd20:
$(MAKE) netbsd-2.0-xenU-build
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/include/public/acm.h
--- a/xen/include/public/acm.h Thu Jul 7 17:12:52 2005
+++ b/xen/include/public/acm.h Sat Jul 9 13:54:10 2005
@@ -1,157 +1,0 @@
-/****************************************************************
- * acm.h
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
- *
- * Contributors:
- * Stefan Berger <stefanb@xxxxxxxxxxxxxx>
- * added network byte order support for binary policies
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype general access control module header file.
- * here are all definitions that are shared between
- * xen-core, guest-kernels, and applications.
- *
- * todo: move from static policy choice to compile option.
- */
-
-#ifndef _XEN_PUBLIC_ACM_H
-#define _XEN_PUBLIC_ACM_H
-
-#include "xen.h"
-#include "sched_ctl.h"
-
-/* if ACM_DEBUG defined, all hooks should
- * print a short trace message (comment it out
- * when not in testing mode )
- */
-/* #define ACM_DEBUG */
-
-#ifdef ACM_DEBUG
-# define printkd(fmt, args...) printk(fmt,## args)
-#else
-# define printkd(fmt, args...)
-#endif
-
-/* default ssid reference value if not supplied */
-#define ACM_DEFAULT_SSID 0x0
-#define ACM_DEFAULT_LOCAL_SSID 0x0
-
-/* Internal ACM ERROR types */
-#define ACM_OK 0
-#define ACM_UNDEF -1
-#define ACM_INIT_SSID_ERROR -2
-#define ACM_INIT_SOID_ERROR -3
-#define ACM_ERROR -4
-
-/* External ACCESS DECISIONS */
-#define ACM_ACCESS_PERMITTED 0
-#define ACM_ACCESS_DENIED -111
-#define ACM_NULL_POINTER_ERROR -200
-
-#define ACM_MAX_POLICY 3
-
-#define ACM_NULL_POLICY 0
-#define ACM_CHINESE_WALL_POLICY 1
-#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
-#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3
-
-/* policy: */
-#define ACM_POLICY_NAME(X) \
- (X == ACM_NULL_POLICY) ? "NULL policy" : \
- (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \
- (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT
policy" : \
- (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE
WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
- "UNDEFINED policy"
-
-/* defines a ssid reference used by xen */
-typedef u32 ssidref_t;
-
-/* -------security policy relevant type definitions-------- */
-
-/* type identifier; compares to "equal" or "not equal" */
-typedef u16 domaintype_t;
-
-/* CHINESE WALL POLICY DATA STRUCTURES
- *
- * current accumulated conflict type set:
- * When a domain is started and has a type that is in
- * a conflict set, the conflicting types are incremented in
- * the aggregate set. When a domain is destroyed, the
- * conflicting types to its type are decremented.
- * If a domain has multiple types, this procedure works over
- * all those types.
- *
- * conflict_aggregate_set[i] holds the number of
- * running domains that have a conflict with type i.
- *
- * running_types[i] holds the number of running domains
- * that include type i in their ssidref-referenced type set
- *
- * conflict_sets[i][j] is "0" if type j has no conflict
- * with type i and is "1" otherwise.
- */
-/* high-16 = version, low-16 = check magic */
-#define ACM_MAGIC 0x0001debc
-
-/* each offset in bytes from start of the struct they
- * the are part of */
-/* each buffer consists of all policy information for
- * the respective policy given in the policy code
- */
-struct acm_policy_buffer {
- u32 magic;
- u32 policyversion;
- u32 len;
- u16 primary_policy_code;
- u16 primary_buffer_offset;
- u16 secondary_policy_code;
- u16 secondary_buffer_offset;
-};
-
-struct acm_chwall_policy_buffer {
- u16 policy_code;
- u16 chwall_max_types;
- u16 chwall_max_ssidrefs;
- u16 chwall_max_conflictsets;
- u16 chwall_ssid_offset;
- u16 chwall_conflict_sets_offset;
- u16 chwall_running_types_offset;
- u16 chwall_conflict_aggregate_offset;
-};
-
-struct acm_ste_policy_buffer {
- u16 policy_code;
- u16 ste_max_types;
- u16 ste_max_ssidrefs;
- u16 ste_ssid_offset;
-};
-
-struct acm_stats_buffer {
- u32 magic;
- u32 policyversion;
- u32 len;
- u16 primary_policy_code;
- u16 primary_stats_offset;
- u16 secondary_policy_code;
- u16 secondary_stats_offset;
-};
-
-struct acm_ste_stats_buffer {
- u32 ec_eval_count;
- u32 gt_eval_count;
- u32 ec_denied_count;
- u32 gt_denied_count;
- u32 ec_cachehit_count;
- u32 gt_cachehit_count;
-};
-
-
-#endif
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/common/event_channel.c
--- a/xen/common/event_channel.c Thu Jul 7 17:12:52 2005
+++ b/xen/common/event_channel.c Sat Jul 9 13:54:10 2005
@@ -283,10 +283,7 @@
{
struct evtchn *chn;
struct domain *d = current->domain;
- int port, ipi_vcpu = bind->ipi_vcpu;
-
- if ( (ipi_vcpu >= MAX_VIRT_CPUS) || (d->vcpu[ipi_vcpu] == NULL) )
- return -EINVAL;
+ int port;
spin_lock(&d->evtchn_lock);
@@ -294,7 +291,7 @@
{
chn = evtchn_from_port(d, port);
chn->state = ECS_IPI;
- chn->notify_vcpu_id = ipi_vcpu;
+ chn->notify_vcpu_id = current->vcpu_id;
}
spin_unlock(&d->evtchn_lock);
@@ -325,7 +322,7 @@
chn = evtchn_from_port(d, port);
d->pirq_to_evtchn[pirq] = port;
- rc = pirq_guest_bind(d->vcpu[chn->notify_vcpu_id], pirq,
+ rc = pirq_guest_bind(d->vcpu[0], pirq,
!!(bind->flags & BIND_PIRQ__WILL_SHARE));
if ( rc != 0 )
{
@@ -437,7 +434,9 @@
BUG();
}
- chn1->state = ECS_FREE;
+ /* Reset binding to vcpu0 when the channel is freed. */
+ chn1->state = ECS_FREE;
+ chn1->notify_vcpu_id = 0;
out:
if ( d2 != NULL )
@@ -566,12 +565,13 @@
status->u.virq = chn->u.virq;
break;
case ECS_IPI:
- status->status = EVTCHNSTAT_ipi;
- status->u.ipi_vcpu = chn->notify_vcpu_id;
+ status->status = EVTCHNSTAT_ipi;
break;
default:
BUG();
}
+
+ status->vcpu = chn->notify_vcpu_id;
out:
spin_unlock(&d->evtchn_lock);
@@ -579,24 +579,41 @@
return rc;
}
-static long evtchn_rebind(evtchn_rebind_t *bind)
+static long evtchn_bind_vcpu(evtchn_bind_vcpu_t *bind)
{
struct domain *d = current->domain;
int port = bind->port;
int vcpu = bind->vcpu;
struct evtchn *chn;
- long rc = 0;
+ long rc = 0;
+
+ if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) ) {
+ printf("vcpu %d bad.\n", vcpu);
+ return -EINVAL;
+ }
spin_lock(&d->evtchn_lock);
if ( !port_is_valid(d, port) )
{
+ printf("port %d bad.\n", port);
rc = -EINVAL;
goto out;
}
chn = evtchn_from_port(d, port);
- chn->notify_vcpu_id = vcpu;
+ switch ( chn->state )
+ {
+ case ECS_UNBOUND:
+ case ECS_INTERDOMAIN:
+ case ECS_PIRQ:
+ chn->notify_vcpu_id = vcpu;
+ break;
+ default:
+ printf("evtchn type %d can't be rebound.\n", chn->state);
+ rc = -EINVAL;
+ break;
+ }
out:
spin_unlock(&d->evtchn_lock);
@@ -660,10 +677,8 @@
rc = -EFAULT;
break;
- case EVTCHNOP_rebind:
- rc = evtchn_rebind(&op.u.rebind);
- if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
- rc = -EFAULT;
+ case EVTCHNOP_bind_vcpu:
+ rc = evtchn_bind_vcpu(&op.u.bind_vcpu);
break;
default:
diff -r 95f14bb8d220 -r c1a7ed266c7e
linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c Thu Jul 7
17:12:52 2005
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c Sat Jul 9
13:54:10 2005
@@ -274,7 +274,7 @@
}
if (irq_desc[irq].handler->set_affinity)
irq_desc[irq].handler->set_affinity(irq, mask);
- else if (irq_desc[irq].action && !(warned++))
+ else if (irq_desc[irq].action)
printk("Cannot set affinity for irq %i\n", irq);
}
diff -r 95f14bb8d220 -r c1a7ed266c7e tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Thu Jul 7 17:12:52 2005
+++ b/tools/libxc/xc_domain.c Sat Jul 9 13:54:10 2005
@@ -123,6 +123,33 @@
if( !nr_doms ) return rc;
return nr_doms;
+}
+
+int xc_domain_getinfolist(int xc_handle,
+ u32 first_domain,
+ unsigned int max_domains,
+ xc_domaininfo_t *info)
+{
+ int ret = 0;
+ dom0_op_t op;
+
+ if(mlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
+ return -1;
+
+ op.cmd = DOM0_GETDOMAININFOLIST;
+ op.u.getdomaininfolist.first_domain = first_domain;
+ op.u.getdomaininfolist.max_domains = max_domains;
+ op.u.getdomaininfolist.buffer = info;
+
+ if(xc_dom0_op(xc_handle, &op) < 0)
+ ret = -1;
+ else
+ ret = op.u.getdomaininfolist.num_domains;
+
+ if(munlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
+ ret = -1;
+
+ return ret;
}
int xc_domain_get_vcpu_context(int xc_handle,
diff -r 95f14bb8d220 -r c1a7ed266c7e tools/libxc/xc.h
--- a/tools/libxc/xc.h Thu Jul 7 17:12:52 2005
+++ b/tools/libxc/xc.h Sat Jul 9 13:54:10 2005
@@ -192,6 +192,24 @@
xc_dominfo_t *info);
/**
+ * This function will return information about one or more domains, using a
+ * single hypercall. The domain information will be stored into the supplied
+ * array of xc_domaininfo_t structures.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm first_domain the first domain to enumerate information from.
+ * Domains are currently enumerate in order of creation.
+ * @parm max_domains the number of elements in info
+ * @parm info an array of max_doms size that will contain the information for
+ * the enumerated domains.
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_domain_getinfolist(int xc_handle,
+ u32 first_domain,
+ unsigned int max_domains,
+ xc_domaininfo_t *info);
+
+/**
* This function returns information about one domain. This information is
* more detailed than the information from xc_domain_getinfo().
*
diff -r 95f14bb8d220 -r c1a7ed266c7e
linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c Thu Jul 7 17:12:52 2005
+++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c Sat Jul 9 13:54:10 2005
@@ -86,7 +86,7 @@
cpu_evtchn_mask[cpu][idx] & \
~(sh)->evtchn_mask[idx])
-static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
{
clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
@@ -99,8 +99,9 @@
((sh)->evtchn_pending[idx] & \
~(sh)->evtchn_mask[idx])
-#define bind_evtchn_to_cpu(chn,cpu) ((void)0)
-
+void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+{
+}
#endif
/* Upcall to generic IRQ layer. */
@@ -228,6 +229,13 @@
if ( HYPERVISOR_event_channel_op(&op) != 0 )
panic("Failed to unbind virtual IRQ %d\n", virq);
+ /* This is a slight hack. Interdomain ports can be allocated
+ directly by userspace, and at that point they get bound by
+ Xen to vcpu 0. We therefore need to make sure that if we
+ get an event on an event channel we don't know about vcpu 0
+ handles it. Binding channels to vcpu 0 when closing them
+ achieves this. */
+ bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = -1;
irq_to_evtchn[irq] = -1;
per_cpu(virq_to_irq, cpu)[virq] = -1;
@@ -236,17 +244,17 @@
spin_unlock(&irq_mapping_update_lock);
}
-int bind_ipi_on_cpu_to_irq(int cpu, int ipi)
+int bind_ipi_on_cpu_to_irq(int ipi)
{
evtchn_op_t op;
int evtchn, irq;
+ int cpu = smp_processor_id();
spin_lock(&irq_mapping_update_lock);
if ( (evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0 )
{
- op.cmd = EVTCHNOP_bind_ipi;
- op.u.bind_ipi.ipi_vcpu = cpu;
+ op.cmd = EVTCHNOP_bind_ipi;
if ( HYPERVISOR_event_channel_op(&op) != 0 )
panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, cpu);
evtchn = op.u.bind_ipi.port;
@@ -271,41 +279,10 @@
return irq;
}
-void rebind_evtchn_from_ipi(int cpu, int newcpu, int ipi)
-{
- evtchn_op_t op;
- int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
-
- spin_lock(&irq_mapping_update_lock);
-
- op.cmd = EVTCHNOP_rebind;
- op.u.rebind.port = evtchn;
- op.u.rebind.vcpu = newcpu;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- printk(KERN_INFO "Failed to rebind IPI%d to CPU%d\n",ipi,newcpu);
-
- spin_unlock(&irq_mapping_update_lock);
-}
-
-void rebind_evtchn_from_irq(int cpu, int newcpu, int irq)
-{
- evtchn_op_t op;
- int evtchn = irq_to_evtchn[irq];
-
- spin_lock(&irq_mapping_update_lock);
-
- op.cmd = EVTCHNOP_rebind;
- op.u.rebind.port = evtchn;
- op.u.rebind.vcpu = newcpu;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- printk(KERN_INFO "Failed to rebind IRQ%d to CPU%d\n",irq,newcpu);
-
- spin_unlock(&irq_mapping_update_lock);
-}
-
-void unbind_ipi_on_cpu_from_irq(int cpu, int ipi)
-{
- evtchn_op_t op;
+void unbind_ipi_from_irq(int ipi)
+{
+ evtchn_op_t op;
+ int cpu = smp_processor_id();
int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
int irq = irq_to_evtchn[evtchn];
@@ -319,6 +296,8 @@
if ( HYPERVISOR_event_channel_op(&op) != 0 )
panic("Failed to unbind virtual IPI %d on cpu %d\n", ipi, cpu);
+ /* See comments in unbind_virq_from_irq */
+ bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = -1;
irq_to_evtchn[irq] = -1;
per_cpu(ipi_to_evtchn, cpu)[ipi] = 0;
@@ -362,6 +341,59 @@
spin_unlock(&irq_mapping_update_lock);
}
+static void do_nothing_function(void *ign)
+{
+}
+
+/* Rebind an evtchn so that it gets delivered to a specific cpu */
+static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+{
+ evtchn_op_t op;
+ int evtchn;
+
+ spin_lock(&irq_mapping_update_lock);
+ evtchn = irq_to_evtchn[irq];
+ if (!VALID_EVTCHN(evtchn)) {
+ spin_unlock(&irq_mapping_update_lock);
+ return;
+ }
+
+ /* Tell Xen to send future instances of this interrupt to the
+ other vcpu */
+ op.cmd = EVTCHNOP_bind_vcpu;
+ op.u.bind_vcpu.port = evtchn;
+ op.u.bind_vcpu.vcpu = tcpu;
+
+ /* If this fails, it usually just indicates that we're dealing
+ with a virq or IPI channel, which don't actually need to be
+ rebound. Ignore it, but don't do the xenlinux-level rebind
+ in that case. */
+ if (HYPERVISOR_event_channel_op(&op) >= 0)
+ bind_evtchn_to_cpu(evtchn, tcpu);
+
+ spin_unlock(&irq_mapping_update_lock);
+
+ /* Now send the new target processor a NOP IPI. When this
+ returns, it will check for any pending interrupts, and so
+ service any that got delivered to the wrong processor by
+ mistake. */
+ /* XXX: The only time this is called with interrupts disabled is
+ from the hotplug/hotunplug path. In that case, all cpus are
+ stopped with interrupts disabled, and the missed interrupts
+ will be picked up when they start again. This is kind of a
+ hack.
+ */
+ if (!irqs_disabled()) {
+ smp_call_function(do_nothing_function, NULL, 0, 0);
+ }
+}
+
+
+static void set_affinity_irq(unsigned irq, cpumask_t dest)
+{
+ unsigned tcpu = first_cpu(dest);
+ rebind_irq_to_cpu(irq, tcpu);
+}
/*
* Interface to generic handling in irq.c
@@ -424,7 +456,7 @@
disable_dynirq,
ack_dynirq,
end_dynirq,
- NULL
+ set_affinity_irq
};
static inline void pirq_unmask_notify(int pirq)
@@ -473,6 +505,7 @@
pirq_query_unmask(irq_to_pirq(irq));
+ bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = irq;
irq_to_evtchn[irq] = evtchn;
@@ -498,6 +531,7 @@
if ( HYPERVISOR_event_channel_op(&op) != 0 )
panic("Failed to unbind physical IRQ %d\n", irq);
+ bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = -1;
irq_to_evtchn[irq] = -1;
}
@@ -548,7 +582,7 @@
disable_pirq,
ack_pirq,
end_pirq,
- NULL
+ set_affinity_irq
};
void irq_suspend(void)
@@ -597,6 +631,7 @@
evtchn = op.u.bind_virq.port;
/* Record the new mapping. */
+ bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = irq;
irq_to_evtchn[irq] = evtchn;
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/include/public/io/domain_controller.h
--- a/xen/include/public/io/domain_controller.h Thu Jul 7 17:12:52 2005
+++ b/xen/include/public/io/domain_controller.h Sat Jul 9 13:54:10 2005
@@ -577,11 +577,12 @@
} usbif_fe_interface_connect_t;
/*
- * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
+ * CMSG_USBIF_FE_INTERFACE_DISCONNECT:
* If successful, the domain controller will acknowledge with a
* STATUS_DISCONNECTED message.
*/
typedef struct usbif_fe_interface_disconnect {
+ int dummy; /* make struct non-empty */
} usbif_fe_interface_disconnect_t;
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h Thu Jul 7 17:12:52 2005
+++ b/xen/include/public/dom0_ops.h Sat Jul 9 13:54:10 2005
@@ -19,7 +19,7 @@
* This makes sure that old versions of dom0 tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define DOM0_INTERFACE_VERSION 0xAAAA100C
+#define DOM0_INTERFACE_VERSION 0xAAAA100E
/************************************************************************/
@@ -356,6 +356,16 @@
vcpu_guest_context_t *ctxt; /* NB. IN/OUT variable. */
u64 cpu_time;
} dom0_getvcpucontext_t;
+
+#define DOM0_GETDOMAININFOLIST 38
+typedef struct {
+ /* IN variables. */
+ domid_t first_domain;
+ memory_t max_domains;
+ dom0_getdomaininfo_t *buffer;
+ /* OUT variables. */
+ memory_t num_domains;
+} dom0_getdomaininfolist_t;
typedef struct {
u32 cmd;
@@ -389,6 +399,7 @@
dom0_microcode_t microcode;
dom0_ioport_permission_t ioport_permission;
dom0_getvcpucontext_t getvcpucontext;
+ dom0_getdomaininfolist_t getdomaininfolist;
} u;
} dom0_op_t;
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c Thu Jul 7 17:12:52 2005
+++ b/xen/common/dom0_ops.c Sat Jul 9 13:54:10 2005
@@ -88,6 +88,60 @@
return err;
}
+static void getdomaininfo(struct domain *d, dom0_getdomaininfo_t *info)
+{
+ struct vcpu *v;
+ u64 cpu_time = 0;
+ int vcpu_count = 0;
+ int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
+
+ info->domain = d->domain_id;
+
+ memset(&info->vcpu_to_cpu, -1, sizeof(info->vcpu_to_cpu));
+ memset(&info->cpumap, 0, sizeof(info->cpumap));
+
+ /*
+ * - domain is marked as paused or blocked only if all its vcpus
+ * are paused or blocked
+ * - domain is marked as running if any of its vcpus is running
+ * - only map vcpus that aren't down. Note, at some point we may
+ * wish to demux the -1 value to indicate down vs. not-ever-booted
+ *
+ */
+ for_each_vcpu ( d, v ) {
+ /* only map vcpus that are up */
+ if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
+ info->vcpu_to_cpu[v->vcpu_id] = v->processor;
+ info->cpumap[v->vcpu_id] = v->cpumap;
+ if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
+ flags &= ~DOMFLAGS_PAUSED;
+ if ( !(v->vcpu_flags & VCPUF_blocked) )
+ flags &= ~DOMFLAGS_BLOCKED;
+ if ( v->vcpu_flags & VCPUF_running )
+ flags |= DOMFLAGS_RUNNING;
+ if ( v->cpu_time > cpu_time )
+ cpu_time += v->cpu_time;
+ vcpu_count++;
+ }
+
+ info->cpu_time = cpu_time;
+ info->n_vcpu = vcpu_count;
+
+ info->flags = flags |
+ ((d->domain_flags & DOMF_dying) ? DOMFLAGS_DYING : 0) |
+ ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
+ d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
+
+ if (d->ssid != NULL)
+ info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
+ else
+ info->ssidref = ACM_DEFAULT_SSID;
+
+ info->tot_pages = d->tot_pages;
+ info->max_pages = d->max_pages;
+ info->shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT;
+}
+
long do_dom0_op(dom0_op_t *u_dom0_op)
{
long ret = 0;
@@ -306,10 +360,6 @@
case DOM0_GETDOMAININFO:
{
struct domain *d;
- struct vcpu *v;
- u64 cpu_time = 0;
- int vcpu_count = 0;
- int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
read_lock(&domlist_lock);
@@ -328,59 +378,59 @@
read_unlock(&domlist_lock);
- op->u.getdomaininfo.domain = d->domain_id;
-
- memset(&op->u.getdomaininfo.vcpu_to_cpu, -1,
- sizeof(op->u.getdomaininfo.vcpu_to_cpu));
- memset(&op->u.getdomaininfo.cpumap, 0,
- sizeof(op->u.getdomaininfo.cpumap));
-
- /*
- * - domain is marked as paused or blocked only if all its vcpus
- * are paused or blocked
- * - domain is marked as running if any of its vcpus is running
- * - only map vcpus that aren't down. Note, at some point we may
- * wish to demux the -1 value to indicate down vs. not-ever-booted
- *
- */
- for_each_vcpu ( d, v ) {
- /* only map vcpus that are up */
- if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
- op->u.getdomaininfo.vcpu_to_cpu[v->vcpu_id] = v->processor;
- op->u.getdomaininfo.cpumap[v->vcpu_id] = v->cpumap;
- if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
- flags &= ~DOMFLAGS_PAUSED;
- if ( !(v->vcpu_flags & VCPUF_blocked) )
- flags &= ~DOMFLAGS_BLOCKED;
- if ( v->vcpu_flags & VCPUF_running )
- flags |= DOMFLAGS_RUNNING;
- if ( v->cpu_time > cpu_time )
- cpu_time += v->cpu_time;
- vcpu_count++;
- }
-
- op->u.getdomaininfo.cpu_time = cpu_time;
- op->u.getdomaininfo.n_vcpu = vcpu_count;
-
- op->u.getdomaininfo.flags = flags |
- ((d->domain_flags & DOMF_dying) ? DOMFLAGS_DYING : 0) |
- ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
- d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
-
- if (d->ssid != NULL)
- op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain
*)d->ssid)->ssidref;
- else
- op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID;
-
- op->u.getdomaininfo.tot_pages = d->tot_pages;
- op->u.getdomaininfo.max_pages = d->max_pages;
- op->u.getdomaininfo.shared_info_frame =
- __pa(d->shared_info) >> PAGE_SHIFT;
+ getdomaininfo(d, &op->u.getdomaininfo);
if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
ret = -EINVAL;
put_domain(d);
+ }
+ break;
+
+ case DOM0_GETDOMAININFOLIST:
+ {
+ struct domain *d;
+ dom0_getdomaininfo_t info;
+ dom0_getdomaininfo_t *buffer = op->u.getdomaininfolist.buffer;
+ u32 num_domains = 0;
+
+ read_lock(&domlist_lock);
+
+ for_each_domain ( d )
+ {
+ if ( d->domain_id < op->u.getdomaininfolist.first_domain )
+ continue;
+ if ( num_domains == op->u.getdomaininfolist.max_domains )
+ break;
+ if ( (d == NULL) || !get_domain(d) )
+ {
+ ret = -ESRCH;
+ break;
+ }
+
+ getdomaininfo(d, &info);
+
+ put_domain(d);
+
+ if ( copy_to_user(buffer, &info, sizeof(dom0_getdomaininfo_t)) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ buffer++;
+ num_domains++;
+ }
+
+ read_unlock(&domlist_lock);
+
+ if ( ret != 0 )
+ break;
+
+ op->u.getdomaininfolist.num_domains = num_domains;
+
+ if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
+ ret = -EINVAL;
}
break;
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/include/acm/acm_core.h
--- a/xen/include/acm/acm_core.h Thu Jul 7 17:12:52 2005
+++ b/xen/include/acm/acm_core.h Sat Jul 9 13:54:10 2005
@@ -20,6 +20,7 @@
#include <xen/spinlock.h>
#include <public/acm.h>
+#include <xen/acm_policy.h>
#include <public/policy_ops.h>
/* Xen-internal representation of the binary policy */
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/include/public/event_channel.h
--- a/xen/include/public/event_channel.h Thu Jul 7 17:12:52 2005
+++ b/xen/include/public/event_channel.h Sat Jul 9 13:54:10 2005
@@ -89,8 +89,6 @@
*/
#define EVTCHNOP_bind_ipi 7
typedef struct evtchn_bind_ipi {
- /* IN parameters. */
- u32 ipi_vcpu;
/* OUT parameters. */
u32 port;
} evtchn_bind_ipi_t;
@@ -144,6 +142,7 @@
#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
u32 status;
+ u32 vcpu; /* VCPU to which this channel is bound. */
union {
struct {
domid_t dom;
@@ -154,16 +153,25 @@
} interdomain; /* EVTCHNSTAT_interdomain */
u32 pirq; /* EVTCHNSTAT_pirq */
u32 virq; /* EVTCHNSTAT_virq */
- u32 ipi_vcpu; /* EVTCHNSTAT_ipi */
} u;
} evtchn_status_t;
-#define EVTCHNOP_rebind 8
-typedef struct {
+/*
+ * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
+ * event is pending.
+ * NOTES:
+ * 1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
+ * the binding. This binding cannot be changed.
+ * 2. All other channels notify vcpu0 by default. This default is set when
+ * the channel is allocated (a port that is freed and subsequently reused
+ * has its binding reset to vcpu0).
+ */
+#define EVTCHNOP_bind_vcpu 8
+typedef struct evtchn_bind_vcpu {
/* IN parameters. */
- u32 port; /* 0 */
- u32 vcpu; /* 4 */
-} evtchn_rebind_t; /* 8 bytes */
+ u32 port;
+ u32 vcpu;
+} evtchn_bind_vcpu_t;
typedef struct evtchn_op {
u32 cmd; /* EVTCHNOP_* */
@@ -176,7 +184,7 @@
evtchn_close_t close;
evtchn_send_t send;
evtchn_status_t status;
- evtchn_rebind_t rebind;
+ evtchn_bind_vcpu_t bind_vcpu;
} u;
} evtchn_op_t;
diff -r 95f14bb8d220 -r c1a7ed266c7e
linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
Thu Jul 7 17:12:52 2005
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
Sat Jul 9 13:54:10 2005
@@ -128,8 +128,8 @@
/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
extern int bind_virq_to_irq(int virq);
extern void unbind_virq_from_irq(int virq);
-extern int bind_ipi_on_cpu_to_irq(int cpu, int ipi);
-extern void unbind_ipi_on_cpu_from_irq(int cpu, int ipi);
+extern int bind_ipi_to_irq(int ipi);
+extern void unbind_ipi_from_irq(int ipi);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
diff -r 95f14bb8d220 -r c1a7ed266c7e
linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c Thu Jul 7
17:12:52 2005
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c Sat Jul 9
13:54:10 2005
@@ -1312,7 +1312,7 @@
/* hotplug down/up funtion pointer and target vcpu */
struct vcpu_hotplug_handler_t {
- void (*fn)();
+ void (*fn)(int vcpu);
u32 vcpu;
};
static struct vcpu_hotplug_handler_t vcpu_hotplug_handler;
@@ -1333,11 +1333,8 @@
while (!cpu_online(cpu))
cpu_relax();
- /* re-route bound IRQs 0 to cpu */
- rebind_evtchn_from_irq(0, cpu, per_cpu(resched_irq, cpu));
- rebind_evtchn_from_irq(0, cpu, per_cpu(callfunc_irq, cpu));
-
fixup_irqs(cpu_online_map);
+
/* counter the disable in fixup_irqs() */
local_irq_enable();
return 0;
@@ -1359,17 +1356,8 @@
if (cpu == 0)
return -EBUSY;
- /* Allow any queued timer interrupts to get serviced */
- local_irq_enable();
- mdelay(1);
- local_irq_disable();
-
cpu_clear(cpu, map);
fixup_irqs(map);
-
- /* re-route IRQs from dead vcpu to another */
- rebind_evtchn_from_irq(cpu, 0, per_cpu(resched_irq, cpu));
- rebind_evtchn_from_irq(cpu, 0, per_cpu(callfunc_irq, cpu));
/* It's now safe to remove this processor from the online map */
cpu_clear(cpu, cpu_online_map);
@@ -1533,13 +1521,13 @@
int cpu = smp_processor_id();
per_cpu(resched_irq, cpu) =
- bind_ipi_on_cpu_to_irq(cpu, RESCHEDULE_VECTOR);
+ bind_ipi_on_cpu_to_irq(RESCHEDULE_VECTOR);
sprintf(resched_name[cpu], "resched%d", cpu);
BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
SA_INTERRUPT, resched_name[cpu], NULL));
per_cpu(callfunc_irq, cpu) =
- bind_ipi_on_cpu_to_irq(cpu, CALL_FUNCTION_VECTOR);
+ bind_ipi_on_cpu_to_irq(CALL_FUNCTION_VECTOR);
sprintf(callfunc_name[cpu], "callfunc%d", cpu);
BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
smp_call_function_interrupt,
diff -r 95f14bb8d220 -r c1a7ed266c7e
linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c
--- a/linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c Thu Jul 7 17:12:52 2005
+++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c Sat Jul 9 13:54:10 2005
@@ -491,6 +491,8 @@
* pick up its end of the event channel from
*/
evtchn_op_t op;
+ extern void bind_evtchn_to_cpu(unsigned port, unsigned cpu);
+
op.cmd = EVTCHNOP_bind_interdomain;
op.u.bind_interdomain.dom1 = DOMID_SELF;
op.u.bind_interdomain.dom2 = DOMID_SELF;
@@ -500,6 +502,7 @@
BUG();
xen_start_info.domain_controller_evtchn = op.u.bind_interdomain.port1;
initdom_ctrlif_domcontroller_port = op.u.bind_interdomain.port2;
+ bind_evtchn_to_cpu(op.u.bind_interdomain.port1, 0);
}
/* Sync up with shared indexes. */
diff -r 95f14bb8d220 -r c1a7ed266c7e xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Thu Jul 7 17:12:52 2005
+++ b/xen/arch/x86/traps.c Sat Jul 9 13:54:10 2005
@@ -94,6 +94,9 @@
DECLARE_TRAP_HANDLER(spurious_interrupt_bug);
DECLARE_TRAP_HANDLER(machine_check);
+long do_set_debugreg(int reg, unsigned long value);
+unsigned long do_get_debugreg(int reg);
+
static int debug_stack_lines = 20;
integer_param("debug_stack_lines", debug_stack_lines);
@@ -568,8 +571,8 @@
static int emulate_privileged_op(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
- unsigned long *reg, eip = regs->eip;
- u8 opcode, modrm_reg = 0, rep_prefix = 0;
+ unsigned long *reg, eip = regs->eip, res;
+ u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0;
unsigned int port, i, op_bytes = 4, data;
/* Legacy prefixes. */
@@ -604,7 +607,9 @@
if ( (opcode & 0xf0) == 0x40 )
{
modrm_reg = (opcode & 4) << 1; /* REX.R */
- /* REX.W, REX.B and REX.X do not need to be decoded. */
+ modrm_rm = (opcode & 1) << 3; /* REX.B */
+
+ /* REX.W and REX.X do not need to be decoded. */
opcode = insn_fetch(u8, 1, eip);
}
#endif
@@ -782,11 +787,10 @@
case 0x20: /* MOV CR?,<reg> */
opcode = insn_fetch(u8, 1, eip);
- if ( (opcode & 0xc0) != 0xc0 )
- goto fail;
- modrm_reg |= opcode & 7;
- reg = decode_register(modrm_reg, regs, 0);
- switch ( (opcode >> 3) & 7 )
+ modrm_reg |= (opcode >> 3) & 7;
+ modrm_rm |= (opcode >> 0) & 7;
+ reg = decode_register(modrm_rm, regs, 0);
+ switch ( modrm_reg )
{
case 0: /* Read CR0 */
*reg = v->arch.guest_context.ctrlreg[0];
@@ -805,13 +809,22 @@
}
break;
+ case 0x21: /* MOV DR?,<reg> */
+ opcode = insn_fetch(u8, 1, eip);
+ modrm_reg |= (opcode >> 3) & 7;
+ modrm_rm |= (opcode >> 0) & 7;
+ reg = decode_register(modrm_rm, regs, 0);
+ if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
+ goto fail;
+ *reg = res;
+ break;
+
case 0x22: /* MOV <reg>,CR? */
opcode = insn_fetch(u8, 1, eip);
- if ( (opcode & 0xc0) != 0xc0 )
- goto fail;
- modrm_reg |= opcode & 7;
- reg = decode_register(modrm_reg, regs, 0);
- switch ( (opcode >> 3) & 7 )
+ modrm_reg |= (opcode >> 3) & 7;
+ modrm_rm |= (opcode >> 0) & 7;
+ reg = decode_register(modrm_rm, regs, 0);
+ switch ( modrm_reg )
{
case 0: /* Write CR0 */
(void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
@@ -826,6 +839,15 @@
(void)new_guest_cr3(*reg);
UNLOCK_BIGLOCK(v->domain);
break;
+
+ case 0x23: /* MOV <reg>,DR? */
+ opcode = insn_fetch(u8, 1, eip);
+ modrm_reg |= (opcode >> 3) & 7;
+ modrm_rm |= (opcode >> 0) & 7;
+ reg = decode_register(modrm_rm, regs, 0);
+ if ( do_set_debugreg(modrm_reg, *reg) != 0 )
+ goto fail;
+ break;
default:
goto fail;
diff -r 95f14bb8d220 -r c1a7ed266c7e tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Jul 7 17:12:52 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Sat Jul 9 13:54:10 2005
@@ -688,7 +688,7 @@
if ( xc_physinfo(xc->xc_handle, &info) != 0 )
return PyErr_SetFromErrno(xc_error);
- return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
+ return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i}",
"threads_per_core", info.threads_per_core,
"cores_per_socket", info.cores_per_socket,
"sockets_per_node", info.sockets_per_node,
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|