qemu

Форк
0
/
iotkit-secctl.c 
845 строк · 23.6 Кб
1
/*
2
 * Arm IoT Kit security controller
3
 *
4
 * Copyright (c) 2018 Linaro Limited
5
 * Written by Peter Maydell
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 or
9
 * (at your option) any later version.
10
 */
11

12
#include "qemu/osdep.h"
13
#include "qemu/log.h"
14
#include "qemu/module.h"
15
#include "qapi/error.h"
16
#include "trace.h"
17
#include "hw/sysbus.h"
18
#include "migration/vmstate.h"
19
#include "hw/registerfields.h"
20
#include "hw/irq.h"
21
#include "hw/misc/iotkit-secctl.h"
22
#include "hw/arm/armsse-version.h"
23
#include "hw/qdev-properties.h"
24

25
/* Registers in the secure privilege control block */
26
REG32(SECRESPCFG, 0x10)
27
REG32(NSCCFG, 0x14)
28
REG32(SECMPCINTSTATUS, 0x1c)
29
REG32(SECPPCINTSTAT, 0x20)
30
REG32(SECPPCINTCLR, 0x24)
31
REG32(SECPPCINTEN, 0x28)
32
REG32(SECMSCINTSTAT, 0x30)
33
REG32(SECMSCINTCLR, 0x34)
34
REG32(SECMSCINTEN, 0x38)
35
REG32(BRGINTSTAT, 0x40)
36
REG32(BRGINTCLR, 0x44)
37
REG32(BRGINTEN, 0x48)
38
REG32(AHBNSPPC0, 0x50)
39
REG32(AHBNSPPCEXP0, 0x60)
40
REG32(AHBNSPPCEXP1, 0x64)
41
REG32(AHBNSPPCEXP2, 0x68)
42
REG32(AHBNSPPCEXP3, 0x6c)
43
REG32(APBNSPPC0, 0x70)
44
REG32(APBNSPPC1, 0x74)
45
REG32(APBNSPPCEXP0, 0x80)
46
REG32(APBNSPPCEXP1, 0x84)
47
REG32(APBNSPPCEXP2, 0x88)
48
REG32(APBNSPPCEXP3, 0x8c)
49
REG32(AHBSPPPC0, 0x90)
50
REG32(AHBSPPPCEXP0, 0xa0)
51
REG32(AHBSPPPCEXP1, 0xa4)
52
REG32(AHBSPPPCEXP2, 0xa8)
53
REG32(AHBSPPPCEXP3, 0xac)
54
REG32(APBSPPPC0, 0xb0)
55
REG32(APBSPPPC1, 0xb4)
56
REG32(APBSPPPCEXP0, 0xc0)
57
REG32(APBSPPPCEXP1, 0xc4)
58
REG32(APBSPPPCEXP2, 0xc8)
59
REG32(APBSPPPCEXP3, 0xcc)
60
REG32(NSMSCEXP, 0xd0)
61
REG32(PID4, 0xfd0)
62
REG32(PID5, 0xfd4)
63
REG32(PID6, 0xfd8)
64
REG32(PID7, 0xfdc)
65
REG32(PID0, 0xfe0)
66
REG32(PID1, 0xfe4)
67
REG32(PID2, 0xfe8)
68
REG32(PID3, 0xfec)
69
REG32(CID0, 0xff0)
70
REG32(CID1, 0xff4)
71
REG32(CID2, 0xff8)
72
REG32(CID3, 0xffc)
73

74
/* Registers in the non-secure privilege control block */
75
REG32(AHBNSPPPC0, 0x90)
76
REG32(AHBNSPPPCEXP0, 0xa0)
77
REG32(AHBNSPPPCEXP1, 0xa4)
78
REG32(AHBNSPPPCEXP2, 0xa8)
79
REG32(AHBNSPPPCEXP3, 0xac)
80
REG32(APBNSPPPC0, 0xb0)
81
REG32(APBNSPPPC1, 0xb4)
82
REG32(APBNSPPPCEXP0, 0xc0)
83
REG32(APBNSPPPCEXP1, 0xc4)
84
REG32(APBNSPPPCEXP2, 0xc8)
85
REG32(APBNSPPPCEXP3, 0xcc)
86
/* PID and CID registers are also present in the NS block */
87

