Compare commits

..

22 Commits
6.1 ... 6

Author SHA1 Message Date
Kinsey Moore
a79813c96e cpukit/libdebugger/server: Use generic TLS accessor
This updates the libdebugger server to use a generic TLS area access
mechanism so that it works across all supported architectures.

Closes #5313
2025-07-31 11:10:56 +10:00
Chris Johns
0cf6de01df cpukit/libio: Support close with IOP references held
- Provide an option for a file system to support close wtih
  references held. This can happen in more complex file systems
  and file descriptor handling with more complete reference
  handling implementations where an fd can hold other fds and
  close can be call on any fd and succeed.

- Fix open IOP leaks in the error paths.

- Provide better definition of the IOP flags to help clarify
  the code.

Fixes #5201
Closes #5311
2025-07-26 21:23:36 -05:00
Kinsey Moore
1240e8f81b cpukit/libdebugger: Add support for TLS variables
This adds support for the "vGetTLSAddr" GDB query which retrieves the
address of a TLS variable by offset from the beginning of the TLS memory
space for the given thread. This offset does not include the size of the
thread control block which is at the beginning of every TLS area as used
by RTEMS. Notably, the returned address is big-endian rather than the
little-endian typical with other responses.

This functionality does not include retrieval of addresses for TLS
variables hosted in loadable modules, only TLS variables in the host
binary.

Closes #5271
2025-07-24 20:31:40 -05:00
Kinsey Moore
b1dbd9eeae bsps/dev/spi/xqspipsu-flash-helper: Explain source
This adds a missing header block and better explains the provenance of
the xqspipsu-flash-helper files and their copyright status.

Closes #5309
2025-07-23 15:18:13 -05:00
Kinsey Moore
84d4c11c30 bsps/include/dev/spi: Add missing extern and guard
This adds missing extern "C" declarations and a missing header guard.

Updates #5309
2025-07-23 15:17:59 -05:00
Matteo Concas
e7fa90ab0c cpu/riscv: Add Smdbltrp extension compatibility
If the Double Trap Extension is implemented, the
MDT bit of the mstatus (or mstatush in RV32)
register will be set when a trap is to be taken.

The MIE (Machine Interrupt Enable) bit can only
be set to 1 if the MDT bit is zero.

Thus, we need to clear MDT first if we want to
enable interrupts when dispatching a thread.

MDT is also cleared in register a1 before
restoring the interrupt frame as writing 1 to MDT
will cause MIE to be set to 0. In RV64 this
happens regardless of the value written to MIE in
the same write.

In RV32, MDT is in the mstatush so we do not need
to clear during restore as this register is not
restored.

With this change all 60 SMP tests pass (compared
to 20/60 before the fix). The tests have been run
on hardware using two RV64 CPUs that implement
the double trap extension.

Close #5288

(cherry picked from commit 19f12d2dca)
2025-07-03 10:07:39 +02:00
Matteo Concas
dd490c5c2d bsps/noelv: Fix using console in polled mode
Before, the console driver needed
`BSP_CONSOLE_USE_INTERRUPTS` to be defined or it
would not build. The intent was to use polled
mode if the macro was equal to zero.

This change makes it so interrupt mode is used if
the macro is defined and polled mode is used if
the macro is not defined.

(cherry picked from commit 5e0a68d3ab)

Close #5283
2025-06-27 09:41:33 +02:00
Matteo Concas
d010f6ae8b bsps/sparc/leon3: Fix GPTIMER timer index logic
The old logic would lead to an error when
multiprocessing was enabled and
`LEON3_GPTIMER_BASE` was defined due to
`leon3_timer_core_index` being undefined.

The new logic fixes this and keeps the same
intent:
 - If multiprocessing is not enabled, the timer
   index is 0
 - If multiprocessing is enabled and
   `LEON3_GPTIMER_BASE` is defined, the timer
   index is twice the CPU boot index
 - If multiprocessing is enabled and
   `LEON3_GPTIMER_BASE` is not defined, we
   fallback to the old logic using the GPTIMER
   core index.

Close #5281
2025-06-25 08:22:13 +02:00
Kinsey Moore
3d8b56f10c cpukit/libdebugger: Prevent hang on memory access
When memory is accessed by the remote debugging client, the access is
sandboxed with setjmp/longjmp and appropriate exception handlers to
prevent the attempted access from causing a failure of the debugger or
otherwise altering execution. The existing implementation works as
expected when the context executing the memory access and the exception
context resulting from a failed access do not share a stack.

In the case of AArch64, a failed access when the debugger is already in
exception context causes a re-entry into exception context where the
machine state is pushed onto the same stack that was in use where the
exception occurred. When setjmp is called inside a stack frame and the
exception occurs outside that stack frame, the stack frame is unwound
before the exception occurs and the exception entry overwrites the area
previously occupied by the stack frame housing the setjmp and corrupting
the link register that is stored there. After restoration of state using
longjmp(), this corrupted link register information is loaded from the
stack frame and undesired behavior occurs.

In the instance of this bug that was encountered, the corrupted link
register contained an unaligned pointer which caused an unending cascade
of prefetch abort exceptions presenting as a hard hang.

Closes #5273
2025-06-18 13:53:35 -05:00
Chris Johns
cb3fba0447 bsps/shared/dev/ide: Initalise ATA request links as off chain
- Fixes the asserts when building with RTEMS_DEBUG

Closes #5254
2025-05-28 13:01:00 +10:00
Chris Johns
6335d7e48a machine/timecounters: Add missing _Timecounter_ decls
Add:

 - _Timecounter_Getboottime
 - _Timecounter_Getboottimebin

Closes #5212
2025-05-09 08:37:01 +10:00
Chris Johns
f769b20c98 cpukit/libdl: Fix loading symbols from an object file at runtime
- Assume a relocation record with a symbol name with a length of
  0 is resolved. ARM seems to create a symbol with no name for
  R_ARM_V4BX relocation records.

- Move the addition of the rtems_rtl_base_sym_global_add symbol
  to the global symbol table to the weak
  rtems_rtl_base_global_syms_init call. If symbols are
  embedded the support for runtime loading symbols is over
  loaded. This change is required so the base object has a
  valid global symbol table attached to track dependencies.

Fixes #5234
2025-04-01 12:31:32 +11:00
Matteo Concas
9dae9f5fe8 spec: Install missing header files for GRLIB and SPARC
The following files will be installed during SPARC/GRLIB builds:
- bsps/include/grlib/apbuart-regs.h
- bsps/include/grlib/gptimer-regs.h
- bsps/include/grlib/irqamp-regs.h
- bsps/sparc/include/grlib/io.h

Closes issue #5232
2025-03-26 17:43:13 +01:00
Amar Takhar
b4149b2282 gitlab: Add link to CI
This runs only the commit message and merge request checker.

Required so we can have 'all pipelines must pass' enabled due to a bug in
Gitlab
2025-02-12 22:22:24 -05:00
Chris Johns
87bf49b715 Revert "build: Provide LDFLAGS for pkg-config"
This reverts commit e36ba91110
2025-02-11 05:38:19 +00:00
Sebastian Huber
e421c922a8 bsp/qoriq: Ignore spurious interrupts
For example, with edge triggered external interrupts we may see spurious
interrupts.   Ignore them instead of issuing a fatal error.

Use eieio to synchronize access to the IACK and EOI registers.

Use a loop to immediately services the next pending interrupt without
having to go through the exception epiloge and prologue.

Close #5173.
2025-02-07 16:18:23 -07:00
Sebastian Huber
e36ba91110 build: Provide LDFLAGS for pkg-config
Some pkg-config variants perform transformations on the --libs options.
This may lead to completely broken linker options.  Provide the LDFLAGS
as a variable.  Remove "Ldflags:" since this is an unsupported field.

Update #5165.
2025-02-07 18:28:01 +00:00
Jan Sommer
a0e4be53f4 grlib/occan: Fix baud rate calculation
Fixes #5205
2025-02-07 08:50:42 -07:00
Jan Sommer
9641e1e97d cpukit/termios: Fix ordering of baud rate table
rtems_termios_set_best_baud expects a sorted baud rate table.

