123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2017-2018, 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #include "hab.h"
- #include <linux/of.h>
- /*
- * set valid mmid value in tbl to show this is valid entry. All inputs here are
- * normalized to 1 based integer
- */
- static int fill_vmid_mmid_tbl(struct vmid_mmid_desc *tbl, int32_t vm_start,
- int32_t vm_range, int32_t mmid_start,
- int32_t mmid_range, int32_t be, int kernel_only)
- {
- int i, j;
- for (i = vm_start; i < vm_start+vm_range; i++) {
- tbl[i].vmid = i; /* set valid vmid value to make it usable */
- for (j = mmid_start; j < mmid_start + mmid_range; j++) {
- /* sanity check */
- if (tbl[i].mmid[j] != HABCFG_VMID_INVALID) {
- pr_err("overwrite previous setting vmid %d, mmid %d, be %d, kernel only %d\n",
- i, j, tbl[i].is_listener[j], tbl[i].kernel_only[j]);
- }
- tbl[i].mmid[j] = j;
- tbl[i].is_listener[j] = be; /* BE IS listen */
- tbl[i].kernel_only[j] = kernel_only;
- }
- }
- return 0;
- }
- void dump_settings(struct local_vmid *settings)
- {
- pr_debug("self vmid is %d\n", settings->self);
- }
- #ifdef CONFIG_MSM_VHOST_HAB
- int fill_default_gvm_settings(struct local_vmid *settings, int vmid_default,
- int mmid_start, int mmid_end)
- {
- int32_t be = HABCFG_BE_TRUE;
- int32_t range = 1;
- int32_t vmremote = vmid_default;
- /* pchan is not kernel only by default */
- int32_t kernel_only = 0;
- /* default gvm always talks to host as vm0 */
- settings->self = 0;
- return fill_vmid_mmid_tbl(settings->vmid_mmid_list, vmremote, range,
- mmid_start/100, (mmid_end-mmid_start)/100+1, be, kernel_only);
- }
- #else
- int fill_default_gvm_settings(struct local_vmid *settings, int vmid_local,
- int mmid_start, int mmid_end)
- {
- int32_t be = HABCFG_BE_FALSE;
- int32_t range = 1;
- int32_t vmremote = 0; /* default to host[0] as local is guest[2] */
- /* pchan is not kernel only by default */
- int32_t kernel_only = 0;
- settings->self = vmid_local;
- /* default gvm always talks to host as vm0 */
- return fill_vmid_mmid_tbl(settings->vmid_mmid_list, vmremote, range,
- mmid_start/100, (mmid_end-mmid_start)/100+1, be, kernel_only);
- }
- #endif
- /* device tree based parser */
- static int hab_parse_dt(struct local_vmid *settings)
- {
- int result, i;
- struct device_node *hab_node = NULL;
- struct device_node *mmid_grp_node = NULL;
- const char *role = NULL;
- int tmp = -1, vmids_num;
- u32 vmids[16];
- int32_t grp_start_id, be;
- int kernel_only;
- /* parse device tree*/
- pr_debug("parsing hab node in device tree...\n");
- hab_node = of_find_compatible_node(NULL, NULL, "qcom,hab");
- if (!hab_node) {
- pr_err("no hab device tree node\n");
- return -ENODEV;
- }
- /* read the local vmid of this VM, like 0 for host, 1 for AGL GVM */
- result = of_property_read_u32(hab_node, "vmid", &tmp);
- if (result) {
- pr_err("failed to read local vmid, result = %d\n", result);
- return result;
- }
- pr_debug("local vmid = %d\n", tmp);
- settings->self = tmp;
- for_each_child_of_node(hab_node, mmid_grp_node) {
- /* read the group starting id */
- result = of_property_read_u32(mmid_grp_node,
- "grp-start-id", &tmp);
- if (result) {
- pr_err("failed to read grp-start-id, result = %d\n",
- result);
- return result;
- }
- pr_debug("grp-start-id = %d\n", tmp);
- grp_start_id = tmp;
- /* read the role(fe/be) of these pchans in this mmid group */
- result = of_property_read_string(mmid_grp_node, "role", &role);
- if (result) {
- pr_err("failed to get role, result = %d\n", result);
- return result;
- }
- pr_debug("local role of this mmid group is %s\n", role);
- if (!strcmp(role, "be"))
- be = 1;
- else
- be = 0;
- /* read the remote vmids for these pchans in this mmid group */
- vmids_num = of_property_count_elems_of_size(mmid_grp_node,
- "remote-vmids", sizeof(u32));
- result = of_property_read_u32_array(mmid_grp_node,
- "remote-vmids", vmids, vmids_num);
- if (result) {
- pr_err("failed to read remote-vmids, result = %d\n",
- result);
- return result;
- }
- /* check the kernel_only flag for these pchans in this mmid group */
- result = of_property_read_bool(mmid_grp_node, "kernel_only");
- if (result) {
- kernel_only = 1;
- pr_debug("kernel_only flag is set for this mmid group\n");
- } else {
- kernel_only = 0;
- pr_debug("kernel_only flag is not set for this mmid group\n");
- }
- for (i = 0; i < vmids_num; i++) {
- pr_debug("vmids_num = %d, vmids[%d] = %d\n",
- vmids_num, i, vmids[i]);
- result = fill_vmid_mmid_tbl(
- settings->vmid_mmid_list,
- vmids[i], 1,
- grp_start_id/100, 1, be, kernel_only);
- if (result) {
- pr_err("fill_vmid_mmid_tbl failed\n");
- return result;
- }
- }
- }
- dump_settings(settings);
- return 0;
- }
- /*
- * 0: successful
- * negative: various failure core
- */
- int hab_parse(struct local_vmid *settings)
- {
- int ret;
- ret = hab_parse_dt(settings);
- return ret;
- }
|