88
static const uint8_t iotkit_secctl_s_idregs[] = {
89
    0x04, 0x00, 0x00, 0x00,
90
    0x52, 0xb8, 0x0b, 0x00,
91
    0x0d, 0xf0, 0x05, 0xb1,
92
};
93

94
static const uint8_t iotkit_secctl_ns_idregs[] = {
95
    0x04, 0x00, 0x00, 0x00,
96
    0x53, 0xb8, 0x0b, 0x00,
97
    0x0d, 0xf0, 0x05, 0xb1,
98
};
99

100
static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
101
    0x04, 0x00, 0x00, 0x00,
102
    0x52, 0xb8, 0x2b, 0x00,
103
    0x0d, 0xf0, 0x05, 0xb1,
104
};
105

106
static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
107
    0x04, 0x00, 0x00, 0x00,
108
    0x53, 0xb8, 0x2b, 0x00,
109
    0x0d, 0xf0, 0x05, 0xb1,
110
};
111

112

113
/* The register sets for the various PPCs (AHB internal, APB internal,
114
 * AHB expansion, APB expansion) are all set up so that they are
115
 * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
116
 * 0, 1, 2, 3 of that type, so we can convert a register address offset
117
 * into an index into a PPC array easily.
118
 */
119
static inline int offset_to_ppc_idx(uint32_t offset)
120
{
121
    return extract32(offset, 2, 2);
122
}
123

124
typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
125

126
static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
127
{
128
    int i;
129

130
    for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
131
        fn(&s->apb[i]);
132
    }
133
    for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
134
        fn(&s->apbexp[i]);
135
    }
136
    for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
137
        fn(&s->ahbexp[i]);
138
    }
139
}
140

141
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
142
                                        uint64_t *pdata,
143
                                        unsigned size, MemTxAttrs attrs)
