diff options
author | Alexander Graf <agraf@suse.de> | 2014-07-13 22:31:53 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-09-08 12:50:52 +0200 |
commit | b981289c493c7ddabc1cdf7de99daa24642c7739 (patch) | |
tree | 1e239e4f64e013f67057eebe2ca4ca9ed360a2ca /hw/misc/macio/cuda.c | |
parent | caae6c961107c4c55731a86572f9a1f53837636b (diff) |
PPC: Cuda: Use cuda timer to expose tbfreq to guest
Mac OS X calibrates a number of frequencies on bootup based on reading
tb values on bootup and comparing them to via cuda timer values.
The only variable we can really steer well (thanks to KVM) is the cuda
frequency. So let's use that one to fake Mac OS X into believing the
bus frequency is tbfreq * 4. That way Mac OS X will automatically
calculate the correct timebase frequency.
With this patch and the patch set I posted earlier I can successfully
run Mac OS X 10.2, 10.3 and 10.4 guests with -M mac99 on TCG and KVM.
Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/misc/macio/cuda.c')
-rw-r--r-- | hw/misc/macio/cuda.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index ff6051defe..b4273aa171 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -123,13 +123,22 @@ static void cuda_update_irq(CUDAState *s) } } +static uint64_t get_tb(uint64_t freq) +{ + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + freq, get_ticks_per_sec()); +} + static unsigned int get_counter(CUDATimer *s) { int64_t d; unsigned int counter; + uint64_t tb_diff; + + /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */ + tb_diff = get_tb(s->frequency) - s->load_time; + d = (tb_diff * 0xBF401675E5DULL) / (s->frequency << 24); - d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->load_time, - CUDA_TIMER_FREQ, get_ticks_per_sec()); if (s->index == 0) { /* the timer goes down from latch to -1 (period of latch + 2) */ if (d <= (s->counter_value + 1)) { @@ -147,7 +156,7 @@ static unsigned int get_counter(CUDATimer *s) static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) { CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val); - ti->load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ti->load_time = get_tb(s->frequency); ti->counter_value = val; cuda_timer_update(s, ti, ti->load_time); } @@ -688,6 +697,8 @@ static void cuda_realizefn(DeviceState *dev, Error **errp) struct tm tm; s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s); + s->timers[0].frequency = s->frequency; + s->timers[1].frequency = s->frequency; qemu_get_timedate(&tm, 0); s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; @@ -713,6 +724,11 @@ static void cuda_initfn(Object *obj) DEVICE(obj), "adb.0"); } +static Property cuda_properties[] = { + DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0), + DEFINE_PROP_END_OF_LIST() +}; + static void cuda_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -720,6 +736,7 @@ static void cuda_class_init(ObjectClass *oc, void *data) dc->realize = cuda_realizefn; dc->reset = cuda_reset; dc->vmsd = &vmstate_cuda; + dc->props = cuda_properties; } static const TypeInfo cuda_type_info = { |