--- qemu-2.4.1/vl.c	2015-11-04 01:31:39.000000000 +0530
+++ qemu-2.4.1_aff/vl.c	2016-01-21 21:36:21.824950348 +0530
@@ -126,6 +126,7 @@
 #define MAX_VIRTIO_CONSOLES 1
 #define MAX_SCLP_CONSOLES 1
 
+#define MAX_VCPUS 32
 static const char *data_dir[16];
 static int data_dir_idx;
 const char *bios_name = NULL;
@@ -162,6 +163,8 @@
 int max_cpus = 0;
 int smp_cores = 1;
 int smp_threads = 1;
+int vcpu_affinity[MAX_VCPUS];
+int num_affinity = 0;
 int acpi_enabled = 1;
 int no_hpet = 0;
 int fd_bootchk = 1;
@@ -1194,6 +1197,61 @@
     },
 };
 
+static QemuOptsList qemu_vcpu_opts = {
+    .name = "vcpu-opts",
+    .implied_opt_name = "vcpunum",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_vcpu_opts.head),
+    .desc = {
+        {
+            .name = "vcpunum",
+            .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "affinity",
+            .type = QEMU_OPT_NUMBER,
+        },
+        { /*End of list */ }
+    },
+};
+
+static int parse_vcpu(void *opaque, QemuOpts *opts, Error **errp)
+{
+   if (opts){
+     unsigned vcpu = qemu_opt_get_number(opts,"vcpunum",0);
+     unsigned affinity = qemu_opt_get_number(opts,"affinity",0);
+
+     if (vcpu < smp_cores) {
+             if (vcpu_affinity[vcpu] == -1){
+		     vcpu_affinity[vcpu] = affinity;
+	     }
+             else {
+               error_report("Duplicate affinity statement for vcpu %d\n",vcpu);
+               return -1;
+             }
+	     num_affinity += 1;
+     }
+     else {
+       error_report("VCPU %d is more than allowed %d VCPUs in the system\n",vcpu,smp_cores);
+       return -1;
+     }
+   }
+   return 0;
+}
+
+static void parse_vcpu_opts(MachineClass *mc)
+{
+    int i;
+    for (i = 0; i < MAX_VCPUS; i++)
+      vcpu_affinity[i] = -1;
+
+    if (qemu_opts_foreach(qemu_find_opts("vcpu-opts"), parse_vcpu, NULL, NULL)) {
+        exit(1);
+    }
+
+    if (num_affinity != smp_cores) {
+      fprintf(stderr,"Warning: affinity is not specified for some (%d) of the %d smp cores. Will be using default mask\n",(smp_cores-num_affinity), smp_cores);
+    }
+}
+
 static void smp_parse(QemuOpts *opts)
 {
     if (opts) {
@@ -2954,6 +3012,9 @@
     Error *main_loop_err = NULL;
     Error *err = NULL;
 
+    printf("*****************************************************************\n");
+    printf("**    QEMU   - MODIFIED FOR CPU AFFINITY                       **\n");
+    printf("*****************************************************************\n");
     qemu_init_cpu_loop();
     qemu_mutex_lock_iothread();
 
@@ -2979,6 +3040,7 @@
     qemu_add_opts(&qemu_machine_opts);
     qemu_add_opts(&qemu_mem_opts);
     qemu_add_opts(&qemu_smp_opts);
+    qemu_add_opts(&qemu_vcpu_opts);
     qemu_add_opts(&qemu_boot_opts);
     qemu_add_opts(&qemu_sandbox_opts);
     qemu_add_opts(&qemu_add_fd_opts);
@@ -3683,6 +3745,12 @@
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_vcpu:
+                if (!qemu_opts_parse_noisily(qemu_find_opts("vcpu-opts"),
+                                             optarg, true)) {
+                    exit(1);
+                }
+                break;
             case QEMU_OPTION_vnc:
             {
 #ifdef CONFIG_VNC
@@ -4097,6 +4165,7 @@
         exit(1);
     }
 
+    parse_vcpu_opts(machine_class);
     /*
      * Get the default machine options from the machine if it is not already
      * specified either by the configuration file or by the command line.


--- qemu-2.4.1/cpus.c	2015-11-04 01:31:31.000000000 +0530
+++ qemu-2.4.1_aff/cpus.c	2016-01-21 21:36:21.976950357 +0530
@@ -50,6 +50,9 @@
 #ifdef CONFIG_LINUX
 
 #include <sys/prctl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
 
 #ifndef PR_MCE_KILL
 #define PR_MCE_KILL 33
@@ -1277,10 +1280,39 @@
     }
 }
 
+#ifdef QEMU_AFFINITY_DEBUG
+static void print_cpu_mask(pthread_t t,int cpuindex,int flag)
+{
+  int i = 0;
+  cpu_set_t cpuset;
+  uint64_t mask_low = 0;
+  uint64_t mask_high = 0;
+  CPU_ZERO(&cpuset);
+  /* Get the current CPU Mask */
+  pthread_getaffinity_np(t, sizeof(cpu_set_t), &cpuset);
+
+  for (i = 0; i< 128; i++){
+       if (CPU_ISSET(i, &cpuset)){
+          if (i < 64)
+             mask_low = mask_low | ((uint64_t)1 << i);
+          else
+             mask_high = mask_high | ((uint64_t)1 << (i-64));
+       }
+   }
+
+   if (flag == 0)
+	   printf ("QEMU DEBUG:: Original CPU mask 0x%016"PRIx64"%016"PRIx64" for VCPU %d\n",mask_high,mask_low,cpuindex);
+   else
+	   printf ("QEMU DEBUG:: New CPU mask 0x%016"PRIx64"%016"PRIx64" for VCPU %d\n",mask_high,mask_low,cpuindex);
+}
+#endif
+
+extern int vcpu_affinity[];
 static void qemu_kvm_start_vcpu(CPUState *cpu)
 {
     char thread_name[VCPU_THREAD_NAME_SIZE];
-
+    cpu_set_t cpuset;
+    
     cpu->thread = g_malloc0(sizeof(QemuThread));
     cpu->halt_cond = g_malloc0(sizeof(QemuCond));
     qemu_cond_init(cpu->halt_cond);
@@ -1288,6 +1320,20 @@
              cpu->cpu_index);
     qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
                        cpu, QEMU_THREAD_JOINABLE);