144
{
145
    uint64_t r;
146
    uint32_t offset = addr & ~0x3;
147
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
148

149
    switch (offset) {
150
    case A_AHBNSPPC0:
151
    case A_AHBSPPPC0:
152
        r = 0;
153
        break;
154
    case A_SECRESPCFG:
155
        r = s->secrespcfg;
156
        break;
157
    case A_NSCCFG:
158
        r = s->nsccfg;
159
        break;
160
    case A_SECMPCINTSTATUS:
161
        r = s->mpcintstatus;
162
        break;
163
    case A_SECPPCINTSTAT:
164
        r = s->secppcintstat;
165
        break;
166
    case A_SECPPCINTEN:
167
        r = s->secppcinten;
168
        break;
169
    case A_BRGINTSTAT:
170
        /* QEMU's bus fabric can never report errors as it doesn't buffer
171
         * writes, so we never report bridge interrupts.
172
         */
173
        r = 0;
174
        break;
175
    case A_BRGINTEN:
176
        r = s->brginten;
177
        break;
178
    case A_AHBNSPPCEXP0:
179
    case A_AHBNSPPCEXP1:
180
    case A_AHBNSPPCEXP2:
181
    case A_AHBNSPPCEXP3:
182
        r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
183
        break;
184
    case A_APBNSPPC0:
185
    case A_APBNSPPC1:
186
        r = s->apb[offset_to_ppc_idx(offset)].ns;
187
        break;
188
    case A_APBNSPPCEXP0:
189
    case A_APBNSPPCEXP1:
190
    case A_APBNSPPCEXP2:
191
    case A_APBNSPPCEXP3:
192
        r = s->apbexp[offset_to_ppc_idx(offset)].ns;
193
        break;
194
    case A_AHBSPPPCEXP0:
195
    case A_AHBSPPPCEXP1:
196
    case A_AHBSPPPCEXP2:
197
    case A_AHBSPPPCEXP3:
198
        r = s->apbexp[offset_to_ppc_idx(offset)].sp;
199
        break;
200
    case A_APBSPPPC0:
201
    case A_APBSPPPC1:
202
        r = s->apb[offset_to_ppc_idx(offset)].sp;
203
        break;
204
    case A_APBSPPPCEXP0:
205
    case A_APBSPPPCEXP1:
206
    case A_APBSPPPCEXP2:
207
    case A_APBSPPPCEXP3:
208
        r = s->apbexp[offset_to_ppc_idx(offset)].sp;
209
        break;
210
    case A_SECMSCINTSTAT:
211
        r = s->secmscintstat;
212
        break;
213
    case A_SECMSCINTEN:
214
        r = s->secmscinten;
215
        break;
216
    case A_NSMSCEXP:
217
        r = s->nsmscexp;
218
        break;
219
    case A_PID4:
220
    case A_PID5:
221
    case A_PID6:
222
    case A_PID7:
223
    case A_PID0:
224
    case A_PID1:
225
    case A_PID2:
226
    case A_PID3:
227
    case A_CID0:
228
    case A_CID1:
229
    case A_CID2:
230
    case A_CID3:
231
        switch (s->sse_version) {
232
        case ARMSSE_SSE300:
233
            r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
234
            break;
235
        default:
236
            r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
            break;
238
        }
239
        break;
240
    case A_SECPPCINTCLR:
241
    case A_SECMSCINTCLR:
242
    case A_BRGINTCLR:
243
        qemu_log_mask(LOG_GUEST_ERROR,
244
                      "IotKit SecCtl S block read: write-only offset 0x%x\n",
245
                      offset);
246
        r = 0;
247
        break;
248
    default:
249
        qemu_log_mask(LOG_GUEST_ERROR,
250
                      "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
251
        r = 0;
252
        break;
253
    }
254

255
    if (size != 4) {
256
        /* None of our registers are access-sensitive, so just pull the right
257
         * byte out of the word read result.
258
         */
259
        r = extract32(r, (addr & 3) * 8, size * 8);
260
    }
261

262
    trace_iotkit_secctl_s_read(offset, r, size);
263
    *pdata = r;
264
    return MEMTX_OK;
265
}
266

267
static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
268
{
269
    int i;
270

271
    for (i = 0; i < ppc->numports; i++) {
272
        bool v;
273

274
        if (extract32(ppc->ns, i, 1)) {
275
            v = extract32(ppc->nsp, i, 1);
276
        } else {
277
            v = extract32(ppc->sp, i, 1);
278
        }
279
        qemu_set_irq(ppc->ap[i], v);
280
    }
281
}
282

283
static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
284
{
285
    int i;
286

287
    ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
288
    for (i = 0; i < ppc->numports; i++) {
289
        qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
290
    }
291
    iotkit_secctl_update_ppc_ap(ppc);
292
}
293

294
static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
295
{
296
    ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
297
    iotkit_secctl_update_ppc_ap(ppc);
298
}
299

300
static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
301
{
302
    ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
303
    iotkit_secctl_update_ppc_ap(ppc);
304
}
305

306
static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
307
{
308
    uint32_t value = ppc->parent->secppcintstat;
309

310
    qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
311
}
312

313
static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
314
{
315
    uint32_t value = ppc->parent->secppcinten;
316

317
    qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
318
}
319

320
static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
321
{
322
    int i;
323

324
    for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
325
        qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
326
    }
327
}
328

329
static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
330
{
331
    /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
332
    bool level = s->secmscintstat & s->secmscinten;
333

334
    qemu_set_irq(s->msc_irq, level);
335
}
336

337
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
338
                                         uint64_t value,
339
                                         unsigned size, MemTxAttrs attrs)