Fixes #5202
2025-02-03 12:04:33 -07:00
Reinking, Janosch
f1c201c508 bsps/shared: NS16550 driver updates the line control register during operation
Fixes: #5179
2025-01-24 00:08:29 +00:00
Zhaoyue Wang
603c168a0b cpukit/libmisc: fix flag in capture.c
The RTEMS_CAPTURE_OVERFLOW is an overflow flag for each CPU, and its
value is the same as RTEMS_CAPTURE_INIT. Executing rtems_capture_flush
will set the RTEMS_CAPTURE_INIT flag to 0 in the global flags.

Fixes #5184.
2025-01-23 23:45:01 +00:00
Ranulfo Raphael
84c2cf3da9 cpukit/libdl/arm: Fix trampoline alignment
This commit aligns trampolines for THUMB and ARM instructions
(CALL/JUMP24 and THM_JUMP24/THM_PC22).

According to the ARM technical reference in section "Register-relative
and PC-relative expressions":
    In Thumb code:
    - For B, BL, CBNZ, and CBZ instructions, the value of the PC is the
      address of the current instruction plus 4 bytes.
    - For all other instructions that use labels, the value of the PC is
      the address of the current instruction plus 4 bytes, with bit[1]
      of the result cleared to 0 to make it word-aligned.

Closes #5189
2025-01-23 19:38:05 -03:00
42 changed files with 720 additions and 219 deletions

4
.gitlab/gitlab-ci.yml Normal file
View File

@@ -0,0 +1,4 @@
include:
- project: 'administration/integration'
file:
- 'ci/config/rtems.yml'

View File

@@ -30,6 +30,10 @@
#include <bsp/utility.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t config;
#define CADENCE_SPI_CONFIG_MODEFAIL_EN BSP_BIT32(17)
@@ -82,4 +86,8 @@ typedef struct {
uint32_t moduleid;
} cadence_spi;
#ifdef __cplusplus
}
#endif
#endif /* LIBBSP_ARM_XILINX_ZYNQ_CADENCE_SPI_REGS_H */

View File

@@ -30,6 +30,10 @@
#include <bsp/utility.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t reserved1[7];
uint32_t globalirq;
@@ -85,4 +89,8 @@ typedef struct {
uint32_t rx_fifo_len;
} xilinx_axi_spi;
#ifdef __cplusplus
}
#endif
#endif /* LIBBSP_ARM_XILINX_AXI_SPI_REGS_H */

View File

