From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 1/2] hvmloader: limit CPUs exposed to guests Date: Thu, 16 Jun 2016 03:40:08 -0600 Message-ID: <5762901802000078000F597A@prv-mh.provo.novell.com> References: <57628EA302000078000F596B@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartC6F0FEE8.1__=" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bDTmW-0006oK-Tk for xen-devel@lists.xenproject.org; Thu, 16 Jun 2016 09:40:13 +0000 In-Reply-To: <57628EA302000078000F596B@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Andrew Cooper List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartC6F0FEE8.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Various Linux versions allocate (partial) per-CPU data for all of them, as there is no indication in MADT whether they're hotpluggable. That's a little wasteful in terms of resource consumption especially for - guests with not overly much memory assigned, - 32-bit guests not having overly much address space available. Therefore limit what we put into MADT to the "maxvcpus" value, and make sure AML doesn't touch memory addresses corresponding to CPUs beyond that value (we can't reasonably make the respective processor objects disappear). Signed-off-by: Jan Beulich --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -48,6 +48,7 @@ struct acpi_info { uint8_t com2_present:1; /* 0[1] - System has COM2? */ uint8_t lpt1_present:1; /* 0[2] - System has LPT1? */ uint8_t hpet_present:1; /* 0[3] - System has HPET? */ + uint16_t nr_cpus; /* 2 - Number of CPUs */ uint32_t pci_min, pci_len; /* 4, 8 - PCI I/O hole boundaries */ uint32_t madt_csum_addr; /* 12 - Address of MADT checksum */ uint32_t madt_lapic0_addr; /* 16 - Address of first MADT LAPIC = struct */ @@ -55,9 +56,6 @@ struct acpi_info { uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI I/O hole boundaries = */ }; =20 -/* Number of processor objects in the chosen DSDT. */ -static unsigned int nr_processor_objects; - static void set_checksum( void *table, uint32_t checksum_offset, uint32_t length) { @@ -89,7 +87,7 @@ static struct acpi_20_madt *construct_ma sz =3D sizeof(struct acpi_20_madt); sz +=3D sizeof(struct acpi_20_madt_intsrcovr) * 16; sz +=3D sizeof(struct acpi_20_madt_ioapic); - sz +=3D sizeof(struct acpi_20_madt_lapic) * nr_processor_objects; + sz +=3D sizeof(struct acpi_20_madt_lapic) * hvm_info->nr_vcpus; =20 madt =3D mem_alloc(sz, 16); if (!madt) return NULL; @@ -142,8 +140,9 @@ static struct acpi_20_madt *construct_ma io_apic->ioapic_addr =3D IOAPIC_BASE_ADDRESS; =20 lapic =3D (struct acpi_20_madt_lapic *)(io_apic + 1); + info->nr_cpus =3D hvm_info->nr_vcpus; info->madt_lapic0_addr =3D (uint32_t)lapic; - for ( i =3D 0; i < nr_processor_objects; i++ ) + for ( i =3D 0; i < hvm_info->nr_vcpus; i++ ) { memset(lapic, 0, sizeof(*lapic)); lapic->type =3D ACPI_PROCESSOR_LOCAL_APIC; @@ -151,8 +150,7 @@ static struct acpi_20_madt *construct_ma /* Processor ID must match processor-object IDs in the DSDT. */ lapic->acpi_processor_id =3D i; lapic->apic_id =3D LAPIC_ID(i); - lapic->flags =3D ((i < hvm_info->nr_vcpus) && - test_bit(i, hvm_info->vcpu_online) + lapic->flags =3D (test_bit(i, hvm_info->vcpu_online) ? ACPI_LOCAL_APIC_ENABLED : 0); lapic++; } @@ -534,14 +532,12 @@ void acpi_build_tables(struct acpi_confi dsdt =3D mem_alloc(config->dsdt_15cpu_len, 16); if (!dsdt) goto oom; memcpy(dsdt, config->dsdt_15cpu, config->dsdt_15cpu_len); - nr_processor_objects =3D 15; } else { dsdt =3D mem_alloc(config->dsdt_anycpu_len, 16); if (!dsdt) goto oom; memcpy(dsdt, config->dsdt_anycpu, config->dsdt_anycpu_len); - nr_processor_objects =3D HVM_MAX_VCPUS; } =20 /* --- a/tools/firmware/hvmloader/acpi/dsdt.asl +++ b/tools/firmware/hvmloader/acpi/dsdt.asl @@ -50,7 +50,8 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, UAR2, 1, LTP1, 1, HPET, 1, - Offset(4), + Offset(2), + NCPU, 16, PMIN, 32, PLEN, 32, MSUA, 32, /* MADT checksum address */ --- a/tools/firmware/hvmloader/acpi/mk_dsdt.c +++ b/tools/firmware/hvmloader/acpi/mk_dsdt.c @@ -150,6 +150,14 @@ int main(int argc, char **argv) indent(); printf("MSU, 8\n"); pop_block(); =20 + /* Processor object helpers. */ + push_block("Method", "PMAT, 2"); + push_block("If", "LLess(Arg0, NCPU)"); + stmt("Return", "ToBuffer(Arg1)"); + pop_block(); + stmt("Return", "Buffer() {0, 8, 0xff, 0xff, 0, 0, 0, 0}"); + pop_block(); + /* Define processor objects and control methods. */ for ( cpu =3D 0; cpu < max_cpus; cpu++) { @@ -171,17 +179,22 @@ int main(int argc, char **argv) pop_block(); =20 push_block("Method", "_MAT, 0"); - stmt("Return", "ToBuffer(MAT)"); + if ( cpu ) + stmt("Return", "PMAT (%d, MAT)", cpu); + else + stmt("Return", "ToBuffer(MAT)"); pop_block(); =20 push_block("Method", "_STA"); + if ( cpu ) + push_block("If", "LLess(%d, \\_SB.NCPU)", cpu); push_block("If", "FLG"); stmt("Return", "0xF"); pop_block(); - push_block("Else", NULL); + if ( cpu ) + pop_block(); stmt("Return", "0x0"); pop_block(); - pop_block(); =20 push_block("Method", "_EJ0, 1, NotSerialized"); stmt("Sleep", "0xC8"); --=__PartC6F0FEE8.1__= Content-Type: text/plain; name="hvmloader-limit-CPUs.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="hvmloader-limit-CPUs.patch" hvmloader: limit CPUs exposed to guests=0A=0AVarious Linux versions = allocate (partial) per-CPU data for all of them,=0Aas there is no = indication in MADT whether they're hotpluggable. That's=0Aa little = wasteful in terms of resource consumption especially for=0A- guests with = not overly much memory assigned,=0A- 32-bit guests not having overly much = address space available.=0ATherefore limit what we put into MADT to the = "maxvcpus" value, and make=0Asure AML doesn't touch memory addresses = corresponding to CPUs beyond=0Athat value (we can't reasonably make the = respective processor objects=0Adisappear).=0A=0ASigned-off-by: Jan Beulich = =0A=0A--- a/tools/firmware/hvmloader/acpi/build.c=0A+++ = b/tools/firmware/hvmloader/acpi/build.c=0A@@ -48,6 +48,7 @@ struct = acpi_info {=0A uint8_t com2_present:1; /* 0[1] - System has COM2? = */=0A uint8_t lpt1_present:1; /* 0[2] - System has LPT1? */=0A = uint8_t hpet_present:1; /* 0[3] - System has HPET? */=0A+ uint16_t = nr_cpus; /* 2 - Number of CPUs */=0A uint32_t pci_min, = pci_len; /* 4, 8 - PCI I/O hole boundaries */=0A uint32_t madt_csum_ad= dr; /* 12 - Address of MADT checksum */=0A uint32_t madt_lapic0_ad= dr; /* 16 - Address of first MADT LAPIC struct */=0A@@ -55,9 +56,6 @@ = struct acpi_info {=0A uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI = I/O hole boundaries */=0A };=0A =0A-/* Number of processor objects in the = chosen DSDT. */=0A-static unsigned int nr_processor_objects;=0A-=0A static = void set_checksum(=0A void *table, uint32_t checksum_offset, uint32_t = length)=0A {=0A@@ -89,7 +87,7 @@ static struct acpi_20_madt *construct_ma= =0A sz =3D sizeof(struct acpi_20_madt);=0A sz +=3D sizeof(struct = acpi_20_madt_intsrcovr) * 16;=0A sz +=3D sizeof(struct acpi_20_madt_ioa= pic);=0A- sz +=3D sizeof(struct acpi_20_madt_lapic) * nr_processor_objec= ts;=0A+ sz +=3D sizeof(struct acpi_20_madt_lapic) * hvm_info->nr_vcpus;= =0A =0A madt =3D mem_alloc(sz, 16);=0A if (!madt) return NULL;=0A@@= -142,8 +140,9 @@ static struct acpi_20_madt *construct_ma=0A = io_apic->ioapic_addr =3D IOAPIC_BASE_ADDRESS;=0A =0A lapic =3D (struct = acpi_20_madt_lapic *)(io_apic + 1);=0A+ info->nr_cpus =3D hvm_info->nr_v= cpus;=0A info->madt_lapic0_addr =3D (uint32_t)lapic;=0A- for ( i = =3D 0; i < nr_processor_objects; i++ )=0A+ for ( i =3D 0; i < hvm_info->= nr_vcpus; i++ )=0A {=0A memset(lapic, 0, sizeof(*lapic));=0A = lapic->type =3D ACPI_PROCESSOR_LOCAL_APIC;=0A@@ -151,8 +150,7 @@ = static struct acpi_20_madt *construct_ma=0A /* Processor ID must = match processor-object IDs in the DSDT. */=0A lapic->acpi_processor= _id =3D i;=0A lapic->apic_id =3D LAPIC_ID(i);=0A- lapic->fla= gs =3D ((i < hvm_info->nr_vcpus) &&=0A- test_bit(i, = hvm_info->vcpu_online)=0A+ lapic->flags =3D (test_bit(i, hvm_info->v= cpu_online)=0A ? ACPI_LOCAL_APIC_ENABLED : 0);=0A = lapic++;=0A }=0A@@ -534,14 +532,12 @@ void acpi_build_tables(str= uct acpi_confi=0A dsdt =3D mem_alloc(config->dsdt_15cpu_len, = 16);=0A if (!dsdt) goto oom;=0A memcpy(dsdt, config->dsdt_1= 5cpu, config->dsdt_15cpu_len);=0A- nr_processor_objects =3D 15;=0A = }=0A else=0A {=0A dsdt =3D mem_alloc(config->dsdt_anycpu= _len, 16);=0A if (!dsdt) goto oom;=0A memcpy(dsdt, = config->dsdt_anycpu, config->dsdt_anycpu_len);=0A- nr_processor_obje= cts =3D HVM_MAX_VCPUS;=0A }=0A =0A /*=0A--- a/tools/firmware/hvmloa= der/acpi/dsdt.asl=0A+++ b/tools/firmware/hvmloader/acpi/dsdt.asl=0A@@ = -50,7 +50,8 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2,=0A UAR2, = 1,=0A LTP1, 1,=0A HPET, 1,=0A- Offset(4),= =0A+ Offset(2),=0A+ NCPU, 16,=0A PMIN, = 32,=0A PLEN, 32,=0A MSUA, 32, /* MADT checksum = address */=0A--- a/tools/firmware/hvmloader/acpi/mk_dsdt.c=0A+++ b/tools/fi= rmware/hvmloader/acpi/mk_dsdt.c=0A@@ -150,6 +150,14 @@ int main(int argc, = char **argv)=0A indent(); printf("MSU, 8\n");=0A pop_block();=0A = =0A+ /* Processor object helpers. */=0A+ push_block("Method", "PMAT, = 2");=0A+ push_block("If", "LLess(Arg0, NCPU)");=0A+ stmt("Return", = "ToBuffer(Arg1)");=0A+ pop_block();=0A+ stmt("Return", "Buffer() {0, = 8, 0xff, 0xff, 0, 0, 0, 0}");=0A+ pop_block();=0A+=0A /* Define = processor objects and control methods. */=0A for ( cpu =3D 0; cpu < = max_cpus; cpu++)=0A {=0A@@ -171,17 +179,22 @@ int main(int argc, char = **argv)=0A pop_block();=0A =0A push_block("Method", "_MAT, = 0");=0A- stmt("Return", "ToBuffer(MAT)");=0A+ if ( cpu )=0A+ = stmt("Return", "PMAT (%d, MAT)", cpu);=0A+ else=0A+ = stmt("Return", "ToBuffer(MAT)");=0A pop_block();=0A =0A = push_block("Method", "_STA");=0A+ if ( cpu )=0A+ = push_block("If", "LLess(%d, \\_SB.NCPU)", cpu);=0A push_block("If",= "FLG");=0A stmt("Return", "0xF");=0A pop_block();=0A- = push_block("Else", NULL);=0A+ if ( cpu )=0A+ = pop_block();=0A stmt("Return", "0x0");=0A pop_block();=0A- = pop_block();=0A =0A push_block("Method", "_EJ0, 1, = NotSerialized");=0A stmt("Sleep", "0xC8");=0A --=__PartC6F0FEE8.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwOi8vbGlzdHMueGVuLm9y Zy94ZW4tZGV2ZWwK --=__PartC6F0FEE8.1__=--