From: Bhavana Nagendra <bnagendr@redhat.com> Date: Wed, 26 Mar 2008 13:51:23 -0400 Subject: [xen] x86: new vcpu_op call to get physical CPU identity Message-id: 47EA8D1B.9090706@redhat.com O-Subject: Re: [RHEL5.2 PATCH 2/2] Xen HV: New vcpu_op call to get physical CPU identity. Bugzilla: 434548 RH-Acked-by: Stephen C. Tweedie <sct@redhat.com> RH-Acked-by: Rik van Riel <riel@redhat.com> With this patch we have the following fixes: 1) Removed global reference to "opt_dom0_vcpus_pin" in schedule.c. This was a mistake. 2) The "opt_dom0_vcpus_pin" definition is global now to match the version removed from schedule.c. The upstream version is static, which is why my back port originally defined it as static. I agree that it's better to match the RHEL specific version. 3) Retained the "opt_dom0_vcpus_pin" in domain_build() as Rik added this in his cpufreq and Power Now! in Xen back port. Stephen is following up separately. The "opt_dom0_vcpus_pin" moved from schedule.c to domain.c due to a dependency, it wasn't an idle move. Also matches upstream in that regard, with some RHEL specific changes noted above. Bhavana diff --git a/arch/x86/acpi/boot.c b/arch/x86/acpi/boot.c index 76f329d..3b76219 100644 --- a/arch/x86/acpi/boot.c +++ b/arch/x86/acpi/boot.c @@ -920,3 +920,17 @@ int __init acpi_boot_init(void) return 0; } + +unsigned int acpi_get_processor_id(unsigned int cpu) +{ + unsigned int acpiid, apicid; + + if ((apicid = x86_cpu_to_apicid[cpu]) == 0xff) + return 0xff; + + for (acpiid = 0; acpiid < ARRAY_SIZE(x86_acpiid_to_apicid); acpiid++) + if (x86_acpiid_to_apicid[acpiid] == apicid) + return acpiid; + + return 0xff; +} diff --git a/arch/x86/domain.c b/arch/x86/domain.c index 9ff936e..db86d09 100644 --- a/arch/x86/domain.c +++ b/arch/x86/domain.c @@ -29,6 +29,7 @@ #include <xen/console.h> #include <xen/percpu.h> #include <xen/compat.h> +#include <xen/acpi.h> #include <asm/regs.h> #include <asm/mc146818rtc.h> #include <asm/system.h> @@ -891,6 +892,25 @@ arch_do_vcpu_op( break; } + case VCPUOP_get_physid: + { + struct vcpu_get_physid cpu_id; + + rc = -EINVAL; + if ( !v->domain->is_pinned ) + break; + + cpu_id.phys_id = (x86_cpu_to_apicid[v->vcpu_id] | + (acpi_get_processor_id(v->vcpu_id) << 8)); + + rc = -EFAULT; + if ( copy_to_guest(arg, &cpu_id, 1) ) + break; + + rc = 0; + break; + } + default: rc = -ENOSYS; break; diff --git a/common/domain.c b/common/domain.c index fa7a2e3..0984cf8 100644 --- a/common/domain.c +++ b/common/domain.c @@ -30,6 +30,24 @@ #include <public/vcpu.h> #include <acm/acm_hooks.h> +/* opt_dom0_vcpus_pin: If true, dom0 VCPUs are pinned. */ +unsigned int opt_dom0_vcpus_pin = 1; +boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin); + +enum cpufreq_controller cpufreq_controller = FREQCTL_dom0_kernel; +static void __init setup_cpufreq_option(char *str) +{ + if ( !strcmp(str, "dom0-kernel") ) + { + cpufreq_controller = FREQCTL_dom0_kernel; + opt_dom0_vcpus_pin = 1; + } else if ( !strcmp(str, "off") || !strcmp(str, "none") ) { + cpufreq_controller = FREQCTL_none; + opt_dom0_vcpus_pin = 0; + } +} +custom_param("cpufreq", setup_cpufreq_option); + /* Protect updates/reads (resp.) of domain_list and domain_hash. */ DEFINE_SPINLOCK(domlist_update_lock); DEFINE_RCU_READ_LOCK(domlist_read_lock); @@ -189,6 +207,9 @@ struct domain *domain_create( if ( domcr_flags & DOMCRF_hvm ) d->is_hvm = 1; + if ( (domid == 0) && opt_dom0_vcpus_pin ) + d->is_pinned = 1; + rangeset_domain_initialise(d); if ( !is_idle_domain(d) ) diff --git a/common/schedule.c b/common/schedule.c index b27771c..cdb9887 100644 --- a/common/schedule.c +++ b/common/schedule.c @@ -37,24 +37,6 @@ static char opt_sched[10] = "credit"; string_param("sched", opt_sched); -/* opt_dom0_vcpus_pin: If true, dom0 VCPUs are pinned. */ -unsigned int opt_dom0_vcpus_pin = 1; -boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin); - -enum cpufreq_controller cpufreq_controller = FREQCTL_dom0_kernel; -static void __init setup_cpufreq_option(char *str) -{ - if ( !strcmp(str, "dom0-kernel") ) - { - cpufreq_controller = FREQCTL_dom0_kernel; - opt_dom0_vcpus_pin = 1; - } else if ( !strcmp(str, "off") || !strcmp(str, "none") ) { - cpufreq_controller = FREQCTL_none; - opt_dom0_vcpus_pin = 0; - } -} -custom_param("cpufreq", setup_cpufreq_option); - #define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */ /* Various timer handlers. */ @@ -119,7 +101,7 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor) * domain-0 VCPUs, are pinned onto their respective physical CPUs. */ v->processor = processor; - if ( is_idle_domain(d) || ((d->domain_id == 0) && opt_dom0_vcpus_pin) ) + if ( is_idle_domain(d) || d->is_pinned ) v->cpu_affinity = cpumask_of_cpu(processor); else cpus_setall(v->cpu_affinity); @@ -304,7 +286,7 @@ static int __vcpu_set_affinity( int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity) { - if ( (v->domain->domain_id == 0) && opt_dom0_vcpus_pin ) + if ( v->domain->is_pinned ) return -EINVAL; return __vcpu_set_affinity(v, affinity, 0, 0); } diff --git a/include/public/vcpu.h b/include/public/vcpu.h index a84eb51..81e425e 100644 --- a/include/public/vcpu.h +++ b/include/public/vcpu.h @@ -170,7 +170,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t); * * This may be called only once per vcpu. */ -#define VCPUOP_register_vcpu_info 10 /* arg == struct vcpu_info */ +#define VCPUOP_register_vcpu_info 10 /* arg == vcpu_register_vcpu_info_t */ struct vcpu_register_vcpu_info { uint64_t mfn; /* mfn of page to place vcpu_info */ uint32_t offset; /* offset within page */ @@ -179,6 +179,22 @@ struct vcpu_register_vcpu_info { typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t; DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t); +/* + * Get the physical ID information for a pinned vcpu's underlying physical + * processor. The physical ID informmation is architecture-specific. + * On x86: id[7:0]=apic_id, id[15:8]=acpi_id, id[63:16]=mbz, + * and an unavailable identifier is returned as 0xff. + * This command returns -EINVAL if it is not a valid operation for this VCPU. + */ +#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */ +struct vcpu_get_physid { + uint64_t phys_id; +}; +typedef struct vcpu_get_physid vcpu_get_physid_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t); +#define xen_vcpu_physid_to_x86_apicid(physid) ((uint8_t)((physid)>>0)) +#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint8_t)((physid)>>8)) + #endif /* __XEN_PUBLIC_VCPU_H__ */ /* diff --git a/include/xen/acpi.h b/include/xen/acpi.h index aa7a36a..4df2fcb 100644 --- a/include/xen/acpi.h +++ b/include/xen/acpi.h @@ -376,6 +376,7 @@ extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT]; typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end); +unsigned int acpi_get_processor_id (unsigned int cpu); char * __acpi_map_table (unsigned long phys_addr, unsigned long size); unsigned long acpi_find_rsdp (void); int acpi_boot_init (void); diff --git a/include/xen/sched.h b/include/xen/sched.h index ec6afa1..2c3fefb 100644 --- a/include/xen/sched.h +++ b/include/xen/sched.h @@ -196,6 +196,8 @@ struct domain enum { DOMDYING_alive, DOMDYING_dying, DOMDYING_dead } is_dying; /* Domain is paused by controller software? */ bool_t is_paused_by_controller; + /* Domain's VCPUs are pinned 1:1 to physical CPUs? */ + bool_t is_pinned; /* Guest has shut down (inc. reason code)? */ spinlock_t shutdown_lock;