[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH v3 2/2] target-ppc: Implement rtas_get_sysparm(PRO
From: |
David Gibson |
Subject: |
Re: [Qemu-ppc] [PATCH v3 2/2] target-ppc: Implement rtas_get_sysparm(PROCESSOR_MODULE_INFO) |
Date: |
Fri, 27 Nov 2015 17:47:56 +1100 |
User-agent: |
Mutt/1.5.24 (2015-08-30) |
On Tue, Nov 24, 2015 at 10:30:31PM -0800, Sukadev Bhattiprolu wrote:
> David, Alexey,
>
> Any comments on this patch?
Sorry, I've been busy, I've sent comments now.
>
> Suka
>
> Sukadev Bhattiprolu address@hidden wrote:
> | Implement RTAS_SYSPARM_PROCESSOR_MODULE_INFO parameter to rtas_get_sysparm()
> | call in qemu. This call returns the processor module (socket), chip and core
> | information as specified in section 7.3.16.17 of LoPAPR v2.7.
> |
> | We walk the /proc/device-tree to determine the number of modules(aka
> sockets),
> | chips and cores in the _host_ system and return this info to the guest
> | application that makes the rtas_get_sysparm() call.
> |
> | We currently hard code the number of module_types to 1 (we currently don't
> | have systems with more than one module type) but we should determine that
> | dynamically somehow later.
> |
> | Thanks to input from Nishanth Aravamudan, Alexey Kardashevskiy, David
> Gibson,
> | Thomas Huth.
> |
> | Signed-off-by: Sukadev Bhattiprolu <address@hidden>
> | ---
> | Changelog[v3]:
> | [David Gibson] Use glob() to simplify pattern matching path names.
> | Move new code into target-ppc/{kvm.c,kvm_ppc.h} to not impact
> | other targets and avoid creating new files.
> | [Alexey Kardashevskiy] Fix indentation, error messages; fold new
> | code into existing files and avoid creating new files for this
> | parameter; since the keys are integer, use g_direct_hash() and
> | GINT_TO_POINTER() and avoid allocating/freeing memory.
> |
> | Changelog[v2]:
> | [Alexey Kardashevskiy] Use existing interfaces like ldl_be_p(),
> | stw_be_phys(), g_hash_table_new_full(), error_report() rather
> | than re-inventing; fix indentation, function prottypes etc;
> | Drop the fts() interface (which doesn't seem to be available
> | on mingw32/mingw64) and use opendir() to walk specific
> | directories in the directory tree.
> | ---
> | hw/ppc/spapr_rtas.c | 31 +++++++++++
> | include/hw/ppc/spapr.h | 13 +++++
> | target-ppc/kvm.c | 141
> +++++++++++++++++++++++++++++++++++++++++++++++++
> | target-ppc/kvm_ppc.h | 8 +++
> | 4 files changed, 193 insertions(+)
> |
> | diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> | index 34b12a3..44b2537 100644
> | --- a/hw/ppc/spapr_rtas.c
> | +++ b/hw/ppc/spapr_rtas.c
> | @@ -38,6 +38,7 @@
> |
> | #include <libfdt.h>
> | #include "hw/ppc/spapr_drc.h"
> | +#include "kvm_ppc.h"
> |
> | /* #define DEBUG_SPAPR */
> |
> | @@ -240,6 +241,36 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU
> *cpu,
> | target_ulong ret = RTAS_OUT_SUCCESS;
> |
> | switch (parameter) {
> | + case RTAS_SYSPARM_PROCESSOR_MODULE_INFO: {
> | + struct sPAPRRTASModuleInfo modinfo;
> | + int i, size = sizeof(modinfo), offset = 0;
> | +
> | + memset(&modinfo, 0, size);
> | + if (kvmppc_rtas_get_module_info(&modinfo)) {
> | + ret = RTAS_OUT_HW_ERROR;
> | + break;
> | + }
> | +
> | + stw_be_phys(&address_space_memory, buffer+offset, size);
> | + offset += 2;
> | +
> | + stw_be_phys(&address_space_memory, buffer+offset,
> modinfo.module_types);
> | + offset += 2;
> | +
> | + for (i = 0; i < modinfo.module_types; i++) {
> | + stw_be_phys(&address_space_memory, buffer+offset,
> | + modinfo.si[i].sockets);
> | + offset += 2;
> | + stw_be_phys(&address_space_memory, buffer+offset,
> | + modinfo.si[i].chips);
> | + offset += 2;
> | + stw_be_phys(&address_space_memory, buffer+offset,
> | + modinfo.si[i].cores_per_chip);
> | + offset += 2;
> | + }
> | + break;
> | + }
> | +
> | case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
> | char *param_val = g_strdup_printf("MaxEntCap=%d,"
> | "DesMem=%llu,"
> | diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> | index 5baa906..f793465 100644
> | --- a/include/hw/ppc/spapr.h
> | +++ b/include/hw/ppc/spapr.h
> | @@ -463,6 +463,7 @@ int spapr_allocate_irq_block(int num, bool lsi, bool
> msi);
> | /* RTAS ibm,get-system-parameter token values */
> | #define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
> | #define RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE 42
> | +#define RTAS_SYSPARM_PROCESSOR_MODULE_INFO 43
> | #define RTAS_SYSPARM_UUID 48
> |
> | /* RTAS indicator/sensor types
> | @@ -646,4 +647,16 @@ int spapr_rng_populate_dt(void *fdt);
> | */
> | #define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008
> |
> | +#define SPAPR_MAX_MODULE_TYPES 1
> | +
> | +struct sPAPRRTASSocketInfo {
> | + unsigned short sockets;
> | + unsigned short chips;
> | + unsigned short cores_per_chip;
> | +};
> | +struct sPAPRRTASModuleInfo {
> | + unsigned short module_types;
> | + struct sPAPRRTASSocketInfo si[SPAPR_MAX_MODULE_TYPES];
> | +};
> | +
> | #endif /* !defined (__HW_SPAPR_H__) */
> | diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> | index 9940a90..bbef78c 100644
> | --- a/target-ppc/kvm.c
> | +++ b/target-ppc/kvm.c
> | @@ -15,6 +15,7 @@
> | */
> |
> | #include <dirent.h>
> | +#include <glob.h>
> | #include <sys/types.h>
> | #include <sys/ioctl.h>
> | #include <sys/mman.h>
> | @@ -2518,3 +2519,143 @@ int kvmppc_enable_hwrng(void)
> |
> | return kvmppc_enable_hcall(kvm_state, H_RANDOM);
> | }
> | +
> | +/* Read an identifier from the file @path and add the identifier
> | + * to the hash table @gt unless its already in the table.
> | + */
> | +static int kvmppc_hash_file_contents(GHashTable *gt, char *path)
> | +{
> | + uint32_t idx;
> | +
> | + idx = kvmppc_read_int_dt(path);
> | + if (idx == -1) {
> | + return -1;
> | + }
> | +
> | + if (g_hash_table_contains(gt, GINT_TO_POINTER(idx))) {
> | + return 0;
> | + }
> | +
> | + if (!g_hash_table_insert(gt, GINT_TO_POINTER(idx), NULL)) {
> | + fprintf(stderr, "%s() Unable to add key %d\n", __func__, idx);
> | + return -1;
> | + }
> | +
> | + return 0;
> | +}
> | +
> | +static int kvmppc_glob_count_ids_dt(const char *pattern, int *count)
> | +{
> | + int i, rc;
> | + glob_t dtglob;
> | + GHashTable *htbl;
> | +
> | + rc = glob(pattern, GLOB_NOSORT, NULL, &dtglob);
> | + if (rc) {
> | + fprintf(stderr, "%s() glob(%s) returns %d, errno %d\n", __func__,
> | + pattern, rc, errno);
> | + return -1;
> | + }
> | +
> | + rc = -1;
> | + htbl = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
> NULL);
> | +
> | + for (i = 0; i < dtglob.gl_pathc; i++) {
> | + if (kvmppc_hash_file_contents(htbl, dtglob.gl_pathv[i])) {
> | + goto cleanup;
> | + }
> | + }
> | +
> | + *count = g_hash_table_size(htbl);
> | + rc = 0;
> | +
> | +cleanup:
> | + globfree(&dtglob);
> | + g_hash_table_remove_all(htbl);
> | + g_hash_table_destroy(htbl);
> | +
> | + return rc;
> | +}
> | +
> | +/* Each socket's (aka module's) id is contained in the 'ibm,hw-module-id'
> | + * file in an "xscom" directory (/proc/device-tree/xscom*). Similarly each
> | + * chip's id is contained in the 'ibm,chip-id' file in an xscom directory.
> | + *
> | + * Since a module can have more than one chip and a chip can have more than
> | + * one core, there are likely to be duplicates in the module and chip ids
> | + * i.e more than one xscom directory can contain the same module/chip id.
> | + *
> | + * Search the xscom directories and count the number of _UNIQUE_ modules
> | + * and chips in the system.
> | + *
> | + * Return 0 if one or more modules and chips each are found. Return -1
> | + * otherwise.
> | + */
> | +static int kvmppc_count_sockets_chips_dt(int *num_sockets, int *num_chips)
> | +{
> | + const char *chip_pattern =
> "/proc/device-tree/address@hidden/ibm,chip-id";
> | + const char *module_pattern =
> "/proc/device-tree/address@hidden/ibm,hw-module-id";
> | +
> | + if (kvmppc_glob_count_ids_dt(module_pattern, num_sockets)
> | + || kvmppc_glob_count_ids_dt(chip_pattern, num_chips)) {
> | + return -1;
> | + }
> | +
> | + if (*num_sockets == 0 || *num_chips == 0) {
> | + return -1;
> | + }
> | +
> | + return 0;
> | +}
> | +
> | +/* Each core in the system is represented by a directory with the prefix
> | + * 'PowerPC,POWER' in directory /proc/device-tree/cpus/. Process that
> | + * directory and count the number of cores in the system.
> | + *
> | + * Return 0 if one or more cores are found. Return -1 otherwise.
> | + */
> | +static int kvmppc_count_cores_dt(int *num_cores)
> | +{
> | + int rc;
> | + glob_t dtglob;
> | + const char *cpus_pattern = "/proc/device-tree/cpus/PowerPC,POWER*";
> | +
> | + rc = glob(cpus_pattern, GLOB_NOSORT, NULL, &dtglob);
> | + if (rc) {
> | + fprintf(stderr, "%s() glob(%s) returns %d, errno %d\n", __func__,
> | + cpus_pattern, rc, errno);
> | + return -1;
> | + }
> | +
> | + *num_cores = dtglob.gl_pathc;
> | + globfree(&dtglob);
> | +
> | + if (*num_cores == 0) {
> | + return -1;
> | + }
> | +
> | + return 0;
> | +}
> | +
> | +int kvmppc_rtas_get_module_info(struct sPAPRRTASModuleInfo *modinfo)
> | +{
> | + int cores, chips, sockets;
> | +
> | + if (kvmppc_count_sockets_chips_dt(&sockets, &chips)
> | + || kvmppc_count_cores_dt(&cores)) {
> | + return -1;
> | + }
> | +
> | + /* TODO: Although the interface allows multiple module types, Power
> | + * systems currently support only one module type per system -
> | + * either Single Chip Module(SCM) or Dual Chip Module(DCM),
> | + * but not both types in the same system. Hard code module_types
> | + * for now till we can determine it dynamically.
> | + */
> | + modinfo->module_types = 1;
> | + modinfo->si[0].sockets = sockets;
> | + modinfo->si[0].chips = chips;
> | + modinfo->si[0].cores_per_chip = cores / chips;
> | +
> | + return 0;
> | +}
> | diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
> | index 309cbe0..46a2768 100644
> | --- a/target-ppc/kvm_ppc.h
> | +++ b/target-ppc/kvm_ppc.h
> | @@ -10,6 +10,7 @@
> | #define __KVM_PPC_H__
> |
> | #define TYPE_HOST_POWERPC_CPU "host-" TYPE_POWERPC_CPU
> | +#include "hw/ppc/spapr.h"
> |
> | #ifdef CONFIG_KVM
> |
> | @@ -55,6 +56,7 @@ void kvmppc_hash64_write_pte(CPUPPCState *env,
> target_ulong pte_index,
> | target_ulong pte0, target_ulong pte1);
> | bool kvmppc_has_cap_fixup_hcalls(void);
> | int kvmppc_enable_hwrng(void);
> | +int kvmppc_rtas_get_module_info(struct sPAPRRTASModuleInfo *modinfo);
> |
> | #else
> |
> | @@ -256,6 +258,12 @@ static inline int kvmppc_enable_hwrng(void)
> | {
> | return -1;
> | }
> | +
> | +static inline int kvmppc_rtas_get_module_info(struct sPAPRRTASModuleInfo
> *mi)
> | +{
> | + return -1;
> | +}
> | +
> | #endif
> |
> | #ifndef CONFIG_KVM
> | --
> | 2.1.0
> |
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature