From: "Jan Beulich" <JBeulich@suse.com>
To: xen-devel <xen-devel@lists.xenproject.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: [PATCH 1/2] hvmloader: limit CPUs exposed to guests
Date: Thu, 16 Jun 2016 03:40:08 -0600 [thread overview]
Message-ID: <5762901802000078000F597A@prv-mh.provo.novell.com> (raw)
In-Reply-To: <57628EA302000078000F596B@prv-mh.provo.novell.com>
[-- Attachment #1: Type: text/plain, Size: 5168 bytes --]
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 <jbeulich@suse.com>
--- 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");
[-- Attachment #2: hvmloader-limit-CPUs.patch --]
[-- Type: text/plain, Size: 5207 bytes --]
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 <jbeulich@suse.com>
--- 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");
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-06-16 9:40 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-16 9:33 [PATCH 0/2] x86: hvmloader improvements Jan Beulich
2016-06-16 9:40 ` Jan Beulich [this message]
2016-06-16 15:09 ` [PATCH 1/2] hvmloader: limit CPUs exposed to guests Boris Ostrovsky
2016-06-16 15:25 ` Jan Beulich
2016-06-16 15:37 ` Boris Ostrovsky
2016-06-16 16:04 ` Jan Beulich
2016-06-16 16:38 ` Boris Ostrovsky
2016-06-17 9:40 ` Andrew Cooper
2016-06-16 9:40 ` [PATCH 2/2] hvmloader: don't hard-code IO-APIC parameters Jan Beulich
2016-06-16 16:49 ` Boris Ostrovsky
2016-06-17 6:00 ` Jan Beulich
2016-06-17 11:51 ` Boris Ostrovsky
2016-06-17 14:26 ` Jan Beulich
2016-06-17 10:05 ` Andrew Cooper
2016-06-17 10:23 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5762901802000078000F597A@prv-mh.provo.novell.com \
--to=jbeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).