340
{
341
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
342
    uint32_t offset = addr;
343
    IoTKitSecCtlPPC *ppc;
344

345
    trace_iotkit_secctl_s_write(offset, value, size);
346

347
    if (size != 4) {
348
        /* Byte and halfword writes are ignored */
349
        qemu_log_mask(LOG_GUEST_ERROR,
350
                      "IotKit SecCtl S block write: bad size, ignored\n");
351
        return MEMTX_OK;
352
    }
353

354
    switch (offset) {
355
    case A_NSCCFG:
356
        s->nsccfg = value & 3;
357
        qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
358
        break;
359
    case A_SECRESPCFG:
360
        value &= 1;
361
        s->secrespcfg = value;
362
        qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
363
        break;
364
    case A_SECPPCINTCLR:
365
        s->secppcintstat &= ~(value & 0x00f000f3);
366
        foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
367
        break;
368
    case A_SECPPCINTEN:
369
        s->secppcinten = value & 0x00f000f3;
370
        foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
371
        break;
372
    case A_BRGINTCLR:
373
        break;
374
    case A_BRGINTEN:
375
        s->brginten = value & 0xffff0000;
376
        break;
377
    case A_AHBNSPPCEXP0:
378
    case A_AHBNSPPCEXP1:
379
    case A_AHBNSPPCEXP2:
380
    case A_AHBNSPPCEXP3:
381
        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
382
        iotkit_secctl_ppc_ns_write(ppc, value);
383
        break;
384
    case A_APBNSPPC0:
385
    case A_APBNSPPC1:
386
        ppc = &s->apb[offset_to_ppc_idx(offset)];
387
        iotkit_secctl_ppc_ns_write(ppc, value);
388
        break;
389
    case A_APBNSPPCEXP0:
390
    case A_APBNSPPCEXP1:
391
    case A_APBNSPPCEXP2:
392
    case A_APBNSPPCEXP3:
393
        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
394
        iotkit_secctl_ppc_ns_write(ppc, value);
395
        break;
396
    case A_AHBSPPPCEXP0:
397
    case A_AHBSPPPCEXP1:
398
    case A_AHBSPPPCEXP2:
399
    case A_AHBSPPPCEXP3:
400
        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
401
        iotkit_secctl_ppc_sp_write(ppc, value);
402
        break;
403
    case A_APBSPPPC0:
404
    case A_APBSPPPC1:
405
        ppc = &s->apb[offset_to_ppc_idx(offset)];
406
        iotkit_secctl_ppc_sp_write(ppc, value);
407
        break;
408
    case A_APBSPPPCEXP0:
409
    case A_APBSPPPCEXP1:
410
    case A_APBSPPPCEXP2:
411
    case A_APBSPPPCEXP3:
412
        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
413
        iotkit_secctl_ppc_sp_write(ppc, value);
414
        break;
415
    case A_SECMSCINTCLR:
416
        iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
417
        break;
418
    case A_SECMSCINTEN:
419
        s->secmscinten = value;
420
        iotkit_secctl_update_msc_irq(s);
421
        break;
422
    case A_NSMSCEXP:
423
        s->nsmscexp = value;
424
        iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
425
        break;
426
    case A_SECMPCINTSTATUS:
427
    case A_SECPPCINTSTAT:
428
    case A_SECMSCINTSTAT:
429
    case A_BRGINTSTAT:
430
    case A_AHBNSPPC0:
431
    case A_AHBSPPPC0:
432
    case A_PID4:
433
    case A_PID5:
434
    case A_PID6:
435
    case A_PID7:
436
    case A_PID0:
437
    case A_PID1:
438
    case A_PID2:
439
    case A_PID3:
440
    case A_CID0:
441
    case A_CID1:
442
    case A_CID2:
443
    case A_CID3:
444
        qemu_log_mask(LOG_GUEST_ERROR,
445
                      "IoTKit SecCtl S block write: "
446
                      "read-only offset 0x%x\n", offset);
447
        break;
448
    default:
449
        qemu_log_mask(LOG_GUEST_ERROR,
450
                      "IotKit SecCtl S block write: bad offset 0x%x\n",
451
                      offset);
452
        break;
453
    }
454

455
    return MEMTX_OK;
456
}
457

