From patchwork Thu Jun 16 09:40:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9180283 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3E41A60573 for ; Thu, 16 Jun 2016 09:42:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F4F2269E2 for ; Thu, 16 Jun 2016 09:42:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2394828308; Thu, 16 Jun 2016 09:42:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3183627D45 for ; Thu, 16 Jun 2016 09:42:28 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bDTmZ-0006oQ-0B; Thu, 16 Jun 2016 09:40:15 +0000 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 Received: from [85.158.137.68] by server-1.bemta-3.messagelabs.com id 47/69-28758-CF372675; Thu, 16 Jun 2016 09:40:12 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrGIsWRWlGSWpSXmKPExsXS6fjDS/d3cVK 4wfJ3yhbft0xmcmD0OPzhCksAYxRrZl5SfkUCa8br1x9ZC1aFV0y+sYm1gXGycxcjJ4eQQJ5E 04WTzCA2r4CdRO/GFjBbQsBQYt/8VWxdjBwcLAKqEteeKYKE2QTUJdqebWcFCYsIGEicO5oEY jIL6EtsW8cCUiEsYCNx6fMaRojhdhIreo6BDeEUsJe4uoIFxOQVEJT4u0MYpIIZqGL6vplsEx h5ZiFkZiHJQNhaEg9/3WKBsLUlli18zTwLbK20xPJ/HBBha4l3X/ahKQGx3SSmHtzGtoCRYxW jRnFqUVlqka6hqV5SUWZ6RkluYmaOrqGBsV5uanFxYnpqTmJSsV5yfu4mRmCYMgDBDsY12z0P MUpyMCmJ8jpqJIUL8SXlp1RmJBZnxBeV5qQWH2KU4eBQkuDVB4a9kGBRanpqRVpmDjBiYNISH DxKIrxuIGne4oLE3OLMdIjUKUZdjp5Xt9cyCbHk5eelSonzqoIUCYAUZZTmwY2ARe8lRlkpYV 5GoKOEeApSi3IzS1DlXzGKczAqCfMygEzhycwrgdv0CugIJqAjbKbHgxxRkoiQkmpgjNWXEbj 84OPpHetlzG9dvlgTpKtpn+b2/tFWDu7bsyZMfOfSyun0ZsUhjVWu3v9fvL9/R3+em431dYP1 XB96rOXTT1Tw/mfctrbhaMk/7/TbOwOvnPDSVp0/SeLZ/xCH+KrH/Q9T3+1Mf/h9/hzDqv6N6 dor/rC+WiI2/2SFb7HewyUxq7/Z8SqxFGckGmoxFxUnAgA6NTUO2QIAAA== X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-3.tower-31.messagelabs.com!1466070009!45691476!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.46; banners=-,-,- X-VirusChecked: Checked Received: (qmail 13875 invoked from network); 16 Jun 2016 09:40:11 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-3.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 16 Jun 2016 09:40:11 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Thu, 16 Jun 2016 03:40:08 -0600 Message-Id: <5762901802000078000F597A@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.0 Date: Thu, 16 Jun 2016 03:40:08 -0600 From: "Jan Beulich" To: "xen-devel" References: <57628EA302000078000F596B@prv-mh.provo.novell.com> In-Reply-To: <57628EA302000078000F596B@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH 1/2] hvmloader: limit CPUs exposed to guests X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 hvmloader: limit CPUs exposed to guests 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 */ }; -/* 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 = sizeof(struct acpi_20_madt); sz += sizeof(struct acpi_20_madt_intsrcovr) * 16; sz += sizeof(struct acpi_20_madt_ioapic); - sz += sizeof(struct acpi_20_madt_lapic) * nr_processor_objects; + sz += sizeof(struct acpi_20_madt_lapic) * hvm_info->nr_vcpus; madt = mem_alloc(sz, 16); if (!madt) return NULL; @@ -142,8 +140,9 @@ static struct acpi_20_madt *construct_ma io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS; lapic = (struct acpi_20_madt_lapic *)(io_apic + 1); + info->nr_cpus = hvm_info->nr_vcpus; info->madt_lapic0_addr = (uint32_t)lapic; - for ( i = 0; i < nr_processor_objects; i++ ) + for ( i = 0; i < hvm_info->nr_vcpus; i++ ) { memset(lapic, 0, sizeof(*lapic)); lapic->type = 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 = i; lapic->apic_id = LAPIC_ID(i); - lapic->flags = ((i < hvm_info->nr_vcpus) && - test_bit(i, hvm_info->vcpu_online) + lapic->flags = (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 = mem_alloc(config->dsdt_15cpu_len, 16); if (!dsdt) goto oom; memcpy(dsdt, config->dsdt_15cpu, config->dsdt_15cpu_len); - nr_processor_objects = 15; } else { dsdt = mem_alloc(config->dsdt_anycpu_len, 16); if (!dsdt) goto oom; memcpy(dsdt, config->dsdt_anycpu, config->dsdt_anycpu_len); - nr_processor_objects = HVM_MAX_VCPUS; } /* --- 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(); + /* 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 = 0; cpu < max_cpus; cpu++) { @@ -171,17 +179,22 @@ int main(int argc, char **argv) pop_block(); push_block("Method", "_MAT, 0"); - stmt("Return", "ToBuffer(MAT)"); + if ( cpu ) + stmt("Return", "PMAT (%d, MAT)", cpu); + else + stmt("Return", "ToBuffer(MAT)"); pop_block(); 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(); push_block("Method", "_EJ0, 1, NotSerialized"); stmt("Sleep", "0xC8"); Acked-by: Andrew Cooper --- 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 */ }; -/* 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 = sizeof(struct acpi_20_madt); sz += sizeof(struct acpi_20_madt_intsrcovr) * 16; sz += sizeof(struct acpi_20_madt_ioapic); - sz += sizeof(struct acpi_20_madt_lapic) * nr_processor_objects; + sz += sizeof(struct acpi_20_madt_lapic) * hvm_info->nr_vcpus; madt = mem_alloc(sz, 16); if (!madt) return NULL; @@ -142,8 +140,9 @@ static struct acpi_20_madt *construct_ma io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS; lapic = (struct acpi_20_madt_lapic *)(io_apic + 1); + info->nr_cpus = hvm_info->nr_vcpus; info->madt_lapic0_addr = (uint32_t)lapic; - for ( i = 0; i < nr_processor_objects; i++ ) + for ( i = 0; i < hvm_info->nr_vcpus; i++ ) { memset(lapic, 0, sizeof(*lapic)); lapic->type = 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 = i; lapic->apic_id = LAPIC_ID(i); - lapic->flags = ((i < hvm_info->nr_vcpus) && - test_bit(i, hvm_info->vcpu_online) + lapic->flags = (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 = mem_alloc(config->dsdt_15cpu_len, 16); if (!dsdt) goto oom; memcpy(dsdt, config->dsdt_15cpu, config->dsdt_15cpu_len); - nr_processor_objects = 15; } else { dsdt = mem_alloc(config->dsdt_anycpu_len, 16); if (!dsdt) goto oom; memcpy(dsdt, config->dsdt_anycpu, config->dsdt_anycpu_len); - nr_processor_objects = HVM_MAX_VCPUS; } /* --- 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(); + /* 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 = 0; cpu < max_cpus; cpu++) { @@ -171,17 +179,22 @@ int main(int argc, char **argv) pop_block(); push_block("Method", "_MAT, 0"); - stmt("Return", "ToBuffer(MAT)"); + if ( cpu ) + stmt("Return", "PMAT (%d, MAT)", cpu); + else + stmt("Return", "ToBuffer(MAT)"); pop_block(); 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(); push_block("Method", "_EJ0, 1, NotSerialized"); stmt("Sleep", "0xC8");