From nobody Mon Feb 9 20:32:15 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1560528902; cv=none; d=zoho.com; s=zohoarc; b=jY2rv4s9m6UiC0hllKiNiIhkuvMS++e+GhcMNKa4h2KFsSz6chOnvHkEwVwDW8nvmKx//EzpexFp+epGF2F3/eJ2XdA38sjWTbNVQb19YZuBGIbo7mW96dislm4V+rj3u8/6Jagsa3Ol/W5EaA7I+LnIZlJue8eqgEspceBCDtU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1560528902; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=m62s/GuicKyFXrAIeoBwY/I7WmmSOEXRXlN89JQGdkI=; b=Woi0D7auRVwkaQHkjGak1667TZosIkKgI4w6Ouy9Ak73vK7Sdeh6aCh+nvdTgvOJx97otz0tybYPXFo8EQ3a3AwqGWQLA+JY4kHBTxacRZtEAUuiWI/POns1awQ9TAQe9yXBTV7EuAmmlKPeylgToAuIqGCCKT1MnDX2zmig+/E= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1560528902556874.7696567065323; Fri, 14 Jun 2019 09:15:02 -0700 (PDT) Received: from localhost ([::1]:53084 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hboqw-0004Ru-Dc for importer@patchew.org; Fri, 14 Jun 2019 12:14:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33936) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hbobp-0001CN-0m for qemu-devel@nongnu.org; Fri, 14 Jun 2019 11:59:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hbobm-0005v2-4I for qemu-devel@nongnu.org; Fri, 14 Jun 2019 11:59:20 -0400 Received: from mga18.intel.com ([134.134.136.126]:2020) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hbobl-0005M2-Lo for qemu-devel@nongnu.org; Fri, 14 Jun 2019 11:59:17 -0400 Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Jun 2019 08:59:12 -0700 Received: from tao-optiplex-7060.sh.intel.com ([10.239.13.104]) by orsmga008.jf.intel.com with ESMTP; 14 Jun 2019 08:59:10 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 From: Tao Xu To: imammedo@redhat.com, eblake@redhat.com, ehabkost@redhat.com Date: Fri, 14 Jun 2019 23:56:23 +0800 Message-Id: <20190614155626.27932-6-tao3.xu@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190614155626.27932-1-tao3.xu@intel.com> References: <20190614155626.27932-1-tao3.xu@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.126 Subject: [Qemu-devel] [PATCH v5 5/8] acpi: introduce AcpiDeviceIfClass.build_mem_ranges hook X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jingqi.liu@intel.com, tao3.xu@intel.com, fan.du@intel.com, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Add build_mem_ranges callback to AcpiDeviceIfClass and use it for generating SRAT and HMAT numa memory ranges. Suggested-by: Igor Mammedov Co-developed-by: Liu Jingqi Signed-off-by: Liu Jingqi Signed-off-by: Tao Xu --- Changes in v5 -> v4: - Add the missing if 'mem_len > 0' in pc_build_mem_ranges() (Igor) - Correct the descriptions of build_mem_ranges in AcpiDeviceIfClass (Igor) - Use GArray for NUMA memory ranges data (Igor) - Add the reason of using stub (Igor) --- hw/acpi/piix4.c | 1 + hw/i386/acpi-build.c | 133 +++++++++++++++++---------- hw/isa/lpc_ich9.c | 1 + include/hw/acpi/acpi_dev_interface.h | 4 + include/hw/i386/pc.h | 1 + include/sysemu/numa.h | 12 +++ stubs/Makefile.objs | 1 + stubs/pc_build_mem_ranges.c | 14 +++ 8 files changed, 120 insertions(+), 47 deletions(-) create mode 100644 stubs/pc_build_mem_ranges.c diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index ec4e186cec..bc078c1ad7 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -702,6 +702,7 @@ static void piix4_pm_class_init(ObjectClass *klass, voi= d *data) adevc->ospm_status =3D piix4_ospm_status; adevc->send_event =3D piix4_send_gpe; adevc->madt_cpu =3D pc_madt_cpu_entry; + adevc->build_mem_ranges =3D pc_build_mem_ranges; } =20 static const TypeInfo piix4_pm_info =3D { diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 055e677c30..44dd447fa5 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2279,18 +2279,89 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, = GArray *tcpalog) #define HOLE_640K_START (640 * KiB) #define HOLE_640K_END (1 * MiB) =20 +void pc_build_mem_ranges(AcpiDeviceIf *adev, MachineState *ms) +{ + uint64_t mem_len, mem_base, next_base; + int i; + PCMachineState *pcms =3D PC_MACHINE(ms); + NumaState *nstat =3D ms->numa_state; + NumaMemRange *mem_range; + nstat->mem_ranges_num =3D 0; + next_base =3D 0; + + /* + * the memory map is a bit tricky, it contains at least one hole + * from 640k-1M and possibly another one from 3.5G-4G. + */ + + for (i =3D 0; i < pcms->numa_nodes; ++i) { + mem_base =3D next_base; + mem_len =3D pcms->node_mem[i]; + next_base =3D mem_base + mem_len; + + /* Cut out the 640K hole */ + if (mem_base <=3D HOLE_640K_START && + next_base > HOLE_640K_START) { + mem_len -=3D next_base - HOLE_640K_START; + if (mem_len > 0) { + mem_range =3D acpi_data_push(nstat->mem_ranges, + sizeof *mem_range); + mem_range->base =3D mem_base; + mem_range->length =3D mem_len; + mem_range->node =3D i; + nstat->mem_ranges_num++; + } + + /* Check for the rare case: 640K < RAM < 1M */ + if (next_base <=3D HOLE_640K_END) { + next_base =3D HOLE_640K_END; + continue; + } + mem_base =3D HOLE_640K_END; + mem_len =3D next_base - HOLE_640K_END; + } + + /* Cut out the ACPI_PCI hole */ + if (mem_base <=3D pcms->below_4g_mem_size && + next_base > pcms->below_4g_mem_size) { + mem_len -=3D next_base - pcms->below_4g_mem_size; + if (mem_len > 0) { + mem_range =3D acpi_data_push(nstat->mem_ranges, + sizeof *mem_range); + mem_range->base =3D mem_base; + mem_range->length =3D mem_len; + mem_range->node =3D i; + nstat->mem_ranges_num++; + } + mem_base =3D 1ULL << 32; + mem_len =3D next_base - pcms->below_4g_mem_size; + next_base =3D mem_base + mem_len; + } + if (mem_len > 0) { + mem_range =3D acpi_data_push(nstat->mem_ranges, + sizeof *mem_range); + mem_range->base =3D mem_base; + mem_range->length =3D mem_len; + mem_range->node =3D i; + nstat->mem_ranges_num++; + } + } +} + static void build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) { AcpiSystemResourceAffinityTable *srat; AcpiSratMemoryAffinity *numamem; =20 - int i; - int srat_start, numa_start, slots; - uint64_t mem_len, mem_base, next_base; + int i, srat_start, numa_start, slots; MachineClass *mc =3D MACHINE_GET_CLASS(machine); const CPUArchIdList *apic_ids =3D mc->possible_cpu_arch_ids(machine); PCMachineState *pcms =3D PC_MACHINE(machine); + AcpiDeviceIfClass *adevc =3D ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev); + AcpiDeviceIf *adev =3D ACPI_DEVICE_IF(pcms->acpi_dev); + NumaState *nstat =3D machine->numa_state; + NumaMemRange *mem_range; ram_addr_t hotplugabble_address_space_size =3D object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZ= E, NULL); @@ -2327,57 +2398,25 @@ build_srat(GArray *table_data, BIOSLinker *linker, = MachineState *machine) } } =20 + if (pcms->numa_nodes && !nstat->mem_ranges_num) { + nstat->mem_ranges =3D g_array_new(false, true /* clear */, + sizeof *mem_range); + adevc->build_mem_ranges(adev, machine); + } =20 - /* the memory map is a bit tricky, it contains at least one hole - * from 640k-1M and possibly another one from 3.5G-4G. - */ - next_base =3D 0; numa_start =3D table_data->len; =20 - for (i =3D 1; i < pcms->numa_nodes + 1; ++i) { - mem_base =3D next_base; - mem_len =3D pcms->node_mem[i - 1]; - next_base =3D mem_base + mem_len; - - /* Cut out the 640K hole */ - if (mem_base <=3D HOLE_640K_START && - next_base > HOLE_640K_START) { - mem_len -=3D next_base - HOLE_640K_START; - if (mem_len > 0) { - numamem =3D acpi_data_push(table_data, sizeof *numamem); - build_srat_memory(numamem, mem_base, mem_len, i - 1, - MEM_AFFINITY_ENABLED); - } - - /* Check for the rare case: 640K < RAM < 1M */ - if (next_base <=3D HOLE_640K_END) { - next_base =3D HOLE_640K_END; - continue; - } - mem_base =3D HOLE_640K_END; - mem_len =3D next_base - HOLE_640K_END; - } - - /* Cut out the ACPI_PCI hole */ - if (mem_base <=3D pcms->below_4g_mem_size && - next_base > pcms->below_4g_mem_size) { - mem_len -=3D next_base - pcms->below_4g_mem_size; - if (mem_len > 0) { - numamem =3D acpi_data_push(table_data, sizeof *numamem); - build_srat_memory(numamem, mem_base, mem_len, i - 1, - MEM_AFFINITY_ENABLED); - } - mem_base =3D 1ULL << 32; - mem_len =3D next_base - pcms->below_4g_mem_size; - next_base =3D mem_base + mem_len; - } - - if (mem_len > 0) { + for (i =3D 0; i < nstat->mem_ranges_num; i++) { + mem_range =3D &g_array_index(nstat->mem_ranges, NumaMemRange, i); + if (mem_range->length > 0) { numamem =3D acpi_data_push(table_data, sizeof *numamem); - build_srat_memory(numamem, mem_base, mem_len, i - 1, + build_srat_memory(numamem, mem_range->base, + mem_range->length, + mem_range->node, MEM_AFFINITY_ENABLED); } } + slots =3D (table_data->len - numa_start) / sizeof *numamem; for (; slots < pcms->numa_nodes + 2; slots++) { numamem =3D acpi_data_push(table_data, sizeof *numamem); diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 35d17246e9..20d919c63d 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -801,6 +801,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, voi= d *data) adevc->ospm_status =3D ich9_pm_ospm_status; adevc->send_event =3D ich9_send_gpe; adevc->madt_cpu =3D pc_madt_cpu_entry; + adevc->build_mem_ranges =3D pc_build_mem_ranges; } =20 static const TypeInfo ich9_lpc_info =3D { diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_de= v_interface.h index 43ff119179..5956b5ea33 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h @@ -39,6 +39,8 @@ void acpi_send_event(DeviceState *dev, AcpiEventStatusBit= s event); * for CPU indexed by @uid in @apic_ids array, * returned structure types are: * 0 - Local APIC, 9 - Local x2APIC, 0xB - GICC + * build_mem_ranges: build memory ranges of ACPI SRAT (except misc + * and hotplug SRAT ranges) and HMAT * * Interface is designed for providing unified interface * to generic ACPI functionality that could be used without @@ -54,5 +56,7 @@ typedef struct AcpiDeviceIfClass { void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev); void (*madt_cpu)(AcpiDeviceIf *adev, int uid, const CPUArchIdList *apic_ids, GArray *entry); + void (*build_mem_ranges)(AcpiDeviceIf *adev, MachineState *ms); + } AcpiDeviceIfClass; #endif diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 5d5636241e..21b9ac3d11 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -281,6 +281,7 @@ void pc_system_firmware_init(PCMachineState *pcms, Memo= ryRegion *rom_memory); /* acpi-build.c */ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, const CPUArchIdList *apic_ids, GArray *entry); +void pc_build_mem_ranges(AcpiDeviceIf *adev, MachineState *ms); =20 /* e820 types */ #define E820_RAM 1 diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h index 437eb21fef..e3c85b77bc 100644 --- a/include/sysemu/numa.h +++ b/include/sysemu/numa.h @@ -20,6 +20,12 @@ struct NumaNodeMem { uint64_t node_plugged_mem; }; =20 +typedef struct NumaMemRange { + uint64_t base; + uint64_t length; + uint32_t node; +} NumaMemRange; + struct NumaState { /* Number of NUMA nodes */ int num_nodes; @@ -29,6 +35,12 @@ struct NumaState { =20 /* NUMA nodes information */ NodeInfo nodes[MAX_NODES]; + + /* Number of NUMA memory ranges */ + uint32_t mem_ranges_num; + + /* NUMA memory ranges */ + GArray *mem_ranges; }; typedef struct NumaState NumaState; =20 diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 9c7393b08c..4f0cdc1a45 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -33,6 +33,7 @@ stub-obj-y +=3D qmp_memory_device.o stub-obj-y +=3D target-monitor-defs.o stub-obj-y +=3D target-get-monitor-def.o stub-obj-y +=3D pc_madt_cpu_entry.o +stub-obj-y +=3D pc_build_mem_ranges.o stub-obj-y +=3D vmgenid.o stub-obj-y +=3D xen-common.o stub-obj-y +=3D xen-hvm.o diff --git a/stubs/pc_build_mem_ranges.c b/stubs/pc_build_mem_ranges.c new file mode 100644 index 0000000000..997cdfe00b --- /dev/null +++ b/stubs/pc_build_mem_ranges.c @@ -0,0 +1,14 @@ +/* + * Stub for pc_build_mem_ranges(). + * piix4 is used not only pc, but also mips and etc. In order to add + * build_mem_ranges callback to AcpiDeviceIfClass and use pc_build_mem_ran= ges + * in hw/acpi/piix4.c, pc_build_mem_ranges() stub is added to make other a= rch + * can compile successfully. + */ + +#include "qemu/osdep.h" +#include "hw/i386/pc.h" + +void pc_build_mem_ranges(AcpiDeviceIf *adev, MachineState *ms) +{ +} --=20 2.20.1