~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/slavio_timer.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn, Serge Hallyn, Adam Conrad
  • Date: 2013-01-04 08:50:24 UTC
  • mfrom: (1.6.6) (10.1.29 sid)
  • Revision ID: package-import@ubuntu.com-20130104085024-k4mr3z3zzjxemww2
Tags: 1.2.0.dfsg-1~exp1-0ubuntu1
[ Serge Hallyn ]
* debian/control:
  - update maintainer
  - remove vde2 recommends
  - build-deps: remove libusbredir, libvdeplug2-dev,
    libspice-server-dev, libspice-protocol-dev, libiscsi-dev,
    and libxen-dev.
  - qemu-keymaps: break/replace qemu-common
  - qemu-system:
    - break/replace qemu-common
    - depend on udev
    - remove openbios-ppc, openbios-sparc, and openhackware from
      Depends.  (Intend to add them back once we can build them.)
    - provides: qemu-kvm
  - qemu-utils: break/replace qemu-kvm
  - set up transitional packages for qemu-kvm, qemu-common, and kvm.
* debian/rules:
  - install kvm-ifup and kvm-ifdown
  - dh_installinit the qemu-kvm upstart job
* install a 30-qemu-kvm.conf into /etc/sysctl.c for nr_hugepages.
* qemu-kvm.upstart:
  - add qemu-system.qemu-kvm.upstart
  - add mv_confile to qemu-system.preinst, postinst, and .postrm to rename
    /etc/init/qemu-kvm.conf to qemu-system.conf
  - debian/rules: add dh_installinit to get qemu-system.upstart installed.
  - take the defaults from the old qemu-kvm.defaults, and move them into
    the upstart job