@@ -31,6 +31,10 @@
#include <dev/flash/flashdev.h>
#include <dev/spi/xqspipsu.h>
#ifdef __cplusplus
extern "C" {
#endif
#define XQSPI_FLASH_MAX_REGIONS ((size_t)32)
/*
@@ -65,4 +69,8 @@ typedef struct xqspi_flash_region_table {
uint32_t xqspi_flash_bit_allocator;
} xqspi_flash_region_table;
#ifdef __cplusplus
}
#endif
#endif /* XILINX_XQSPI_FLASH_H */

View File

@@ -3,8 +3,27 @@
* SPDX-License-Identifier: MIT
******************************************************************************/
/**
* @file xqspipsu_flash_helper.h
*
* This file contains flash helper function prototypes for the QSPIPSU driver.
* It consists of modified functions from Xilinx's flash example in
* examples/xqspipsu_generic_flash_interrupt_example.c of the qspipsu driver.
*
* Since the comment blocks and general form of the functions has not changed,
* the Xilinx copyright above is maintained, but this file is not part of the
* upstream embeddedsw distribution.
*/
#ifndef LIBBSP_DEV_SPI_XQSPIPSU_HELPER_H
#define LIBBSP_DEV_SPI_XQSPIPSU_HELPER_H
#include "xqspipsu.h"
#ifdef __cplusplus
extern "C" {
#endif
int QspiPsu_NOR_Initialize(
XQspiPsu *QspiPsuInstancePtr,
u16 QspiPsuIntrId
@@ -231,3 +250,9 @@ u32 QspiPsu_NOR_Get_Page_Size(XQspiPsu *QspiPsuPtr);
* @return The JEDEC ID of attached flash in bytes.
******************************************************************************/
u32 QspiPsu_NOR_Get_JEDEC_ID(XQspiPsu *QspiPsuPtr);
#ifdef __cplusplus
}
#endif
#endif /* LIBBSP_DEV_SPI_XQSPIPSU_HELPER_H */

View File

@@ -9,7 +9,7 @@
*/
/*
* Copyright (C) 2010, 2017 embedded brains GmbH & Co. KG
* Copyright (C) 2010, 2024 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -162,8 +162,6 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
void bsp_interrupt_dispatch(uintptr_t exception_number)
{
unsigned int vector;
if (exception_number == 10) {
qoriq_decrementer_dispatch();
return;
@@ -176,22 +174,25 @@ void bsp_interrupt_dispatch(uintptr_t exception_number)
}
#endif
/*
* This works only if the "has-external-proxy" property is present in the
* "epapr,hv-pic" device tree node.
*/
PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR, vector);
if (vector != SPURIOUS) {
while (true) {
unsigned int vector;
uint32_t msr;
/*
* This works only if the "has-external-proxy" property is present in the
* "epapr,hv-pic" device tree node.
*/
PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR, vector);
if (vector == SPURIOUS) {
return;
}
msr = ppc_external_exceptions_enable();
bsp_interrupt_handler_dispatch(vector);
ppc_external_exceptions_disable(msr);
ev_int_eoi(vector);
} else {
bsp_interrupt_handler_default(vector);
}
}
@@ -586,19 +587,20 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
void bsp_interrupt_dispatch(uintptr_t exception_number)
{
rtems_vector_number vector = qoriq.pic.iack;
while (true) {
rtems_vector_number vector = qoriq.pic.iack;
uint32_t msr;
if (vector != SPURIOUS) {
uint32_t msr = ppc_external_exceptions_enable();
if (vector == SPURIOUS) {
return;
}
msr = ppc_external_exceptions_enable();
bsp_interrupt_handler_dispatch(vector);
ppc_external_exceptions_disable(msr);
qoriq.pic.eoi = 0;
qoriq.pic.whoami;
} else {
bsp_interrupt_handler_default(vector);
ppc_enforce_in_order_execution_of_io();
}
}

View File

@@ -181,11 +181,14 @@ rtems_status_code console_initialize(
rtems_termios_initialize();
const rtems_termios_device_handler *handler = &apbuart_handler_polled;
const rtems_termios_device_handler *handler;
if (BSP_CONSOLE_USE_INTERRUPTS) {
#ifdef BSP_CONSOLE_USE_INTERRUPTS
handler = &apbuart_handler_interrupt;
}
#else
handler = &apbuart_handler_polled;
#endif
for (size_t i = 0; i < apbuart_devices; ++i) {
struct apbuart_context *ctx;

View File

@@ -225,6 +225,7 @@ ata_io_data_request(ata_ide_dev_t *ata_dev, rtems_blkdev_request *req)
areq->breq->bufnum * (areq->breq->bufs[0].length / ATA_SECTOR_SIZE);
/* add request to the queue of awaiting requests to the controller */
rtems_chain_set_off_chain(&areq->link);
ata_add_to_controller_queue(ctrl_minor, areq);
return RTEMS_SUCCESSFUL;
@@ -1249,6 +1250,7 @@ rtems_ata_initialize(rtems_device_major_number major,
rtems_message_queue_delete(ata_queue_id);
return status;
}
rtems_chain_set_off_chain(&int_st->link);
#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
rtems_chain_append(
&ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],

View File

@@ -590,7 +590,7 @@ int ns16550_set_attributes(
* turn into the LSB and MSB divisor latch registers.
*/
(*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
(*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB | ucLineControl);
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);

View File

@@ -10,6 +10,9 @@
* consists of modified functions from Xilinx's flash example in
* examples/xqspipsu_generic_flash_interrupt_example.c of the qspipsu driver.
*
* Since the comment blocks and general form of the functions has not changed,
* the Xilinx copyright above is maintained, but this file is not part of the
* upstream embeddedsw distribution.
*/
#include "xqspipsu_flash_config.h"

View File

@@ -62,7 +62,8 @@ int grlib_canbtrs_calc_timing(
tseg++) {
/* calculate scaler */
tmp = ((br->divfactor + tseg) * baud);
sc = (core_hz * 2)/ tmp - core_hz / tmp;
/* Core frequency is always divided by 2 before scaler */
sc = core_hz / (2 * tmp);
if (sc <= 0 || sc > br->max_scaler)
continue;
if (br->has_bpr &&
@@ -71,7 +72,7 @@ int grlib_canbtrs_calc_timing(
((sc > 256 * 4) && (sc <= 256 * 8) && (sc & 0x7))))
continue;
error = baud - core_hz / (sc * (br->divfactor + tseg));
error = baud - core_hz / (2 * sc * (br->divfactor + tseg));
#ifdef GRLIB_CANBTRS_DEBUG
printf(" baud=%d, tseg=%d, sc=%d, error=%d\n",
baud, tseg, sc, error);

View File

@@ -1019,7 +1019,9 @@ static void convert_timing_to_btrs(
{
btrs->btr0 = (t->rsj << OCCAN_BUSTIM_SJW_BIT) |
(t->scaler & OCCAN_BUSTIM_BRP);
btrs->btr1 = (0<<7) | (t->ps2 << OCCAN_BUSTIM_TSEG2_BIT) | t->ps1;
/* Core adds +1 to the register values, so compensate here by decrementing */
btrs->btr1 = (0<<7) | ((t->ps2-1) << OCCAN_BUSTIM_TSEG2_BIT) | (t->ps1-1);
}
static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing)

View File

@@ -21,14 +21,6 @@
#include <leon.h>
#include <rtems/btimer.h>
#if defined(RTEMS_MULTIPROCESSING)
#define LEON3_TIMER_INDEX \
((rtems_configuration_get_user_multiprocessing_table()) ? \
(rtems_configuration_get_user_multiprocessing_table()->node) - 1 : 1)
#else
#define LEON3_TIMER_INDEX 0
#endif
bool benchmark_timer_find_average_overhead;
bool benchmark_timer_is_initialized = false;
@@ -39,7 +31,7 @@ void benchmark_timer_initialize(void)
* Timer runs long and accurate enough not to require an interrupt.
*/
if (LEON3_Timer_Regs) {
gptimer_timer *timer = &LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX];
gptimer_timer *timer = &LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX];
if ( benchmark_timer_is_initialized == false ) {
/* approximately 1 us per countdown */
grlib_store_32( &timer->trldval, 0xffffff );
@@ -61,7 +53,7 @@ benchmark_timer_t benchmark_timer_read(void)
if (LEON3_Timer_Regs) {
total =
grlib_load_32( &LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].tcntval );
grlib_load_32( &LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].tcntval );
total = 0xffffff - total;

View File

@@ -216,11 +216,12 @@ extern unsigned int leon3_timer_prescaler;
* @brief This constant defines the index of the GPTIMER timer used by the
* clock driver.
*/
#if defined(RTEMS_MULTIPROCESSING)
#define LEON3_CLOCK_INDEX \
( leon3_timer_core_index != 0 ? 0 : 2 * LEON3_Cpu_Index )
#else
#if !defined(RTEMS_MULTIPROCESSING)
#define LEON3_CLOCK_INDEX 0
#elif defined(LEON3_GPTIMER_BASE)
#define LEON3_CLOCK_INDEX ( 2 * LEON3_Cpu_Index )
#else
#define LEON3_CLOCK_INDEX ( leon3_timer_core_index != 0 ? 0 : 2 * LEON3_Cpu_Index )
#endif
/**

View File

@@ -58,6 +58,8 @@ void _Timecounter_Getmicrouptime(struct timeval *);
void _Timecounter_Getbintime(struct bintime *);
void _Timecounter_Getnanotime(struct timespec *);
void _Timecounter_Getmicrotime(struct timeval *);
void _Timecounter_Getboottime(struct timeval *);
void _Timecounter_Getboottimebin(struct bintime *);
__END_DECLS
#endif /* _MACHINE__TIMECOUNTER_H_ */

View File

@@ -18,6 +18,8 @@
* Modifications to support reference counting in the file system are
* Copyright (C) 2012 embedded brains GmbH & Co. KG
*
* Copyright (C) 2025 Contemporary Software
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -1378,18 +1380,23 @@ typedef struct {
} rtems_libio_ioctl_args_t;
/**
* @name Flag Values
* @name Flag Values and Masks
*/
/**@{**/
#define LIBIO_FLAGS_NO_DELAY 0x0001U /* return immediately if no data */
#define LIBIO_FLAGS_READ 0x0002U /* reading */
#define LIBIO_FLAGS_WRITE 0x0004U /* writing */
#define LIBIO_FLAGS_OPEN 0x0100U /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200U /* all writes append */
#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800U /* close on process exec() */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
#define LIBIO_FLAGS_REFERENCE_INC 0x1000U
#define LIBIO_FLAGS_FREE 0x0001U /* on the free list */
#define LIBIO_FLAGS_NO_DELAY 0x0002U /* return immediately if no data */
#define LIBIO_FLAGS_READ 0x0004U /* reading */
#define LIBIO_FLAGS_WRITE 0x0008U /* writing */
#define LIBIO_FLAGS_OPEN 0x0100U /* device is open */
#define LIBIO_FLAGS_APPEND 0x0200U /* all writes append */
#define LIBIO_FLAGS_CLOSE_BUSY 0x0400U /* close with refs held */
#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800U /* close on process exec() */
#define LIBIO_FLAGS_REFERENCE_INC 0x1000U
/* masks */
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
#define LIBIO_FLAGS_FLAGS_MASK (LIBIO_FLAGS_REFERENCE_INC - 1U)
#define LIBIO_FLAGS_REFERENCE_MASK (~LIBIO_FLAGS_FLAGS_MASK)
/** @} */
@@ -1398,6 +1405,20 @@ static inline unsigned int rtems_libio_iop_flags( const rtems_libio_t *iop )
return _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED );
}
/**
* @brief Returns true if the iop is a bad file descriptor, otherwise
* returns false. A bad file descriptor means free or not open.
*
* @param[in] flags The flags.
*/
static inline unsigned int rtems_libio_iop_flags_bad_fd(
const unsigned int flags
)
{
return ( ( flags & LIBIO_FLAGS_FREE ) != 0 )
|| ( ( flags & LIBIO_FLAGS_OPEN ) == 0 );
}
/**
* @brief Returns true if this is a no delay iop, otherwise returns false.
*
@@ -1428,6 +1449,16 @@ static inline bool rtems_libio_iop_is_writeable( const rtems_libio_t *iop )
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_WRITE ) != 0;
}
/**
* @brief Returns true if the iop is open, otherwise returns false.
*
* @param[in] iop The iop.
*/
static inline bool rtems_libio_iop_is_open( const rtems_libio_t *iop )
{
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_OPEN ) != 0;
}
/**
* @brief Returns true if this is an append iop, otherwise returns false.
*
@@ -1438,6 +1469,28 @@ static inline bool rtems_libio_iop_is_append( const rtems_libio_t *iop )
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_APPEND ) != 0;
}
/**
* @brief Returns true if the iop is held, otherwise returns false.
*
* @param[in] iop The iop.
*/
static inline bool rtems_libio_iop_is_held( const rtems_libio_t *iop )
{
const unsigned int ref_count =
rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_REFERENCE_MASK;
return ref_count != 0;
}
/**
* @brief Returns true if the iop is free, otherwise returns false.
*
* @param[in] iop The iop.
*/
static inline bool rtems_libio_iop_is_free( const rtems_libio_t *iop )
{
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_FREE ) != 0;
}
/**
* @name External I/O Handlers
*/

View File

