tegra_bootloader_debug: update access to profiler carveout

Guest VM has access to all of the profiler carveout right now so that
it can read full carveout and dump all the entries.

Right now address and size of Guest VM owned profiler carveout is parsed
from kernel command line. And the address of full profiler carveout
(containing logs of other VMs too) is calculated based on assumptions.

Current architecture is now getting reworked so that only a privileged
Guest VM can access full carveout and that too in read-only mode. Each
VM will have read-write access to its own carveout to read/write
profiler entries of that VM.

Update tegra_bootloader_debug_init.c to parse tegra_bl_prof_ro_start and
tegra_bl_prof_ro_size from kernel command line. These values indicate
address and size of the full read only carveout.

In tegra_bootloader_debuginit(), map the address of read only carveout
to tegra_bl_mapped_prof_ro_start and set is_privileged_vm to true.
Only privileged VM will be assigned this read only address by BL.

tegra_bl_mapped_prof_start continues to map to read-write carveout
owned by the VM.

Update profiler_show() so that it reads entries from the read-only
carveout if is_privileged_vm is set, otherwise it reads from read
write carveout.

Bug 3566403

Change-Id: I3c1e5d42d67f7724c6fa43b7e27f08ce2cd607b7
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2868921
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Deepak Nibade
2023-03-07 08:46:40 +00:00
committed by mobile promotions
parent 8bb99f5a5d
commit a87c10d72c
3 changed files with 112 additions and 44 deletions

View File

