diff options
Diffstat (limited to 'hw/core')
-rw-r--r-- | hw/core/clock-vmstate.c | 40 | ||||
-rw-r--r-- | hw/core/clock.c | 31 | ||||
-rw-r--r-- | hw/core/machine.c | 3 | ||||
-rw-r--r-- | hw/core/trace-events | 1 |
4 files changed, 70 insertions, 5 deletions
diff --git a/hw/core/clock-vmstate.c b/hw/core/clock-vmstate.c index 260b13fc2c..9d9174ffbd 100644 --- a/hw/core/clock-vmstate.c +++ b/hw/core/clock-vmstate.c @@ -14,12 +14,50 @@ #include "migration/vmstate.h" #include "hw/clock.h" +static bool muldiv_needed(void *opaque) +{ + Clock *clk = opaque; + + return clk->multiplier != 1 || clk->divider != 1; +} + +static int clock_pre_load(void *opaque) +{ + Clock *clk = opaque; + /* + * The initial out-of-reset settings of the Clock might have been + * configured by the device to be different from what we set + * in clock_initfn(), so we must here set the default values to + * be used if they are not in the inbound migration state. + */ + clk->multiplier = 1; + clk->divider = 1; + + return 0; +} + +const VMStateDescription vmstate_muldiv = { + .name = "clock/muldiv", + .version_id = 1, + .minimum_version_id = 1, + .needed = muldiv_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT32(multiplier, Clock), + VMSTATE_UINT32(divider, Clock), + }, +}; + const VMStateDescription vmstate_clock = { .name = "clock", .version_id = 0, .minimum_version_id = 0, + .pre_load = clock_pre_load, .fields = (VMStateField[]) { VMSTATE_UINT64(period, Clock), VMSTATE_END_OF_LIST() - } + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_muldiv, + NULL + }, }; diff --git a/hw/core/clock.c b/hw/core/clock.c index fc5a99683f..916875e07a 100644 --- a/hw/core/clock.c +++ b/hw/core/clock.c @@ -64,6 +64,15 @@ bool clock_set(Clock *clk, uint64_t period) return true; } +static uint64_t clock_get_child_period(Clock *clk) +{ + /* + * Return the period to be used for child clocks, which is the parent + * clock period adjusted for for multiplier and divider effects. + */ + return muldiv64(clk->period, clk->multiplier, clk->divider); +} + static void clock_call_callback(Clock *clk, ClockEvent event) { /* @@ -78,15 +87,16 @@ static void clock_call_callback(Clock *clk, ClockEvent event) static void clock_propagate_period(Clock *clk, bool call_callbacks) { Clock *child; + uint64_t child_period = clock_get_child_period(clk); QLIST_FOREACH(child, &clk->children, sibling) { - if (child->period != clk->period) { + if (child->period != child_period) { if (call_callbacks) { clock_call_callback(child, ClockPreUpdate); } - child->period = clk->period; + child->period = child_period; trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk), - CLOCK_PERIOD_TO_HZ(clk->period), + CLOCK_PERIOD_TO_HZ(child->period), call_callbacks); if (call_callbacks) { clock_call_callback(child, ClockUpdate); @@ -110,7 +120,7 @@ void clock_set_source(Clock *clk, Clock *src) trace_clock_set_source(CLOCK_PATH(clk), CLOCK_PATH(src)); - clk->period = src->period; + clk->period = clock_get_child_period(src); QLIST_INSERT_HEAD(&src->children, clk, sibling); clk->source = src; clock_propagate_period(clk, false); @@ -133,10 +143,23 @@ char *clock_display_freq(Clock *clk) return freq_to_str(clock_get_hz(clk)); } +void clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider) +{ + assert(divider != 0); + + trace_clock_set_mul_div(CLOCK_PATH(clk), clk->multiplier, multiplier, + clk->divider, divider); + clk->multiplier = multiplier; + clk->divider = divider; +} + static void clock_initfn(Object *obj) { Clock *clk = CLOCK(obj); + clk->multiplier = 1; + clk->divider = 1; + QLIST_INIT(&clk->children); } diff --git a/hw/core/machine.c b/hw/core/machine.c index 54e040587d..067f42b528 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -37,6 +37,9 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" +GlobalProperty hw_compat_6_1[] = {}; +const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1); + GlobalProperty hw_compat_6_0[] = { { "gpex-pcihost", "allow-unmapped-accesses", "false" }, { "i8042", "extended-state", "false"}, diff --git a/hw/core/trace-events b/hw/core/trace-events index 360ddeb2c8..9b3ecce3b2 100644 --- a/hw/core/trace-events +++ b/hw/core/trace-events @@ -34,3 +34,4 @@ clock_disconnect(const char *clk) "'%s'" clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', %"PRIu64"Hz->%"PRIu64"Hz" clock_propagate(const char *clk) "'%s'" clock_update(const char *clk, const char *src, uint64_t hz, int cb) "'%s', src='%s', val=%"PRIu64"Hz cb=%d" +clock_set_mul_div(const char *clk, uint32_t oldmul, uint32_t mul, uint32_t olddiv, uint32_t div) "'%s', mul: %u -> %u, div: %u -> %u" |