@@ -103,6 +103,63 @@ extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
*/
extern rtems_filesystem_global_location_t rtems_filesystem_global_location_null;
/*
* File Descriptor Routine Prototypes
*/
/**
* This routine searches the IOP Table for an unused entry. If it
* finds one, it returns it. Otherwise, it returns NULL.
*/
rtems_libio_t *rtems_libio_allocate(void);
/**
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
unsigned int rtems_libio_from_fcntl_flags( int fcntl_flags );
/**
* Convert RTEMS internal flags to UNIX fnctl(2) flags
*/
int rtems_libio_to_fcntl_flags( unsigned int flags );
/**
* This routine frees the resources associated with an IOP (file
* descriptor) and clears the slot in the IOP Table. No checks are
* made on the state of the IOP.
*/
void rtems_libio_free_iop(
rtems_libio_t *iop
);
/**
* This routine frees the resources associated with an IOP (file
* descriptor) and clears the slot in the IOP Table. The IOP has to
* close (open flag not set) and no references held or the call will
* ignore the request.
*/
static inline void rtems_libio_free(
rtems_libio_t *iop
)
{
/*
* The IOP cannot be open and there can be no references held for it
* to be returned to the free list.
*
* Note, the open flag indicates the user owns the fd that indexes
* the iop so consider it an indirect reference. We cannot return
* the iop to the free list while the user owns the fd.
*
* Read the flags once as it is an atomic and we need to test 2
* flags. No convenience call as this is the only case we have.
*/
const unsigned int flags = rtems_libio_iop_flags( iop );
if ( ( ( flags & LIBIO_FLAGS_OPEN ) == 0 )
&& ( ( flags & LIBIO_FLAGS_REFERENCE_MASK ) == 0 ) ) {
rtems_libio_free_iop( iop );
}
}
/**
* @brief Sets the specified flags in the iop.
*
@@ -184,6 +241,7 @@ static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
_Assert( flags >= LIBIO_FLAGS_REFERENCE_INC );
desired = flags - LIBIO_FLAGS_REFERENCE_INC;
success = _Atomic_Compare_exchange_uint(
&iop->flags,
&flags,
@@ -199,6 +257,8 @@ static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
ATOMIC_ORDER_RELEASE
);
#endif
/* free the IOP is not open or held */
rtems_libio_free( iop );
}
/*
@@ -218,56 +278,83 @@ static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
*/
#define rtems_libio_check_is_open(_iop) \
do { \
if ((rtems_libio_iop_flags(_iop) & LIBIO_FLAGS_OPEN) == 0) { \
errno = EBADF; \
return -1; \
} \
do { \
if (rtems_libio_iop_is_open(_iop)) { \
errno = EBADF; \
return -1; \
} \
} while (0)
/**
* @brief Macro to get the iop for the specified file descriptor.
* @brief Function to get the iop for the specified file descriptor.
*
* Checks that the file descriptor is in the valid range and open.
*/
static inline int rtems_libio_get_iop( int fd, rtems_libio_t **iop )
{
unsigned int flags;
if ( (uint32_t) ( fd ) >= rtems_libio_number_iops ) {
return EBADF;
}
*iop = rtems_libio_iop( fd );
flags = rtems_libio_iop_hold( *iop );
if ( rtems_libio_iop_flags_bad_fd( flags ) ) {
rtems_libio_iop_drop( *iop );
return EBADF;
}
return 0;
}
/**
* @brief Macro to get the iop for the specified file descriptor.
*/
#define LIBIO_GET_IOP( _fd, _iop ) \
do { \
unsigned int _flags; \
if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
rtems_set_errno_and_return_minus_one( EBADF ); \
} \
_iop = rtems_libio_iop( _fd ); \
_flags = rtems_libio_iop_hold( _iop ); \
if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
rtems_libio_iop_drop( _iop ); \
rtems_set_errno_and_return_minus_one( EBADF ); \
int _error = rtems_libio_get_iop( _fd, &_iop ); \
if ( _error != 0 ) { \
rtems_set_errno_and_return_minus_one( _error ); \
} \
} while ( 0 )
/**
* @brief Macro to get the iop for the specified file descriptor with access
* flags and error.
* @brief Function to get the iop for the specified file descriptor
* with access flags and error.
*
* Checks that the file descriptor is in the valid range and open.
*/
static inline int rtems_libio_get_iop_with_access(
int fd, rtems_libio_t **iop, unsigned int access_flags, int access_error
)
{
const unsigned int mandatory = LIBIO_FLAGS_OPEN | access_flags ;
unsigned int flags;
if ( (uint32_t) ( fd ) >= rtems_libio_number_iops ) {
return EBADF;
}
*iop = rtems_libio_iop( fd );
flags = rtems_libio_iop_hold( *iop );
if ( ( flags & mandatory ) != mandatory ) {
rtems_libio_iop_drop( *iop );
*iop = NULL;
if ( ( flags & LIBIO_FLAGS_OPEN ) == 0 ) {
return EBADF;
} else {
return access_error;
}
}
return 0;
}
/**
* @brief Macro to wrap the function to allow returning the IOP and
* using the error set and return macro.
*/
#define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \
do { \
unsigned int _flags; \
unsigned int _mandatory; \
if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
rtems_set_errno_and_return_minus_one( EBADF ); \
} \
_iop = rtems_libio_iop( _fd ); \
_flags = rtems_libio_iop_hold( _iop ); \
_mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \
if ( ( _flags & _mandatory ) != _mandatory ) { \
int _error; \
rtems_libio_iop_drop( _iop ); \
if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
_error = EBADF; \
} else { \
_error = _access_error; \
} \
int _error = rtems_libio_get_iop_with_access( \
_fd, &_iop, _access_flags, _access_error \
); \
if ( _error != 0 ) { \
rtems_set_errno_and_return_minus_one( _error ); \
} \
} while ( 0 )
@@ -435,34 +522,6 @@ int rtems_filesystem_utime_update(
struct timespec new_times[2]
);
/*
* File Descriptor Routine Prototypes
*/
/**
* This routine searches the IOP Table for an unused entry. If it
* finds one, it returns it. Otherwise, it returns NULL.
*/
rtems_libio_t *rtems_libio_allocate(void);
/**
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
*/
unsigned int rtems_libio_fcntl_flags( int fcntl_flags );
/**
* Convert RTEMS internal flags to UNIX fnctl(2) flags
*/
int rtems_libio_to_fcntl_flags( unsigned int flags );
/**
* This routine frees the resources associated with an IOP (file descriptor)
* and clears the slot in the IOP Table.
*/
void rtems_libio_free(
rtems_libio_t *iop
);
/**
* Return the number of open iop descriptors
*/

View File