458
static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
459
                                         uint64_t *pdata,
460
                                         unsigned size, MemTxAttrs attrs)
461
{
462
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
463
    uint64_t r;
464
    uint32_t offset = addr & ~0x3;
465

466
    switch (offset) {
467
    case A_AHBNSPPPC0:
468
        r = 0;
469
        break;
470
    case A_AHBNSPPPCEXP0:
471
    case A_AHBNSPPPCEXP1:
472
    case A_AHBNSPPPCEXP2:
473
    case A_AHBNSPPPCEXP3:
474
        r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
475
        break;
476
    case A_APBNSPPPC0:
477
    case A_APBNSPPPC1:
478
        r = s->apb[offset_to_ppc_idx(offset)].nsp;
479
        break;
480
    case A_APBNSPPPCEXP0:
481
    case A_APBNSPPPCEXP1:
482
    case A_APBNSPPPCEXP2:
483
    case A_APBNSPPPCEXP3:
484
        r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
485
        break;
486
    case A_PID4:
487
    case A_PID5:
488
    case A_PID6:
489
    case A_PID7:
490
    case A_PID0:
491
    case A_PID1:
492
    case A_PID2:
493
    case A_PID3:
494
    case A_CID0:
495
    case A_CID1:
496
    case A_CID2:
497
    case A_CID3:
498
        switch (s->sse_version) {
499
        case ARMSSE_SSE300:
500
            r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
501
            break;
502
        default:
503
            r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
504
            break;
505
        }
506
        break;
507
    default:
508
        qemu_log_mask(LOG_GUEST_ERROR,
509
                      "IotKit SecCtl NS block write: bad offset 0x%x\n",
510
                      offset);
511
        r = 0;
512
        break;
513
    }
514

515
    if (size != 4) {
516
        /* None of our registers are access-sensitive, so just pull the right
517
         * byte out of the word read result.
518
         */
519
        r = extract32(r, (addr & 3) * 8, size * 8);
520
    }
521

522
    trace_iotkit_secctl_ns_read(offset, r, size);
523
    *pdata = r;
524
    return MEMTX_OK;
525
}
526

527
static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
528
                                          uint64_t value,
529
                                          unsigned size, MemTxAttrs attrs)
530
{
531
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
532
    uint32_t offset = addr;
533
    IoTKitSecCtlPPC *ppc;
534

535
    trace_iotkit_secctl_ns_write(offset, value, size);
536

537
    if (size != 4) {
538
        /* Byte and halfword writes are ignored */
539
        qemu_log_mask(LOG_GUEST_ERROR,
540
                      "IotKit SecCtl NS block write: bad size, ignored\n");
541
        return MEMTX_OK;
542
    }
543

544
    switch (offset) {
545
    case A_AHBNSPPPCEXP0:
546
    case A_AHBNSPPPCEXP1:
547
    case A_AHBNSPPPCEXP2:
548
    case A_AHBNSPPPCEXP3:
549
        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
550
        iotkit_secctl_ppc_nsp_write(ppc, value);
551
        break;
552
    case A_APBNSPPPC0:
553
    case A_APBNSPPPC1:
554
        ppc = &s->apb[offset_to_ppc_idx(offset)];
555
        iotkit_secctl_ppc_nsp_write(ppc, value);
556
        break;
557
    case A_APBNSPPPCEXP0:
558
    case A_APBNSPPPCEXP1:
559
    case A_APBNSPPPCEXP2:
560
    case A_APBNSPPPCEXP3:
561
        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
562
        iotkit_secctl_ppc_nsp_write(ppc, value);
563
        break;
564
    case A_AHBNSPPPC0:
565
    case A_PID4:
566
    case A_PID5:
567
    case A_PID6:
568
    case A_PID7:
569
    case A_PID0:
570
    case A_PID1:
571
    case A_PID2:
572
    case A_PID3:
573
    case A_CID0:
574
    case A_CID1:
575
    case A_CID2:
576
    case A_CID3:
577
        qemu_log_mask(LOG_GUEST_ERROR,
578
                      "IoTKit SecCtl NS block write: "
579
                      "read-only offset 0x%x\n", offset);
580
        break;
581
    default:
582
        qemu_log_mask(LOG_GUEST_ERROR,
583
                      "IotKit SecCtl NS block write: bad offset 0x%x\n",
584
                      offset);
585
        break;
586
    }
587

588
    return MEMTX_OK;
589
}
590

