From: Alexey Kardashevskiy <aik@ozlabs.ru>
To: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: stewart@linux.vnet.ibm.com, benh@au1.ibm.com,
nacc@linux.vnet.ibm.com, agraf@suse.de, qemu-devel@nongnu.org,
qemu-ppc@nongnu.org, paulus@au1.ibm.com,
david@gibson.dropbear.id.au
Subject: Re: [Qemu-devel] [PATCH v2 1/1] target-ppc: Implement rtas_get_sysparm(PROCESSOR_MODULE_INFO)
Date: Tue, 10 Nov 2015 15:25:38 +1100 [thread overview]
Message-ID: <564171C2.8040700@ozlabs.ru> (raw)
In-Reply-To: <20151110035757.GA20030@us.ibm.com>
On 11/10/2015 02:57 PM, Sukadev Bhattiprolu wrote:
> Alexey Kardashevskiy [aik@ozlabs.ru] wrote:
> | On 11/05/2015 10:06 AM, Sukadev Bhattiprolu 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.18 of PAPR v2.7.
> | >
> | >We walk the /proc/device-tree to determine the number of chips, cores and
> | >modules 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, but we should determine
> | >that dynamically somehow later.
> | >
> | >Thanks to input from Nishanth Aravamudan and Alexey Kardashevsk.
> |
> | "iy" is missing :)
>
> Argh. Sorry :-)
>
> Agree with your other comments. Couple of questions/comments below.
>
> |
> | checkpatch.pl does not warn on this but new lines start under
> | opening brace in the previous line.
> |
> | In terms on vim, it would be:
> | set expandtab
> | set tabstop=4
> | set shiftwidth=4
> | set cino=:0,(0
> |
> |
> |
> | >+ 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/hw/ppc/spapr_rtas_modinfo.c b/hw/ppc/spapr_rtas_modinfo.c
> | >new file mode 100644
> | >index 0000000..068fc2c
> | >--- /dev/null
> | >+++ b/hw/ppc/spapr_rtas_modinfo.c
> | >@@ -0,0 +1,230 @@
> | >+/*
> | >+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
> | >+ *
> | >+ * Hypercall based emulated RTAS
> |
> |
> | This is a description of hw/ppc/spapr_rtas.c, not of the new file.
>
> Agree.
>
> |
> | Not sure the new code deserves a separate file, I'd either:
> | - add it into hw/ppc/spapr_rtas.c OR
> | - move rtas_ibm_get_system_parameter() +
> | rtas_ibm_set_system_parameter() to a separate file (let's call it
> | hw/ppc/spapr_rtas_syspar.c) and add this new parameter there as
> | there will be new parameters in the future anyway.
> |
> | But I'll leave to the maintainer (David, hi :) ).
>
> Will discuss this on the other thread from David (maybe move to
> target-ppc/kvm.c?)
Sounds right.
>
> |
> |
> <snip>
>
> | >+
> | >+static int file_read_buf(char *file_name, char *buf, int len)
> | >+{
> | >+ int rc;
> | >+ FILE *fp;
> | >+
> | >+ fp = fopen(file_name, "r");
> | >+ if (!fp) {
> | >+ error_report("%s: Error opening %s\n", __func__, file_name);
> |
> |
> | error_report() does not need "\n", remote it here and below.
> |
> | Another thing - you passed __func__ here but you did not in other
> | places, please make this consistent and pass __func__ everywhere OR
> | make error messages more descriptive, the latter seems to be
> | preferable way in QEMU, either way this should be easily grep'able,
> | for example - "Unable to open %s, error %d" is too generic.
>
> will change to "Error opening device tree file %s" and drop the
> __func__.
>
> |
> |
> | >+ return -1;
> | >+ }
> | >+
> | >+ rc = fread(buf, 1, len, fp);
> | >+ fclose(fp);
> | >+
> | >+ if (rc != len) {
> | >+ return -1;
> | >+ }
> | >+
> | >+ return 0;
> | >+}
> | >+
> | >+/*
> | >+ * Read an identifier from the file @path and add the identifier
> | >+ * to the hash table @gt unless its already in the table.
> | >+ */
> | >+static int hash_table_add_contents(GHashTable *gt, char *path)
> |
> | Move this helper before count_modules_chips(). I thought for a sec
> | that count_cores() uses it too :)
>
> Ok.
>
> |
> |
> | >+{
> | >+ int idx;
> | >+ char buf[16];
> | >+ int *key;
> | >+
> | >+ if (file_read_buf(path, buf, sizeof(int))) {
> | >+ return -1;
> | >+ }
> | >+
> | >+ idx = ldl_be_p(buf);
> | >+
> | >+ if (g_hash_table_contains(gt, &idx)) {
> | >+ return 0;
> | >+ }
> | >+
> | >+ key = g_malloc(sizeof(int));
> |
> |
> | I kind of hoped that g_direct_hash() (and probably GINT_TO_POINTER()
> | but I do not see kvm-all.c using it) will let you avoid
> | g_malloc()'ing the keys.
>
> I think g_direct_hash() and GINT_TO_POINTER will work. Will try them
> out.
>
> |
> |
> |
> | >+
> | >+ *key = idx;
> | >+ if (!g_hash_table_insert(gt, key, NULL)) {
> | >+ error_report("Unable to insert key %d into chips hash table\n", idx);
> | >+ g_free(key);
> | >+ return -1;
> | >+ }
> | >+
> | >+ return 0;
> | >+}
> | >+
> | >+/*
> | >+ * Each core in the system is represented by a directory with the
> | >+ * prefix 'PowerPC,POWER' in the directory /proc/device-tree/cpus/.
> | >+ * Process that directory and count the number of cores in the system.
> | >+ */
> | >+static int count_cores(int *num_cores)
> | >+{
> | >+ int rc;
> | >+ DIR *dir;
> | >+ struct dirent *ent;
> | >+ const char *cpus_dir = "/proc/device-tree/cpus";
> | >+ const char *ppc_prefix = "PowerPC,POWER";
> | >+
> | >+ dir = opendir(cpus_dir);
> | >+ if (!dir) {
> | >+ error_report("Unable to open %s, error %d\n", cpus_dir, errno);
> | >+ return -1;
> | >+ }
> | >+
> | >+ *num_cores = 0;
> | >+ while (1) {
> | >+ errno = 0;
> | >+ ent = readdir(dir);
> | >+ if (!ent) {
> |
> | rc = -errno; ....
>
> Yes. Thanks,
> |
> |
> | >+ break;
> | >+ }
> | >+
> | >+ if (!strncmp(ppc_prefix, ent->d_name, strlen(ppc_prefix))) {
> | >+ (*num_cores)++;
> | >+ }
> | >+ }
> | >+
> | >+ rc = 0;
> | >+ if (errno) {
> | >+ rc = -1;
> | >+ }
> |
> |
> | ... and remove these 4 lines above?
>
> Ok.
>
> |
> |
> |
> | >+
> | >+ closedir(dir);
> | >+ return rc;
> | >+}
> | >+
> | >+/*
> | >+ * Each module's (aka socket's) id is contained in the 'ibm,hw-module-id'
> | >+ * file in the "xscom" directory (/proc/device-tree/xscom*). Similarly each
> | >+ * chip's id is contained in the 'ibm,chip-id' file in the xscom directory.
> | >+ *
> | >+ * A module can contain more than one chip and a chip can contain more
> | >+ * than one core. So there are likely to be duplicates in the module
> | >+ * and chip identifiers (i.e more than one xscom directory can contain
> | >+ * the same module/chip id).
> | >+ *
> | >+ * Search the xscom directories and count the number of _UNIQUE_ module
> | >+ * and chip identifiers in the system.
> | >+ */
> | >+static int count_modules_chips(int *num_modules, int *num_chips)
> | >+{
> | >+ int rc;
> |
> | int rc = -1;
> |
> |
> | >+ DIR *dir;
> | >+ struct dirent *ent;
> | >+ char path[PATH_MAX];
> | >+ const char *xscom_dir = "/proc/device-tree";
> | >+ const char *xscom_prefix = "xscom@";
> | >+ GHashTable *chips_tbl, *modules_tbl;
> | >+
> | >+ dir = opendir(xscom_dir);
> | >+ if (!dir) {
> | >+ error_report("Unable to open %s, error %d\n", xscom_dir, errno);
> | >+ return -1;
> | >+ }
> | >+
> | >+ modules_tbl = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
> | >+ chips_tbl = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
> | >+
> | >+ rc = -1;
> |
> |
> | Remove this.
> |
> | >+ while (1) {
> | >+ errno = 0;
> | >+ ent = readdir(dir);
> | >+ if (!ent) {
> |
> | Add this:
> | rc = -errno;
> | goto cleanup;
> |
> | >+ break;
> | >+ }
> | >+
> | >+ if (strncmp(xscom_prefix, ent->d_name, strlen(xscom_prefix))) {
> | >+ continue;
> | >+ }
> | >+
> | >+ sprintf(path, "%s/%s/ibm,chip-id", xscom_dir, ent->d_name);
> | >+ if (hash_table_add_contents(chips_tbl, path)) {
> | >+ goto cleanup;
> | >+ }
> | >+
> | >+ sprintf(path, "%s/%s/ibm,hw-module-id", xscom_dir, ent->d_name);
> | >+ if (hash_table_add_contents(modules_tbl, path)) {
> | >+ goto cleanup;
> | >+ }
> | >+ }
> | >+
> | >+ if (errno) {
> | >+ goto cleanup;
> | >+ }
> |
> | Do not need these 3 lines.
> |
> |
> | >+
> | >+ *num_modules = g_hash_table_size(modules_tbl);
> | >+ *num_chips = g_hash_table_size(chips_tbl);
> | >+ rc = 0;
> |
> |
> | Remove this.
> |
> | count_modules_chips() and count_cores() do pretty similar things, it
> | would improve the code if error handling was done similar ways.
>
> Agree.
>
> |
> |
> | >+
> | >+cleanup:
> | >+ g_hash_table_remove_all(modules_tbl);
> | >+ g_hash_table_destroy(modules_tbl);
> | >+
> | >+ g_hash_table_remove_all(chips_tbl);
> | >+ g_hash_table_destroy(chips_tbl);
> | >+
> | >+ closedir(dir);
> | >+
> | >+ return rc;
> | >+}
> | >+
> | >+int rtas_get_module_info(struct rtas_module_info *modinfo)
> | >+{
> | >+ int cores;
> | >+ int chips;
> | >+ int modules;
> |
> | Nit - could be one line.
> |
> |
> | >+
> | >+ memset(modinfo, 0, sizeof(struct rtas_module_info));
> | >+
> | >+ if (count_modules_chips(&modules, &chips) || count_cores(&cores)) {
> | >+ return -1;
> | >+ }
> | >+
> | >+ /*
> | >+ * TODO: Hard code number of module_types for now till
> | >+ * we figure out how to determine it dynamically.
> | >+ */
> | >+ modinfo->module_types = 1;
> | >+ modinfo->si[0].sockets = modules;
> |
> |
> | A "module" here is what modinfo describes so I'd expect @modules to
> | be "1" in the existing code and count_modules_chips() to be named
> | count_sockets_chips() and return @sockets, not @modules.
> |
> | When exactly does a socket become a module? The SPAPR spec uses "sockets" here.
>
> I am trying to get the terminology too :-) Is socket a slot where a
> module is attached?
Sorry, no idea.
>
> I will change the variable name 'modules' to 'sockets'.
> |
> |
> | >+ modinfo->si[0].chips = chips;
> | >+ modinfo->si[0].cores_per_chip = cores / chips;
> |
> |
> | What if no "ibm,chip-id" was found and chips == 0?
>
> If we fail to readdir(xscom) or fail to read the 'ibm,chip-id',
> we return an error which we check above.
You assume that if there is /proc/device-tree, then there is always
"xscom@" but this might not be always the case, like PR KVM on embedded PPC64.
>
> |
> |
> | >+
> | >+ return 0;
> | >+}
> | >diff --git a/hw/ppc/spapr_rtas_modinfo.h b/hw/ppc/spapr_rtas_modinfo.h
> | >new file mode 100644
> | >index 0000000..356a2b5
> | >--- /dev/null
> | >+++ b/hw/ppc/spapr_rtas_modinfo.h
> |
> |
> | This file is missing a license and
> | #ifndef SPAPR_RTAS_MODINFO_H
> | #define SPAPR_RTAS_MODINFO_H
> | #endif
> |
> | But I'd rather put the content to include/hw/ppc/spapr.h and avoid
> | creating new files.
>
> Ok.
>
> |
> |
> | >@@ -0,0 +1,12 @@
> | >+
> | >+struct rtas_socket_info {
> | >+ unsigned short sockets;
> | >+ unsigned short chips;
> | >+ unsigned short cores_per_chip;
> | >+};
> | >+struct rtas_module_info {
> | >+ unsigned short module_types;
> | >+ struct rtas_socket_info si[1];
> | >+};
> |
> |
> | Will the number of rtas_socket_info be always a constant or (sure,
> | in the future) it may take different values?
>
> TBH, I am not sure. One thing though, array size of rtas_socket_info
> depends on number of module _types_. Like Nishanth Aravamudan mentioned
> offline, we are not sure if both a DCM and SCM types can be on a system
> at once (or even if they can be added dynamically).
What are DCM and SCM? What type do we have in Tuleta?
> Another thing I have on my list to check is how this works with
> hotplug CPU (in the host). If the device-tree is properly updated
> then these calls will return the updated info? The values in the
> array will change but the number of entries (types) in the array is
> still 1.
>
> |
> | Normally when you invent API like rtas_get_module_info(), you tell
> | the helper how much memory is allocated in the rtas_module_info
> | struct (in our case it is ARRAY_SIZE(rtas_module_info.si) which is
> | fine) and then the helper signals somehow how many module types it
> | has found (which is missing here).
>
> Can we assume that the number of types is static for now i.e both
> caller and callee know the size (although I should fix the computation
> of size in spapr_rtas.c and use MAX_MODULE_TYPES that David pointed out).
I do not know what these modules can be so I cannot advise on this, sorry.
I honestly do not see much point in implementing this system parameter -
what will the guest do with this information?
You could get rid of rtas_module_info for now and have a helper for
rtas_socket_info only - rtas_get_xxx_module_info() (where xxx is DCM or SCM
or whatever it is now and what we support). Then it would be up to
rtas_ibm_get_system_parameter() to decide how many modules types we want to
expose to the guest (now - one) and when we get a new module type, we will
either extend rtas_get_xxx_module_info() or implement another helper.
--
Alexey
next prev parent reply other threads:[~2015-11-10 4:25 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-04 23:06 [Qemu-devel] [PATCH v2 1/1] target-ppc: Implement rtas_get_sysparm(PROCESSOR_MODULE_INFO) Sukadev Bhattiprolu
2015-11-09 1:57 ` Alexey Kardashevskiy
2015-11-09 5:01 ` David Gibson
2015-11-10 3:57 ` Sukadev Bhattiprolu
2015-11-10 4:25 ` Alexey Kardashevskiy [this message]
2015-11-10 4:46 ` Sukadev Bhattiprolu
2015-11-10 6:58 ` Alexey Kardashevskiy
2015-11-10 18:27 ` Sukadev Bhattiprolu
2015-11-09 4:58 ` David Gibson
2015-11-10 4:22 ` Sukadev Bhattiprolu
2015-11-10 9:53 ` Thomas Huth
2015-11-13 20:29 ` Sukadev Bhattiprolu
2015-11-11 0:17 ` David Gibson
2015-11-11 0:56 ` Nishanth Aravamudan
2015-11-11 1:41 ` David Gibson
2015-11-11 22:10 ` Nishanth Aravamudan
2015-11-12 4:47 ` David Gibson
2015-11-12 16:46 ` Nishanth Aravamudan
2015-12-01 3:41 ` David Gibson
2015-12-05 1:04 ` Nishanth Aravamudan
2015-12-10 3:55 ` David Gibson
2015-11-13 20:21 ` Sukadev Bhattiprolu
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=564171C2.8040700@ozlabs.ru \
--to=aik@ozlabs.ru \
--cc=agraf@suse.de \
--cc=benh@au1.ibm.com \
--cc=david@gibson.dropbear.id.au \
--cc=nacc@linux.vnet.ibm.com \
--cc=paulus@au1.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=stewart@linux.vnet.ibm.com \
--cc=sukadev@linux.vnet.ibm.com \
/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).