@@ -374,7 +374,7 @@ static inline size_t rtems_rtl_obj_align (size_t offset,
}
/**
* Is the symbol in this object's files globa symbol table?
* Is the symbol in this object's files global symbol table?
*
* @param obj The object file's descriptor to search.
* @param sym The symbol to check.

View File

@@ -97,6 +97,15 @@ bool rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
*/
void rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols);
/**
* Insert a symbol into a symbol table.
*
* @param symbols Symbol table
* @param symbols Symbol to add
*/
void rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
rtems_rtl_obj_sym* symbol);
/**
* Add a table of exported symbols to the symbol table.
*

View File

@@ -63,8 +63,11 @@ int close(
rtems_set_errno_and_return_minus_one( EBADF );
}
/* The expected flags */
flags &= LIBIO_FLAGS_REFERENCE_INC - 1U;
/* The expected flags depends on close when busy flag. If set
* there can be references held when calling the close handler */
if ( ( flags & LIBIO_FLAGS_CLOSE_BUSY ) == 0 ) {
flags &= LIBIO_FLAGS_FLAGS_MASK;
}
desired = flags & ~LIBIO_FLAGS_OPEN;
success = _Atomic_Compare_exchange_uint(
@@ -79,7 +82,7 @@ int close(
break;
}
if ( ( flags & ~( LIBIO_FLAGS_REFERENCE_INC - 1U ) ) != 0 ) {
if ( ( flags & LIBIO_FLAGS_REFERENCE_MASK ) != 0 ) {
rtems_set_errno_and_return_minus_one( EBUSY );
}
}

View File

@@ -58,7 +58,7 @@ static int duplicate_iop( rtems_libio_t *iop )
rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo );
rtems_filesystem_instance_unlock( &iop->pathinfo );
rtems_libio_iop_flags_set( diop, rtems_libio_fcntl_flags( oflag ) );
rtems_libio_iop_flags_set( diop, rtems_libio_from_fcntl_flags( oflag ) );
/*
* XXX: We call the open handler here to have a proper open and close pair.
*
@@ -99,7 +99,7 @@ static int duplicate2_iop( rtems_libio_t *iop, int fd2 )
if (rv == 0) {
oflag = rtems_libio_to_fcntl_flags( rtems_libio_iop_flags( iop ) );
rtems_libio_iop_flags_set( iop2, rtems_libio_fcntl_flags( oflag ) );
rtems_libio_iop_flags_set( iop2, rtems_libio_from_fcntl_flags( oflag ) );
rtems_filesystem_instance_lock( &iop->pathinfo );
rtems_filesystem_location_clone( &iop2->pathinfo, &iop->pathinfo );
@@ -177,7 +177,7 @@ static int vfcntl(
break;
case F_SETFL:
flags = rtems_libio_fcntl_flags( va_arg( ap, int ) );
flags = rtems_libio_from_fcntl_flags( va_arg( ap, int ) );
mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;
/*
@@ -226,7 +226,10 @@ static int vfcntl(
if (ret >= 0) {
int err = (*iop->pathinfo.handlers->fcntl_h)( iop, cmd );
if (err) {
if (err == 0 && !rtems_libio_iop_is_open( iop ) ) {
err = EBADF;
}
if (err != 0) {
errno = err;
ret = -1;
}

View File

@@ -43,8 +43,10 @@
void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc )
{
rtems_filesystem_instance_lock( loc );
(*loc->mt_entry->ops->freenod_h)( loc );
rtems_filesystem_instance_unlock( loc );
rtems_filesystem_location_remove_from_mt_entry( loc );
if ( loc->mt_entry != NULL ) {
rtems_filesystem_instance_lock( loc );
(*loc->mt_entry->ops->freenod_h)( loc );
rtems_filesystem_instance_unlock( loc );
rtems_filesystem_location_remove_from_mt_entry( loc );
}
}

View File

@@ -65,6 +65,10 @@ int fstat(
memset( sbuf, 0, sizeof(struct stat) );
rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, sbuf );
if (rv == 0 && !rtems_libio_iop_is_open( iop ) ) {
errno = EBADF;
rv = -1;
}
rtems_libio_iop_drop( iop );
return rv;
}

View File

@@ -77,7 +77,7 @@ static const rtems_assoc_t status_flags_assoc[] = {
{ 0, 0, 0 },
};
unsigned int rtems_libio_fcntl_flags( int fcntl_flags )
unsigned int rtems_libio_from_fcntl_flags( int fcntl_flags )
{
unsigned int flags = 0;
uint32_t access_modes;
@@ -136,6 +136,8 @@ rtems_libio_t *rtems_libio_allocate( void )
if ( iop != NULL ) {
void *next;
rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_FREE );
next = iop->data1;
rtems_libio_iop_free_head = next;
@@ -149,30 +151,32 @@ rtems_libio_t *rtems_libio_allocate( void )
return iop;
}
void rtems_libio_free(
void rtems_libio_free_iop(
rtems_libio_t *iop
)
{
size_t zero;
rtems_filesystem_location_free( &iop->pathinfo );
rtems_libio_lock();
/*
* Clear everything except the reference count part. At this point in time
* there may be still some holders of this file descriptor.
*/
rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_REFERENCE_INC - 1U );
zero = offsetof( rtems_libio_t, offset );
memset( (char *) iop + zero, 0, sizeof( *iop ) - zero );
if ( !rtems_libio_iop_is_free( iop ) ) {
/*
* Clear the flags. All references should have been dropped.
*/
_Atomic_Store_uint( &iop->flags, LIBIO_FLAGS_FREE, ATOMIC_ORDER_RELAXED );
/*
* Append it to the free list. This increases the likelihood that a use
* after close is detected.
*/
*rtems_libio_iop_free_tail = iop;
rtems_libio_iop_free_tail = &iop->data1;
rtems_filesystem_location_free( &iop->pathinfo );
zero = offsetof( rtems_libio_t, offset );
memset( (char *) iop + zero, 0, sizeof( *iop ) - zero );
/*
* Append it to the free list. This increases the likelihood that
* a use after close is detected.
*/
*rtems_libio_iop_free_tail = iop;
rtems_libio_iop_free_tail = &iop->data1;
}
rtems_libio_unlock();
}

View File

@@ -72,8 +72,10 @@ static void rtems_libio_init( void )
if (rtems_libio_number_iops > 0)
{
iop = rtems_libio_iop_free_head = &rtems_libio_iops[0];
for (i = 0 ; (i + 1) < rtems_libio_number_iops ; i++, iop++)
for (i = 0 ; (i + 1) < rtems_libio_number_iops ; i++, iop++) {
rtems_libio_iop_flags_set( iop, LIBIO_FLAGS_FREE );
iop->data1 = iop + 1;
}
iop->data1 = NULL;
rtems_libio_iop_free_tail = &iop->data1;
}

View File

