HVM vcpu add/remove: parse 'vcpu_avail' to firmware and set up madt
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 14 Dec 2009 09:25:47 +0000 (09:25 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 14 Dec 2009 09:25:47 +0000 (09:25 +0000)
accordingly

-- currently firmware has got 'vcpus' from xend, this patch add parse
   'vcpu_avail' to firmware;
-- setup madt 'lapic' subitems of processors accoring to vcpus and
   vcpu_avail which finally come from config;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
tools/firmware/hvmloader/acpi/build.c
tools/firmware/hvmloader/config.h
tools/firmware/hvmloader/util.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/image.py
xen/include/public/hvm/hvm_info_table.h

index 3b4b85ed20e68aa785a8e3796f4bc38a295a0c23..cc429929362ee50302eaea2c13ef41485a4ad91f 100644 (file)
@@ -115,7 +115,7 @@ static int construct_madt(struct acpi_20_madt *madt)
 
     lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
     madt_lapic0_addr = (uint32_t)lapic;
-    for ( i = 0; i < MAX_VCPUS; i++ )
+    for ( i = 0; i < HVM_MAX_VCPUS; i++ )
     {
         memset(lapic, 0, sizeof(*lapic));
         lapic->type    = ACPI_PROCESSOR_LOCAL_APIC;
@@ -123,7 +123,9 @@ static int construct_madt(struct acpi_20_madt *madt)
         /* Processor ID must match processor-object IDs in the DSDT. */
         lapic->acpi_processor_id = i;
         lapic->apic_id = LAPIC_ID(i);
-        lapic->flags = (i < hvm_info->nr_vcpus) ? ACPI_LOCAL_APIC_ENABLED : 0;
+        lapic->flags = ((i < hvm_info->nr_vcpus) &&
+                        test_bit(i, hvm_info->vcpu_online)
+                        ? ACPI_LOCAL_APIC_ENABLED : 0);
         offset += sizeof(*lapic);
         lapic++;
     }
index bdb8824ae3280e2bfdcdecd97c1e8704eb69e9e5..60d52571ab06506fb56bc4bbad6070514ed4510f 100644 (file)
@@ -50,9 +50,6 @@ extern unsigned long pci_mem_start, pci_mem_end;
 #define XEN_PF_IOBASE   0x10
 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
 
-/* Maximum we can support with current vLAPIC ID mapping. */
-#define MAX_VCPUS 128
-
 /* Located at BIOS_INFO_PHYSICAL_ADDRESS. */
 struct bios_info {
     uint8_t  com1_present:1;    /* 0[0] - System has COM1? */
index c12a47f6c211bc0b18ae2b09e8bf0d8fe34faa25..b70015893f9a614acc7d3db1e292f82fde7ac03e 100644 (file)
@@ -30,6 +30,11 @@ void __bug(char *file, int line) __attribute__((noreturn));
 #define BUG_ON(p) do { if (p) BUG(); } while (0)
 #define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)]))
 
+static inline int test_bit(unsigned int b, void *p)
+{
+    return !!(((uint8_t *)p)[b>>3] & (1u<<(b&7)));
+}
+
 /* MSR access */
 void wrmsr(uint32_t idx, uint64_t v);
 uint64_t rdmsr(uint32_t idx);
index 83096048cd3f0d670e72c642f7294e68921044d0..c4e8840016bfcfdd3234be285dfaa223b8baa273 100644 (file)
@@ -915,13 +915,14 @@ static PyObject *pyxc_hvm_build(XcObject *self,
 #endif
     char *image;
     int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1;
+    uint64_t vcpu_avail = 1;
 
     static char *kwd_list[] = { "domid",
-                                "memsize", "image", "target", "vcpus", "acpi",
-                                "apic", NULL };
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
+                                "memsize", "image", "target", "vcpus", 
+                                "vcpu_avail", "acpi", "apic", NULL };
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iilii", kwd_list,
                                       &dom, &memsize, &image, &target, &vcpus,
-                                      &acpi, &apic) )
+                                      &vcpu_avail, &acpi, &apic) )
         return NULL;
 
     if ( target == -1 )
@@ -942,6 +943,8 @@ static PyObject *pyxc_hvm_build(XcObject *self,
     va_hvm->acpi_enabled = acpi;
     va_hvm->apic_mode    = apic;
     va_hvm->nr_vcpus     = vcpus;
+    ((uint64_t *)va_hvm->vcpu_online)[0] = vcpu_avail;
+    ((uint64_t *)va_hvm->vcpu_online)[1] = 0;    
     for ( i = 0, sum = 0; i < va_hvm->length; i++ )
         sum += ((uint8_t *)va_hvm)[i];
     va_hvm->checksum -= sum;
@@ -1810,6 +1813,7 @@ static PyMethodDef pyxc_methods[] = {
       " dom     [int]:      Identifier of domain to build into.\n"
       " image   [str]:      Name of HVM loader image file.\n"
       " vcpus   [int, 1]:   Number of Virtual CPUS in domain.\n\n"
+      " vcpu_avail [long, 1]: Which Virtual CPUS available.\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
     { "hvm_get_param", 
index 7dd7cf0200aaf1aac07a3506921cb95ec8e9fdb5..ee2e03375c5b68db757864a53b6b6a6fa350d444 100644 (file)
@@ -938,6 +938,7 @@ class HVMImageHandler(ImageHandler):
         log.debug("memsize        = %d", memmax_mb)
         log.debug("target         = %d", mem_mb)
         log.debug("vcpus          = %d", self.vm.getVCpuCount())
+        log.debug("vcpu_avail     = %li", self.vm.getVCpuAvail())
         log.debug("acpi           = %d", self.acpi)
         log.debug("apic           = %d", self.apic)
 
@@ -946,6 +947,7 @@ class HVMImageHandler(ImageHandler):
                           memsize        = memmax_mb,
                           target         = mem_mb,
                           vcpus          = self.vm.getVCpuCount(),
+                          vcpu_avail     = self.vm.getVCpuAvail(),
                           acpi           = self.acpi,
                           apic           = self.apic)
         rc['notes'] = { 'SUSPEND_CANCEL': 1 }
index b89845515db672670d295fad2f5ab60f8170f535..adb3fb9041ce11e419285410c67c1b9fefdd0da8 100644 (file)
@@ -29,6 +29,9 @@
 #define HVM_INFO_OFFSET      0x800
 #define HVM_INFO_PADDR       ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
 
+/* Maximum we can support with current vLAPIC ID mapping. */
+#define HVM_MAX_VCPUS        128
+
 struct hvm_info_table {
     char        signature[8]; /* "HVM INFO" */
     uint32_t    length;
@@ -64,6 +67,9 @@ struct hvm_info_table {
      *    RAM above 4GB
      */
     uint32_t    high_mem_pgend;
+
+    /* Bitmap of which CPUs are online at boot time. */
+    uint8_t     vcpu_online[HVM_MAX_VCPUS/8];
 };
 
 #endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */