mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-22 09:32:40 -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;
|
uint64_t cur_tick;
|
||||||
|
|
||||||
trace_hpet_ram_read(addr);
|
trace_hpet_ram_read(addr);
|
||||||
|
addr &= ~4;
|
||||||
|
|
||||||
/*address range of all TN regs*/
|
/*address range of all global regs*/
|
||||||
if (addr >= 0x100 && addr <= 0x3ff) {
|
if (addr <= 0xff) {
|
||||||
uint8_t timer_id = (addr - 0x100) / 0x20;
|
switch (addr) {
|
||||||
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) {
|
|
||||||
case HPET_ID: // including HPET_PERIOD
|
case HPET_ID: // including HPET_PERIOD
|
||||||
return s->capability >> shift;
|
return s->capability >> shift;
|
||||||
case HPET_CFG:
|
case HPET_CFG:
|
||||||
|
@ -468,6 +449,26 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
||||||
trace_hpet_ram_read_invalid();
|
trace_hpet_ram_read_invalid();
|
||||||
break;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -482,9 +483,67 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
||||||
uint64_t old_val, new_val, cleared;
|
uint64_t old_val, new_val, cleared;
|
||||||
|
|
||||||
trace_hpet_ram_write(addr, value);
|
trace_hpet_ram_write(addr, value);
|
||||||
|
addr &= ~4;
|
||||||
|
|
||||||
/*address range of all TN regs*/
|
/*address range of all global regs*/
|
||||||
if (addr >= 0x100 && addr <= 0x3ff) {
|
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;
|
uint8_t timer_id = (addr - 0x100) / 0x20;
|
||||||
HPETTimer *timer = &s->timer[timer_id];
|
HPETTimer *timer = &s->timer[timer_id];
|
||||||
|
|
||||||
|
@ -550,63 +609,6 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
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