@@ -137,7 +137,7 @@ static int do_open(
rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo );
rtems_filesystem_eval_path_cleanup( &ctx );
rtems_libio_iop_flags_set( iop, rtems_libio_fcntl_flags( oflag ) );
rtems_libio_iop_flags_set( iop, rtems_libio_from_fcntl_flags( oflag ) );
rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode );
@@ -168,10 +168,6 @@ static int do_open(
}
}
if ( rv < 0 ) {
rtems_libio_free( iop );
}
return rv;
}
@@ -192,6 +188,9 @@ int open( const char *path, int oflag, ... )
iop = rtems_libio_allocate();
if ( iop != NULL ) {
rv = do_open( iop, path, oflag, mode );
if ( rv < 0 ) {
rtems_libio_free( iop );
}
} else {
errno = ENFILE;
rv = -1;

View File

@@ -53,11 +53,11 @@ const rtems_assoc_t rtems_termios_baud_table [] = {
{ "B1800", 1800, B1800 },
{ "B2400", 2400, B2400 },
{ "B4800", 4800, B4800 },
{ "B7200", 7200, B7200 },
{ "B9600", 9600, B9600 },
{ "B14400", 14400, B14400 },
{ "B19200", 19200, B19200 },
{ "B38400", 38400, B38400 },
{ "B7200", 7200, B7200 },
{ "B14400", 14400, B14400 },
{ "B28800", 28800, B28800 },
{ "B57600", 57600, B57600 },
{ "B76800", 76800, B76800 },

View File

@@ -33,6 +33,7 @@
#include <rtems/bspIo.h>
#include <rtems/score/smp.h>
#include <rtems/score/tls.h>
#include <rtems/rtems-debugger.h>
#include <rtems/debugger/rtems-debugger-server.h>
@@ -696,6 +697,25 @@ remote_packet_out_append_hex(const uint8_t* data, size_t size)
return 0;
}
/* output data in big-endian instead of little-endian */
static int
remote_packet_out_append_hex_be(const uint8_t* data, size_t size)
{
size_t ol = rtems_debugger->output_level;
size_t i = size;
while (i > 0) {
uint8_t byte = data[--i];
if (rtems_debugger->output_level >= (RTEMS_DEBUGGER_BUFFER_SIZE - 2)) {
rtems_debugger->output_level = ol;
rtems_debugger_printf("rtems-db: output overflow\n");
return -1;
}
rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(byte >> 4);
rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(byte);
}
return 0;
}
static int
remote_packet_out_append_str(const char* str)
{
@@ -1019,6 +1039,116 @@ remote_gq_attached(uint8_t* buffer, int size)
return 0;
}
static rtems_debugger_thread* get_debugger_thread_from_id(const char* thread_id)
{
int r;
DB_UINT pid = 0;
DB_UINT tid = 0;
bool extended;
rtems_debugger_threads* threads = rtems_debugger->threads;
rtems_debugger_thread* current;
extended = thread_id_decode(thread_id, &pid, &tid);
if (!extended && !check_pid(pid)) {
return NULL;
}
r = rtems_debugger_thread_find_index(tid);
if (r < 0) {
return NULL;
}
current = rtems_debugger_thread_current(threads);
return &current[r];
}
static int
parse_get_tls_addr(
uint8_t* buffer,
int size,
const char** thread_id_str,
const char** offset_str,
const char** lm_str
)
{
if (thread_id_str == NULL || offset_str == NULL || lm_str == NULL) {
return 1;
}
*thread_id_str = strchr((const char*) buffer, ':') + 1;
if (*thread_id_str == NULL || *thread_id_str - (char*)buffer > size) {
/* malformed packet */
return 1;
}
*offset_str = strchr(*thread_id_str, ',') + 1;
if (*offset_str == NULL || *offset_str - (char*)buffer > size) {
/* malformed packet */
return 1;
}
*lm_str = strchr(*offset_str, ',') + 1;
if (*lm_str == NULL || *lm_str - (char*)buffer > size) {
/* malformed packet */
return 1;
}
return 0;
}
static int
remote_gq_get_tls_addr(uint8_t* buffer, int size)
{
const char* thread_id_str;
const char* offset_str;
const char* lm_str;
uint64_t target_address;
int r;
rtems_debugger_thread* thread;
DB_UINT offset;
DB_UINT lm;
if (parse_get_tls_addr(buffer, size, &thread_id_str, &offset_str, &lm_str)) {
/* malformed packet */
remote_packet_out_str(r_E01);
remote_packet_out_send();
return 0;
}
offset = hex_decode_uint((const uint8_t*) offset_str);
lm = hex_decode_uint((const uint8_t*) lm_str);
if (lm != 0) {
/*
* TODO(kmoore) lm is the load module identifier. It is ignored and expected
* to be 0 until TLS support for dynamically loaded modules is added.
*/
remote_packet_out_str(r_E01);
remote_packet_out_send();
return 0;
}
thread = get_debugger_thread_from_id(thread_id_str);
if (thread == NULL) {
remote_packet_out_str(r_E01);
remote_packet_out_send();
return 0;
}
target_address =
(uintptr_t)_CPU_Get_TLS_thread_pointer(&thread->tcb->Registers);
target_address += sizeof(TLS_Thread_control_block) + offset;
remote_packet_out_reset();
r = remote_packet_out_append_hex_be((const uint8_t*) &target_address,
sizeof(target_address));
if (r < 0) {
remote_packet_out_str(r_E01);
}
remote_packet_out_send();
return 0;
}
static const rtems_debugger_packet general_query[] = {
{ .label = "qfThreadInfo",
.command = remote_gq_thread_info_first },
@@ -1032,6 +1162,8 @@ static const rtems_debugger_packet general_query[] = {
.command = remote_gq_attached },
{ .label = "qXfer",
.command = remote_gq_uninterpreted_transfer },
{ .label = "qGetTLSAddr",
.command = remote_gq_get_tls_addr },
};
#define REMOTE_GENERAL_QUERIES RTEMS_DEBUGGER_NUMOF(general_query)

View File

@@ -601,14 +601,6 @@ rtems_debugger_target_exception_thread_resume(rtems_debugger_thread* thread)
}
}
int
rtems_debugger_target_start_memory_access(void)
{
rtems_debugger_target* target = rtems_debugger->target;
target->memory_access = true;
return setjmp(target->access_return);
}
void
rtems_debugger_target_end_memory_access(void)
{

View File

@@ -284,8 +284,20 @@ extern int rtems_debugger_target_cache_sync(rtems_debugger_target_swbreak* swbre
/**
* Start a target memory access. If 0 is return the access can proceed and if
* -1 is return the access has failed.
*
* The call to setjmp() must not reside inside a stack frame relative to the
* expected location of the possible failure. If the debugger is already
* executing in exception context and setjmp is called with its own stack frame,
* that stack frame will be released before the failure. The failure causes an
* exception which will continue using the same stack and is highly likely to
* overwrite stack information which is critical for the debugger to continue
* execution.
*/
extern int rtems_debugger_target_start_memory_access(void);
#define rtems_debugger_target_start_memory_access() \
({ \
rtems_debugger->target->memory_access = true, \
setjmp(rtems_debugger->target->access_return); \
})
/**
* End a target memory access.

View File

@@ -557,6 +557,8 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
resolved = rtems_rtl_elf_find_symbol (obj,
&sym, symname,
&symbol, &symvalue);
if (symname != NULL && strlen(symname) == 0)
resolved = true;
if (!handler (obj,
is_rela, relbuf, targetsect,

View File

@@ -315,6 +315,10 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
return rtems_rtl_elf_rel_failure;
}
/*
* Align tramp_brk as necessary.
*/
obj->tramp_brk = (void *)RTEMS_ALIGN_UP((uintptr_t)obj->tramp_brk, 4);
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
@@ -519,6 +523,10 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
return rtems_rtl_elf_rel_failure;
}
/*
* Align tramp_brk as necessary.
*/
obj->tramp_brk = (void *)RTEMS_ALIGN_UP((uintptr_t)obj->tramp_brk, 4);
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
tmp = tramp_addr + addend;
if (isThumb(symvalue)) {
@@ -526,11 +534,9 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
tmp = tmp - (Elf_Addr)where;
} else {
/*
* The B[L]X expects ARM code at the target. Align tramp_brk as
* necessary.
*/
obj->tramp_brk = (void *)RTEMS_ALIGN_UP((uintptr_t)obj->tramp_brk, 4);
tramp_addr = (Elf_Addr) obj->tramp_brk;
* The B[L]X expects ARM code at the target.
*/
tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_arm_veneer(obj->tramp_brk, symvalue);
/*
* where[1:0] are set to 0 for ARM-targeted relocations because the jump

View File

@@ -48,16 +48,6 @@
#include <rtems/rtl/rtl-sym.h>
#include <rtems/rtl/rtl-trace.h>
/**
* The single symbol forced into the global symbol table that is used to load a
* symbol table from an object file.
*/
static rtems_rtl_obj_sym global_sym_add =
{
.name = "rtems_rtl_base_sym_global_add",
.value = (void*) rtems_rtl_base_sym_global_add
};
static uint_fast32_t
rtems_rtl_symbol_hash (const char *s)
{
@@ -68,15 +58,6 @@ rtems_rtl_symbol_hash (const char *s)
return h & 0xffffffff;
}
static void
rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
rtems_rtl_obj_sym* symbol)
{
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
&symbol->node);
}
static const rtems_rtl_tls_offset*
rtems_rtl_symbol_find_tls_offset (size_t index,
const rtems_rtl_tls_offset* tls_offsets,
@@ -108,7 +89,6 @@ rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
symbols->nbuckets = buckets;
for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
rtems_chain_initialize_empty (&symbols->buckets[buckets]);
rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
return true;
}
@@ -118,6 +98,15 @@ rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols)
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
}
void
rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
rtems_rtl_obj_sym* symbol)
{
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
&symbol->node);
}
bool
rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
const unsigned char* esyms,

View File

@@ -562,10 +562,18 @@ rtems_rtl_unresolved_add (rtems_rtl_obj* obj,
rtems_rtl_unresolv_block* block;
rtems_rtl_unresolv_rec* rec;
int name_index;
const int name_len = (int) strlen(name);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
rtems_rtl_obj_oname (obj), sect, name);
printf ("rtl: unresolv: add: %s(s:%d) -> '%s' (len: %i)\n",
rtems_rtl_obj_oname (obj), sect, name, name_len);
/*
* No name or an empty name is not able to resolved?
*/
if (name_len == 0) {
return false;
}
unresolved = rtems_rtl_unresolved_unprotected ();
if (!unresolved)

