1#![no_std]
5#![doc = include_str!("../README.md")]
6#![deny(clippy::undocumented_unsafe_blocks)]
7#![deny(unsafe_op_in_unsafe_fn)]
8
9mod fail;
10mod region;
11mod utils;
12
13use bitflags::bitflags;
14use safe_mmio::{
15 SharedMmioPointer, UniqueMmioPointer, field, field_shared,
16 fields::{ReadOnly, ReadPure, ReadPureWrite, WriteOnly},
17};
18use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
19
20pub use crate::fail::{FailAccessDirection, FailControlRegister, FailIDRegister, TzcFail};
21pub use crate::region::{RegionAttributes, RegionIDAccess, SecureAccess, TzcRegion, TzcRegionMut};
22use crate::{
23 fail::FailRegisters,
24 region::RegionRegisters,
25 utils::{extract_bits, get_bit, set_bit},
26};
27
28macro_rules! for_in_slice {
29 ($var:ident in $slice:expr, $($body:stmt)*) => {
30 let mut i = 0;
31 while i < $slice.len() {
32 let $var = &$slice[i];
33 $($body)*
34 i += 1;
35 }
36 };
37}
38pub(crate) use for_in_slice;
39
40#[derive(Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
41#[repr(transparent)]
43pub struct BuildConfigRegister(u32);
44
45impl BuildConfigRegister {
46 const NF_1: u32 = 0b00;
48 const NF_2: u32 = 0b01;
49 const NF_4: u32 = 0b11;
50
51 pub const fn number_of_filters(&self) -> usize {
53 match extract_bits(self.0, 25, 24) {
54 Self::NF_1 => 1,
55 Self::NF_2 => 2,
56 Self::NF_4 => 4,
57 _ => panic!("Use of reserved value for number of filters"),
58 }
59 }
60
61 const AW_32: u32 = 0b011111;
63 const AW_36: u32 = 0b100011;
64 const AW_40: u32 = 0b100111;
65 const AW_48: u32 = 0b101111;
66 const AW_64: u32 = 0b111111;
67
68 pub const fn address_width(&self) -> usize {
70 match extract_bits(self.0, 13, 8) {
71 Self::AW_32 => 32,
72 Self::AW_36 => 36,
73 Self::AW_40 => 40,
74 Self::AW_48 => 48,
75 Self::AW_64 => 64,
76 _ => panic!("Use of reserved value for address width"),
77 }
78 }
79
80 const NR_9: u32 = 0b01000;
82
83 pub fn number_of_regions(&self) -> usize {
85 match extract_bits(self.0, 4, 0) {
86 Self::NR_9 => 9,
87 _ => panic!("Use of reserved value for number of regions"),
88 }
89 }
90}
91
92#[derive(Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
93#[repr(transparent)]
96pub struct ActionRegister(u32);
97
98impl ActionRegister {
99 pub const TZCINTLOW_OKAY: ActionRegister = ActionRegister(0b00);
101 pub const TZCINTLOW_DECERR: ActionRegister = ActionRegister(0b01);
103 pub const TZCINTHIGH_OKAY: ActionRegister = ActionRegister(0b10);
105 pub const TZCINTHIGH_DECERR: ActionRegister = ActionRegister(0b11);
107}
108
109#[derive(Clone, Copy, Debug, Eq, PartialEq)]
110#[repr(u32)]
111pub enum GateKeeperStatus {
113 Closed = 0,
115 Opened = 1,
117}
118
119#[derive(Debug)]
120pub struct GateKeeper<'reg> {
124 reg: SharedMmioPointer<'reg, ReadPureWrite<u32>>,
125 index: usize,
126}
127
128impl<'reg> GateKeeper<'reg> {
129 pub fn status(&self) -> GateKeeperStatus {
132 if get_bit(self.reg.read(), self.index + 16) {
133 GateKeeperStatus::Opened
134 } else {
135 GateKeeperStatus::Closed
136 }
137 }
138}
139
140#[derive(Debug)]
141pub struct GateKeeperMut<'reg> {
148 reg: UniqueMmioPointer<'reg, ReadPureWrite<u32>>,
149 index: usize,
150}
151
152impl<'reg> GateKeeperMut<'reg> {
153 pub fn status(&self) -> GateKeeperStatus {
155 GateKeeper {
156 reg: *self.reg,
157 index: self.index,
158 }
159 .status()
160 }
161
162 pub fn request(&mut self, status: GateKeeperStatus) {
165 let mut value = self.reg.read();
166
167 set_bit(
168 &mut value,
169 self.index,
170 matches!(status, GateKeeperStatus::Opened),
171 );
172 self.reg.write(value);
173
174 while self.status() != status {}
175 }
176}
177
178#[derive(Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
179#[repr(transparent)]
181pub struct SpeculationControlRegister(u32);
182
183bitflags! {
184 impl SpeculationControlRegister: u32 {
185 const READ_SPEC_DISABLE = 1 << 0;
190
191 const WRITE_SPEC_DISABLE = 1 << 1;
196 }
197}
198
199#[derive(Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
200#[repr(transparent)]
203pub struct InterruptStatusRegister(u32);
204
205impl InterruptStatusRegister {
206 pub const fn overlap(&self, index: usize) -> bool {
217 assert!(index < 4);
218 get_bit(self.0, index + 16)
219 }
220
221 pub const fn overrun(&self, index: usize) -> bool {
230 assert!(index < 4);
231 get_bit(self.0, index + 8)
232 }
233
234 pub const fn status(&self, index: usize) -> bool {
245 assert!(index < 4);
246 get_bit(self.0, index)
247 }
248}
249
250#[derive(
251 Debug, Clone, Copy, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq, Default,
252)]
253#[repr(transparent)]
255pub struct InterruptClearRegister(u32);
256
257impl InterruptClearRegister {
258 pub const fn new(interrupts: &[usize]) -> Self {
261 let mut s = Self(0);
262
263 for_in_slice!(int in interrupts, s.0 |= 1 << *int);
264
265 s
266 }
267}
268#[derive(Debug, Clone, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
270#[repr(C, align(4))]
271pub struct TzcRegisters {
272 build_config: ReadPure<BuildConfigRegister>,
274 action: ReadPureWrite<ActionRegister>,
276 gate_keeper: ReadPureWrite<u32>,
278 speculation_ctrl: ReadPureWrite<SpeculationControlRegister>,
280 int_status: ReadOnly<InterruptStatusRegister>,
282 int_clear: WriteOnly<InterruptClearRegister>,
284 reserved_18: [u32; 2],
286
287 fail_registers: [FailRegisters; 4],
291 reserved_60: [u32; 40],
293
294 region_registers: [RegionRegisters; 9],
299
300 reserved_220: [u32; 823],
305 padding_f00: [u32; 53],
306
307 pid4: ReadPure<u32>,
309 pid5: ReadPure<u32>,
311 pid6: ReadPure<u32>,
313 pid7: ReadPure<u32>,
315 pid0: ReadPure<u32>,
317 pid1: ReadPure<u32>,
319 pid2: ReadPure<u32>,
321 pid3: ReadPure<u32>,
323
324 cid0: ReadPure<u32>,
326 cid1: ReadPure<u32>,
328 cid2: ReadPure<u32>,
330 cid3: ReadPure<u32>,
332}
333
334pub struct Tzc<'a> {
336 regs: UniqueMmioPointer<'a, TzcRegisters>,
337}
338
339impl<'a> Tzc<'a> {
340 pub const fn new(regs: UniqueMmioPointer<'a, TzcRegisters>) -> Self {
343 Self { regs }
344 }
345
346 pub fn build_configuration(&self) -> BuildConfigRegister {
348 field_shared!(self.regs, build_config).read()
349 }
350
351 pub fn action(&self) -> ActionRegister {
353 field_shared!(self.regs, action).read()
354 }
355 pub fn set_action(&mut self, value: ActionRegister) {
357 field!((self.regs), action).write(value);
358 }
359
360 pub fn gate_keeper<'reg>(&'reg self, index: usize) -> Option<GateKeeper<'reg>> {
362 if index < self.build_configuration().number_of_filters() {
363 Some(GateKeeper {
364 reg: field_shared!(self.regs, gate_keeper),
365 index,
366 })
367 } else {
368 None
369 }
370 }
371
372 pub fn gate_keeper_mut<'reg>(&'reg mut self, index: usize) -> Option<GateKeeperMut<'reg>> {
374 if index < self.build_configuration().number_of_filters() {
375 Some(GateKeeperMut {
376 reg: field!(self.regs, gate_keeper),
377 index,
378 })
379 } else {
380 None
381 }
382 }
383
384 pub fn speculation_control(&self) -> SpeculationControlRegister {
386 field_shared!(self.regs, speculation_ctrl).read()
387 }
388 pub fn set_speculation_control(&mut self, value: SpeculationControlRegister) {
390 field!(self.regs, speculation_ctrl).write(value);
391 }
392
393 pub fn interrupt_status(&mut self) -> InterruptStatusRegister {
395 field!(self.regs, int_status).read()
396 }
397
398 pub fn clear_interrupts(&mut self, value: InterruptClearRegister) {
400 field!(self.regs, int_clear).write(value);
401 }
402
403 pub fn filter_failure<'regs>(&'regs self, idx: usize) -> Option<TzcFail<'regs>> {
406 if idx < self.build_configuration().number_of_filters() {
407 let fails = field_shared!(self.regs, fail_registers);
408 fails.get(idx).map(|regs| TzcFail { regs })
409 } else {
410 None
411 }
412 }
413
414 pub fn region<'regs>(&'regs self, idx: usize) -> Option<TzcRegion<'regs>> {
417 let config = self.build_configuration();
418
419 if idx < config.number_of_regions() {
420 let regions = field_shared!(self.regs, region_registers);
421 regions.get(idx).map(|regs| TzcRegion {
422 regs,
423 address_width_mask: ((1_u64.unbounded_shl(config.address_width() as u32))
424 .wrapping_sub(1)),
425 })
426 } else {
427 None
428 }
429 }
430
431 pub fn region_mut<'regs>(&'regs mut self, idx: usize) -> Option<TzcRegionMut<'regs>> {
434 let config = self.build_configuration();
435
436 if idx < config.number_of_regions() {
437 let regions = field!(self.regs, region_registers);
438 regions.take(idx).map(|regs| TzcRegionMut {
439 regs,
440 addresses_writable: idx != 0,
441 address_width_mask: ((1_u64.unbounded_shl(config.address_width() as u32))
442 .wrapping_sub(1)),
443 })
444 } else {
445 None
446 }
447 }
448
449 pub fn peripheral_id(&self) -> u64 {
451 let values = [
452 field_shared!(self.regs, pid0).read(),
453 field_shared!(self.regs, pid1).read(),
454 field_shared!(self.regs, pid2).read(),
455 field_shared!(self.regs, pid3).read(),
456 field_shared!(self.regs, pid4).read(),
457 field_shared!(self.regs, pid5).read(),
458 field_shared!(self.regs, pid6).read(),
459 field_shared!(self.regs, pid7).read(),
460 ];
461
462 values
463 .into_iter()
464 .map(|v| v as u64)
465 .enumerate()
466 .fold(0, |acc, (idx, value)| (value << (8 * idx as u64)) | acc)
467 }
468
469 pub fn component_id(&self) -> u64 {
472 let values = [
473 field_shared!(self.regs, cid0).read(),
474 field_shared!(self.regs, cid1).read(),
475 field_shared!(self.regs, cid2).read(),
476 field_shared!(self.regs, cid3).read(),
477 ];
478
479 values
480 .into_iter()
481 .map(|v| v as u64)
482 .enumerate()
483 .fold(0, |acc, (idx, value)| (value << (8 * idx as u64)) | acc)
484 }
485}
486
487#[cfg(test)]
488pub(crate) mod tests {
489 use safe_mmio::UniqueMmioPointer;
490 use zerocopy::transmute_mut;
491
492 use crate::*;
493
494 const DEFAULT_BUILD_CONFIG: u32 = 0b0000_0001_0000_0000_0010_1111_0000_1000;
495
496 pub(crate) struct FakeTZCRegisters {
497 regs: [u32; 1024],
498 }
499
500 impl FakeTZCRegisters {
501 pub fn new() -> Self {
502 let mut s = Self { regs: [0u32; 1024] };
503 s.reg_write(0x000, DEFAULT_BUILD_CONFIG);
504 s
505 }
506
507 pub fn reg_write(&mut self, offset: usize, value: u32) {
508 self.regs[offset / 4] = value;
509 }
510
511 pub fn reg_read(&self, offset: usize) -> u32 {
512 self.regs[offset / 4]
513 }
514
515 fn get(&mut self) -> UniqueMmioPointer<'_, TzcRegisters> {
516 UniqueMmioPointer::from(transmute_mut!(&mut self.regs))
517 }
518
519 pub fn tzc_for_test(&mut self) -> Tzc<'_> {
520 Tzc::new(self.get())
521 }
522 }
523
524 #[test]
525 fn size() {
526 assert_eq!(size_of::<TzcRegisters>(), 4096);
527 }
528
529 #[test]
530 fn build_config() {
531 let mut regs = FakeTZCRegisters::new();
532
533 let config = regs.tzc_for_test().build_configuration();
534 assert_eq!(config.number_of_filters(), 2);
535 assert_eq!(config.address_width(), 48);
536 assert_eq!(config.number_of_regions(), 9);
537
538 regs.reg_write(0x000, 0b0000_0000_0000_0000_0011_1111_0000_1000);
539 let config = regs.tzc_for_test().build_configuration();
540 assert_eq!(config.number_of_filters(), 1);
541 assert_eq!(config.address_width(), 64);
542 assert_eq!(config.number_of_regions(), 9);
543
544 regs.reg_write(0x000, 0b0000_0011_0000_0000_0010_0111_0000_1000);
545 let config = regs.tzc_for_test().build_configuration();
546 assert_eq!(config.number_of_filters(), 4);
547 assert_eq!(config.address_width(), 40);
548 assert_eq!(config.number_of_regions(), 9);
549
550 regs.reg_write(0x000, 0b0000_0011_0000_0000_0010_0011_0000_1000);
551 let config = regs.tzc_for_test().build_configuration();
552 assert_eq!(config.number_of_filters(), 4);
553 assert_eq!(config.address_width(), 36);
554 assert_eq!(config.number_of_regions(), 9);
555
556 regs.reg_write(0x000, 0b0000_0011_0000_0000_0001_1111_0000_1000);
557 let config = regs.tzc_for_test().build_configuration();
558 assert_eq!(config.number_of_filters(), 4);
559 assert_eq!(config.address_width(), 32);
560 assert_eq!(config.number_of_regions(), 9);
561 }
562
563 #[test]
564 #[should_panic]
565 fn build_config_reserved_filters() {
566 let mut regs = FakeTZCRegisters::new();
567 regs.reg_write(0x000, 0b0000_0010_0000_0000_0010_1111_0000_1000);
568 let config = regs.tzc_for_test().build_configuration();
569
570 config.number_of_filters();
571 }
572
573 #[test]
574 #[should_panic]
575 fn build_config_reserved_address_width() {
576 fn run(address_width: u32, regs: &mut FakeTZCRegisters) {
577 regs.reg_write(
578 0x000,
579 0b0000_0001_0000_0000_0000_0000_0000_1000 | address_width << 8,
580 );
581 regs.tzc_for_test().build_configuration().address_width();
582 }
583
584 let mut regs = FakeTZCRegisters::new();
585
586 run(0b11_0011, &mut regs);
587 run(0b11_1101, &mut regs);
588 run(0b00_0000, &mut regs);
589 }
590
591 #[test]
592 #[should_panic]
593 fn build_config_reserved_regions() {
594 fn run(region_count: u32, regs: &mut FakeTZCRegisters) {
595 regs.reg_write(
596 0x000,
597 0b0000_0001_0000_0000_0011_1111_0000_0000 | region_count,
598 );
599 regs.tzc_for_test()
600 .build_configuration()
601 .number_of_regions();
602 }
603
604 let mut regs = FakeTZCRegisters::new();
605
606 run(0b1_1111, &mut regs);
607 run(0b0_0000, &mut regs);
608 run(0b0_1100, &mut regs);
609 }
610
611 #[test]
612 fn build_config_64_bit_address_region() {
613 let mut regs = FakeTZCRegisters::new();
614
615 regs.reg_write(0x000, 0b0000_0000_0000_0000_0011_1111_0000_1000);
617
618 let mut tzc = regs.tzc_for_test();
619
620 let region = tzc.region(1);
621 assert!(region.is_some());
622 assert_eq!(u64::MAX, region.unwrap().address_width_mask);
623
624 let region = tzc.region_mut(1);
625 assert!(region.is_some());
626 assert_eq!(u64::MAX, region.unwrap().address_width_mask);
627 }
628
629 #[test]
630 fn get_action() {
631 let mut regs = FakeTZCRegisters::new();
632
633 regs.reg_write(0x004, 0b0000_0000_0000_0000_0000_0000_0000_0000);
634 assert_eq!(regs.tzc_for_test().action(), ActionRegister::TZCINTLOW_OKAY);
635
636 regs.reg_write(0x004, 0b0000_0000_0000_0000_0000_0000_0000_0001);
637 assert_eq!(
638 regs.tzc_for_test().action(),
639 ActionRegister::TZCINTLOW_DECERR
640 );
641
642 regs.reg_write(0x004, 0b0000_0000_0000_0000_0000_0000_0000_0010);
643 assert_eq!(
644 regs.tzc_for_test().action(),
645 ActionRegister::TZCINTHIGH_OKAY
646 );
647
648 regs.reg_write(0x004, 0b0000_0000_0000_0000_0000_0000_0000_0011);
649 assert_eq!(
650 regs.tzc_for_test().action(),
651 ActionRegister::TZCINTHIGH_DECERR
652 );
653 }
654
655 #[test]
656 fn set_action() {
657 let mut regs = FakeTZCRegisters::new();
658 let mut tzc = regs.tzc_for_test();
659
660 tzc.set_action(ActionRegister::TZCINTLOW_OKAY);
661 assert_eq!(tzc.action(), ActionRegister::TZCINTLOW_OKAY);
662
663 tzc.set_action(ActionRegister::TZCINTLOW_DECERR);
664 assert_eq!(tzc.action(), ActionRegister::TZCINTLOW_DECERR);
665
666 tzc.set_action(ActionRegister::TZCINTHIGH_OKAY);
667 assert_eq!(tzc.action(), ActionRegister::TZCINTHIGH_OKAY);
668
669 tzc.set_action(ActionRegister::TZCINTHIGH_DECERR);
670 assert_eq!(tzc.action(), ActionRegister::TZCINTHIGH_DECERR);
671 }
672
673 #[test]
674 fn gate_keeper_oob() {
675 let mut regs = FakeTZCRegisters::new();
676 regs.reg_write(0x008, 0b0000_0000_0000_0010_0000_0000_0000_0000);
677 let mut tzc = regs.tzc_for_test();
678
679 assert!(tzc.gate_keeper(2).is_none());
680 assert!(tzc.gate_keeper(3).is_none());
681 assert!(tzc.gate_keeper(4).is_none());
682 assert!(tzc.gate_keeper(18).is_none());
683
684 assert!(tzc.gate_keeper_mut(2).is_none());
685 assert!(tzc.gate_keeper_mut(3).is_none());
686 assert!(tzc.gate_keeper_mut(4).is_none());
687 assert!(tzc.gate_keeper_mut(18).is_none());
688 }
689
690 #[test]
691 fn gate_keeper_status() {
692 let mut regs = FakeTZCRegisters::new();
693 regs.reg_write(0x008, 0b0000_0000_0000_0010_0000_0000_0000_0000);
694 let tzc = regs.tzc_for_test();
695
696 assert_eq!(
697 tzc.gate_keeper(0).unwrap().status(),
698 GateKeeperStatus::Closed
699 );
700 assert_eq!(
701 tzc.gate_keeper(1).unwrap().status(),
702 GateKeeperStatus::Opened
703 );
704 }
705
706 #[test]
707 fn gate_keeper_request() {
708 let mut regs = FakeTZCRegisters::new();
709 regs.reg_write(0x008, 0b0000_0000_0000_0010_0000_0000_0000_0001);
710 let mut tzc = regs.tzc_for_test();
711
712 tzc.gate_keeper_mut(0)
713 .unwrap()
714 .request(GateKeeperStatus::Closed);
715 tzc.gate_keeper_mut(1)
716 .unwrap()
717 .request(GateKeeperStatus::Opened);
718
719 assert_eq!(
720 regs.reg_read(0x008),
721 0b0000_0000_0000_0010_0000_0000_0000_0010,
722 )
723 }
724
725 #[test]
726 fn get_speculation_control() {
727 fn run(flags: u32, regs: &mut FakeTZCRegisters, value: SpeculationControlRegister) {
728 regs.reg_write(0x00C, flags);
729 let spec = regs.tzc_for_test().speculation_control();
730 assert_eq!(spec, value);
731 }
732
733 let mut regs = FakeTZCRegisters::new();
734
735 run(0b00, &mut regs, SpeculationControlRegister::empty());
736 run(
737 0b01,
738 &mut regs,
739 SpeculationControlRegister::READ_SPEC_DISABLE,
740 );
741 run(
742 0b10,
743 &mut regs,
744 SpeculationControlRegister::WRITE_SPEC_DISABLE,
745 );
746 run(
747 0b11,
748 &mut regs,
749 SpeculationControlRegister::READ_SPEC_DISABLE
750 | SpeculationControlRegister::WRITE_SPEC_DISABLE,
751 );
752 }
753
754 #[test]
755 fn set_speculation_control() {
756 fn run(flags: u32, regs: &mut FakeTZCRegisters, value: SpeculationControlRegister) {
757 regs.tzc_for_test().set_speculation_control(value);
758 assert_eq!(regs.reg_read(0x00C), flags);
759 }
760
761 let mut regs = FakeTZCRegisters::new();
762
763 run(0b00, &mut regs, SpeculationControlRegister::empty());
764 run(
765 0b01,
766 &mut regs,
767 SpeculationControlRegister::READ_SPEC_DISABLE,
768 );
769 run(
770 0b10,
771 &mut regs,
772 SpeculationControlRegister::WRITE_SPEC_DISABLE,
773 );
774 run(
775 0b11,
776 &mut regs,
777 SpeculationControlRegister::READ_SPEC_DISABLE
778 | SpeculationControlRegister::WRITE_SPEC_DISABLE,
779 );
780 }
781
782 #[test]
783 pub fn interrupt_status() {
784 let mut regs = FakeTZCRegisters::new();
785 regs.reg_write(0x010, 0b0000_0000_0000_0010_0000_0001_0000_0010);
786 let mut tzc = regs.tzc_for_test();
787
788 let status = tzc.interrupt_status();
789
790 assert!(!status.overlap(0));
791 assert!(status.overlap(1));
792
793 assert!(status.overrun(0));
794 assert!(!status.overrun(1));
795
796 assert!(!status.status(0));
797 assert!(status.status(1));
798 }
799
800 #[test]
801 pub fn interrupt_clear() {
802 let mut regs = FakeTZCRegisters::new();
803 let mut tzc = regs.tzc_for_test();
804
805 let clear = InterruptClearRegister::new(&[0, 3]);
806 tzc.clear_interrupts(clear);
807
808 assert_eq!(
809 regs.reg_read(0x014),
810 0b0000_0000_0000_0000_0000_0000_0000_1001
811 );
812 }
813
814 #[test]
815 fn peripheral_id() {
816 let mut regs = FakeTZCRegisters::new();
817 regs.reg_write(0xFD0, 0x04);
818 regs.reg_write(0xFD4, 0x00);
819 regs.reg_write(0xFD8, 0x00);
820 regs.reg_write(0xFDC, 0x00);
821 regs.reg_write(0xFE0, 0x60);
822 regs.reg_write(0xFE4, 0xB4);
823 regs.reg_write(0xFE8, 0x2B);
824 regs.reg_write(0xFEC, 0x00);
825
826 let tzc = regs.tzc_for_test();
827 assert_eq!(tzc.peripheral_id(), 0x0000_0004_002B_B460);
828 }
829
830 #[test]
831 fn component_id() {
832 let mut regs = FakeTZCRegisters::new();
833 regs.reg_write(0xFF0, 0x0D);
834 regs.reg_write(0xFF4, 0xF0);
835 regs.reg_write(0xFF8, 0x05);
836 regs.reg_write(0xFFC, 0xB1);
837
838 let tzc = regs.tzc_for_test();
839 assert_eq!(tzc.component_id(), 0xB105F00D);
840 }
841
842 #[test]
843 fn fail_oob() {
844 let mut regs = FakeTZCRegisters::new();
845 let tzc = regs.tzc_for_test();
846
847 assert!(tzc.filter_failure(4).is_none());
848 assert!(tzc.filter_failure(8).is_none());
849 assert!(tzc.filter_failure(123124).is_none());
850 }
851
852 #[test]
853 fn region_oob() {
854 let mut regs = FakeTZCRegisters::new();
855 let tzc = regs.tzc_for_test();
856
857 assert!(tzc.region(9).is_none());
858 assert!(tzc.region(32).is_none());
859 assert!(tzc.region(123124).is_none());
860 }
861
862 #[test]
863 fn region_mut_oob() {
864 let mut regs = FakeTZCRegisters::new();
865 let mut tzc = regs.tzc_for_test();
866
867 assert!(tzc.region_mut(9).is_none());
868 assert!(tzc.region_mut(32).is_none());
869 assert!(tzc.region_mut(123124).is_none());
870 }
871}