1+ use log:: debug;
2+ use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
13/// LoongArch IOCSR Mailbox and Control Registers
24///
35/// This module provides emulation for LoongArch IOCSR (I/O Control and Status Register)
46/// mailbox system used for inter-processor communication.
5-
67use std:: sync:: Arc ;
7- use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
8- use log:: debug;
98
109/// Maximum Number of LoongArch vCpus supported
11- const MAX_LOONGARCH_VCPUS : usize = 16 ;
10+ const MAX_LOONGARCH_VCPUS : usize = 16 ;
1211
1312/// IOCSR Mailbox addresses (each 8 bytes apart)
1413pub const LOONGARCH_IOCSR_MBUF0 : u64 = 0x1020 ;
1514pub const LOONGARCH_IOCSR_MBUF1 : u64 = 0x1028 ;
1615pub const LOONGARCH_IOCSR_MBUF2 : u64 = 0x1030 ;
1716pub const LOONGARCH_IOCSR_MBUF3 : u64 = 0x1038 ;
1817
19-
2018/// IOCSR Mailbox send command register
2119pub const LOONGARCH_IOCSR_MBUF_SEND : u64 = 0x1048 ;
2220
@@ -61,12 +59,14 @@ impl LoongArchIocsrState {
6159 Self {
6260 misc_func : AtomicU64 :: new ( 0 ) ,
6361 mailboxes : ( 0 ..count)
64- . map ( |_| [
65- AtomicU64 :: new ( 0 ) ,
66- AtomicU64 :: new ( 0 ) ,
67- AtomicU64 :: new ( 0 ) ,
68- AtomicU64 :: new ( 0 ) ,
69- ] )
62+ . map ( |_| {
63+ [
64+ AtomicU64 :: new ( 0 ) ,
65+ AtomicU64 :: new ( 0 ) ,
66+ AtomicU64 :: new ( 0 ) ,
67+ AtomicU64 :: new ( 0 ) ,
68+ ]
69+ } )
7070 . collect ( ) ,
7171 }
7272 }
@@ -100,6 +100,7 @@ impl LoongArchIocsrState {
100100 /// Process a mailbox send command
101101 ///
102102 /// This function parses the MBUF_SEND register value and updates the target CPU's mailbox.
103+ /// Currently used only for SMP support, which is disabled in single-vCPU mode.
103104 ///
104105 /// # Arguments
105106 /// * `value` - The 64-bit value written to MBUF_SEND register
@@ -113,13 +114,21 @@ impl LoongArchIocsrState {
113114 pub fn process_mbuf_send ( & self , value : u64 ) -> Result < ( ) , String > {
114115 // Extract fields from the value
115116 let target_cpu = ( ( value >> IOCSR_MBUF_SEND_CPU_SHIFT ) & 0x3FFF ) as usize ;
116- let box_hi = ( ( value >> 3 ) & 1 ) != 0 ;
117- let box_lo = ( ( value >> 2 ) & 1 ) != 0 ;
118- let box_num = ( box_lo as u32 ) ^ ( box_hi as u32 ) ;
117+ // Linux encodes mailbox selector as:
118+ // (IOCSR_MBUF_SEND_BOX_{LO,HI}(box) << IOCSR_MBUF_SEND_BOX_SHIFT)
119+ // where BOX_LO(box)=(box<<1), BOX_HI(box)=((box<<1)+1).
120+ // So the packed field is 3 bits: [box_num(2b), hi_low(1b)].
121+ let box_sel = ( ( value >> IOCSR_MBUF_SEND_BOX_SHIFT ) & 0x7 ) as u32 ;
122+ let box_hi = ( box_sel & 0x1 ) != 0 ;
123+ let box_num = ( box_sel >> 1 ) as usize ;
119124 let data32 = ( ( value >> IOCSR_MBUF_SEND_BUF_SHIFT ) & 0xFFFFFFFF ) as u32 ;
120125 // Validate target CPU
121126 if target_cpu >= self . mailboxes . len ( ) {
122- return Err ( format ! ( "Invalid target CPU: {} (max: {})" , target_cpu, self . mailboxes. len( ) - 1 ) ) ;
127+ return Err ( format ! (
128+ "Invalid target CPU: {} (max: {})" ,
129+ target_cpu,
130+ self . mailboxes. len( ) - 1
131+ ) ) ;
123132 }
124133 // Validate mailbox number
125134 if box_num >= 4 {
@@ -128,14 +137,14 @@ impl LoongArchIocsrState {
128137 // Update the target mailbox
129138 if box_hi {
130139 // Write high 32 bits
131- let current = self . read_mailbox ( target_cpu, box_num as usize ) ;
140+ let current = self . read_mailbox ( target_cpu, box_num) ;
132141 let new_val = ( current & 0xFFFFFFFF ) | ( ( data32 as u64 ) << 32 ) ;
133- self . write_mailbox ( target_cpu, box_num as usize , new_val) ;
142+ self . write_mailbox ( target_cpu, box_num, new_val) ;
134143 } else {
135144 // Write low 32 bits
136- let current = self . read_mailbox ( target_cpu, box_num as usize ) ;
145+ let current = self . read_mailbox ( target_cpu, box_num) ;
137146 let new_val = ( current & 0xFFFFFFFF00000000 ) | ( data32 as u64 ) ;
138- self . write_mailbox ( target_cpu, box_num as usize , new_val) ;
147+ self . write_mailbox ( target_cpu, box_num, new_val) ;
139148 }
140149 Ok ( ( ) )
141150 }
@@ -168,7 +177,8 @@ pub fn process_iocsr_read(
168177 addr : u64 ,
169178 data : & mut [ u8 ] ,
170179 iocsr_state : & Arc < LoongArchIocsrState > ,
171- cpu_id : u8 ) -> IocsrReadResult {
180+ cpu_id : u8 ,
181+ ) -> IocsrReadResult {
172182 match ( addr, data. len ( ) ) {
173183 ( LOONGARCH_IOCSR_FEATURES , 4 ) => {
174184 // Feature flags: EXTIOI, CSRIPI, VM support
@@ -208,7 +218,8 @@ pub fn process_iocsr_write(
208218 addr : u64 ,
209219 data : & [ u8 ] ,
210220 iocsr_state : & Arc < LoongArchIocsrState > ,
211- cpu_id : u8 ) -> IocsrWriteResult {
221+ cpu_id : u8 ,
222+ ) -> IocsrWriteResult {
212223 match ( addr, data. len ( ) ) {
213224 ( LOONGARCH_IOCSR_MISC_FUNC , 8 ) => {
214225 // Miscellaneous function register
0 commit comments