View File

@@ -78,17 +78,47 @@
static rtems_rtl_data* rtl;
static bool rtl_data_init;
/**
* The single symbol forced into the global symbol table that is used to load a
* symbol table from an object file.
*/
static rtems_rtl_obj_sym default_global_syms =
{
.name = "rtems_rtl_base_sym_global_add",
.value = (void*) rtems_rtl_base_sym_global_add
};
/**
* Define a default base global symbol loader function that is weak
* so a real table can be linked in when the user wants one.
*
* The default init handler add the one symbol used when loading
* symbols with an object file. It is an unresolved external in that
* object file.
*/
void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak));
void
rtems_rtl_base_global_syms_init (void)
{
/*
* Do nothing.
*/
rtems_rtl_symbols* symbols;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
printf ("rtl: adding default global symbol\n");
if (!rtems_rtl_lock ())
{
rtems_rtl_set_error (EINVAL, "global add cannot lock rtl");
return;
}
symbols = rtems_rtl_global_symbols ();
rtl->base->global_table = &default_global_syms;
rtl->base->global_syms = 1;
rtems_rtl_symbol_global_insert (symbols, &default_global_syms);
rtems_rtl_unlock ();
}
static bool

View File

@@ -801,9 +801,7 @@ rtems_capture_flush (bool prime)
_Thread_Iterate (rtems_capture_flush_tcb, NULL);
if (prime)
capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
else
capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW;
capture_flags_global &= ~RTEMS_CAPTURE_TRIGGERED;
for (cpu=0; cpu < rtems_scheduler_get_processor_maximum(); cpu++) {
RTEMS_INTERRUPT_LOCK_REFERENCE( lock, &(capture_lock_on_cpu( cpu )) )
@@ -811,6 +809,7 @@ rtems_capture_flush (bool prime)
rtems_interrupt_lock_acquire (lock, &lock_context_per_cpu);
capture_count_on_cpu(cpu) = 0;
capture_flags_on_cpu(cpu) &= ~RTEMS_CAPTURE_OVERFLOW;
if (capture_records_on_cpu(cpu).buffer)
rtems_capture_buffer_flush( &capture_records_on_cpu(cpu) );
rtems_interrupt_lock_release (lock, &lock_context_per_cpu);

View File

@@ -45,6 +45,8 @@ extern "C" {
#include <rtems/score/riscv.h>
#define RISCV_MSTATUS_MIE 0x8
#define RISCV_MSTATUS_MDT 0x40000000000
#define RISCV_MSTATUSH_MDT 0x400
#define CPU_ISR_PASSES_FRAME_POINTER FALSE

View File

@@ -106,6 +106,20 @@ SYM(_RISCV_Exception_handler):
/* Check if this is a synchronous or interrupt exception */
bgez a0, .Lsynchronous_exception
/*
* Interrupt exception, clear MDT bit.
* This is only necessary if the Smdbltrp extension is implemented.
* In that case not clearing the MDT bit would prevent us from setting
* the MIE bit later.
*/
#if __riscv_xlen == 64
li t0, RISCV_MSTATUS_MDT
csrrc zero, mstatus, t0
#elif __riscv_xlen == 32
li t0, RISCV_MSTATUSH_MDT
csrrc zero, mstatush, t0
#endif
/* Increment interrupt nest and thread dispatch disable level */
lw t0, PER_CPU_ISR_NEST_LEVEL(s0)
lw t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
@@ -185,7 +199,6 @@ SYM(_RISCV_Exception_handler):
/* Restore */
LREG a0, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
LREG a1, RISCV_INTERRUPT_FRAME_MEPC(sp)
LREG a2, RISCV_INTERRUPT_FRAME_A2(sp)
LREG s0, RISCV_INTERRUPT_FRAME_S0(sp)
LREG s1, RISCV_INTERRUPT_FRAME_S1(sp)
LREG ra, RISCV_INTERRUPT_FRAME_RA(sp)
@@ -201,6 +214,20 @@ SYM(_RISCV_Exception_handler):
LREG t4, RISCV_INTERRUPT_FRAME_T4(sp)
LREG t5, RISCV_INTERRUPT_FRAME_T5(sp)
LREG t6, RISCV_INTERRUPT_FRAME_T6(sp)
/*
* Clear MDT bit before restoring mstatus register.
* This is only necessary if the Smdbltrp extension is implemented.
* In that case, writing to mstatus with MDT set would clear the MIE
* bit, regardless of the MIE value written.
* On RV32, the MDT bit is in the mstatush CSR which is not restored.
*/
#if __riscv_xlen == 64
li a2, RISCV_MSTATUS_MDT
not a2, a2
and a0, a0, a2
#endif
csrw mstatus, a0
csrw mepc, a1
#if __riscv_flen > 0
@@ -229,6 +256,7 @@ SYM(_RISCV_Exception_handler):
#endif
LREG a0, RISCV_INTERRUPT_FRAME_A0(sp)
LREG a1, RISCV_INTERRUPT_FRAME_A1(sp)
LREG a2, RISCV_INTERRUPT_FRAME_A2(sp)
addi sp, sp, CPU_INTERRUPT_FRAME_SIZE

View File

@@ -16,6 +16,7 @@ install:
- bsps/include/grlib/ambapp_bus_grlib.h
- bsps/include/grlib/ambapp_ids.h
- bsps/include/grlib/apbuart.h
- bsps/include/grlib/apbuart-regs.h
- bsps/include/grlib/apbuart_cons.h
- bsps/include/grlib/apbuart_termios.h
- bsps/include/grlib/b1553brm.h
@@ -28,6 +29,7 @@ install:
- bsps/include/grlib/genirq.h
- bsps/include/grlib/gpiolib.h
- bsps/include/grlib/gptimer.h
- bsps/include/grlib/gptimer-regs.h
- bsps/include/grlib/gr1553b.h
- bsps/include/grlib/gr1553bc.h
- bsps/include/grlib/gr1553bc_list.h
@@ -59,6 +61,7 @@ install:
- bsps/include/grlib/grtc.h
- bsps/include/grlib/grtm.h
- bsps/include/grlib/i2cmst.h
- bsps/include/grlib/irqamp-regs.h
- bsps/include/grlib/l2c.h
- bsps/include/grlib/l4stat.h
- bsps/include/grlib/mctrl.h

View File

@@ -15,6 +15,9 @@ install:
- destination: ${BSP_INCLUDEDIR}/drvmgr
source:
- bsps/sparc/include/drvmgr/leon2_amba_bus.h
- destination: ${BSP_INCLUDEDIR}/grlib
source:
- bsps/sparc/include/grlib/io.h
ldflags: []
links:
- role: build-dependency

View File

@@ -1,6 +1,8 @@
/*
* Copyright (C) 2012, 2020 embedded brains GmbH & Co. KG
*
* Copyright (C) 2025 Contemporary Software
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -44,6 +46,7 @@ const char rtems_test_name[] = "FSCLOSE 1";
typedef enum {
ACTION_CLOSE,
ACTION_CLOSE_BUSY,
ACTION_FCNTL,
ACTION_FDATASYNC,
ACTION_FCHDIR,
@@ -67,6 +70,7 @@ typedef struct {
test_action action;
bool wait_in_close;
bool wait_in_fstat;
bool test_close_busy;
int close_count;
int fcntl_count;
int fdatasync_count;
@@ -84,6 +88,16 @@ typedef struct {
static test_context test_instance;
static size_t free_iops(void) {
size_t count = 0;
rtems_libio_t *iop = rtems_libio_iop_free_head;
while (iop != NULL) {
++count;
iop = iop->data1;
}
return count;
}
static void wait(void)
{
rtems_status_code sc;
@@ -112,6 +126,10 @@ static int handler_open(
ctx = IMFS_generic_get_context_by_iop(iop);
++ctx->open_count;
if (ctx->action == ACTION_CLOSE_BUSY) {
iop->flags |= LIBIO_FLAGS_CLOSE_BUSY;
}
return 0;
}
@@ -344,6 +362,12 @@ static void worker_task(rtems_task_argument arg)
rv = close(ctx->fd);
rtems_test_assert(rv == 0);
break;
case ACTION_CLOSE_BUSY:
ctx->wait_in_fstat = true;
rv = fstat(ctx->fd, &st);
rtems_test_assert(rv == -1);
rtems_test_assert(errno == EBADF);
break;
case ACTION_FCNTL:
rv = fcntl(ctx->fd, F_GETFD);
rtems_test_assert(rv >= 0);
@@ -418,6 +442,7 @@ static void worker_task(rtems_task_argument arg)
static void test_fd_free_fifo(const char *path)
{
const size_t iops_free = free_iops();
int a;
int b;
int rv;
@@ -435,10 +460,13 @@ static void test_fd_free_fifo(const char *path)
rtems_test_assert(rv == 0);
rtems_test_assert(a != b);
rtems_test_assert(iops_free == free_iops());
}
static void test_close(test_context *ctx)
{
const size_t iops_free = free_iops();
const char *path = "generic";
int rv;
rtems_status_code sc;
@@ -483,40 +511,47 @@ static void test_close(test_context *ctx)
wakeup_worker(ctx);
rv = close(ctx->fd);
rtems_test_assert(rv == -1);
if (ac == ACTION_CLOSE) {
rtems_test_assert(errno == EBADF);
flags = rtems_libio_iop_hold(iop);
expected_flags = LIBIO_FLAGS_READ_WRITE;
rtems_test_assert(flags == expected_flags);
flags = rtems_libio_iop_flags(iop);
expected_flags = LIBIO_FLAGS_REFERENCE_INC | LIBIO_FLAGS_READ_WRITE;
rtems_test_assert(flags == expected_flags);
} else {
rtems_test_assert(errno == EBUSY);
switch (ac) {
case ACTION_CLOSE:
rtems_test_assert(rv == -1);
rtems_test_assert(errno == EBADF);
flags = rtems_libio_iop_flags(iop);
expected_flags = LIBIO_FLAGS_READ_WRITE;
rtems_test_assert(flags == expected_flags);
rtems_test_assert((iops_free - 1) == free_iops());
break;
case ACTION_CLOSE_BUSY:
rtems_test_assert(rv == 0);
break;
default:
rtems_test_assert(rv == -1);
rtems_test_assert(errno == EBUSY);
break;
}
wakeup_worker(ctx);
if (ac == ACTION_CLOSE) {
flags = rtems_libio_iop_flags(iop);
expected_flags = LIBIO_FLAGS_REFERENCE_INC;
rtems_test_assert(flags == expected_flags);
rtems_libio_iop_drop(iop);
flags = rtems_libio_iop_flags(iop);
expected_flags = 0;
rtems_test_assert(flags == expected_flags);
switch (ac) {
case ACTION_CLOSE:
rtems_test_assert(rtems_libio_iop_is_free(iop));
default:
break;
}
rv = close(ctx->fd);
if (ac == ACTION_CLOSE) {
rtems_test_assert(rv == -1);
rtems_test_assert(errno == EBADF);
} else {
rtems_test_assert(rv == 0);
rtems_test_assert(iops_free == free_iops());
switch (ac) {
case ACTION_CLOSE:
case ACTION_CLOSE_BUSY:
rtems_test_assert(rv == -1);
rtems_test_assert(errno == EBADF);
break;
default:
rtems_test_assert(rv == 0);
break;
}
}
@@ -526,21 +561,81 @@ static void test_close(test_context *ctx)
rv = unlink(path);
rtems_test_assert(rv == 0);
rtems_test_assert(ctx->close_count == 17);
rtems_test_assert(ctx->close_count == 18);
rtems_test_assert(ctx->fcntl_count == 1);
rtems_test_assert(ctx->fdatasync_count == 1);
rtems_test_assert(ctx->fstat_count == 42);
rtems_test_assert(ctx->fstat_count == 45);
rtems_test_assert(ctx->fsync_count == 1);
rtems_test_assert(ctx->ftruncate_count == 1);
rtems_test_assert(ctx->ioctl_count == 1);
rtems_test_assert(ctx->lseek_count == 1);
rtems_test_assert(ctx->open_count == 17);
rtems_test_assert(ctx->open_count == 18);
rtems_test_assert(ctx->read_count == 1);
rtems_test_assert(ctx->readv_count == 1);
rtems_test_assert(ctx->write_count == 1);
rtems_test_assert(ctx->writev_count == 1);
}
static void test_iop(test_context *ctx) {
const size_t iops_free = free_iops();
rtems_libio_t *iop;
rtems_libio_t *iop2;
unsigned int flags;
unsigned int expected;
/* test allocatior */
iop = rtems_libio_allocate();
rtems_test_assert(iop != NULL);
rtems_test_assert(iop->flags == 0);
iop2 = rtems_libio_allocate();
rtems_test_assert(iop2 != NULL);
rtems_test_assert(rtems_libio_allocate() == NULL);
rtems_libio_free(iop2);
rtems_test_assert(iop2->flags == LIBIO_FLAGS_FREE);
/* test flags, flag set/clear and bit tests */
rtems_test_assert(!rtems_libio_iop_is_open(iop));
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_OPEN);
rtems_test_assert(rtems_libio_iop_is_open(iop));
rtems_test_assert(!rtems_libio_iop_is_no_delay(iop));
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_NO_DELAY);
rtems_test_assert(rtems_libio_iop_is_no_delay(iop));
rtems_test_assert(!rtems_libio_iop_is_readable(iop));
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_READ);
rtems_test_assert(rtems_libio_iop_is_readable(iop));
rtems_test_assert(!rtems_libio_iop_is_writeable(iop));
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_WRITE);
rtems_test_assert(rtems_libio_iop_is_writeable(iop));
rtems_test_assert(!rtems_libio_iop_is_append(iop));
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_APPEND);
rtems_test_assert(rtems_libio_iop_is_append(iop));
/* test hold and drop and if drop frees the iop */
expected =
LIBIO_FLAGS_OPEN | LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_READ |
LIBIO_FLAGS_WRITE | LIBIO_FLAGS_APPEND;
flags = rtems_libio_iop_flags(iop);
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
rtems_test_assert((flags & LIBIO_FLAGS_REFERENCE_MASK) == 0);
flags = rtems_libio_iop_hold(iop);
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
flags = rtems_libio_iop_flags(iop);
rtems_test_assert(
(flags & LIBIO_FLAGS_REFERENCE_MASK) == LIBIO_FLAGS_REFERENCE_INC);
rtems_libio_free(iop);
flags = rtems_libio_iop_flags(iop);
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
rtems_test_assert(
(flags & LIBIO_FLAGS_REFERENCE_MASK) == LIBIO_FLAGS_REFERENCE_INC);
rtems_libio_iop_drop(iop);
flags = rtems_libio_iop_flags(iop);
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
rtems_libio_iop_flags_clear(iop, LIBIO_FLAGS_OPEN);
rtems_libio_iop_hold(iop);
rtems_libio_iop_drop(iop);
flags = rtems_libio_iop_flags(iop);
rtems_test_assert(flags == LIBIO_FLAGS_FREE);
rtems_test_assert(iops_free == free_iops());
}
static void test_tmpfile(test_context *ctx)
{
rtems_resource_snapshot before;
@@ -566,6 +661,7 @@ static void test_tmpfile(test_context *ctx)
static void Init(rtems_task_argument arg)
{
TEST_BEGIN();
test_iop(&test_instance);
test_close(&test_instance);
test_tmpfile(&test_instance);
TEST_END();

View File

@@ -35,7 +35,7 @@
#define FS_PASS() do {puts("PASS");} while (0)
#define FS_FAIL() do {\
printf( "FAIL %s: %d \n", __FILE__, __LINE__ );\
printf( "FAIL errno=%s %s: %d \n", strerror(errno), __FILE__, __LINE__ );\
fs_test_notify_failure(); \
} while (0)