mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
hw/timer/hpet: Reorganize register decoding
For Rust HPET, since the commit 519088b7cf
("rust: hpet: decode HPET
registers into enums"), it decodes register address by checking if the
register belongs to global register space. And for C HPET, it checks
timer register space first.
While both approaches are fine, it's best to be as consistent as
possible.
Synchronize changes from the rust side to C side.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250520152750.2542612-2-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
ddc25eb404
commit
d74169e09e
1 changed files with 84 additions and 82 deletions
166
hw/timer/hpet.c
166
hw/timer/hpet.c
|
@ -426,30 +426,11 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
uint64_t cur_tick;
|
||||
|
||||
trace_hpet_ram_read(addr);
|
||||
addr &= ~4;
|
||||
|
||||
/*address range of all TN regs*/
|
||||
if (addr >= 0x100 && addr <= 0x3ff) {
|
||||
uint8_t timer_id = (addr - 0x100) / 0x20;
|
||||
HPETTimer *timer = &s->timer[timer_id];
|
||||
|
||||
if (timer_id > s->num_timers) {
|
||||
trace_hpet_timer_id_out_of_range(timer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (addr & 0x18) {
|
||||
case HPET_TN_CFG: // including interrupt capabilities
|
||||
return timer->config >> shift;
|
||||
case HPET_TN_CMP: // comparator register
|
||||
return timer->cmp >> shift;
|
||||
case HPET_TN_ROUTE:
|
||||
return timer->fsb >> shift;
|
||||
default:
|
||||
trace_hpet_ram_read_invalid();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (addr & ~4) {
|
||||
/*address range of all global regs*/
|
||||
if (addr <= 0xff) {
|
||||
switch (addr) {
|
||||
case HPET_ID: // including HPET_PERIOD
|
||||
return s->capability >> shift;
|
||||
case HPET_CFG:
|
||||
|
@ -468,6 +449,26 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
trace_hpet_ram_read_invalid();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint8_t timer_id = (addr - 0x100) / 0x20;
|
||||
HPETTimer *timer = &s->timer[timer_id];
|
||||
|
||||
if (timer_id > s->num_timers) {
|
||||
trace_hpet_timer_id_out_of_range(timer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (addr & 0x1f) {
|
||||
case HPET_TN_CFG: // including interrupt capabilities
|
||||
return timer->config >> shift;
|
||||
case HPET_TN_CMP: // comparator register
|
||||
return timer->cmp >> shift;
|
||||
case HPET_TN_ROUTE:
|
||||
return timer->fsb >> shift;
|
||||
default:
|
||||
trace_hpet_ram_read_invalid();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -482,9 +483,67 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
uint64_t old_val, new_val, cleared;
|
||||
|
||||
trace_hpet_ram_write(addr, value);
|
||||
addr &= ~4;
|
||||
|
||||
/*address range of all TN regs*/
|
||||
if (addr >= 0x100 && addr <= 0x3ff) {
|
||||
/*address range of all global regs*/
|
||||
if (addr <= 0xff) {
|
||||
switch (addr) {
|
||||
case HPET_ID:
|
||||
return;
|
||||
case HPET_CFG:
|
||||
old_val = s->config;
|
||||
new_val = deposit64(old_val, shift, len, value);
|
||||
new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
|
||||
s->config = new_val;
|
||||
if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
|
||||
/* Enable main counter and interrupt generation. */
|
||||
s->hpet_offset =
|
||||
ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
for (i = 0; i < s->num_timers; i++) {
|
||||
if (timer_enabled(&s->timer[i]) && (s->isr & (1 << i))) {
|
||||
update_irq(&s->timer[i], 1);
|
||||
}
|
||||
hpet_set_timer(&s->timer[i]);
|
||||
}
|
||||
} else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
|
||||
/* Halt main counter and disable interrupt generation. */
|
||||
s->hpet_counter = hpet_get_ticks(s);
|
||||
for (i = 0; i < s->num_timers; i++) {
|
||||
hpet_del_timer(&s->timer[i]);
|
||||
}
|
||||
}
|
||||
/* i8254 and RTC output pins are disabled
|
||||
* when HPET is in legacy mode */
|
||||
if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
|
||||
qemu_set_irq(s->pit_enabled, 0);
|
||||
qemu_irq_lower(s->irqs[0]);
|
||||
qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
|
||||
} else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
|
||||
qemu_irq_lower(s->irqs[0]);
|
||||
qemu_set_irq(s->pit_enabled, 1);
|
||||
qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
|
||||
}
|
||||
break;
|
||||
case HPET_STATUS:
|
||||
new_val = value << shift;
|
||||
cleared = new_val & s->isr;
|
||||
for (i = 0; i < s->num_timers; i++) {
|
||||
if (cleared & (1 << i)) {
|
||||
update_irq(&s->timer[i], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HPET_COUNTER:
|
||||
if (hpet_enabled(s)) {
|
||||
trace_hpet_ram_write_counter_write_while_enabled();
|
||||
}
|
||||
s->hpet_counter = deposit64(s->hpet_counter, shift, len, value);
|
||||
break;
|
||||
default:
|
||||
trace_hpet_ram_write_invalid();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint8_t timer_id = (addr - 0x100) / 0x20;
|
||||
HPETTimer *timer = &s->timer[timer_id];
|
||||
|
||||
|
@ -550,63 +609,6 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
break;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
switch (addr & ~4) {
|
||||
case HPET_ID:
|
||||
return;
|
||||
case HPET_CFG:
|
||||
old_val = s->config;
|
||||
new_val = deposit64(old_val, shift, len, value);
|
||||
new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
|
||||
s->config = new_val;
|
||||
if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
|
||||
/* Enable main counter and interrupt generation. */
|
||||
s->hpet_offset =
|
||||
ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
for (i = 0; i < s->num_timers; i++) {
|
||||
if (timer_enabled(&s->timer[i]) && (s->isr & (1 << i))) {
|
||||
update_irq(&s->timer[i], 1);
|
||||
}
|
||||
hpet_set_timer(&s->timer[i]);
|
||||
}
|
||||
} else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
|
||||
/* Halt main counter and disable interrupt generation. */
|
||||
s->hpet_counter = hpet_get_ticks(s);
|
||||
for (i = 0; i < s->num_timers; i++) {
|
||||
hpet_del_timer(&s->timer[i]);
|
||||
}
|
||||
}
|
||||
/* i8254 and RTC output pins are disabled
|
||||
* when HPET is in legacy mode */
|
||||
if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
|
||||
qemu_set_irq(s->pit_enabled, 0);
|
||||
qemu_irq_lower(s->irqs[0]);
|
||||
qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
|
||||
} else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
|
||||
qemu_irq_lower(s->irqs[0]);
|
||||
qemu_set_irq(s->pit_enabled, 1);
|
||||
qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
|
||||
}
|
||||
break;
|
||||
case HPET_STATUS:
|
||||
new_val = value << shift;
|
||||
cleared = new_val & s->isr;
|
||||
for (i = 0; i < s->num_timers; i++) {
|
||||
if (cleared & (1 << i)) {
|
||||
update_irq(&s->timer[i], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HPET_COUNTER:
|
||||
if (hpet_enabled(s)) {
|
||||
trace_hpet_ram_write_counter_write_while_enabled();
|
||||
}
|
||||
s->hpet_counter = deposit64(s->hpet_counter, shift, len, value);
|
||||
break;
|
||||
default:
|
||||
trace_hpet_ram_write_invalid();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue