ich9: implement SMI_LOCK
Add write mask for the smi enable register, so we can disable write access to certain bits. Open all bits on reset. Disable write access to GBL_SMI_EN when SMI_LOCK (in ich9 lpc pci config space) is set. Write access to SMI_LOCK itself is disabled too. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									bafc90bdc5
								
							
						
					
					
						commit
						11e66a15a0
					
				@ -94,7 +94,8 @@ static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
 | 
				
			|||||||
    ICH9LPCPMRegs *pm = opaque;
 | 
					    ICH9LPCPMRegs *pm = opaque;
 | 
				
			||||||
    switch (addr) {
 | 
					    switch (addr) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
        pm->smi_en = val;
 | 
					        pm->smi_en &= ~pm->smi_en_wmask;
 | 
				
			||||||
 | 
					        pm->smi_en |= (val & pm->smi_en_wmask);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -198,6 +199,7 @@ static void pm_reset(void *opaque)
 | 
				
			|||||||
         * support SMM mode. */
 | 
					         * support SMM mode. */
 | 
				
			||||||
        pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
 | 
					        pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    pm->smi_en_wmask = ~0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acpi_update_sci(&pm->acpi_regs, pm->irq);
 | 
					    acpi_update_sci(&pm->acpi_regs, pm->irq);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -407,12 +407,28 @@ static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rbca_old)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* config:GEN_PMCON* */
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					ich9_lpc_pmcon_update(ICH9LPCState *lpc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t gen_pmcon_1 = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1);
 | 
				
			||||||
 | 
					    uint16_t wmask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gen_pmcon_1 & ICH9_LPC_GEN_PMCON_1_SMI_LOCK) {
 | 
				
			||||||
 | 
					        wmask = pci_get_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1);
 | 
				
			||||||
 | 
					        wmask &= ~ICH9_LPC_GEN_PMCON_1_SMI_LOCK;
 | 
				
			||||||
 | 
					        pci_set_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1, wmask);
 | 
				
			||||||
 | 
					        lpc->pm.smi_en_wmask &= ~1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ich9_lpc_post_load(void *opaque, int version_id)
 | 
					static int ich9_lpc_post_load(void *opaque, int version_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ICH9LPCState *lpc = opaque;
 | 
					    ICH9LPCState *lpc = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ich9_lpc_pmbase_update(lpc);
 | 
					    ich9_lpc_pmbase_update(lpc);
 | 
				
			||||||
    ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */);
 | 
					    ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */);
 | 
				
			||||||
 | 
					    ich9_lpc_pmcon_update(lpc);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -435,6 +451,9 @@ static void ich9_lpc_config_write(PCIDevice *d,
 | 
				
			|||||||
    if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
 | 
					    if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
 | 
				
			||||||
        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
 | 
					        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (ranges_overlap(addr, len, ICH9_LPC_GEN_PMCON_1, 8)) {
 | 
				
			||||||
 | 
					        ich9_lpc_pmcon_update(lpc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ich9_lpc_reset(DeviceState *qdev)
 | 
					static void ich9_lpc_reset(DeviceState *qdev)
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,7 @@ typedef struct ICH9LPCPMRegs {
 | 
				
			|||||||
    MemoryRegion io_smi;
 | 
					    MemoryRegion io_smi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t smi_en;
 | 
					    uint32_t smi_en;
 | 
				
			||||||
 | 
					    uint32_t smi_en_wmask;
 | 
				
			||||||
    uint32_t smi_sts;
 | 
					    uint32_t smi_sts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_irq irq;      /* SCI */
 | 
					    qemu_irq irq;      /* SCI */
 | 
				
			||||||
 | 
				
			|||||||
@ -152,6 +152,12 @@ Object *ich9_lpc_find(void);
 | 
				
			|||||||
#define ICH9_LPC_PIRQ_ROUT_MASK                 Q35_MASK(8, 3, 0)
 | 
					#define ICH9_LPC_PIRQ_ROUT_MASK                 Q35_MASK(8, 3, 0)
 | 
				
			||||||
#define ICH9_LPC_PIRQ_ROUT_DEFAULT              0x80
 | 
					#define ICH9_LPC_PIRQ_ROUT_DEFAULT              0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICH9_LPC_GEN_PMCON_1                    0xa0
 | 
				
			||||||
 | 
					#define ICH9_LPC_GEN_PMCON_1_SMI_LOCK           (1 << 4)
 | 
				
			||||||
 | 
					#define ICH9_LPC_GEN_PMCON_2                    0xa2
 | 
				
			||||||
 | 
					#define ICH9_LPC_GEN_PMCON_3                    0xa4
 | 
				
			||||||
 | 
					#define ICH9_LPC_GEN_PMCON_LOCK                 0xa6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ICH9_LPC_RCBA                           0xf0
 | 
					#define ICH9_LPC_RCBA                           0xf0
 | 
				
			||||||
#define ICH9_LPC_RCBA_BA_MASK                   Q35_MASK(32, 31, 14)
 | 
					#define ICH9_LPC_RCBA_BA_MASK                   Q35_MASK(32, 31, 14)
 | 
				
			||||||
#define ICH9_LPC_RCBA_EN                        0x1
 | 
					#define ICH9_LPC_RCBA_EN                        0x1
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user