ANDROID: virt: gunyah: Probe for the info_area page
The Gunyah info_area page contains a series of descriptors of "information". Probe the info_area page during probe and expose a function to fetch information by its identifier. Bug: 395833312 Change-Id: I380fa59259f487f1ca9b48c12eb07957603ea099 Signed-off-by: Elliot Berman <elliot.berman@oss.qualcomm.com>
This commit is contained in:
@@ -8,9 +8,45 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct gunyah_info_desc {
|
||||
__le16 id;
|
||||
__le16 owner;
|
||||
__le32 size;
|
||||
__le32 offset;
|
||||
#define INFO_DESC_VALID BIT(31)
|
||||
__le32 flags;
|
||||
};
|
||||
|
||||
static void *info_area;
|
||||
|
||||
void *gunyah_get_info(u16 owner, u16 id, size_t *size)
|
||||
{
|
||||
struct gunyah_info_desc *desc = info_area;
|
||||
__le16 le_owner = cpu_to_le16(owner);
|
||||
__le16 le_id = cpu_to_le16(id);
|
||||
|
||||
if (!desc)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
for (desc = info_area; le32_to_cpu(desc->offset); desc++) {
|
||||
if (!(le32_to_cpu(desc->flags) & INFO_DESC_VALID))
|
||||
continue;
|
||||
mb();
|
||||
if (le_owner == desc->owner && le_id == desc->id) {
|
||||
if (size)
|
||||
*size = le32_to_cpu(desc->size);
|
||||
return info_area + le32_to_cpu(desc->offset);
|
||||
}
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gunyah_get_info);
|
||||
|
||||
static int gunyah_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gunyah_hypercall_hyp_identify_resp gunyah_api;
|
||||
unsigned long info_ipa, info_size;
|
||||
enum gunyah_error gh_error;
|
||||
|
||||
if (!arch_is_gunyah_guest())
|
||||
return -ENODEV;
|
||||
@@ -28,6 +64,18 @@ static int gunyah_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
gh_error = gunyah_hypercall_addrspace_find_info_area(&info_ipa, &info_size);
|
||||
/* ignore errors for compatability with gh without info_area support */
|
||||
if (gh_error != GUNYAH_ERROR_OK)
|
||||
goto out;
|
||||
|
||||
info_area = memremap(info_ipa, info_size, MEMREMAP_WB);
|
||||
if (!info_area) {
|
||||
pr_err("Failed to map addrspace info area\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
out:
|
||||
return devm_of_platform_populate(&pdev->dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -363,6 +363,18 @@ enum gunyah_api_feature {
|
||||
|
||||
bool arch_is_gunyah_guest(void);
|
||||
|
||||
enum gunyah_info_owner {
|
||||
/* clang-format off */
|
||||
GUNYAH_INFO_OWNER_INVALID = 0,
|
||||
GUNYAH_INFO_OWNER_HYP = 1,
|
||||
GUNYAH_INFO_OWNER_ROOTVM = 2,
|
||||
GUNYAH_INFO_OWNER_RM = 3,
|
||||
GUNYAH_INFO_OWNER_QCRM = 16,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
void *gunyah_get_info(u16 owner, u16 id, size_t *size);
|
||||
|
||||
#define GUNYAH_API_V1 1
|
||||
|
||||
/* Other bits reserved for future use and will be zero */
|
||||
|
||||
Reference in New Issue
Block a user