+
+#ifdef QEMU_AFFINITY_DEBUG
+    print_cpu_mask((cpu->thread)->thread,cpu->cpu_index,0); 
+#endif
+    if (vcpu_affinity[cpu->cpu_index] != -1) {
+	    printf("QEMU INFO:: Pinning vcpu %d to Physical CPU %d\n",cpu->cpu_index, vcpu_affinity[cpu->cpu_index]);
+	    CPU_ZERO(&cpuset);
+	    CPU_SET(vcpu_affinity[cpu->cpu_index], &cpuset); 
+	    pthread_setaffinity_np((cpu->thread)->thread, sizeof(cpu_set_t), &cpuset);
+#ifdef QEMU_AFFINITY_DEBUG
+	    print_cpu_mask((cpu->thread)->thread,cpu->cpu_index,1); 
+#endif
+    }
+     
     while (!cpu->created) {
         qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
     }


--- qemu-2.4.1/qemu-options.hx	2015-11-04 01:31:35.000000000 +0530
+++ qemu-2.4.1_aff/qemu-options.hx	2016-01-21 21:36:22.369950380 +0530
@@ -113,6 +113,16 @@
 specifies the maximum number of hotpluggable CPUs.
 ETEXI
 
+DEF("vcpu", HAS_ARG, QEMU_OPTION_vcpu,
+    "-vcpu [vcpunum=]n[,affinity=affinity]\n"
+    "-vcpu [vcpunum=]n[,affinity=affinity]\n", QEMU_ARCH_ALL)
+STEXI
+@item -vcpu [vcpunum=]@var{n}[,affinity=@var{affinity}]
+@itemx -vcpu [vcpunum=]@var{n}[,affinity=@var{affinity}]
+@findex -vcpu
+VCPU Affinity. If specified, specify for all the CPUs.
+ETEXI
+
 DEF("numa", HAS_ARG, QEMU_OPTION_numa,
     "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n"
     "-numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
