Skip to content

Conversation

segfauIt
Copy link
Contributor

@segfauIt segfauIt commented Oct 9, 2025

Currently, interrupt manipulations are completed by several instructions. For example,

void
push_off(void)
{
  int old = intr_get(); => csrr    a5, sstatus
                           mv      s1, a5
  intr_off();           => csrr    a5, sstatus
                           andi    a5, a5, -3
                           csrw    sstatus, a5
  ...                      ^^^^^^^^^^^^^^^^^^^
}                          At this point, interrupts are actually
                           disabled; before this, the CPU can still
                           be interrupted.

This commit uses the CSR set, clear and read-clear instructions to make interrupt manipulation more efficient and reliable.

Reference:
https://elixir.bootlin.com/linux/v6.15/source/arch/riscv/include/asm/irqflags.h#L18-L34 https://riscv.github.io/riscv-isa-manual/snapshot/unprivileged/#csrinsts

Currently, interrupt manipulations are completed by several
instructions. For example,

void
push_off(void)
{
  int old = intr_get(); => csrr    a5, sstatus
                           mv      s1, a5
  intr_off();           => csrr    a5, sstatus
                           andi    a5, a5, -3
                           csrw    sstatus, a5
  ...                      ^^^^^^^^^^^^^^^^^^^
}                          At this point, interrupts are actually
                           disabled; before this, the CPU can still
                           be interrupted.

This commit uses the CSR set, clear and read-clear instructions to
make interrupt manipulation more efficient and reliable.

Reference:
https://elixir.bootlin.com/linux/v6.15/source/arch/riscv/include/asm/irqflags.h#L18-L34
https://riscv.github.io/riscv-isa-manual/snapshot/unprivileged/#csrinsts
When bit 32 in flags is set and we attempt to test that bit, the
right-hand expression result in 4294967296UL.

According to the ANSI C standard, assigning 4294967296UL to a 32-bit
signed integer variable is implementation-defined behavior.

Therefore, according to the GCC manual, 4294967296 will be modulo
2^32 and then stored in a 32-bit signed integer variable.

However, 4294967296 modulo 2^32 equals 0, which conflicts with the
fact that "bit 32 in flags is set".

This commit uses the "bang-bang" common C idiom for mapping integers
to [0,1].

Reference:
https://port70.net/~nsz/c/c89/c89-draft.html#3.2.1.2
When an integer is demoted to a signed integer with smaller size, or
an unsigned integer is converted to its corresponding signed integer,
if the value cannot be represented the result is implementation-defined.

https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
The result of, or the signal raised by, converting an integer to a
signed integer type when the value cannot be represented in an object
of that type (C90 6.2.1.2, C99 and C11 6.3.1.3, C23 6.3.2.3).
For conversion to a type of width N, the value is reduced modulo 2^N
to be within range of the type; no signal is raised.

https://en.cppreference.com/w/c/language/operator_logical.html#Logical_NOT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant