xref: /openbmc/qemu/rust/hw/char/pl011/src/device.rs (revision 26453a7f3572068d2731c9f712b26ca2f74097e0)
1 // Copyright 2024, Linaro Limited
2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 use std::{
6     ffi::{c_int, c_void, CStr},
7     mem::size_of,
8     ptr::NonNull,
9 };
10 
11 use qemu_api::{
12     bindings::{qdev_prop_bool, qdev_prop_chr},
13     chardev::{CharBackend, Chardev, Event},
14     impl_vmstate_forward,
15     irq::{IRQState, InterruptSource},
16     log::Log,
17     log_mask_ln,
18     memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder},
19     prelude::*,
20     qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesImpl},
21     qom::{ObjectImpl, Owned, ParentField, ParentInit},
22     static_assert,
23     sysbus::{SysBusDevice, SysBusDeviceImpl},
24     uninit_field_mut,
25     vmstate::VMStateDescription,
26     vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_unused,
27     zeroable::Zeroable,
28 };
29 
30 use crate::registers::{self, Interrupt, RegisterOffset};
31 
32 // TODO: You must disable the UART before any of the control registers are
33 // reprogrammed. When the UART is disabled in the middle of transmission or
34 // reception, it completes the current character before stopping
35 
36 /// Integer Baud Rate Divider, `UARTIBRD`
37 const IBRD_MASK: u32 = 0xffff;
38 
39 /// Fractional Baud Rate Divider, `UARTFBRD`
40 const FBRD_MASK: u32 = 0x3f;
41 
42 /// QEMU sourced constant.
43 pub const PL011_FIFO_DEPTH: u32 = 16;
44 
45 #[derive(Clone, Copy)]
46 struct DeviceId(&'static [u8; 8]);
47 
48 impl std::ops::Index<hwaddr> for DeviceId {
49     type Output = u8;
50 
index(&self, idx: hwaddr) -> &Self::Output51     fn index(&self, idx: hwaddr) -> &Self::Output {
52         &self.0[idx as usize]
53     }
54 }
55 
56 // FIFOs use 32-bit indices instead of usize, for compatibility with
57 // the migration stream produced by the C version of this device.
58 #[repr(transparent)]
59 #[derive(Debug, Default)]
60 pub struct Fifo([registers::Data; PL011_FIFO_DEPTH as usize]);
61 impl_vmstate_forward!(Fifo);
62 
63 impl Fifo {
len(&self) -> u3264     const fn len(&self) -> u32 {
65         self.0.len() as u32
66     }
67 }
68 
69 impl std::ops::IndexMut<u32> for Fifo {
index_mut(&mut self, idx: u32) -> &mut Self::Output70     fn index_mut(&mut self, idx: u32) -> &mut Self::Output {
71         &mut self.0[idx as usize]
72     }
73 }
74 
75 impl std::ops::Index<u32> for Fifo {
76     type Output = registers::Data;
77 
index(&self, idx: u32) -> &Self::Output78     fn index(&self, idx: u32) -> &Self::Output {
79         &self.0[idx as usize]
80     }
81 }
82 
83 #[repr(C)]
84 #[derive(Debug, Default)]
85 pub struct PL011Registers {
86     #[doc(alias = "fr")]
87     pub flags: registers::Flags,
88     #[doc(alias = "lcr")]
89     pub line_control: registers::LineControl,
90     #[doc(alias = "rsr")]
91     pub receive_status_error_clear: registers::ReceiveStatusErrorClear,
92     #[doc(alias = "cr")]
93     pub control: registers::Control,
94     pub dmacr: u32,
95     pub int_enabled: Interrupt,
96     pub int_level: Interrupt,
97     pub read_fifo: Fifo,
98     pub ilpr: u32,
99     pub ibrd: u32,
100     pub fbrd: u32,
101     pub ifl: u32,
102     pub read_pos: u32,
103     pub read_count: u32,
104     pub read_trigger: u32,
105 }
106 
107 #[repr(C)]
108 #[derive(qemu_api_macros::Object)]
109 /// PL011 Device Model in QEMU
110 pub struct PL011State {
111     pub parent_obj: ParentField<SysBusDevice>,
112     pub iomem: MemoryRegion,
113     #[doc(alias = "chr")]
114     pub char_backend: CharBackend,
115     pub regs: BqlRefCell<PL011Registers>,
116     /// QEMU interrupts
117     ///
118     /// ```text
119     ///  * sysbus MMIO region 0: device registers
120     ///  * sysbus IRQ 0: `UARTINTR` (combined interrupt line)
121     ///  * sysbus IRQ 1: `UARTRXINTR` (receive FIFO interrupt line)
122     ///  * sysbus IRQ 2: `UARTTXINTR` (transmit FIFO interrupt line)
123     ///  * sysbus IRQ 3: `UARTRTINTR` (receive timeout interrupt line)
124     ///  * sysbus IRQ 4: `UARTMSINTR` (momem status interrupt line)
125     ///  * sysbus IRQ 5: `UARTEINTR` (error interrupt line)
126     /// ```
127     #[doc(alias = "irq")]
128     pub interrupts: [InterruptSource; IRQMASK.len()],
129     #[doc(alias = "clk")]
130     pub clock: Owned<Clock>,
131     #[doc(alias = "migrate_clk")]
132     pub migrate_clock: bool,
133 }
134 
135 // Some C users of this device embed its state struct into their own
136 // structs, so the size of the Rust version must not be any larger
137 // than the size of the C one. If this assert triggers you need to
138 // expand the padding_for_rust[] array in the C PL011State struct.
139 static_assert!(size_of::<PL011State>() <= size_of::<qemu_api::bindings::PL011State>());
140 
141 qom_isa!(PL011State : SysBusDevice, DeviceState, Object);
142 
143 #[repr(C)]
144 pub struct PL011Class {
145     parent_class: <SysBusDevice as ObjectType>::Class,
146     /// The byte string that identifies the device.
147     device_id: DeviceId,
148 }
149 
150 trait PL011Impl: SysBusDeviceImpl + IsA<PL011State> {
151     const DEVICE_ID: DeviceId;
152 }
153 
154 impl PL011Class {
class_init<T: PL011Impl>(&mut self)155     fn class_init<T: PL011Impl>(&mut self) {
156         self.device_id = T::DEVICE_ID;
157         self.parent_class.class_init::<T>();
158     }
159 }
160 
161 unsafe impl ObjectType for PL011State {
162     type Class = PL011Class;
163     const TYPE_NAME: &'static CStr = crate::TYPE_PL011;
164 }
165 
166 impl PL011Impl for PL011State {
167     const DEVICE_ID: DeviceId = DeviceId(&[0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1]);
168 }
169 
170 impl ObjectImpl for PL011State {
171     type ParentType = SysBusDevice;
172 
173     const INSTANCE_INIT: Option<unsafe fn(ParentInit<Self>)> = Some(Self::init);
174     const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init);
175     const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
176 }
177 
178 impl DeviceImpl for PL011State {
properties() -> &'static [Property]179     fn properties() -> &'static [Property] {
180         &PL011_PROPERTIES
181     }
vmsd() -> Option<&'static VMStateDescription>182     fn vmsd() -> Option<&'static VMStateDescription> {
183         Some(&VMSTATE_PL011)
184     }
185     const REALIZE: Option<fn(&Self) -> qemu_api::Result<()>> = Some(Self::realize);
186 }
187 
188 impl ResettablePhasesImpl for PL011State {
189     const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset_hold);
190 }
191 
192 impl SysBusDeviceImpl for PL011State {}
193 
194 impl PL011Registers {
read(&mut self, offset: RegisterOffset) -> (bool, u32)195     pub(self) fn read(&mut self, offset: RegisterOffset) -> (bool, u32) {
196         use RegisterOffset::*;
197 
198         let mut update = false;
199         let result = match offset {
200             DR => self.read_data_register(&mut update),
201             RSR => u32::from(self.receive_status_error_clear),
202             FR => u32::from(self.flags),
203             FBRD => self.fbrd,
204             ILPR => self.ilpr,
205             IBRD => self.ibrd,
206             LCR_H => u32::from(self.line_control),
207             CR => u32::from(self.control),
208             FLS => self.ifl,
209             IMSC => u32::from(self.int_enabled),
210             RIS => u32::from(self.int_level),
211             MIS => u32::from(self.int_level & self.int_enabled),
212             ICR => {
213                 // "The UARTICR Register is the interrupt clear register and is write-only"
214                 // Source: ARM DDI 0183G 3.3.13 Interrupt Clear Register, UARTICR
215                 0
216             }
217             DMACR => self.dmacr,
218         };
219         (update, result)
220     }
221 
write( &mut self, offset: RegisterOffset, value: u32, char_backend: &CharBackend, ) -> bool222     pub(self) fn write(
223         &mut self,
224         offset: RegisterOffset,
225         value: u32,
226         char_backend: &CharBackend,
227     ) -> bool {
228         // eprintln!("write offset {offset} value {value}");
229         use RegisterOffset::*;
230         match offset {
231             DR => return self.write_data_register(value),
232             RSR => {
233                 self.receive_status_error_clear = 0.into();
234             }
235             FR => {
236                 // flag writes are ignored
237             }
238             ILPR => {
239                 self.ilpr = value;
240             }
241             IBRD => {
242                 self.ibrd = value;
243             }
244             FBRD => {
245                 self.fbrd = value;
246             }
247             LCR_H => {
248                 let new_val: registers::LineControl = value.into();
249                 // Reset the FIFO state on FIFO enable or disable
250                 if self.line_control.fifos_enabled() != new_val.fifos_enabled() {
251                     self.reset_rx_fifo();
252                     self.reset_tx_fifo();
253                 }
254                 let update = (self.line_control.send_break() != new_val.send_break()) && {
255                     let break_enable = new_val.send_break();
256                     let _ = char_backend.send_break(break_enable);
257                     self.loopback_break(break_enable)
258                 };
259                 self.line_control = new_val;
260                 self.set_read_trigger();
261                 return update;
262             }
263             CR => {
264                 // ??? Need to implement the enable bit.
265                 self.control = value.into();
266                 return self.loopback_mdmctrl();
267             }
268             FLS => {
269                 self.ifl = value;
270                 self.set_read_trigger();
271             }
272             IMSC => {
273                 self.int_enabled = Interrupt::from(value);
274                 return true;
275             }
276             RIS => {}
277             MIS => {}
278             ICR => {
279                 self.int_level &= !Interrupt::from(value);
280                 return true;
281             }
282             DMACR => {
283                 self.dmacr = value;
284                 if value & 3 > 0 {
285                     log_mask_ln!(Log::Unimp, "pl011: DMA not implemented");
286                 }
287             }
288         }
289         false
290     }
291 
read_data_register(&mut self, update: &mut bool) -> u32292     fn read_data_register(&mut self, update: &mut bool) -> u32 {
293         self.flags.set_receive_fifo_full(false);
294         let c = self.read_fifo[self.read_pos];
295 
296         if self.read_count > 0 {
297             self.read_count -= 1;
298             self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1);
299         }
300         if self.read_count == 0 {
301             self.flags.set_receive_fifo_empty(true);
302         }
303         if self.read_count + 1 == self.read_trigger {
304             self.int_level &= !Interrupt::RX;
305         }
306         self.receive_status_error_clear.set_from_data(c);
307         *update = true;
308         u32::from(c)
309     }
310 
write_data_register(&mut self, value: u32) -> bool311     fn write_data_register(&mut self, value: u32) -> bool {
312         if !self.control.enable_uart() {
313             log_mask_ln!(Log::GuestError, "PL011 data written to disabled UART");
314         }
315         if !self.control.enable_transmit() {
316             log_mask_ln!(Log::GuestError, "PL011 data written to disabled TX UART");
317         }
318         // interrupts always checked
319         let _ = self.loopback_tx(value.into());
320         self.int_level |= Interrupt::TX;
321         true
322     }
323 
324     #[inline]
325     #[must_use]
loopback_tx(&mut self, value: registers::Data) -> bool326     fn loopback_tx(&mut self, value: registers::Data) -> bool {
327         // Caveat:
328         //
329         // In real hardware, TX loopback happens at the serial-bit level
330         // and then reassembled by the RX logics back into bytes and placed
331         // into the RX fifo. That is, loopback happens after TX fifo.
332         //
333         // Because the real hardware TX fifo is time-drained at the frame
334         // rate governed by the configured serial format, some loopback
335         // bytes in TX fifo may still be able to get into the RX fifo
336         // that could be full at times while being drained at software
337         // pace.
338         //
339         // In such scenario, the RX draining pace is the major factor
340         // deciding which loopback bytes get into the RX fifo, unless
341         // hardware flow-control is enabled.
342         //
343         // For simplicity, the above described is not emulated.
344         self.loopback_enabled() && self.fifo_rx_put(value)
345     }
346 
347     #[must_use]
loopback_mdmctrl(&mut self) -> bool348     fn loopback_mdmctrl(&mut self) -> bool {
349         if !self.loopback_enabled() {
350             return false;
351         }
352 
353         /*
354          * Loopback software-driven modem control outputs to modem status inputs:
355          *   FR.RI  <= CR.Out2
356          *   FR.DCD <= CR.Out1
357          *   FR.CTS <= CR.RTS
358          *   FR.DSR <= CR.DTR
359          *
360          * The loopback happens immediately even if this call is triggered
361          * by setting only CR.LBE.
362          *
363          * CTS/RTS updates due to enabled hardware flow controls are not
364          * dealt with here.
365          */
366 
367         self.flags.set_ring_indicator(self.control.out_2());
368         self.flags.set_data_carrier_detect(self.control.out_1());
369         self.flags.set_clear_to_send(self.control.request_to_send());
370         self.flags
371             .set_data_set_ready(self.control.data_transmit_ready());
372 
373         // Change interrupts based on updated FR
374         let mut il = self.int_level;
375 
376         il &= !Interrupt::MS;
377 
378         if self.flags.data_set_ready() {
379             il |= Interrupt::DSR;
380         }
381         if self.flags.data_carrier_detect() {
382             il |= Interrupt::DCD;
383         }
384         if self.flags.clear_to_send() {
385             il |= Interrupt::CTS;
386         }
387         if self.flags.ring_indicator() {
388             il |= Interrupt::RI;
389         }
390         self.int_level = il;
391         true
392     }
393 
loopback_break(&mut self, enable: bool) -> bool394     fn loopback_break(&mut self, enable: bool) -> bool {
395         enable && self.loopback_tx(registers::Data::BREAK)
396     }
397 
set_read_trigger(&mut self)398     fn set_read_trigger(&mut self) {
399         self.read_trigger = 1;
400     }
401 
reset(&mut self)402     pub fn reset(&mut self) {
403         self.line_control.reset();
404         self.receive_status_error_clear.reset();
405         self.dmacr = 0;
406         self.int_enabled = 0.into();
407         self.int_level = 0.into();
408         self.ilpr = 0;
409         self.ibrd = 0;
410         self.fbrd = 0;
411         self.read_trigger = 1;
412         self.ifl = 0x12;
413         self.control.reset();
414         self.flags.reset();
415         self.reset_rx_fifo();
416         self.reset_tx_fifo();
417     }
418 
reset_rx_fifo(&mut self)419     pub fn reset_rx_fifo(&mut self) {
420         self.read_count = 0;
421         self.read_pos = 0;
422 
423         // Reset FIFO flags
424         self.flags.set_receive_fifo_full(false);
425         self.flags.set_receive_fifo_empty(true);
426     }
427 
reset_tx_fifo(&mut self)428     pub fn reset_tx_fifo(&mut self) {
429         // Reset FIFO flags
430         self.flags.set_transmit_fifo_full(false);
431         self.flags.set_transmit_fifo_empty(true);
432     }
433 
434     #[inline]
fifo_enabled(&self) -> bool435     pub fn fifo_enabled(&self) -> bool {
436         self.line_control.fifos_enabled() == registers::Mode::FIFO
437     }
438 
439     #[inline]
loopback_enabled(&self) -> bool440     pub fn loopback_enabled(&self) -> bool {
441         self.control.enable_loopback()
442     }
443 
444     #[inline]
fifo_depth(&self) -> u32445     pub fn fifo_depth(&self) -> u32 {
446         // Note: FIFO depth is expected to be power-of-2
447         if self.fifo_enabled() {
448             return PL011_FIFO_DEPTH;
449         }
450         1
451     }
452 
453     #[must_use]
fifo_rx_put(&mut self, value: registers::Data) -> bool454     pub fn fifo_rx_put(&mut self, value: registers::Data) -> bool {
455         let depth = self.fifo_depth();
456         assert!(depth > 0);
457         let slot = (self.read_pos + self.read_count) & (depth - 1);
458         self.read_fifo[slot] = value;
459         self.read_count += 1;
460         self.flags.set_receive_fifo_empty(false);
461         if self.read_count == depth {
462             self.flags.set_receive_fifo_full(true);
463         }
464 
465         if self.read_count == self.read_trigger {
466             self.int_level |= Interrupt::RX;
467             return true;
468         }
469         false
470     }
471 
post_load(&mut self) -> Result<(), ()>472     pub fn post_load(&mut self) -> Result<(), ()> {
473         /* Sanity-check input state */
474         if self.read_pos >= self.read_fifo.len() || self.read_count > self.read_fifo.len() {
475             return Err(());
476         }
477 
478         if !self.fifo_enabled() && self.read_count > 0 && self.read_pos > 0 {
479             // Older versions of PL011 didn't ensure that the single
480             // character in the FIFO in FIFO-disabled mode is in
481             // element 0 of the array; convert to follow the current
482             // code's assumptions.
483             self.read_fifo[0] = self.read_fifo[self.read_pos];
484             self.read_pos = 0;
485         }
486 
487         self.ibrd &= IBRD_MASK;
488         self.fbrd &= FBRD_MASK;
489 
490         Ok(())
491     }
492 }
493 
494 impl PL011State {
495     /// Initializes a pre-allocated, uninitialized instance of `PL011State`.
496     ///
497     /// # Safety
498     ///
499     /// `self` must point to a correctly sized and aligned location for the
500     /// `PL011State` type. It must not be called more than once on the same
501     /// location/instance. All its fields are expected to hold uninitialized
502     /// values with the sole exception of `parent_obj`.
init(mut this: ParentInit<Self>)503     unsafe fn init(mut this: ParentInit<Self>) {
504         static PL011_OPS: MemoryRegionOps<PL011State> = MemoryRegionOpsBuilder::<PL011State>::new()
505             .read(&PL011State::read)
506             .write(&PL011State::write)
507             .native_endian()
508             .impl_sizes(4, 4)
509             .build();
510 
511         // SAFETY: this and this.iomem are guaranteed to be valid at this point
512         MemoryRegion::init_io(
513             &mut uninit_field_mut!(*this, iomem),
514             &PL011_OPS,
515             "pl011",
516             0x1000,
517         );
518 
519         uninit_field_mut!(*this, regs).write(Default::default());
520 
521         let clock = DeviceState::init_clock_in(
522             &mut this,
523             "clk",
524             &Self::clock_update,
525             ClockEvent::ClockUpdate,
526         );
527         uninit_field_mut!(*this, clock).write(clock);
528     }
529 
clock_update(&self, _event: ClockEvent)530     const fn clock_update(&self, _event: ClockEvent) {
531         /* pl011_trace_baudrate_change(s); */
532     }
533 
post_init(&self)534     fn post_init(&self) {
535         self.init_mmio(&self.iomem);
536         for irq in self.interrupts.iter() {
537             self.init_irq(irq);
538         }
539     }
540 
read(&self, offset: hwaddr, _size: u32) -> u64541     fn read(&self, offset: hwaddr, _size: u32) -> u64 {
542         match RegisterOffset::try_from(offset) {
543             Err(v) if (0x3f8..0x400).contains(&(v >> 2)) => {
544                 let device_id = self.get_class().device_id;
545                 u64::from(device_id[(offset - 0xfe0) >> 2])
546             }
547             Err(_) => {
548                 log_mask_ln!(Log::GuestError, "PL011State::read: Bad offset {offset}");
549                 0
550             }
551             Ok(field) => {
552                 let (update_irq, result) = self.regs.borrow_mut().read(field);
553                 if update_irq {
554                     self.update();
555                     self.char_backend.accept_input();
556                 }
557                 result.into()
558             }
559         }
560     }
561 
write(&self, offset: hwaddr, value: u64, _size: u32)562     fn write(&self, offset: hwaddr, value: u64, _size: u32) {
563         let mut update_irq = false;
564         if let Ok(field) = RegisterOffset::try_from(offset) {
565             // qemu_chr_fe_write_all() calls into the can_receive
566             // callback, so handle writes before entering PL011Registers.
567             if field == RegisterOffset::DR {
568                 // ??? Check if transmitter is enabled.
569                 let ch: [u8; 1] = [value as u8];
570                 // XXX this blocks entire thread. Rewrite to use
571                 // qemu_chr_fe_write and background I/O callbacks
572                 let _ = self.char_backend.write_all(&ch);
573             }
574 
575             update_irq = self
576                 .regs
577                 .borrow_mut()
578                 .write(field, value as u32, &self.char_backend);
579         } else {
580             log_mask_ln!(
581                 Log::GuestError,
582                 "PL011State::write: Bad offset {offset} value {value}"
583             );
584         }
585         if update_irq {
586             self.update();
587         }
588     }
589 
can_receive(&self) -> u32590     fn can_receive(&self) -> u32 {
591         let regs = self.regs.borrow();
592         // trace_pl011_can_receive(s->lcr, s->read_count, r);
593         regs.fifo_depth() - regs.read_count
594     }
595 
receive(&self, buf: &[u8])596     fn receive(&self, buf: &[u8]) {
597         let mut regs = self.regs.borrow_mut();
598         if regs.loopback_enabled() {
599             // In loopback mode, the RX input signal is internally disconnected
600             // from the entire receiving logics; thus, all inputs are ignored,
601             // and BREAK detection on RX input signal is also not performed.
602             return;
603         }
604 
605         let mut update_irq = false;
606         for &c in buf {
607             let c: u32 = c.into();
608             update_irq |= regs.fifo_rx_put(c.into());
609         }
610 
611         // Release the BqlRefCell before calling self.update()
612         drop(regs);
613         if update_irq {
614             self.update();
615         }
616     }
617 
event(&self, event: Event)618     fn event(&self, event: Event) {
619         let mut update_irq = false;
620         let mut regs = self.regs.borrow_mut();
621         if event == Event::CHR_EVENT_BREAK && !regs.loopback_enabled() {
622             update_irq = regs.fifo_rx_put(registers::Data::BREAK);
623         }
624         // Release the BqlRefCell before calling self.update()
625         drop(regs);
626 
627         if update_irq {
628             self.update()
629         }
630     }
631 
realize(&self) -> qemu_api::Result<()>632     fn realize(&self) -> qemu_api::Result<()> {
633         self.char_backend
634             .enable_handlers(self, Self::can_receive, Self::receive, Self::event);
635         Ok(())
636     }
637 
reset_hold(&self, _type: ResetType)638     fn reset_hold(&self, _type: ResetType) {
639         self.regs.borrow_mut().reset();
640     }
641 
update(&self)642     fn update(&self) {
643         let regs = self.regs.borrow();
644         let flags = regs.int_level & regs.int_enabled;
645         for (irq, i) in self.interrupts.iter().zip(IRQMASK) {
646             irq.set(flags.any_set(i));
647         }
648     }
649 
post_load(&self, _version_id: u32) -> Result<(), ()>650     pub fn post_load(&self, _version_id: u32) -> Result<(), ()> {
651         self.regs.borrow_mut().post_load()
652     }
653 }
654 
655 /// Which bits in the interrupt status matter for each outbound IRQ line ?
656 const IRQMASK: [Interrupt; 6] = [
657     Interrupt::all(),
658     Interrupt::RX,
659     Interrupt::TX,
660     Interrupt::RT,
661     Interrupt::MS,
662     Interrupt::E,
663 ];
664 
665 /// # Safety
666 ///
667 /// We expect the FFI user of this function to pass a valid pointer for `chr`
668 /// and `irq`.
669 #[no_mangle]
pl011_create( addr: u64, irq: *mut IRQState, chr: *mut Chardev, ) -> *mut DeviceState670 pub unsafe extern "C" fn pl011_create(
671     addr: u64,
672     irq: *mut IRQState,
673     chr: *mut Chardev,
674 ) -> *mut DeviceState {
675     // SAFETY: The callers promise that they have owned references.
676     // They do not gift them to pl011_create, so use `Owned::from`.
677     let irq = unsafe { Owned::<IRQState>::from(&*irq) };
678 
679     let dev = PL011State::new();
680     if !chr.is_null() {
681         let chr = unsafe { Owned::<Chardev>::from(&*chr) };
682         dev.prop_set_chr("chardev", &chr);
683     }
684     dev.sysbus_realize();
685     dev.mmio_map(0, addr);
686     dev.connect_irq(0, &irq);
687 
688     // The pointer is kept alive by the QOM tree; drop the owned ref
689     dev.as_mut_ptr()
690 }
691 
692 #[repr(C)]
693 #[derive(qemu_api_macros::Object)]
694 /// PL011 Luminary device model.
695 pub struct PL011Luminary {
696     parent_obj: ParentField<PL011State>,
697 }
698 
699 qom_isa!(PL011Luminary : PL011State, SysBusDevice, DeviceState, Object);
700 
701 unsafe impl ObjectType for PL011Luminary {
702     type Class = <PL011State as ObjectType>::Class;
703     const TYPE_NAME: &'static CStr = crate::TYPE_PL011_LUMINARY;
704 }
705 
706 impl ObjectImpl for PL011Luminary {
707     type ParentType = PL011State;
708 
709     const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
710 }
711 
712 impl PL011Impl for PL011Luminary {
713     const DEVICE_ID: DeviceId = DeviceId(&[0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1]);
714 }
715 
716 impl DeviceImpl for PL011Luminary {}
717 impl ResettablePhasesImpl for PL011Luminary {}
718 impl SysBusDeviceImpl for PL011Luminary {}
719 
pl011_clock_needed(opaque: *mut c_void) -> bool720 extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
721     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
722     unsafe { state.as_ref().migrate_clock }
723 }
724 
725 /// Migration subsection for [`PL011State`] clock.
726 static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
727     name: c"pl011/clock".as_ptr(),
728     version_id: 1,
729     minimum_version_id: 1,
730     needed: Some(pl011_clock_needed),
731     fields: vmstate_fields! {
732         vmstate_clock!(PL011State, clock),
733     },
734     ..Zeroable::ZERO
735 };
736 
pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int737 extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
738     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
739     let result = unsafe { state.as_ref().post_load(version_id as u32) };
740     if result.is_err() {
741         -1
742     } else {
743         0
744     }
745 }
746 
747 static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
748     name: c"pl011/regs".as_ptr(),
749     version_id: 2,
750     minimum_version_id: 2,
751     fields: vmstate_fields! {
752         vmstate_of!(PL011Registers, flags),
753         vmstate_of!(PL011Registers, line_control),
754         vmstate_of!(PL011Registers, receive_status_error_clear),
755         vmstate_of!(PL011Registers, control),
756         vmstate_of!(PL011Registers, dmacr),
757         vmstate_of!(PL011Registers, int_enabled),
758         vmstate_of!(PL011Registers, int_level),
759         vmstate_of!(PL011Registers, read_fifo),
760         vmstate_of!(PL011Registers, ilpr),
761         vmstate_of!(PL011Registers, ibrd),
762         vmstate_of!(PL011Registers, fbrd),
763         vmstate_of!(PL011Registers, ifl),
764         vmstate_of!(PL011Registers, read_pos),
765         vmstate_of!(PL011Registers, read_count),
766         vmstate_of!(PL011Registers, read_trigger),
767     },
768     ..Zeroable::ZERO
769 };
770 
771 pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
772     name: c"pl011".as_ptr(),
773     version_id: 2,
774     minimum_version_id: 2,
775     post_load: Some(pl011_post_load),
776     fields: vmstate_fields! {
777         vmstate_unused!(core::mem::size_of::<u32>()),
778         vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
779     },
780     subsections: vmstate_subsections! {
781         VMSTATE_PL011_CLOCK
782     },
783     ..Zeroable::ZERO
784 };
785 
786 qemu_api::declare_properties! {
787     PL011_PROPERTIES,
788     qemu_api::define_property!(
789         c"chardev",
790         PL011State,
791         char_backend,
792         unsafe { &qdev_prop_chr },
793         CharBackend
794     ),
795     qemu_api::define_property!(
796         c"migrate-clk",
797         PL011State,
798         migrate_clock,
799         unsafe { &qdev_prop_bool },
800         bool,
801         default = true
802     ),
803 }
804