From 46e13263f71a5d27b6ce873838f489fe48b43a22 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 12 Sep 2022 16:50:07 +0100 Subject: [PATCH 1/3] Add Linux helpers to map physical to virtual addresses Some tests require to access some physical memory addresses as advertised by the SCMI backend server (e.g. FastChannels). When running the Linux test app, such physical memory needs to be properly mapped in the virtual address space of the test suite process in order to be accessible. Non-Linux test apps behaviour is left unchanged. Signed-off-by: Cristian Marussi --- platform/baremetal/pal_platform.c | 27 +++++++ platform/linux/common/common.c | 76 ++++++++++++++++++++ platform/linux/sgm776/include/pal_platform.h | 6 ++ platform/linux/sgm776/pal_platform.c | 24 +++++++ platform/linux/tc/include/pal_platform.h | 6 ++ platform/linux/tc/pal_platform.c | 24 +++++++ platform/mocker/pal_platform.c | 27 +++++++ val/include/pal_interface.h | 4 ++ val/include/val_interface.h | 2 + val/val_interface.c | 34 +++++++++ 10 files changed, 230 insertions(+) create mode 100644 platform/linux/common/common.c diff --git a/platform/baremetal/pal_platform.c b/platform/baremetal/pal_platform.c index 0b23318..9ec4b56 100644 --- a/platform/baremetal/pal_platform.c +++ b/platform/baremetal/pal_platform.c @@ -41,6 +41,33 @@ extern void pal_reset_set_expected(const void *); extern void pal_voltage_set_expected(const void *); #endif +/** + @brief This API is used to map a physical memory area to a virtual one. + It does nothing in the baremetal case. + @param paddr physical address to map + @param length size of the memory to map + @param vaddr the mapped resulting virtual address + @return 0 on Success +**/ +int pal_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr) +{ + *vaddr = paddr; + return 0; +} + +/** + @brief This API is used to unmap a previously mapped memory area + It does nothing in the baremetal case. + @param paddr physical address that has been mapped + @param length size of the mapped memory + @param vaddr the mapped virtual address + @return 0 on Success +**/ +int pal_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length) +{ + return 0; +} + /** @brief This API is used to call platform function to send command @param cmd message header diff --git a/platform/linux/common/common.c b/platform/linux/common/common.c new file mode 100644 index 0000000..75a7994 --- /dev/null +++ b/platform/linux/common/common.c @@ -0,0 +1,76 @@ +/** @file + * Copyright (c) 2022 Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include +#include +#include +#include +#include + +/*! + * @brief Interface function that maps a physical memory area to a virtual one + * using Linux OS facilities. + * + */ +int linux_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr) +{ + int fd; + long page_size; + unsigned long map_mask; + void *map_base; + + page_size = sysconf(_SC_PAGESIZE); + if (page_size == -1) + return page_size; + + fd = open("/dev/mem", O_RDWR, O_SYNC); + if (fd < 0) + return fd; + + map_mask = page_size - 1; + map_base = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, (paddr & ~map_mask)); + close(fd); + if (map_base == (void *) - 1) + return -1; + + *vaddr = (unsigned long)map_base + (paddr & map_mask); + + return 0; +} + +/*! + * @brief Interface function that unmaps a previously mapped virtual memory area + * using Linux OS facilities. + * + */ +int linux_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length) +{ + long page_size; + unsigned long map_mask, map_base; + + page_size = sysconf(_SC_PAGESIZE); + if (page_size == -1) + return page_size; + + map_mask = page_size - 1; + map_base = vaddr - (paddr & map_mask); + + munmap((void *)map_base, length); + + return 0; +} diff --git a/platform/linux/sgm776/include/pal_platform.h b/platform/linux/sgm776/include/pal_platform.h index 3242113..6e93a36 100644 --- a/platform/linux/sgm776/include/pal_platform.h +++ b/platform/linux/sgm776/include/pal_platform.h @@ -40,6 +40,12 @@ #define TIMEOUT 100 +int linux_map_phys_to_virt(unsigned long paddr, size_t length, + unsigned long *vaddr); + +int linux_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, + size_t length); + int32_t linux_send_message(uint32_t message_header_send, size_t parameter_count, const uint32_t *parameters, uint32_t *message_header_rcv, int32_t *status, size_t *return_values_count, uint32_t *return_values); diff --git a/platform/linux/sgm776/pal_platform.c b/platform/linux/sgm776/pal_platform.c index 231bd1f..20d1adc 100644 --- a/platform/linux/sgm776/pal_platform.c +++ b/platform/linux/sgm776/pal_platform.c @@ -18,6 +18,30 @@ #include "pal_platform.h" #include "pal_interface.h" +/** + @brief This API is used to map a physical memory area to a virtual one. + @param paddr physical address to map + @param length size of the memory to map + @param vaddr the mapped resulting virtual address + @return 0 on Success +**/ +int pal_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr) +{ + return linux_map_phys_to_virt(paddr, length, vaddr); +} + +/** + @brief This API is used to unmap a previously mapped memory area + @param paddr physical address that has been mapped + @param length size of the mapped memory + @param vaddr the mapped virtual address + @return 0 on Success +**/ +int pal_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length) +{ + return linux_unmap_phys_to_virt(paddr, vaddr, length); +} + /** @brief This API is used to call platform function to send command @param cmd message header diff --git a/platform/linux/tc/include/pal_platform.h b/platform/linux/tc/include/pal_platform.h index a75bfa6..4f5e079 100644 --- a/platform/linux/tc/include/pal_platform.h +++ b/platform/linux/tc/include/pal_platform.h @@ -38,6 +38,12 @@ #define TIMEOUT 100 +int linux_map_phys_to_virt(unsigned long paddr, size_t length, + unsigned long *vaddr); + +int linux_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, + size_t length); + int32_t linux_send_message(uint32_t message_header_send, size_t parameter_count, const uint32_t *parameters, uint32_t *message_header_rcv, int32_t *status, size_t *return_values_count, uint32_t *return_values); diff --git a/platform/linux/tc/pal_platform.c b/platform/linux/tc/pal_platform.c index f35ec25..3cb196c 100644 --- a/platform/linux/tc/pal_platform.c +++ b/platform/linux/tc/pal_platform.c @@ -18,6 +18,30 @@ #include "pal_platform.h" #include "pal_interface.h" +/** + @brief This API is used to map a physical memory area to a virtual one. + @param paddr physical address to map + @param length size of the memory to map + @param vaddr the mapped resulting virtual address + @return 0 on Success +**/ +int pal_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr) +{ + return linux_map_phys_to_virt(paddr, length, vaddr); +} + +/** + @brief This API is used to unmap a previously mapped memory area + @param paddr physical address that has been mapped + @param length size of the mapped memory + @param vaddr the mapped virtual address + @return 0 on Success +**/ +int pal_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length) +{ + return linux_unmap_phys_to_virt(paddr, vaddr, length); +} + /** @brief This API is used to call platform function to send command @param cmd message header diff --git a/platform/mocker/pal_platform.c b/platform/mocker/pal_platform.c index 97bedea..c75b6c5 100644 --- a/platform/mocker/pal_platform.c +++ b/platform/mocker/pal_platform.c @@ -18,6 +18,33 @@ #include #include +/** + @brief This API is used to map a physical memory area to a virtual one. + It does nothing in the mocker case. + @param paddr physical address to map + @param length size of the memory to map + @param vaddr the mapped resulting virtual address + @return 0 on Success +**/ +int pal_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr) +{ + *vaddr = paddr; + return 0; +} + +/** + @brief This API is used to unmap a previously mapped memory area + It does nothing in the mocker case. + @param paddr physical address that has been mapped + @param length size of the mapped memory + @param vaddr the mapped virtual address + @return 0 on Success +**/ +int pal_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length) +{ + return 0; +} + void pal_send_message(uint32_t message_header_send, size_t parameter_count, const uint32_t *parameters, uint32_t *message_header_rcv, int32_t *status, size_t *return_values_count, uint32_t *return_values) diff --git a/val/include/pal_interface.h b/val/include/pal_interface.h index f6de16d..c2b5cd7 100644 --- a/val/include/pal_interface.h +++ b/val/include/pal_interface.h @@ -47,6 +47,10 @@ /************ PAL API'S ****************/ uint32_t pal_initialize_system(void *info); + +int pal_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr); +int pal_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length); + void pal_send_message(uint32_t message_header_send, size_t parameter_count, const uint32_t *parameters, uint32_t *message_header_rcv, int32_t *status, size_t *return_values_count, uint32_t *return_values); diff --git a/val/include/val_interface.h b/val/include/val_interface.h index 5b7b7e6..29c2842 100644 --- a/val/include/val_interface.h +++ b/val/include/val_interface.h @@ -119,6 +119,8 @@ char *val_get_result_string(uint32_t test_status); char *val_get_protocol_str(uint32_t protocol_id); char *val_get_status_string(int32_t status); uint32_t val_compare_return_count(uint32_t received, uint32_t expected); +int val_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr); +int val_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length); void val_send_message(uint32_t msg_hdr, size_t num_parameter, uint32_t *parameter_buffer, uint32_t *rcvd_msg_hdr, int32_t *status, size_t *rcvd_buffer_size, uint32_t *rcvd_buffer); void val_receive_delayed_response(uint32_t *message_header_rcv, int32_t *status, diff --git a/val/val_interface.c b/val/val_interface.c index e3cc6f0..52e0c98 100644 --- a/val/val_interface.c +++ b/val/val_interface.c @@ -389,6 +389,40 @@ uint32_t val_compare_return_count(uint32_t received, uint32_t expected) return VAL_STATUS_PASS; } +/** + @brief This function is used to map a physical address in the virtual memory + space of the process + 1. Caller - Test Suite. + @param paddr The physical address to map + @param length The length of the memory area to map + @param vaddr A pointer holding the mapped virtual address returned + @return 0 on success + */ +int val_map_phys_to_virt(unsigned long paddr, size_t length, unsigned long *vaddr) +{ + int ret; + + ret = pal_map_phys_to_virt(paddr, length, vaddr); + if (!ret) + val_print(VAL_PRINT_DEBUG, "\n MAPPED 0x%x TO VIRTUAL ADDRESS: 0x%x", paddr, *vaddr); + + return ret; +} + +/** + @brief This function is used to unmap a virtual memory address previously + mapped + 1. Caller - Test Suite. + @param paddr The physical address to map + @param vaddr A pointer holding the mapped virtual + @param length The length of the memory area to unmap + @return 0 on success + */ +int val_unmap_phys_to_virt(unsigned long paddr, unsigned long vaddr, size_t length) +{ + return pal_unmap_phys_to_virt(paddr, vaddr, length); +} + /** @brief This function is used to send command data to platform and receive response 1. Caller - Test Suite. -- GitLab From b5f1e5902f025b542887d5b1613324f5a6fe1a77 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 12 Sep 2022 16:54:43 +0100 Subject: [PATCH 2/3] Fix Performance test 028 to use new phys_to_virt helpers Use common helpers to properly map SCMI-server provided FCs physical addresses to virtual ones before accessing them on Linux test app. Signed-off-by: Cristian Marussi --- test_pool/performance/test_d028.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/test_pool/performance/test_d028.c b/test_pool/performance/test_d028.c index f9eff31..eb1b42e 100644 --- a/test_pool/performance/test_d028.c +++ b/test_pool/performance/test_d028.c @@ -33,9 +33,9 @@ uint32_t performance_level_get_fast_channel(void) uint32_t return_values[MAX_RETURNS_SIZE]; uint32_t domain_id, num_domains, message_id, attributes; uint32_t parameters[PARAMETER_SIZE], perf_level; - uint32_t chl_addr_low, chl_addr_high ; + uint32_t chl_addr_low, chl_addr_high, ch_size; uint32_t run_flag = 0; - uint64_t chl_addr = 0x0; + uint64_t chl_addr, v_chl_addr; if (val_test_initialize(TEST_NUM, TEST_DESC) != VAL_STATUS_PASS) return VAL_STATUS_SKIP; @@ -107,12 +107,19 @@ uint32_t performance_level_get_fast_channel(void) chl_addr_low = return_values[CHAN_ADDR_LOW_OFFSET]; chl_addr_high = return_values[CHAN_ADDR_HIGH_OFFSET]; - chl_addr = (uint64_t) chl_addr_high << 32 | chl_addr_low; + chl_addr = (uint64_t)chl_addr_high << 32 | chl_addr_low; + ch_size = return_values[CHAN_SIZE_OFFSET]; - if (chl_addr_high) - perf_level = *(volatile uint64_t *)chl_addr; - else - perf_level = *(volatile uint32_t*)chl_addr; + if (!chl_addr || !ch_size) + return VAL_STATUS_FAIL; + + if (val_map_phys_to_virt(chl_addr, ch_size, &v_chl_addr)) + return VAL_STATUS_FAIL; + + perf_level = *((volatile uint32_t *)v_chl_addr); + + if (val_unmap_phys_to_virt(chl_addr, v_chl_addr, ch_size)) + return VAL_STATUS_FAIL; /* Get perf level from normal channel and and compare */ val_print(VAL_PRINT_TEST, "\n [Check 2] Get perf level via normal channel"); -- GitLab From fdede6312d37805807435ce106f9ae0b4291d232 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 12 Sep 2022 16:55:37 +0100 Subject: [PATCH 3/3] Fix Performance test 029 to use new phys_to_virt helpers Use common helpers to properly map SCMI-server provided FCs physical addresses to virtual ones before accessing them on Linux test app. Signed-off-by: Cristian Marussi --- test_pool/performance/test_d029.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/test_pool/performance/test_d029.c b/test_pool/performance/test_d029.c index 7633e20..9b2bbd1 100644 --- a/test_pool/performance/test_d029.c +++ b/test_pool/performance/test_d029.c @@ -33,9 +33,9 @@ uint32_t performance_limits_get_fast_channel(void) uint32_t return_values[MAX_RETURNS_SIZE]; uint32_t domain_id, num_domains, message_id, attributes; uint32_t parameters[PARAMETER_SIZE], perf_limit_max, perf_limit_min; - uint64_t chl_addr_low, chl_addr_high; + uint32_t chl_addr_low, chl_addr_high, ch_size; uint32_t run_flag = 0; - uint64_t chl_addr = 0x0; + uint64_t chl_addr, v_chl_addr; if (val_test_initialize(TEST_NUM, TEST_DESC) != VAL_STATUS_PASS) return VAL_STATUS_SKIP; @@ -104,16 +104,20 @@ uint32_t performance_limits_get_fast_channel(void) chl_addr_low = return_values[CHAN_ADDR_LOW_OFFSET]; chl_addr_high = return_values[CHAN_ADDR_HIGH_OFFSET]; - chl_addr = chl_addr_high << 32 | chl_addr_low; - - if (chl_addr_high) { - perf_limit_max = *(volatile uint64_t *)chl_addr; - perf_limit_min = *((volatile uint64_t *)chl_addr + 1); - } - else { - perf_limit_max = *(volatile uint32_t*)chl_addr_low; - perf_limit_min = *((volatile uint32_t*)chl_addr_low + 1); - } + chl_addr = (uint64_t)chl_addr_high << 32 | chl_addr_low; + ch_size = return_values[CHAN_SIZE_OFFSET]; + + if (!chl_addr || !ch_size) + return VAL_STATUS_FAIL; + + if (val_map_phys_to_virt(chl_addr, ch_size, &v_chl_addr)) + return VAL_STATUS_FAIL; + + perf_limit_max = *((volatile uint32_t *)v_chl_addr); + perf_limit_min = *((volatile uint32_t *)v_chl_addr + 1); + + if (val_unmap_phys_to_virt(chl_addr, v_chl_addr, ch_size)) + return VAL_STATUS_FAIL; /* Get perf limits from normal channel and and compare */ val_print(VAL_PRINT_TEST, "\n [Check 2] Get perf limits via normal channel"); -- GitLab