diff options
-rw-r--r-- | common/bl_common.c | 69 | ||||
-rw-r--r-- | common/runtime_svc.c | 29 | ||||
-rw-r--r-- | docs/user-guide.md | 13 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_private.h | 2 | ||||
-rw-r--r-- | include/drivers/arm/gicv3.h | 6 | ||||
-rw-r--r-- | include/lib/utils.h | 7 | ||||
-rw-r--r-- | include/plat/arm/board/common/board_arm_def.h | 28 | ||||
-rw-r--r-- | lib/psci/psci_common.c | 4 | ||||
-rw-r--r-- | lib/psci/psci_main.c | 4 | ||||
-rw-r--r-- | lib/psci/psci_private.h | 2 | ||||
-rw-r--r-- | lib/psci/psci_stat.c | 6 | ||||
-rw-r--r-- | lib/psci/psci_suspend.c | 14 | ||||
-rw-r--r-- | plat/arm/board/common/board_common.mk | 6 | ||||
-rw-r--r-- | plat/arm/board/fvp/include/platform_def.h | 22 | ||||
-rw-r--r-- | plat/arm/board/juno/include/platform_def.h | 58 | ||||
-rw-r--r-- | plat/arm/board/juno/platform.mk | 2 |
16 files changed, 169 insertions, 103 deletions
diff --git a/common/bl_common.c b/common/bl_common.c index acb2ec62..be56256b 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -38,6 +38,7 @@ #include <io_storage.h> #include <platform.h> #include <string.h> +#include <utils.h> #include <xlat_tables.h> uintptr_t page_align(uintptr_t value, unsigned dir) @@ -59,12 +60,44 @@ static inline unsigned int is_page_aligned (uintptr_t addr) { /****************************************************************************** * Determine whether the memory region delimited by 'addr' and 'size' is free, * given the extents of free memory. - * Return 1 if it is free, 0 otherwise. + * Return 1 if it is free, 0 if it is not free or if the input values are + * invalid. *****************************************************************************/ static int is_mem_free(uintptr_t free_base, size_t free_size, uintptr_t addr, size_t size) { - return (addr >= free_base) && (addr + size <= free_base + free_size); + uintptr_t free_end, requested_end; + + /* + * Handle corner cases first. + * + * The order of the 2 tests is important, because if there's no space + * left (i.e. free_size == 0) but we don't ask for any memory + * (i.e. size == 0) then we should report that the memory is free. + */ + if (size == 0) + return 1; /* A zero-byte region is always free */ + if (free_size == 0) + return 0; + + /* + * Check that the end addresses don't overflow. + * If they do, consider that this memory region is not free, as this + * is an invalid scenario. + */ + if (check_uptr_overflow(free_base, free_size - 1)) + return 0; + free_end = free_base + (free_size - 1); + + if (check_uptr_overflow(addr, size - 1)) + return 0; + requested_end = addr + (size - 1); + + /* + * Finally, check that the requested memory region lies within the free + * region. + */ + return (addr >= free_base) && (requested_end <= free_end); } /****************************************************************************** @@ -100,7 +133,8 @@ static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end, * Reserve the memory region delimited by 'addr' and 'size'. The extents of free * memory are passed in 'free_base' and 'free_size' and they will be updated to * reflect the memory usage. - * The caller must ensure the memory to reserve is free. + * The caller must ensure the memory to reserve is free and that the addresses + * and sizes passed in arguments are sane. *****************************************************************************/ void reserve_mem(uintptr_t *free_base, size_t *free_size, uintptr_t addr, size_t size) @@ -113,8 +147,13 @@ void reserve_mem(uintptr_t *free_base, size_t *free_size, assert(free_size != NULL); assert(is_mem_free(*free_base, *free_size, addr, size)); - pos = choose_mem_pos(*free_base, *free_base + *free_size, - addr, addr + size, + if (size == 0) { + WARN("Nothing to allocate, requested size is zero\n"); + return; + } + + pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1), + addr, addr + (size - 1), &discard_size); reserved_size = size + discard_size; @@ -135,10 +174,10 @@ static void dump_load_info(uintptr_t image_load_addr, INFO("Trying to load image at address %p, size = 0x%zx\n", (void *)image_load_addr, image_size); INFO("Current memory layout:\n"); - INFO(" total region = [%p, %p]\n", (void *)mem_layout->total_base, - (void *)(mem_layout->total_base + mem_layout->total_size)); - INFO(" free region = [%p, %p]\n", (void *)mem_layout->free_base, - (void *)(mem_layout->free_base + mem_layout->free_size)); + INFO(" total region = [base = %p, size = 0x%zx]\n", + (void *) mem_layout->total_base, mem_layout->total_size); + INFO(" free region = [base = %p, size = 0x%zx]\n", + (void *) mem_layout->free_base, mem_layout->free_size); } /* Generic function to return the size of an image */ @@ -248,8 +287,8 @@ int load_image(meminfo_t *mem_layout, /* Check that the memory where the image will be loaded is free */ if (!is_mem_free(mem_layout->free_base, mem_layout->free_size, image_base, image_size)) { - WARN("Failed to reserve memory: %p - %p\n", (void *) image_base, - (void *) (image_base + image_size)); + WARN("Failed to reserve region [base = %p, size = 0x%zx]\n", + (void *) image_base, image_size); dump_load_info(image_base, image_size, mem_layout); io_result = -ENOMEM; goto exit; @@ -278,8 +317,8 @@ int load_image(meminfo_t *mem_layout, image_base, image_size); entry_point_info->pc = image_base; } else { - INFO("Skip reserving memory: %p - %p\n", (void *) image_base, - (void *) (image_base + image_size)); + INFO("Skip reserving region [base = %p, size = 0x%zx]\n", + (void *) image_base, image_size); } /* @@ -289,8 +328,8 @@ int load_image(meminfo_t *mem_layout, */ flush_dcache_range(image_base, image_size); - INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base, - (void *) (image_base + image_size)); + INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id, + (void *) image_base, image_size); exit: io_close(image_handle); diff --git a/common/runtime_svc.c b/common/runtime_svc.c index 337421bc..b8af6cd8 100644 --- a/common/runtime_svc.c +++ b/common/runtime_svc.c @@ -54,7 +54,7 @@ static rt_svc_desc_t *rt_svc_descs; /******************************************************************************* * Simple routine to sanity check a runtime service descriptor before using it ******************************************************************************/ -static int32_t validate_rt_svc_desc(rt_svc_desc_t *desc) +static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc) { if (desc == NULL) return -EINVAL; @@ -99,18 +99,18 @@ void runtime_svc_init(void) rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START; for (index = 0; index < RT_SVC_DECS_NUM; index++) { + rt_svc_desc_t *service = &rt_svc_descs[index]; /* * An invalid descriptor is an error condition since it is * difficult to predict the system behaviour in the absence * of this service. */ - rc = validate_rt_svc_desc(&rt_svc_descs[index]); + rc = validate_rt_svc_desc(service); if (rc) { - ERROR("Invalid runtime service descriptor %p (%s)\n", - (void *) &rt_svc_descs[index], - rt_svc_descs[index].name); - goto error; + ERROR("Invalid runtime service descriptor %p\n", + (void *) service); + panic(); } /* @@ -120,11 +120,11 @@ void runtime_svc_init(void) * an initialisation routine defined. Call the initialisation * routine for this runtime service, if it is defined. */ - if (rt_svc_descs[index].init) { - rc = rt_svc_descs[index].init(); + if (service->init) { + rc = service->init(); if (rc) { ERROR("Error initializing runtime service %s\n", - rt_svc_descs[index].name); + service->name); continue; } } @@ -136,15 +136,12 @@ void runtime_svc_init(void) * entity range. */ start_idx = get_unique_oen(rt_svc_descs[index].start_oen, - rt_svc_descs[index].call_type); + service->call_type); + assert(start_idx < MAX_RT_SVCS); end_idx = get_unique_oen(rt_svc_descs[index].end_oen, - rt_svc_descs[index].call_type); - + service->call_type); + assert(end_idx < MAX_RT_SVCS); for (; start_idx <= end_idx; start_idx++) rt_svc_descs_indices[start_idx] = index; } - - return; -error: - panic(); } diff --git a/docs/user-guide.md b/docs/user-guide.md index 41a272fa..c9312f2c 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -465,12 +465,13 @@ map is explained in the [Firmware Design]. match the frame used by the Non-Secure image (normally the Linux kernel). Default is true (access to the frame is allowed). -* `ARM_BOARD_OPTIMISE_MMAP`: Boolean option to enable or disable optimisation - of page table and MMU related macros `PLAT_ARM_MMAP_ENTRIES` and - `MAX_XLAT_TABLES`. By default this flag is 0, which means it uses the - default unoptimised values for these macros. ARM development platforms - that wish to optimise memory usage for page tables need to set this flag to 1 - and must override the related macros. +* `ARM_BOARD_OPTIMISE_MEM`: Boolean option to enable or disable optimisation + of the memory reserved for each image. This affects the maximum size of each + BL image as well as the number of allocated memory regions and translation + tables. By default this flag is 0, which means it uses the default + unoptimised values for these macros. ARM development platforms that wish to + optimise memory usage need to set this flag to 1 and must override the + related macros. * 'ARM_BL31_IN_DRAM': Boolean option to select loading of BL31 in TZC secured DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h index 5e2409fc..9aa83382 100644 --- a/drivers/arm/gic/v3/gicv3_private.h +++ b/drivers/arm/gic/v3/gicv3_private.h @@ -141,6 +141,7 @@ static inline unsigned int gicd_read_pidr2(uintptr_t base) static inline unsigned long long gicd_read_irouter(uintptr_t base, unsigned int id) { + assert(id >= MIN_SPI_ID); return mmio_read_64(base + GICD_IROUTER + (id << 3)); } @@ -148,6 +149,7 @@ static inline void gicd_write_irouter(uintptr_t base, unsigned int id, unsigned long long affinity) { + assert(id >= MIN_SPI_ID); mmio_write_64(base + GICD_IROUTER + (id << 3), affinity); } diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h index e915c072..b7ad7785 100644 --- a/include/drivers/arm/gicv3.h +++ b/include/drivers/arm/gicv3.h @@ -55,7 +55,11 @@ #define GICD_SETSPI_SR 0x50 #define GICD_CLRSPI_SR 0x50 #define GICD_IGRPMODR 0xd00 -#define GICD_IROUTER 0x6100 +/* + * GICD_IROUTER<n> register is at 0x6000 + 8n, where n is the interrupt id and + * n >= 32, making the effective offset as 0x6100. + */ +#define GICD_IROUTER 0x6000 #define GICD_PIDR2_GICV3 0xffe8 #define IGRPMODR_SHIFT 5 diff --git a/include/lib/utils.h b/include/lib/utils.h index 9cc5468b..0936cbb3 100644 --- a/include/lib/utils.h +++ b/include/lib/utils.h @@ -55,4 +55,11 @@ #define round_down(value, boundary) \ ((value) & ~round_boundary(value, boundary)) +/* + * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. + * Both arguments must be unsigned pointer values (i.e. uintptr_t). + */ +#define check_uptr_overflow(ptr, inc) \ + (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0) + #endif /* __UTILS_H__ */ diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index d70fbb46..ad82923e 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -61,10 +61,10 @@ /* * The constants below are not optimised for memory usage. Platforms that wish - * to optimise these constants should set `ARM_BOARD_OPTIMISE_MMAP` to 1 and + * to optimise these constants should set `ARM_BOARD_OPTIMISE_MEM` to 1 and * provide there own values. */ -#if !ARM_BOARD_OPTIMISE_MMAP +#if !ARM_BOARD_OPTIMISE_MEM /* * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the * plat_arm_mmap array defined for each BL stage. @@ -81,7 +81,29 @@ # define MAX_XLAT_TABLES 5 #endif -#endif /* ARM_BOARD_OPTIMISE_MMAP */ +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xA000 + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0xF000 +#endif + +/* + * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x1D000 + +#endif /* ARM_BOARD_OPTIMISE_MEM */ #define MAX_IO_DEVICES 3 #define MAX_IO_HANDLES 4 diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c index c6fea5b0..e87e8c05 100644 --- a/lib/psci/psci_common.c +++ b/lib/psci/psci_common.c @@ -252,8 +252,8 @@ static plat_local_state_t *psci_get_req_local_pwr_states(unsigned int pwrlvl, * function will be called after a cpu is powered on to find the local state * each power domain has emerged from. *****************************************************************************/ -static void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, - psci_power_state_t *target_state) +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state) { unsigned int parent_idx, lvl; plat_local_state_t *pd_state = target_state->pwr_domain_state; diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c index d412be3c..3ad3dd40 100644 --- a/lib/psci/psci_main.c +++ b/lib/psci/psci_main.c @@ -97,6 +97,10 @@ int psci_cpu_suspend(unsigned int power_state, == PSCI_E_SUCCESS); target_pwrlvl = psci_find_target_suspend_lvl(&state_info); + if (target_pwrlvl == PSCI_INVALID_PWR_LVL) { + ERROR("Invalid target power level for suspend operation\n"); + panic(); + } /* Fast path for CPU standby.*/ if (is_cpu_standby_req(is_power_down_state, target_pwrlvl)) { diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h index 49352144..b795c8e0 100644 --- a/lib/psci/psci_private.h +++ b/lib/psci/psci_private.h @@ -192,6 +192,8 @@ int psci_validate_power_state(unsigned int power_state, void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info); int psci_validate_mpidr(u_register_t mpidr); void psci_init_req_local_pwr_states(void); +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state); int psci_validate_entry_point(entry_point_info_t *ep, uintptr_t entrypoint, u_register_t context_id); void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, diff --git a/lib/psci/psci_stat.c b/lib/psci/psci_stat.c index 155bbb07..ecbe592b 100644 --- a/lib/psci/psci_stat.c +++ b/lib/psci/psci_stat.c @@ -259,8 +259,10 @@ int psci_get_stat(u_register_t target_cpu, unsigned int power_state, /* Find the highest power level */ pwrlvl = psci_find_target_suspend_lvl(&state_info); - if (pwrlvl == PSCI_INVALID_PWR_LVL) - return PSCI_E_INVALID_PARAMS; + if (pwrlvl == PSCI_INVALID_PWR_LVL) { + ERROR("Invalid target power level for PSCI statistics operation\n"); + panic(); + } /* Get the index into the stats array */ local_state = state_info.pwr_domain_state[pwrlvl]; diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c index 904a4e75..0887e3b2 100644 --- a/lib/psci/psci_suspend.c +++ b/lib/psci/psci_suspend.c @@ -45,17 +45,25 @@ * from standby/retention states at multiple power levels. ******************************************************************************/ static void psci_suspend_to_standby_finisher(unsigned int cpu_idx, - psci_power_state_t *state_info, unsigned int end_pwrlvl) { + psci_power_state_t state_info; + psci_acquire_pwr_domain_locks(end_pwrlvl, cpu_idx); /* + * Find out which retention states this CPU has exited from until the + * 'end_pwrlvl'. The exit retention state could be deeper than the entry + * state as a result of state coordination amongst other CPUs post wfi. + */ + psci_get_target_local_pwr_states(end_pwrlvl, &state_info); + + /* * Plat. management: Allow the platform to do operations * on waking up from retention. */ - psci_plat_pm_ops->pwr_domain_suspend_finish(state_info); + psci_plat_pm_ops->pwr_domain_suspend_finish(&state_info); /* * Set the requested and target state of this CPU and all the higher @@ -222,7 +230,7 @@ exit: * After we wake up from context retaining suspend, call the * context retaining suspend finisher. */ - psci_suspend_to_standby_finisher(idx, state_info, end_pwrlvl); + psci_suspend_to_standby_finisher(idx, end_pwrlvl); } /******************************************************************************* diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk index 6ddc0c92..a5636d5e 100644 --- a/plat/arm/board/common/board_common.mk +++ b/plat/arm/board/common/board_common.mk @@ -61,8 +61,8 @@ ifneq (${TRUSTED_BOARD_BOOT},0) endif # This flag controls whether memory usage needs to be optimised -ARM_BOARD_OPTIMISE_MMAP ?= 0 +ARM_BOARD_OPTIMISE_MEM ?= 0 # Process flags -$(eval $(call assert_boolean,ARM_BOARD_OPTIMISE_MMAP)) -$(eval $(call add_define,ARM_BOARD_OPTIMISE_MMAP)) +$(eval $(call assert_boolean,ARM_BOARD_OPTIMISE_MEM)) +$(eval $(call add_define,ARM_BOARD_OPTIMISE_MEM)) diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 1e906d82..d0898adc 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -146,26 +146,4 @@ #define PLAT_ARM_G0_IRQS ARM_G0_IRQS -/* - * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size - * plus a little space for growth. - */ -#define PLAT_ARM_MAX_BL1_RW_SIZE 0xA000 - -/* - * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a - * little space for growth. - */ -#if TRUSTED_BOARD_BOOT -# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 -#else -# define PLAT_ARM_MAX_BL2_SIZE 0xC000 -#endif - -/* - * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a - * little space for growth. - */ -#define PLAT_ARM_MAX_BL31_SIZE 0x1D000 - #endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index a2cf0368..c53e938f 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -74,10 +74,10 @@ #endif /* TRUSTED_BOARD_BOOT */ /* - * If ARM_BOARD_OPTIMISE_MMAP=0 then Juno uses the default, unoptimised values + * If ARM_BOARD_OPTIMISE_MEM=0 then Juno uses the default, unoptimised values * defined for ARM development platforms. */ -#if ARM_BOARD_OPTIMISE_MMAP +#if ARM_BOARD_OPTIMISE_MEM /* * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the * plat_arm_mmap array defined for each BL stage. @@ -107,7 +107,33 @@ # define MAX_XLAT_TABLES 3 #endif -#endif /* ARM_BOARD_OPTIMISE_MMAP */ +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL1_RW_SIZE 0x9000 +#else +# define PLAT_ARM_MAX_BL1_RW_SIZE 0x6000 +#endif + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0xC000 +#endif + +/* + * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x1D000 + +#endif /* ARM_BOARD_OPTIMISE_MEM */ /* CCI related constants */ #define PLAT_ARM_CCI_BASE 0x2c090000 @@ -183,30 +209,4 @@ /* CSS SoC NIC-400 Global Programmers View (GPV) */ #define PLAT_SOC_CSS_NIC400_BASE 0x2a000000 -/* - * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size - * plus a little space for growth. - */ -#if TRUSTED_BOARD_BOOT -# define PLAT_ARM_MAX_BL1_RW_SIZE 0x9000 -#else -# define PLAT_ARM_MAX_BL1_RW_SIZE 0x6000 -#endif - -/* - * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a - * little space for growth. - */ -#if TRUSTED_BOARD_BOOT -# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 -#else -# define PLAT_ARM_MAX_BL2_SIZE 0xC000 -#endif - -/* - * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a - * little space for growth. - */ -#define PLAT_ARM_MAX_BL31_SIZE 0x1D000 - #endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 4fda4ca1..c1cfffc4 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -79,7 +79,7 @@ SKIP_A57_L1_FLUSH_PWR_DWN := 1 ENABLE_PLAT_COMPAT := 0 # Enable memory map related constants optimisation -ARM_BOARD_OPTIMISE_MMAP := 1 +ARM_BOARD_OPTIMISE_MEM := 1 include plat/arm/board/common/board_css.mk include plat/arm/common/arm_common.mk |