Skip to content

Commit

Permalink
fix: asan/ubsan complaints
Browse files Browse the repository at this point in the history
  • Loading branch information
VisualEhrmanntraut committed Feb 8, 2025
1 parent 34c48e5 commit 79c0557
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 35 deletions.
7 changes: 4 additions & 3 deletions hw/arm/apple-silicon/sart.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ struct AppleSARTState {
uint32_t reg[0x8000 / sizeof(uint32_t)];
};

static inline uint64_t sart_get_reg(AppleSARTState *s, uint32_t offset)
static inline uint32_t sart_get_reg(AppleSARTState *s, uint32_t offset)
{
// TODO: ASAN complains about uint64_t*, wants uint32_t*
return *(uint64_t *)((char *)s->reg + offset);
g_assert_cmphex(offset + sizeof(uint32_t), <=, sizeof(s->reg));
g_assert_cmphex(offset % sizeof(uint32_t), ==, 0);
return s->reg[offset / sizeof(uint32_t)];
}

static inline hwaddr sart_get_region_addr(AppleSARTState *s, int region)
Expand Down
16 changes: 0 additions & 16 deletions hw/gpio/apple_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,6 @@
#define CFG_FUNC1 (INPUT_ENABLE | FUNC_ALT1 | INT_MASKED)
#define CFG_FUNC2 (INPUT_ENABLE | FUNC_ALT2 | INT_MASKED)

static inline unsigned long find_first_bit32(const uint32_t *addr,
unsigned long size)
{
unsigned long result, tmp;

for (result = 0; result < size;
result += (BITS_PER_BYTE * sizeof(uint32_t))) {
tmp = *addr++;
if (tmp) {
result += ctz32(tmp);
return result < size ? result : size;
}
}
return size;
}