591
static const MemoryRegionOps iotkit_secctl_s_ops = {
592
    .read_with_attrs = iotkit_secctl_s_read,
593
    .write_with_attrs = iotkit_secctl_s_write,
594
    .endianness = DEVICE_LITTLE_ENDIAN,
595
    .valid.min_access_size = 1,
596
    .valid.max_access_size = 4,
597
    .impl.min_access_size = 1,
598
    .impl.max_access_size = 4,
599
};
600

601
static const MemoryRegionOps iotkit_secctl_ns_ops = {
602
    .read_with_attrs = iotkit_secctl_ns_read,
603
    .write_with_attrs = iotkit_secctl_ns_write,
604
    .endianness = DEVICE_LITTLE_ENDIAN,
605
    .valid.min_access_size = 1,
606
    .valid.max_access_size = 4,
607
    .impl.min_access_size = 1,
608
    .impl.max_access_size = 4,
609
};
610

611
static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
612
{
613
    ppc->ns = 0;
614
    ppc->sp = 0;
615
    ppc->nsp = 0;
616
}
617

618
static void iotkit_secctl_reset(DeviceState *dev)
619
{
620
    IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
621

622
    s->secppcintstat = 0;
623
    s->secppcinten = 0;
624
    s->secrespcfg = 0;
625
    s->nsccfg = 0;
626
    s->brginten = 0;
627

628
    foreach_ppc(s, iotkit_secctl_reset_ppc);
629
}
630

631
static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
632
{
633
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
634

635
    s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
636
}
637

638
static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
639
{
640
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
641

642
    s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
643
}
644

645
static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
646
{
647
    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
648

649
    s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
650
    iotkit_secctl_update_msc_irq(s);
651
}
652

653
static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
654
{
655
    IoTKitSecCtlPPC *ppc = opaque;
656
    IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
657
    int irqbit = ppc->irq_bit_offset + n;
658

659
    s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
660
}
661

662
static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
663
                                   IoTKitSecCtlPPC *ppc,
664
                                   const char *name,
665
                                   int numports,
666
                                   int irq_bit_offset)
667
{
668
    char *gpioname;
669
    DeviceState *dev = DEVICE(s);
670

671
    ppc->numports = numports;
672
    ppc->irq_bit_offset = irq_bit_offset;
673
    ppc->parent = s;
674

675
    gpioname = g_strdup_printf("%s_nonsec", name);
676
    qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
677
    g_free(gpioname);
678
    gpioname = g_strdup_printf("%s_ap", name);
679
    qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
680
    g_free(gpioname);
681
    gpioname = g_strdup_printf("%s_irq_enable", name);
682
    qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
683
    g_free(gpioname);
684
    gpioname = g_strdup_printf("%s_irq_clear", name);
685
    qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
686
    g_free(gpioname);
687
    gpioname = g_strdup_printf("%s_irq_status", name);
688
    qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
689
                                        ppc, gpioname, 1);
690
    g_free(gpioname);
691
}
692

693
static void iotkit_secctl_init(Object *obj)
694
{
695
    IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
696
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
697
    DeviceState *dev = DEVICE(obj);
698
    int i;
699

700
    iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
701
                           IOTS_APB_PPC0_NUM_PORTS, 0);
702
    iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
703
                           IOTS_APB_PPC1_NUM_PORTS, 1);
704

705
    for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
706
        IoTKitSecCtlPPC *ppc = &s->apbexp[i];
707
        char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
708
        iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
709
        g_free(ppcname);
710
    }
711
    for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
712
        IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
713
        char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
714
        iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
