@@ -77,45 +77,6 @@ void pch_msi_set_irq(struct kvm *kvm, int irq, int level)
7777 eiointc_set_irq (kvm -> arch .eiointc , irq , level );
7878}
7979
80- /*
81- * pch pic register is 64-bit, but it is accessed by 32-bit,
82- * so we use high to get whether low or high 32 bits we want
83- * to read.
84- */
85- static u32 pch_pic_read_reg (u64 * s , int high )
86- {
87- u64 val = * s ;
88-
89- /* read the high 32 bits when high is 1 */
90- return high ? (u32 )(val >> 32 ) : (u32 )val ;
91- }
92-
93- /*
94- * pch pic register is 64-bit, but it is accessed by 32-bit,
95- * so we use high to get whether low or high 32 bits we want
96- * to write.
97- */
98- static u32 pch_pic_write_reg (u64 * s , int high , u32 v )
99- {
100- u64 val = * s , data = v ;
101-
102- if (high ) {
103- /*
104- * Clear val high 32 bits
105- * Write the high 32 bits when the high is 1
106- */
107- * s = (val << 32 >> 32 ) | (data << 32 );
108- val >>= 32 ;
109- } else
110- /*
111- * Clear val low 32 bits
112- * Write the low 32 bits when the high is 0
113- */
114- * s = (val >> 32 << 32 ) | v ;
115-
116- return (u32 )val ;
117- }
118-
11980static int loongarch_pch_pic_read (struct loongarch_pch_pic * s , gpa_t addr , int len , void * val )
12081{
12182 int ret = 0 , offset ;
@@ -205,81 +166,69 @@ static int kvm_pch_pic_read(struct kvm_vcpu *vcpu,
205166static int loongarch_pch_pic_write (struct loongarch_pch_pic * s , gpa_t addr ,
206167 int len , const void * val )
207168{
208- int ret ;
209- u32 old , data , offset , index ;
210- u64 irq ;
169+ int ret = 0 , offset ;
170+ u64 old , data , mask ;
171+ void * ptemp ;
211172
212- ret = 0 ;
213- data = * (u32 * )val ;
214- offset = addr - s -> pch_pic_base ;
173+ switch (len ) {
174+ case 1 :
175+ data = * (u8 * )val ;
176+ mask = 0xFF ;
177+ break ;
178+ case 2 :
179+ data = * (u16 * )val ;
180+ mask = USHRT_MAX ;
181+ break ;
182+ case 4 :
183+ data = * (u32 * )val ;
184+ mask = UINT_MAX ;
185+ break ;
186+ case 8 :
187+ default :
188+ data = * (u64 * )val ;
189+ mask = ULONG_MAX ;
190+ break ;
191+ }
192+
193+ offset = (addr - s -> pch_pic_base ) & 7 ;
194+ mask = mask << (offset * 8 );
195+ data = data << (offset * 8 );
196+ offset = (addr - s -> pch_pic_base ) - offset ;
215197
216198 spin_lock (& s -> lock );
217199 switch (offset ) {
218- case PCH_PIC_MASK_START ... PCH_PIC_MASK_END :
219- offset -= PCH_PIC_MASK_START ;
220- /* get whether high or low 32 bits we want to write */
221- index = offset >> 2 ;
222- old = pch_pic_write_reg (& s -> mask , index , data );
223- /* enable irq when mask value change to 0 */
224- irq = (old & ~data ) << (32 * index );
225- pch_pic_update_batch_irqs (s , irq , 1 );
226- /* disable irq when mask value change to 1 */
227- irq = (~old & data ) << (32 * index );
228- pch_pic_update_batch_irqs (s , irq , 0 );
229- break ;
230- case PCH_PIC_HTMSI_EN_START ... PCH_PIC_HTMSI_EN_END :
231- offset -= PCH_PIC_HTMSI_EN_START ;
232- index = offset >> 2 ;
233- pch_pic_write_reg (& s -> htmsi_en , index , data );
200+ case PCH_PIC_MASK_START :
201+ old = s -> mask ;
202+ s -> mask = (old & ~mask ) | data ;
203+ if (old & ~data )
204+ pch_pic_update_batch_irqs (s , old & ~data , 1 );
205+ if (~old & data )
206+ pch_pic_update_batch_irqs (s , ~old & data , 0 );
234207 break ;
235- case PCH_PIC_EDGE_START ... PCH_PIC_EDGE_END :
236- offset -= PCH_PIC_EDGE_START ;
237- index = offset >> 2 ;
238- /* 1: edge triggered, 0: level triggered */
239- pch_pic_write_reg (& s -> edge , index , data );
240- break ;
241- case PCH_PIC_CLEAR_START ... PCH_PIC_CLEAR_END :
242- offset -= PCH_PIC_CLEAR_START ;
243- index = offset >> 2 ;
244- /* write 1 to clear edge irq */
245- old = pch_pic_read_reg (& s -> irr , index );
246- /*
247- * get the irq bitmap which is edge triggered and
248- * already set and to be cleared
249- */
250- irq = old & pch_pic_read_reg (& s -> edge , index ) & data ;
251- /* write irr to the new state where irqs have been cleared */
252- pch_pic_write_reg (& s -> irr , index , old & ~irq );
253- /* update cleared irqs */
254- pch_pic_update_batch_irqs (s , irq , 0 );
208+ case PCH_PIC_HTMSI_EN_START :
209+ s -> htmsi_en = (s -> htmsi_en & ~mask ) | data ;
255210 break ;
256- case PCH_PIC_AUTO_CTRL0_START ... PCH_PIC_AUTO_CTRL0_END :
257- offset -= PCH_PIC_AUTO_CTRL0_START ;
258- index = offset >> 2 ;
259- /* we only use default mode: fixed interrupt distribution mode */
260- pch_pic_write_reg (& s -> auto_ctrl0 , index , 0 );
211+ case PCH_PIC_EDGE_START :
212+ s -> edge = (s -> edge & ~mask ) | data ;
261213 break ;
262- case PCH_PIC_AUTO_CTRL1_START ... PCH_PIC_AUTO_CTRL1_END :
263- offset -= PCH_PIC_AUTO_CTRL1_START ;
264- index = offset >> 2 ;
265- /* we only use default mode: fixed interrupt distribution mode */
266- pch_pic_write_reg (& s -> auto_ctrl1 , index , 0 );
214+ case PCH_PIC_POLARITY_START :
215+ s -> polarity = (s -> polarity & ~mask ) | data ;
267216 break ;
268- case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END :
269- offset -= PCH_PIC_ROUTE_ENTRY_START ;
270- /* only route to int0: eiointc */
271- s -> route_entry [offset ] = 1 ;
217+ case PCH_PIC_CLEAR_START :
218+ old = s -> irr & s -> edge & data ;
219+ if (old ) {
220+ s -> irr &= ~old ;
221+ pch_pic_update_batch_irqs (s , old , 0 );
222+ }
272223 break ;
273224 case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END :
274- /* route table to eiointc */
275- offset -= PCH_PIC_HTMSI_VEC_START ;
276- s -> htmsi_vector [offset ] = (u8 )data ;
225+ ptemp = s -> htmsi_vector + (offset - PCH_PIC_HTMSI_VEC_START );
226+ * (u64 * )ptemp = (* (u64 * )ptemp & ~mask ) | data ;
277227 break ;
278- case PCH_PIC_POLARITY_START ... PCH_PIC_POLARITY_END :
279- offset -= PCH_PIC_POLARITY_START ;
280- index = offset >> 2 ;
281- /* we only use defalut value 0: high level triggered */
282- pch_pic_write_reg (& s -> polarity , index , 0 );
228+ /* Not implemented */
229+ case PCH_PIC_AUTO_CTRL0_START :
230+ case PCH_PIC_AUTO_CTRL1_START :
231+ case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END :
283232 break ;
284233 default :
285234 ret = - EINVAL ;
0 commit comments