* debian/patches:
  - apply gridcentric patches from lp:~amscanne/+junk/gridcentric-qemu-patches
  - apply arm patches from git://git.linaro.org/qemu/qemu-linaro.git
  - apply nbd-fixes-to-read-only-handling.patch from upstream to
    make read-write mount after read-only mount work.  (LP: #1077838)
* ifup/down:
  - copy Ubuntu qemu-kvm's kvm-ifup/down into debian/
  - fix dh_install for kvm-ifup/down in debian/rules
  - add links for qemu-ifup/down in qemu-system.links
  - remove (debian's original) qemu-ifup from qemu-system.install
* debian/qemu-system.postinst
  - udevadm trigger to fix up /dev/kvm perms
  - make the 'qemu' symlink point to qemu-system-x86_64, not -i386.
* debian/qemu-system.links:
  - point 'kvm' to qemu-system-x86_64
  - remove pxe-virtio, pxe-e1000 and pxe-rtl8139 links (which conflict
    with ones from kvm-ipxe).  We may want to move the links from kvm-ipxe
    back to qemu-system at some point.
  - add qemu-ifdown and qemu-ifup links
* debian/qemu-system.install:
  - remove /etc/qemu-ifup link
  - add /etc/sysctl.d/30-qemu-kvm.conf

[ Adam Conrad ]
* Appease apt-get's dist-upgrade resolver by creating a qemu-common
  transitional package to upgrade more gracefully to qemu-keymaps.
* Move all the empty transitional packages to the oldlibs section. 
* Restore the versioned dep from qemu-kvm (and kvm) to qemu-system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
22
 * THE SOFTWARE.
23
23
 */
24
 
#include "hw.h"
 
24
 
25
25
#include "sun4m.h"
26
26
#include "qemu-timer.h"
27
 
 
28
 
//#define DEBUG_TIMER
29
 
 
30
 
#ifdef DEBUG_TIMER
31
 
#define DPRINTF(fmt, args...) \
32
 
do { printf("TIMER: " fmt , ##args); } while (0)
33
 
#else
34
 
#define DPRINTF(fmt, args...) do {} while (0)
35
 
#endif
 
27
#include "ptimer.h"
 
28
#include "sysbus.h"
 
29
#include "trace.h"
36
30
 
37
31
/*
38
32
 * Registers of hardware timer in sun4m.
51
45
 
52
46
#define MAX_CPUS 16
53
47
 
54
 
typedef struct SLAVIO_TIMERState {
 
48
typedef struct CPUTimerState {
55
49
    qemu_irq irq;
56
50
    ptimer_state *timer;
57
51
    uint32_t count, counthigh, reached;
 
52
    /* processor only */
 
53
    uint32_t running;
58
54
    uint64_t limit;
59
 
    // processor only
60
 
    uint32_t running;
61
 
    struct SLAVIO_TIMERState *master;
62
 
    uint32_t slave_index;
63
 
    // system only
64
 
    uint32_t num_slaves;
65
 
    struct SLAVIO_TIMERState *slave[MAX_CPUS];
66
 
    uint32_t slave_mode;
 
55
} CPUTimerState;
 
56
 
 
57
typedef struct SLAVIO_TIMERState {
 
58
    SysBusDevice busdev;
 
59
    uint32_t num_cpus;
 
60
    uint32_t cputimer_mode;
 
61
    CPUTimerState cputimer[MAX_CPUS + 1];
67
62
} SLAVIO_TIMERState;
68
63
 
 
64
typedef struct TimerContext {
 
65
    MemoryRegion iomem;
 
66
    SLAVIO_TIMERState *s;
 
67
    unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
 
68
} TimerContext;
 
69
 
69
70
#define SYS_TIMER_SIZE 0x14
70
71
#define CPU_TIMER_SIZE 0x10
71
72
 
72
 
#define SYS_TIMER_OFFSET      0x10000ULL
73
 
#define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu)
74
 
 
75
73
#define TIMER_LIMIT         0
76
74
#define TIMER_COUNTER       1
77
75
#define TIMER_COUNTER_NORST 2
84
82
#define TIMER_MAX_COUNT32  0x7ffffe00ULL
85
83
#define TIMER_REACHED      0x80000000
86
84
#define TIMER_PERIOD       500ULL // 500ns
87
 
#define LIMIT_TO_PERIODS(l) ((l) >> 9)
88
 
#define PERIODS_TO_LIMIT(l) ((l) << 9)
 
85
#define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1)
 
86
#define PERIODS_TO_LIMIT(l) (((l) + 1) << 9)
89
87
 
90
 
static int slavio_timer_is_user(SLAVIO_TIMERState *s)
 
88
static int slavio_timer_is_user(TimerContext *tc)
91
89
{
92
 
    return s->master && (s->master->slave_mode & (1 << s->slave_index));
 
90
    SLAVIO_TIMERState *s = tc->s;
 
91
    unsigned int timer_index = tc->timer_index;
 
92
 
 
93
    return timer_index != 0 && (s->cputimer_mode & (1 << (timer_index - 1)));
93
94
}
94
95
 
95
96
// Update count, set irq, update expire_time
96
97
// Convert from ptimer countdown units
97
 
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
 
98
static void slavio_timer_get_out(CPUTimerState *t)
98
99
{
99
100
    uint64_t count, limit;
100
101
 
101
 
    if (s->limit == 0) /* free-run processor or system counter */
 
102
    if (t->limit == 0) { /* free-run system or processor counter */
102
103
        limit = TIMER_MAX_COUNT32;
103
 
    else
104
 
        limit = s->limit;
105
 
 
106
 
    if (s->timer)
107
 
        count = limit - PERIODS_TO_LIMIT(ptimer_get_count(s->timer));
108
 
    else
109
 
        count = 0;
110
 
 
111
 
    DPRINTF("get_out: limit %" PRIx64 " count %x%08x\n", s->limit,
112
 
            s->counthigh, s->count);
113
 
    s->count = count & TIMER_COUNT_MASK32;
114
 
    s->counthigh = count >> 32;
 
104
    } else {
 
105
        limit = t->limit;
 
106
    }
 
107
    count = limit - PERIODS_TO_LIMIT(ptimer_get_count(t->timer));
 
108
 
 
109
    trace_slavio_timer_get_out(t->limit, t->counthigh, t->count);
 
110
    t->count = count & TIMER_COUNT_MASK32;
 
111
    t->counthigh = count >> 32;
115
112
}
116
113
 
117
114
// timer callback
118
115
static void slavio_timer_irq(void *opaque)
119
116
{
120
 
    SLAVIO_TIMERState *s = opaque;
 
117
    TimerContext *tc = opaque;
 
118
    SLAVIO_TIMERState *s = tc->s;
 
119
    CPUTimerState *t = &s->cputimer[tc->timer_index];
121
120
 
122
 
    slavio_timer_get_out(s);
123
 
    DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
124
 
    s->reached = TIMER_REACHED;
125
 
    if (!slavio_timer_is_user(s))
126
 
        qemu_irq_raise(s->irq);
 
121
    slavio_timer_get_out(t);
 
122
    trace_slavio_timer_irq(t->counthigh, t->count);
 
123
    /* if limit is 0 (free-run), there will be no match */
 
124
    if (t->limit != 0) {
 
125
        t->reached = TIMER_REACHED;
 
126
    }
 
127
    /* there is no interrupt if user timer or free-run */
 
128
    if (!slavio_timer_is_user(tc) && t->limit != 0) {
 
129
        qemu_irq_raise(t->irq);
 
130
    }
127
131
}
128
132
 
129
 
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
 
133
static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr,
 
134
                                       unsigned size)
130
135
{
131
 
    SLAVIO_TIMERState *s = opaque;
 
136
    TimerContext *tc = opaque;
 
137
    SLAVIO_TIMERState *s = tc->s;
132
138
    uint32_t saddr, ret;
 
139
    unsigned int timer_index = tc->timer_index;
 
140
    CPUTimerState *t = &s->cputimer[timer_index];
133
141
 
134
142
    saddr = addr >> 2;
135
143
    switch (saddr) {
136
144
    case TIMER_LIMIT:
137
145
        // read limit (system counter mode) or read most signifying
138
146
        // part of counter (user mode)
139
 
        if (slavio_timer_is_user(s)) {
 
147
        if (slavio_timer_is_user(tc)) {
140
148
            // read user timer MSW
141
 
            slavio_timer_get_out(s);
142
 
            ret = s->counthigh | s->reached;
 
149
            slavio_timer_get_out(t);
 
150
            ret = t->counthigh | t->reached;
143
151
        } else {
144
152
            // read limit
145
153
            // clear irq
146
 
            qemu_irq_lower(s->irq);
147
 
            s->reached = 0;
148
 
            ret = s->limit & TIMER_LIMIT_MASK32;
 
154
            qemu_irq_lower(t->irq);
 
155
            t->reached = 0;
 
156
            ret = t->limit & TIMER_LIMIT_MASK32;
149
157
        }
150
158
        break;
151
159
    case TIMER_COUNTER:
152
160
        // read counter and reached bit (system mode) or read lsbits
153
161
        // of counter (user mode)
154
 
        slavio_timer_get_out(s);
155
 
        if (slavio_timer_is_user(s)) // read user timer LSW
156
 
            ret = s->count & TIMER_MAX_COUNT64;
157
 
        else // read limit
158
 
            ret = (s->count & TIMER_MAX_COUNT32) | s->reached;
 
162
        slavio_timer_get_out(t);
 
163
        if (slavio_timer_is_user(tc)) { // read user timer LSW
 
164
            ret = t->count & TIMER_MAX_COUNT64;
 
165
        } else { // read limit
 
166
            ret = (t->count & TIMER_MAX_COUNT32) |
 
167
                t->reached;
 
168
        }
159
169
        break;
160
170
    case TIMER_STATUS:
161
171
        // only available in processor counter/timer
162
172
        // read start/stop status
163
 
        ret = s->running;
 
173
        if (timer_index > 0) {
 
174
            ret = t->running;
 
175
        } else {
 
176
            ret = 0;
 
177
        }
164
178
        break;
165
179
    case TIMER_MODE:
166
180
        // only available in system counter
167
181
        // read user/system mode
168
 
        ret = s->slave_mode;
 
182
        ret = s->cputimer_mode;
169
183
        break;
170
184
    default:
171
 
        DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
 
185
        trace_slavio_timer_mem_readl_invalid(addr);
172
186
        ret = 0;
173
187
        break;
174
188
    }
175
 
    DPRINTF("read " TARGET_FMT_plx " = %08x\n", addr, ret);
176
 
 
 
189
    trace_slavio_timer_mem_readl(addr, ret);
177
190
    return ret;
178
191
}
179
192
 
180
193
static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
181
 
                                    uint32_t val)
 
194
                                    uint64_t val, unsigned size)
182
195
{
183
 
    SLAVIO_TIMERState *s = opaque;
 
196
    TimerContext *tc = opaque;
 
197
    SLAVIO_TIMERState *s = tc->s;
184
198
    uint32_t saddr;
 
199
    unsigned int timer_index = tc->timer_index;
 
200
    CPUTimerState *t = &s->cputimer[timer_index];
185
201
 
186
 
    DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
 
202
    trace_slavio_timer_mem_writel(addr, val);
187
203
    saddr = addr >> 2;
188
204
    switch (saddr) {
189
205
    case TIMER_LIMIT:
190
 
        if (slavio_timer_is_user(s)) {
 
206
        if (slavio_timer_is_user(tc)) {
191
207
            uint64_t count;
192
208
 
193
209
            // set user counter MSW, reset counter
194
 
            s->limit = TIMER_MAX_COUNT64;
195
 
            s->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
196
 
            s->reached = 0;
197
 
            count = ((uint64_t)s->counthigh << 32) | s->count;
198
 
            DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
199
 
                    count);
200
 
            if (s->timer)
201
 
                ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
 
210
            t->limit = TIMER_MAX_COUNT64;
 
211
            t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
 
212
            t->reached = 0;
 
213
            count = ((uint64_t)t->counthigh << 32) | t->count;
 
214
            trace_slavio_timer_mem_writel_limit(timer_index, count);
 
215
            ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
202
216
        } else {
203
217
            // set limit, reset counter
204
 
            qemu_irq_lower(s->irq);
205
 
            s->limit = val & TIMER_MAX_COUNT32;
206
 
            if (s->timer) {
207
 
                if (s->limit == 0) /* free-run */
208
 
                    ptimer_set_limit(s->timer,
 
218
            qemu_irq_lower(t->irq);
 
219
            t->limit = val & TIMER_MAX_COUNT32;
 
220
            if (t->timer) {
 
221
                if (t->limit == 0) { /* free-run */
 
222
                    ptimer_set_limit(t->timer,
209
223
                                     LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
210
 
                else
211
 
                    ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
 
224
                } else {
 
225
                    ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
 
226
                }
212
227
            }
213
228
        }
214
229
        break;
215
230
    case TIMER_COUNTER:
216
 
        if (slavio_timer_is_user(s)) {
 
231
        if (slavio_timer_is_user(tc)) {
217
232
            uint64_t count;
218
233
 
219
234
            // set user counter LSW, reset counter
220
 
            s->limit = TIMER_MAX_COUNT64;
221
 
            s->count = val & TIMER_MAX_COUNT64;
222
 
            s->reached = 0;
223
 
            count = ((uint64_t)s->counthigh) << 32 | s->count;
224
 
            DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
225
 
                    count);
226
 
            if (s->timer)
227
 
                ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
228
 
        } else
229
 
            DPRINTF("not user timer\n");
 
235
            t->limit = TIMER_MAX_COUNT64;
 
236
            t->count = val & TIMER_MAX_COUNT64;
 
237
            t->reached = 0;
 
238
            count = ((uint64_t)t->counthigh) << 32 | t->count;
 
239
            trace_slavio_timer_mem_writel_limit(timer_index, count);
 
240
            ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
 
241
        } else {
 
242
            trace_slavio_timer_mem_writel_counter_invalid();
 
243
        }
230
244
        break;
231
245
    case TIMER_COUNTER_NORST:
232
246
        // set limit without resetting counter
233
 
        s->limit = val & TIMER_MAX_COUNT32;
234
 
        if (s->timer) {
235
 
            if (s->limit == 0)  /* free-run */
236
 
                ptimer_set_limit(s->timer,
237
 
                                 LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
238
 
            else
239
 
                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
 
247
        t->limit = val & TIMER_MAX_COUNT32;
 
248
        if (t->limit == 0) { /* free-run */
 
249
            ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
 
250
        } else {
 
251
            ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
240
252
        }
241
253
        break;
242
254
    case TIMER_STATUS:
243
 
        if (slavio_timer_is_user(s)) {
 
255
        if (slavio_timer_is_user(tc)) {
244
256
            // start/stop user counter
245
 
            if ((val & 1) && !s->running) {
246
 
                DPRINTF("processor %d user timer started\n", s->slave_index);
247
 
                if (s->timer)
248
 
                    ptimer_run(s->timer, 0);
249
 
                s->running = 1;
250
 
            } else if (!(val & 1) && s->running) {
251
 
                DPRINTF("processor %d user timer stopped\n", s->slave_index);
252
 
                if (s->timer)
253
 
                    ptimer_stop(s->timer);
254
 
                s->running = 0;
 
257
            if ((val & 1) && !t->running) {
 
258
                trace_slavio_timer_mem_writel_status_start(timer_index);
 
259
                ptimer_run(t->timer, 0);
 
260
                t->running = 1;
 
261
            } else if (!(val & 1) && t->running) {
 
262
                trace_slavio_timer_mem_writel_status_stop(timer_index);
 
263
                ptimer_stop(t->timer);
 
264
                t->running = 0;
255
265
            }
256
266
        }
257
267
        break;
258
268
    case TIMER_MODE:
259
 
        if (s->master == NULL) {
 
269
        if (timer_index == 0) {
260
270
            unsigned int i;
261
271
 
262
 
            for (i = 0; i < s->num_slaves; i++) {
 
272
            for (i = 0; i < s->num_cpus; i++) {
263
273
                unsigned int processor = 1 << i;
 
274
                CPUTimerState *curr_timer = &s->cputimer[i + 1];
264
275
 
265
276
                // check for a change in timer mode for this processor
266
 
                if ((val & processor) != (s->slave_mode & processor)) {
 
277
                if ((val & processor) != (s->cputimer_mode & processor)) {
267
278
                    if (val & processor) { // counter -> user timer
268
 
                        qemu_irq_lower(s->slave[i]->irq);
 
279
                        qemu_irq_lower(curr_timer->irq);
269
280
                        // counters are always running
270
 
                        ptimer_stop(s->slave[i]->timer);
271
 
                        s->slave[i]->running = 0;
 
281
                        ptimer_stop(curr_timer->timer);
 
282
                        curr_timer->running = 0;
272
283
                        // user timer limit is always the same
273
 
                        s->slave[i]->limit = TIMER_MAX_COUNT64;
274
 
                        ptimer_set_limit(s->slave[i]->timer,
275
 
                                         LIMIT_TO_PERIODS(s->slave[i]->limit),
 
284
                        curr_timer->limit = TIMER_MAX_COUNT64;
 
285
                        ptimer_set_limit(curr_timer->timer,
 
286
                                         LIMIT_TO_PERIODS(curr_timer->limit),
276
287
                                         1);
277
288
                        // set this processors user timer bit in config
278
289
                        // register
279
 
                        s->slave_mode |= processor;
280
 
                        DPRINTF("processor %d changed from counter to user "
281
 
                                "timer\n", s->slave[i]->slave_index);
 
290
                        s->cputimer_mode |= processor;
 
291
                        trace_slavio_timer_mem_writel_mode_user(timer_index);
282
292
                    } else { // user timer -> counter
283
293
                        // stop the user timer if it is running
284
 
                        if (s->slave[i]->running)
285
 
                            ptimer_stop(s->slave[i]->timer);
 
294
                        if (curr_timer->running) {
 
295
                            ptimer_stop(curr_timer->timer);
 
296
                        }
286
297
                        // start the counter
287
 
                        ptimer_run(s->slave[i]->timer, 0);
288
 
                        s->slave[i]->running = 1;
 
298
                        ptimer_run(curr_timer->timer, 0);
 
299
                        curr_timer->running = 1;
289
300
                        // clear this processors user timer bit in config
290
301
                        // register
291
 
                        s->slave_mode &= ~processor;
292
 
                        DPRINTF("processor %d changed from user timer to "
293
 
                                "counter\n", s->slave[i]->slave_index);
 
302
                        s->cputimer_mode &= ~processor;
 
303
                        trace_slavio_timer_mem_writel_mode_counter(timer_index);
294
304
                    }
295
305
                }
296
306
            }
297
 
        } else
298
 
            DPRINTF("not system timer\n");
 
307
        } else {
 
308
            trace_slavio_timer_mem_writel_mode_invalid();
 
309
        }
299
310
        break;
300
311
    default:
301
 
        DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
 
312
        trace_slavio_timer_mem_writel_invalid(addr);
302
313
        break;
303
314
    }
304
315
}
305
316
 
306
 
static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
307
 
    NULL,
308
 
    NULL,
309
 
    slavio_timer_mem_readl,
310
 
};
311
 
 
312
 
static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
313
 
    NULL,
314
 
    NULL,
315
 
    slavio_timer_mem_writel,
316
 
};
317
 
 
318
 
static void slavio_timer_save(QEMUFile *f, void *opaque)
 
317
static const MemoryRegionOps slavio_timer_mem_ops = {
 
318
    .read = slavio_timer_mem_readl,
 
319
    .write = slavio_timer_mem_writel,
 
320
    .endianness = DEVICE_NATIVE_ENDIAN,
 
321
    .valid = {
 
322
        .min_access_size = 4,
 
323
        .max_access_size = 4,
 
324
    },
 
325
};
 
326
 
 
327
static const VMStateDescription vmstate_timer = {
 
328
    .name ="timer",
 
329
    .version_id = 3,
 
330
    .minimum_version_id = 3,
 
331
    .minimum_version_id_old = 3,
 
332
    .fields      = (VMStateField []) {
 
333
        VMSTATE_UINT64(limit, CPUTimerState),
 
334
        VMSTATE_UINT32(count, CPUTimerState),
 
335
        VMSTATE_UINT32(counthigh, CPUTimerState),
 
336
        VMSTATE_UINT32(reached, CPUTimerState),
 
337
        VMSTATE_UINT32(running, CPUTimerState),
 
338
        VMSTATE_PTIMER(timer, CPUTimerState),
 
339
        VMSTATE_END_OF_LIST()
 
340
    }
 
341
};
 
342
 
 
343
static const VMStateDescription vmstate_slavio_timer = {
 
344
    .name ="slavio_timer",
 
345
    .version_id = 3,
 
346
    .minimum_version_id = 3,
 
347
    .minimum_version_id_old = 3,
 
348
    .fields      = (VMStateField []) {
 
349
        VMSTATE_STRUCT_ARRAY(cputimer, SLAVIO_TIMERState, MAX_CPUS + 1, 3,
 
350
                             vmstate_timer, CPUTimerState),
 
351
        VMSTATE_END_OF_LIST()
 
352
    }
 
353
};
 
354
 
 
355
static void slavio_timer_reset(DeviceState *d)
319
356
{
320
 
    SLAVIO_TIMERState *s = opaque;
 
357
    SLAVIO_TIMERState *s = container_of(d, SLAVIO_TIMERState, busdev.qdev);
 
358
    unsigned int i;
 
359
    CPUTimerState *curr_timer;
321
360
 
322
 
    qemu_put_be64s(f, &s->limit);
323
 
    qemu_put_be32s(f, &s->count);
324
 
    qemu_put_be32s(f, &s->counthigh);
325
 
    qemu_put_be32s(f, &s->reached);
326
 
    qemu_put_be32s(f, &s->running);
327
 
    if (s->timer)
328
 
        qemu_put_ptimer(f, s->timer);
 
361
    for (i = 0; i <= MAX_CPUS; i++) {
 
362
        curr_timer = &s->cputimer[i];
 
363
        curr_timer->limit = 0;
 
364
        curr_timer->count = 0;
 
365
        curr_timer->reached = 0;
 
366
        if (i <= s->num_cpus) {
 
367
            ptimer_set_limit(curr_timer->timer,
 
368
                             LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
 
369
            ptimer_run(curr_timer->timer, 0);
 
370
            curr_timer->running = 1;
 
371
        }
 
372
    }
 
373
    s->cputimer_mode = 0;
329
374
}
330
375
 
331
 
static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
 
376
static int slavio_timer_init1(SysBusDevice *dev)
332
377
{
333
 
    SLAVIO_TIMERState *s = opaque;
334
 
 
335
 
    if (version_id != 3)
336
 
        return -EINVAL;
337
 
 
338
 
    qemu_get_be64s(f, &s->limit);
339
 
    qemu_get_be32s(f, &s->count);
340
 
    qemu_get_be32s(f, &s->counthigh);
341
 
    qemu_get_be32s(f, &s->reached);
342
 
    qemu_get_be32s(f, &s->running);
343
 
    if (s->timer)
344
 
        qemu_get_ptimer(f, s->timer);
 
378
    SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
 
379
    QEMUBH *bh;
 
380
    unsigned int i;
 
381
    TimerContext *tc;
 
382
 
 
383
    for (i = 0; i <= MAX_CPUS; i++) {
 
384
        uint64_t size;
 
385
        char timer_name[20];
 
386
 
 
387
        tc = g_malloc0(sizeof(TimerContext));
 
388
        tc->s = s;
 
389
        tc->timer_index = i;
 
390
 
 
391
        bh = qemu_bh_new(slavio_timer_irq, tc);
 
392
        s->cputimer[i].timer = ptimer_init(bh);
 
393
        ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
 
394
 
 
395
        size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
 
396
        snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
 
397
        memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc,
 
398
                              timer_name, size);
 
399
        sysbus_init_mmio(dev, &tc->iomem);
 
400
 
 
401
        sysbus_init_irq(dev, &s->cputimer[i].irq);
 
402
    }
345
403
 
346
404
    return 0;
347
405
}
348
406
 
349
 
static void slavio_timer_reset(void *opaque)
350
 
{
351
 
    SLAVIO_TIMERState *s = opaque;
352
 
 
353
 
    s->limit = 0;
354
 
    s->count = 0;
355
 
    s->reached = 0;
356
 
    s->slave_mode = 0;
357
 
    if (!s->master || s->slave_index < s->master->num_slaves) {
358
 
        ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
359
 
        ptimer_run(s->timer, 0);
360
 
    }
361
 
    s->running = 1;
362
 
    qemu_irq_lower(s->irq);
363
 
}
364
 
 
365
 
static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
366
 
                                            qemu_irq irq,
367
 
                                            SLAVIO_TIMERState *master,
368
 
                                            uint32_t slave_index)
369
 
{
370
 
    int slavio_timer_io_memory;
371
 
    SLAVIO_TIMERState *s;
372
 
    QEMUBH *bh;
373
 
 
374
 
    s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
375
 
    s->irq = irq;
376
 
    s->master = master;
377
 
    s->slave_index = slave_index;
378
 
    if (!master || slave_index < master->num_slaves) {
379
 
        bh = qemu_bh_new(slavio_timer_irq, s);
380
 
        s->timer = ptimer_init(bh);
381
 
        ptimer_set_period(s->timer, TIMER_PERIOD);
382
 
    }
383
 
 
384
 
    slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
385
 
                                                    slavio_timer_mem_write, s);
386
 
    if (master)
387
 
        cpu_register_physical_memory(addr, CPU_TIMER_SIZE,
388
 
                                     slavio_timer_io_memory);
389
 
    else
390
 
        cpu_register_physical_memory(addr, SYS_TIMER_SIZE,
391
 
                                     slavio_timer_io_memory);
392
 
    register_savevm("slavio_timer", addr, 3, slavio_timer_save,
393
 
                    slavio_timer_load, s);
394
 
    qemu_register_reset(slavio_timer_reset, s);
395
 
    slavio_timer_reset(s);
396
 
 
397
 
    return s;
398
 
}
399
 
 
400
 
void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
401
 
                           qemu_irq *cpu_irqs, unsigned int num_cpus)
402
 
{
403
 
    SLAVIO_TIMERState *master;
404
 
    unsigned int i;
405
 
 
406
 
    master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0);
407
 
 
408
 
    master->num_slaves = num_cpus;
409
 
 
410
 
    for (i = 0; i < MAX_CPUS; i++) {
411
 
        master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
412
 
                                             CPU_TIMER_OFFSET(i),
413
 
                                             cpu_irqs[i], master, i);
414
 
    }
415
 
}
 
407
static Property slavio_timer_properties[] = {
 
408
    DEFINE_PROP_UINT32("num_cpus",  SLAVIO_TIMERState, num_cpus,  0),
 
409
    DEFINE_PROP_END_OF_LIST(),
 
410
};
 
411
 
 
412
static void slavio_timer_class_init(ObjectClass *klass, void *data)
 
413
{
 
414
    DeviceClass *dc = DEVICE_CLASS(klass);
 
415
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
416
 
 
417
    k->init = slavio_timer_init1;
 
418
    dc->reset = slavio_timer_reset;
 
419
    dc->vmsd = &vmstate_slavio_timer;
 
420
    dc->props = slavio_timer_properties;
 
421
}
 
422
 
 
423
static TypeInfo slavio_timer_info = {
 
424
    .name          = "slavio_timer",
 
425
    .parent        = TYPE_SYS_BUS_DEVICE,
 
426
    .instance_size = sizeof(SLAVIO_TIMERState),
 
427
    .class_init    = slavio_timer_class_init,
 
428
};
 
429
 
 
430
static void slavio_timer_register_types(void)
 
431
{
 
432
    type_register_static(&slavio_timer_info);
 
433
}
 
434
 
 
435
type_init(slavio_timer_register_types)