715
        g_free(ppcname);
716
    }
717

718
    qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
719
    qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
720

721
    qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
722
                            IOTS_NUM_MPC);
723
    qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
724
                            "mpcexp_status", IOTS_NUM_EXP_MPC);
725

726
    qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
727
                            "mscexp_status", IOTS_NUM_EXP_MSC);
728
    qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
729
                             IOTS_NUM_EXP_MSC);
730
    qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
731
                             IOTS_NUM_EXP_MSC);
732
    qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
733

734
    memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
735
                          s, "iotkit-secctl-s-regs", 0x1000);
736
    memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
737
                          s, "iotkit-secctl-ns-regs", 0x1000);
738
    sysbus_init_mmio(sbd, &s->s_regs);
739
    sysbus_init_mmio(sbd, &s->ns_regs);
740
}
741

742
static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
743
{
744
    IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
745

746
    if (!armsse_version_valid(s->sse_version)) {
747
        error_setg(errp, "invalid sse-version value %d", s->sse_version);
748
        return;
749
    }
750
}
751

752
static const VMStateDescription iotkit_secctl_ppc_vmstate = {
753
    .name = "iotkit-secctl-ppc",
754
    .version_id = 1,
755
    .minimum_version_id = 1,
756
    .fields = (const VMStateField[]) {
757
        VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
758
        VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
759
        VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
760
        VMSTATE_END_OF_LIST()
761
    }
762
};
763

764
static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
765
    .name = "iotkit-secctl-mpcintstatus",
766
    .version_id = 1,
767
    .minimum_version_id = 1,
768
    .fields = (const VMStateField[]) {
769
        VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
770
        VMSTATE_END_OF_LIST()
771
    }
772
};
773

774
static bool needed_always(void *opaque)
775
{
776
    return true;
777
}
778

779
static const VMStateDescription iotkit_secctl_msc_vmstate = {
780
    .name = "iotkit-secctl/msc",
781
    .version_id = 1,
782
    .minimum_version_id = 1,
783
    .needed = needed_always,
784
    .fields = (const VMStateField[]) {
785
        VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
786
        VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
787
        VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
788
        VMSTATE_END_OF_LIST()
789
    }
790
};
791

792
static const VMStateDescription iotkit_secctl_vmstate = {
793
    .name = "iotkit-secctl",
794
    .version_id = 1,
795
    .minimum_version_id = 1,
796
    .fields = (const VMStateField[]) {
797
        VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
798
        VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
799
        VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
800
        VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
801
        VMSTATE_UINT32(brginten, IoTKitSecCtl),
802
        VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
803
                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
804
        VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
805
                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
806
        VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
807
                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
808
        VMSTATE_END_OF_LIST()
809
    },
810
    .subsections = (const VMStateDescription * const []) {
811
        &iotkit_secctl_mpcintstatus_vmstate,
812
        &iotkit_secctl_msc_vmstate,
813
        NULL
814
    },
815
};
816

817
static Property iotkit_secctl_props[] = {
818
    DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
819
    DEFINE_PROP_END_OF_LIST()
820
};
821

822
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
823
{
824
    DeviceClass *dc = DEVICE_CLASS(klass);
825

826
    dc->vmsd = &iotkit_secctl_vmstate;
827
    dc->reset = iotkit_secctl_reset;
828
    dc->realize = iotkit_secctl_realize;
829
    device_class_set_props(dc, iotkit_secctl_props);
830
}
831

832
static const TypeInfo iotkit_secctl_info = {
833
    .name = TYPE_IOTKIT_SECCTL,
834
    .parent = TYPE_SYS_BUS_DEVICE,
835
    .instance_size = sizeof(IoTKitSecCtl),
836
    .instance_init = iotkit_secctl_init,
837
    .class_init = iotkit_secctl_class_init,
838
};
839

840
static void iotkit_secctl_register_types(void)
841
{
842
    type_register_static(&iotkit_secctl_info);
843
}
844

845
type_init(iotkit_secctl_register_types);
846

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.