ioapic: introduce ioapic_entry_parse() helper
Abstract IOAPIC entry parsing logic into a helper function. Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									cb135f59b8
								
							
						
					
					
						commit
						c15fa0bea9
					
				
							
								
								
									
										110
									
								
								hw/intc/ioapic.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								hw/intc/ioapic.c
									
									
									
									
									
								
							| @ -50,18 +50,56 @@ static IOAPICCommonState *ioapics[MAX_IOAPICS]; | ||||
| /* global variable from ioapic_common.c */ | ||||
| extern int ioapic_no; | ||||
| 
 | ||||
| struct ioapic_entry_info { | ||||
|     /* fields parsed from IOAPIC entries */ | ||||
|     uint8_t masked; | ||||
|     uint8_t trig_mode; | ||||
|     uint16_t dest_idx; | ||||
|     uint8_t dest_mode; | ||||
|     uint8_t delivery_mode; | ||||
|     uint8_t vector; | ||||
| 
 | ||||
|     /* MSI message generated from above parsed fields */ | ||||
|     uint32_t addr; | ||||
|     uint32_t data; | ||||
| }; | ||||
| 
 | ||||
| static void ioapic_entry_parse(uint64_t entry, struct ioapic_entry_info *info) | ||||
| { | ||||
|     memset(info, 0, sizeof(*info)); | ||||
|     info->masked = (entry >> IOAPIC_LVT_MASKED_SHIFT) & 1; | ||||
|     info->trig_mode = (entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1; | ||||
|     /*
 | ||||
|      * By default, this would be dest_id[8] + reserved[8]. When IR | ||||
|      * is enabled, this would be interrupt_index[15] + | ||||
|      * interrupt_format[1]. This field never means anything, but | ||||
|      * only used to generate corresponding MSI. | ||||
|      */ | ||||
|     info->dest_idx = (entry >> IOAPIC_LVT_DEST_IDX_SHIFT) & 0xffff; | ||||
|     info->dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1; | ||||
|     info->delivery_mode = (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) \ | ||||
|         & IOAPIC_DM_MASK; | ||||
|     if (info->delivery_mode == IOAPIC_DM_EXTINT) { | ||||
|         info->vector = pic_read_irq(isa_pic); | ||||
|     } else { | ||||
|         info->vector = entry & IOAPIC_VECTOR_MASK; | ||||
|     } | ||||
| 
 | ||||
|     info->addr = APIC_DEFAULT_ADDRESS | \ | ||||
|         (info->dest_idx << MSI_ADDR_DEST_IDX_SHIFT) | \ | ||||
|         (info->dest_mode << MSI_ADDR_DEST_MODE_SHIFT); | ||||
|     info->data = (info->vector << MSI_DATA_VECTOR_SHIFT) | \ | ||||
|         (info->trig_mode << MSI_DATA_TRIGGER_SHIFT) | \ | ||||
|         (info->delivery_mode << MSI_DATA_DELIVERY_MODE_SHIFT); | ||||
| } | ||||
| 
 | ||||
| static void ioapic_service(IOAPICCommonState *s) | ||||
| { | ||||
|     AddressSpace *ioapic_as = PC_MACHINE(qdev_get_machine())->ioapic_as; | ||||
|     uint32_t addr, data; | ||||
|     struct ioapic_entry_info info; | ||||
|     uint8_t i; | ||||
|     uint8_t trig_mode; | ||||
|     uint8_t vector; | ||||
|     uint8_t delivery_mode; | ||||
|     uint32_t mask; | ||||
|     uint64_t entry; | ||||
|     uint16_t dest_idx; | ||||
|     uint8_t dest_mode; | ||||
| 
 | ||||
|     for (i = 0; i < IOAPIC_NUM_PINS; i++) { | ||||
|         mask = 1 << i; | ||||
| @ -69,33 +107,18 @@ static void ioapic_service(IOAPICCommonState *s) | ||||
|             int coalesce = 0; | ||||
| 
 | ||||
|             entry = s->ioredtbl[i]; | ||||
|             if (!(entry & IOAPIC_LVT_MASKED)) { | ||||
|                 trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1); | ||||
|                 /*
 | ||||
|                  * By default, this would be dest_id[8] + | ||||
|                  * reserved[8]. When IR is enabled, this would be | ||||
|                  * interrupt_index[15] + interrupt_format[1]. This | ||||
|                  * field never means anything, but only used to | ||||
|                  * generate corresponding MSI. | ||||
|                  */ | ||||
|                 dest_idx = entry >> IOAPIC_LVT_DEST_IDX_SHIFT; | ||||
|                 dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1; | ||||
|                 delivery_mode = | ||||
|                     (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK; | ||||
|                 if (trig_mode == IOAPIC_TRIGGER_EDGE) { | ||||
|             ioapic_entry_parse(entry, &info); | ||||
|             if (!info.masked) { | ||||
|                 if (info.trig_mode == IOAPIC_TRIGGER_EDGE) { | ||||
|                     s->irr &= ~mask; | ||||
|                 } else { | ||||
|                     coalesce = s->ioredtbl[i] & IOAPIC_LVT_REMOTE_IRR; | ||||
|                     s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR; | ||||
|                 } | ||||
|                 if (delivery_mode == IOAPIC_DM_EXTINT) { | ||||
|                     vector = pic_read_irq(isa_pic); | ||||
|                 } else { | ||||
|                     vector = entry & IOAPIC_VECTOR_MASK; | ||||
|                 } | ||||
| 
 | ||||
| #ifdef CONFIG_KVM | ||||
|                 if (kvm_irqchip_is_split()) { | ||||
|                     if (trig_mode == IOAPIC_TRIGGER_EDGE) { | ||||
|                     if (info.trig_mode == IOAPIC_TRIGGER_EDGE) { | ||||
|                         kvm_set_irq(kvm_state, i, 1); | ||||
|                         kvm_set_irq(kvm_state, i, 0); | ||||
|                     } else { | ||||
| @ -112,13 +135,7 @@ static void ioapic_service(IOAPICCommonState *s) | ||||
|                  * the IOAPIC message into a MSI one, and its | ||||
|                  * address space will decide whether we need a | ||||
|                  * translation. */ | ||||
|                 addr = APIC_DEFAULT_ADDRESS | \ | ||||
|                     (dest_idx << MSI_ADDR_DEST_IDX_SHIFT) | | ||||
|                     (dest_mode << MSI_ADDR_DEST_MODE_SHIFT); | ||||
|                 data = (vector << MSI_DATA_VECTOR_SHIFT) | | ||||
|                     (trig_mode << MSI_DATA_TRIGGER_SHIFT) | | ||||
|                     (delivery_mode << MSI_DATA_DELIVERY_MODE_SHIFT); | ||||
|                 stl_le_phys(ioapic_as, addr, data); | ||||
|                 stl_le_phys(ioapic_as, info.addr, info.data); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -169,30 +186,11 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s) | ||||
| 
 | ||||
|     if (kvm_irqchip_is_split()) { | ||||
|         for (i = 0; i < IOAPIC_NUM_PINS; i++) { | ||||
|             uint64_t entry = s->ioredtbl[i]; | ||||
|             uint8_t trig_mode; | ||||
|             uint8_t delivery_mode; | ||||
|             uint8_t dest; | ||||
|             uint8_t dest_mode; | ||||
|             uint64_t pin_polarity; | ||||
|             MSIMessage msg; | ||||
| 
 | ||||
|             trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1); | ||||
|             dest = entry >> IOAPIC_LVT_DEST_SHIFT; | ||||
|             dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1; | ||||
|             pin_polarity = (entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1; | ||||
|             delivery_mode = | ||||
|                 (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK; | ||||
| 
 | ||||
|             msg.address = APIC_DEFAULT_ADDRESS; | ||||
|             msg.address |= dest_mode << 2; | ||||
|             msg.address |= dest << 12; | ||||
| 
 | ||||
|             msg.data = entry & IOAPIC_VECTOR_MASK; | ||||
|             msg.data |= delivery_mode << APIC_DELIVERY_MODE_SHIFT; | ||||
|             msg.data |= pin_polarity << APIC_POLARITY_SHIFT; | ||||
|             msg.data |= trig_mode << APIC_TRIG_MODE_SHIFT; | ||||
| 
 | ||||
|             struct ioapic_entry_info info; | ||||
|             ioapic_entry_parse(s->ioredtbl[i], &info); | ||||
|             msg.address = info.addr; | ||||
|             msg.data = info.data; | ||||
|             kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL); | ||||
|         } | ||||
|         kvm_irqchip_commit_routes(kvm_state); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Xu
						Peter Xu