@@ -74,7 +74,8 @@ struct spi_boot_rx_frame_full {
static spinlock_t tegra_bl_lock;
static struct kobject *boot_profiler_kobj;
static void *tegra_bl_mapped_prof_start;
static void *tegra_bl_mapped_full_carveout;
static void *tegra_bl_mapped_prof_ro_start;
static bool is_privileged_vm;
#ifdef CONFIG_DEBUG_FS
static const uint32_t gr_mb1 = enum_gr_mb1;
@@ -139,22 +140,15 @@ struct profiler_record {
uint64_t timestamp;
} __packed;
static ssize_t profiler_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
static void profiler_show_entries(void *addr, int size)
{
struct profiler_record *profiler_data;
int count = 0;
int i = 0;
int prof_data_section_valid = 0;
if (!tegra_bl_mapped_full_carveout) {
pr_err("%s\n", "Error mapping profiling data\n");
return 0;
}
profiler_data = (struct profiler_record *)tegra_bl_mapped_full_carveout;
count = SIZE_OF_FULL_CARVEOUT / sizeof(struct profiler_record);
profiler_data = (struct profiler_record *)addr;
count = size / sizeof(struct profiler_record);
i = -1;
pr_info("\n");
while (count--) {
@@ -174,6 +168,27 @@ static ssize_t profiler_show(struct kobject *kobj,
}
prof_data_section_valid = 1;
}
}
static ssize_t profiler_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
if (is_privileged_vm) {
if (!tegra_bl_mapped_prof_ro_start) {
pr_err("%s\n", "Error mapping RO profiling data\n");
return -EINVAL;
}
profiler_show_entries(tegra_bl_mapped_prof_ro_start, tegra_bl_prof_ro_size);
} else {
if (!tegra_bl_mapped_prof_start) {
pr_err("%s\n", "Error mapping RW profiling data\n");
return -EINVAL;
}
profiler_show_entries(tegra_bl_mapped_prof_start, tegra_bl_prof_size);
}
return 0;
}
@@ -304,9 +319,9 @@ static int dbg_golden_register_open_cpu_bl( __attribute((unused))struct inode *i
static int __init tegra_bootloader_debuginit(void)
{
void __iomem *ptr_bl_full_carveout = NULL;
void __iomem *ptr_bl_prof_ro_carveout = NULL;
void __iomem *ptr_bl_prof_carveout = NULL;
int bl_debug_verify_file_entry;
phys_addr_t tegra_bl_full_carveout;
#ifdef CONFIG_DEBUG_FS
void __iomem *ptr_bl_debug_data_start = NULL;
void __iomem *ptr_bl_boot_cfg_start = NULL;
@@ -425,36 +440,43 @@ static int __init tegra_bootloader_debuginit(void)
goto out_err;
}
/* MB1 guarantees 64kb alignment during allocation,
* below arithmetic gives address of full carveout
*/
tegra_bl_full_carveout =
tegra_bl_prof_start & (~(SIZE_OF_FULL_CARVEOUT - 1));
if (tegra_bl_full_carveout != 0
&& !pfn_valid(__phys_to_pfn(tegra_bl_full_carveout))) {
ptr_bl_full_carveout = ioremap(tegra_bl_full_carveout,
SIZE_OF_FULL_CARVEOUT);
WARN_ON(!ptr_bl_full_carveout);
if (!ptr_bl_full_carveout) {
pr_err("%s: Failed to map tegra_bl_full_carveout%08x\n",
__func__, (unsigned int)tegra_bl_full_carveout);
if (tegra_bl_prof_start != 0 && tegra_bl_prof_size != 0 &&
!pfn_valid(__phys_to_pfn(tegra_bl_prof_start))) {
ptr_bl_prof_carveout = ioremap(tegra_bl_prof_start, tegra_bl_prof_size);
if (!ptr_bl_prof_carveout) {
pr_err("%s: failed to map tegra_bl_prof_start\n", __func__);
goto out_err;
}
pr_info("Remapped tegra_bl_full_carveout(0x%llx) "
"to address 0x%llx, size(0x%llx)\n",
(u64)tegra_bl_full_carveout,
(__force u64)ptr_bl_full_carveout,
(u64)SIZE_OF_FULL_CARVEOUT);
tegra_bl_mapped_full_carveout = (__force void *)ptr_bl_full_carveout;
pr_info("Remapped tegra_bl_prof_start(0x%llx) "
"to address 0x%llx, size(0x%llx)\n",
(u64)tegra_bl_prof_start,
(__force u64)ptr_bl_prof_carveout,
(u64)tegra_bl_prof_size);
tegra_bl_mapped_prof_start = (__force void *)ptr_bl_prof_carveout;
}
tegra_bl_mapped_prof_start = tegra_bl_mapped_full_carveout +
(tegra_bl_prof_start - tegra_bl_full_carveout);
pr_info("tegra_bl_prof_start(0x%llx) size(0x%llx)\n",
(u64)tegra_bl_prof_start,
(u64)tegra_bl_prof_size);
if (tegra_bl_prof_ro_start != 0 && tegra_bl_prof_ro_size != 0 &&
!pfn_valid(__phys_to_pfn(tegra_bl_prof_ro_start))) {
ptr_bl_prof_ro_carveout = ioremap(tegra_bl_prof_ro_start, tegra_bl_prof_ro_size);
if (!ptr_bl_prof_ro_carveout) {
pr_err("%s: failed to map tegra_bl_prof_ro_start\n", __func__);
goto out_err;
}
pr_info("Remapped tegra_bl_prof_ro_start(0x%llx) "
"to address 0x%llx, size(0x%llx)\n",
(u64)tegra_bl_prof_ro_start,
(__force u64)ptr_bl_prof_ro_carveout,
(u64)tegra_bl_prof_ro_size);
tegra_bl_mapped_prof_ro_start = (__force void *)ptr_bl_prof_ro_carveout;
is_privileged_vm = true;
} else {
is_privileged_vm = false;
}
usc = ioremap(TEGRA_US_COUNTER_REG, 4);
if (!usc) {
@@ -475,8 +497,10 @@ out_err:
if (ptr_bl_boot_cfg_start)
iounmap(ptr_bl_boot_cfg_start);
#endif
if (ptr_bl_full_carveout)
iounmap(ptr_bl_full_carveout);
if (ptr_bl_prof_carveout)
iounmap(ptr_bl_prof_carveout);
if (ptr_bl_prof_ro_carveout)
iounmap(ptr_bl_prof_ro_carveout);
if (boot_profiler_kobj) {
sysfs_remove_file(boot_profiler_kobj,
@@ -554,8 +578,11 @@ static void __exit tegra_bl_debuginit_module_exit(void)
if (tegra_bl_mapped_boot_cfg_start)
iounmap((void __iomem *)tegra_bl_mapped_boot_cfg_start);
#endif
if (tegra_bl_mapped_full_carveout)
iounmap((void __iomem *)tegra_bl_mapped_full_carveout);
if (tegra_bl_mapped_prof_ro_start)
iounmap((void __iomem *)tegra_bl_mapped_prof_ro_start);
if (tegra_bl_mapped_prof_start)
iounmap((void __iomem *)tegra_bl_mapped_prof_start);
if (boot_profiler_kobj) {
sysfs_remove_file(boot_profiler_kobj,

View File

@@ -7,6 +7,8 @@ extern phys_addr_t tegra_bl_debug_data_start;
extern phys_addr_t tegra_bl_debug_data_size;
extern phys_addr_t tegra_bl_prof_start;
extern phys_addr_t tegra_bl_prof_size;
extern phys_addr_t tegra_bl_prof_ro_start;
extern phys_addr_t tegra_bl_prof_ro_size;
extern phys_addr_t tegra_bl_bcp_start;
extern phys_addr_t tegra_bl_bcp_size;

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
// Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
#include <linux/types.h>
#include <linux/export.h>
@@ -21,6 +21,12 @@ EXPORT_SYMBOL(tegra_bl_prof_start);
phys_addr_t tegra_bl_prof_size;
EXPORT_SYMBOL(tegra_bl_prof_size);
phys_addr_t tegra_bl_prof_ro_start;
EXPORT_SYMBOL(tegra_bl_prof_ro_start);
phys_addr_t tegra_bl_prof_ro_size;
EXPORT_SYMBOL(tegra_bl_prof_ro_size);
phys_addr_t tegra_bl_bcp_start;
EXPORT_SYMBOL(tegra_bl_bcp_start);
@@ -60,9 +66,42 @@ static int __init tegra_bl_prof_arg(char *option)
return 0;
}
early_param("bl_prof_dataptr", tegra_bl_prof_arg);
static int __init tegra_bl_prof_ro_arg(char *option)
{
char *p = option;
tegra_bl_prof_ro_size = memparse(p, &p);
if (!p)
return -EINVAL;
if (*p != '@')
return -EINVAL;
tegra_bl_prof_ro_start = memparse(p + 1, &p);
if (!tegra_bl_prof_ro_size || !tegra_bl_prof_ro_start) {
tegra_bl_prof_ro_size = 0;
tegra_bl_prof_ro_start = 0;
return -ENXIO;
}
if (pfn_valid(__phys_to_pfn(tegra_bl_prof_ro_start))) {
if (memblock_reserve(tegra_bl_prof_ro_start, tegra_bl_prof_ro_size)) {
pr_err("Failed to reserve bl_prof_ro_data %08llx@%08llx\n",
(u64)tegra_bl_prof_ro_size,
(u64)tegra_bl_prof_ro_start);
tegra_bl_prof_ro_size = 0;
tegra_bl_prof_ro_start = 0;
return -ENXIO;
}
}
return 0;
}
early_param("bl_prof_ro_ptr", tegra_bl_prof_ro_arg);
static int __init tegra_bl_debug_data_arg(char *options)
{
char *p = options;