static void apple_gpio_update_pincfg(AppleGPIOState *s, int pin, uint32_t value)
{
if ((value & INT_MASKED) != INT_MASKED) {
Expand Down
29 changes: 13 additions & 16 deletions hw/intc/apple_aic.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,12 @@ static void apple_aic_update(AppleAICState *s)
}

i = -1;
while ((i = find_next_bit((unsigned long *)s->eir_state, s->numIRQ,
i + 1)) < s->numIRQ) {
while ((i = find_next_bit32(s->eir_state, s->numIRQ, i + 1)) < s->numIRQ) {
int dest;
if ((test_bit(i, (unsigned long *)s->eir_mask) == 0) &&
(dest = s->eir_dest[i])) {
if ((test_bit32(i, s->eir_mask) == 0) && (dest = s->eir_dest[i])) {
if (((intr & dest) == 0)) {
/* The interrupt doesn't have a cpu that can process it yet */
uint32_t cpu =
find_first_bit((unsigned long *)&s->eir_dest[i], s->numCPU);
uint32_t cpu = find_first_bit32(&s->eir_dest[i], s->numCPU);
intr |= (1 << cpu);
potential |= dest;
} else {
Expand Down Expand Up @@ -177,9 +174,9 @@ static void apple_aic_set_irq(void *opaque, int irq, int level)

trace_aic_set_irq(irq, level);
if (level) {
set_bit(irq, (unsigned long *)s->eir_state);
set_bit32(irq, s->eir_state);
} else {
clear_bit(irq, (unsigned long *)s->eir_state);
clear_bit32(irq, s->eir_state);
}
}

Expand Down Expand Up @@ -238,7 +235,7 @@ static void apple_aic_write(void *opaque, hwaddr addr, uint64_t data,

for (i = 0; i < s->numCPU; i++) {
if (val & (1 << i)) {
set_bit(o->cpu_id, (unsigned long *)&s->cpus[i].pendingIPI);
set_bit32(o->cpu_id, &s->cpus[i].pendingIPI);
if (~s->cpus[i].ipi_mask & AIC_IPI_NORMAL) {
qemu_irq_raise(s->cpus[i].irq);
}
Expand All @@ -258,7 +255,7 @@ static void apple_aic_write(void *opaque, hwaddr addr, uint64_t data,

for (i = 0; i < s->numCPU; i++) {
if (val & (1 << i)) {
clear_bit(o->cpu_id, (unsigned long *)&s->cpus[i].pendingIPI);
clear_bit32(o->cpu_id, &s->cpus[i].pendingIPI);
}
}

Expand All @@ -278,7 +275,7 @@ static void apple_aic_write(void *opaque, hwaddr addr, uint64_t data,

for (i = 0; i < s->numCPU; i++) {
if (val & (1 << i)) {
set_bit(o->cpu_id, (unsigned long *)&s->cpus[i].deferredIPI);
set_bit32(o->cpu_id, &s->cpus[i].deferredIPI);
}
}

Expand All @@ -292,7 +289,7 @@ static void apple_aic_write(void *opaque, hwaddr addr, uint64_t data,

for (i = 0; i < s->numCPU; i++) {
if (val & (1 << i)) {
clear_bit(o->cpu_id, (unsigned long *)&s->cpus[i].deferredIPI);
clear_bit32(o->cpu_id, &s->cpus[i].deferredIPI);
}
}

Expand Down Expand Up @@ -408,11 +405,11 @@ static uint64_t apple_aic_read(void *opaque, hwaddr addr, unsigned size)
}

i = -1;
while ((i = find_next_bit((unsigned long *)s->eir_state, s->numIRQ,
i + 1)) < s->numIRQ) {
if (test_bit(i, (unsigned long *)s->eir_mask) == 0) {
while ((i = find_next_bit32(s->eir_state, s->numIRQ, i + 1)) <
s->numIRQ) {
if (test_bit32(i, s->eir_mask) == 0) {
if (s->eir_dest[i] & (1 << o->cpu_id)) {
set_bit(i, (unsigned long *)s->eir_mask);
set_bit32(i, s->eir_mask);
return kAIC_INT_EXT | AIC_INT_EXTID(i);
}
}
Expand Down
19 changes: 19 additions & 0 deletions include/qemu/bitops.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "atomic.h"

#define BITS_PER_BYTE CHAR_BIT
#define BITS_PER_INT (sizeof (unsigned int) * BITS_PER_BYTE)
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define BITS_TO_U32S(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t))
Expand Down Expand Up @@ -382,6 +383,24 @@ static inline int test_bit32(long nr, const uint32_t *addr)
return 1U & (addr[BIT32_WORD(nr)] >> (nr & 31));
}

unsigned long find_next_bit32(const unsigned int *addr, unsigned long size,
unsigned long offset);

static inline unsigned long find_first_bit32(const uint32_t *addr,
unsigned long size)
{
unsigned long result, tmp;

for (result = 0; result < size; result += BITS_PER_INT) {
tmp = *addr++;
if (tmp) {
result += ctz32(tmp);
return result < size ? result : size;
}
}
return size;
}

/**
* DOC: Miscellaneous bit operations on single values
*
Expand Down
61 changes: 61 additions & 0 deletions util/bitops.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,67 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
return result + ctzl(tmp);
}

unsigned long find_next_bit32(const unsigned int *addr, unsigned long size,
unsigned long offset)
{
const unsigned int *p = addr + BIT32_WORD(offset);
unsigned long result = offset & ~(BITS_PER_INT-1);
unsigned long tmp;

if (offset >= size) {
return size;
}
size -= result;
offset %= BITS_PER_INT;
if (offset) {
tmp = *(p++);
tmp &= (~0UL << offset);
if (size < BITS_PER_INT) {
goto found_first;
}
if (tmp) {
goto found_middle;
}
size -= BITS_PER_INT;
result += BITS_PER_INT;
}
while (size >= 4*BITS_PER_INT) {
unsigned int d1, d2, d3;
tmp = *p;
d1 = *(p+1);
d2 = *(p+2);
d3 = *(p+3);
if (tmp) {
goto found_middle;
}
if (d1 | d2 | d3) {
break;
}
p += 4;
result += 4*BITS_PER_INT;
size -= 4*BITS_PER_INT;
}
while (size >= BITS_PER_INT) {
if ((tmp = *(p++))) {
goto found_middle;
}
result += BITS_PER_INT;
size -= BITS_PER_INT;
}
if (!size) {
return result;
}
tmp = *p;

found_first:
tmp &= (~0UL >> (BITS_PER_INT - size));
if (tmp == 0UL) { /* Are any bits set? */
return result + size; /* Nope. */
}
found_middle:
return result + ctz32(tmp);
}

/*
* This implementation of find_{first,next}_zero_bit was stolen from
* Linus' asm-alpha/bitops.h.
Expand Down

0 comments on commit 79c0557

Please sign in to comment.