rc |= ioports_deny_access(dom0, 0x40, 0x43);
/* PIT Channel 2 / PC Speaker Control. */
rc |= ioports_deny_access(dom0, 0x61, 0x61);
- /* PCI configuration spaces. */
- rc |= ioports_deny_access(dom0, 0xcf8, 0xcff);
+ /* PCI configuration space (NB. 0xcf8 has special treatment). */
+ rc |= ioports_deny_access(dom0, 0xcfc, 0xcff);
/* Command-line I/O ranges. */
process_dom0_ioports_disable();
unsigned int port, unsigned int bytes,
struct vcpu *v, struct cpu_user_regs *regs)
{
+ /*
+ * Port 0xcf8 (CONFIG_ADDRESS) is only visible for DWORD accesses.
+ * We never permit direct access to that register.
+ */
+ if ( (port == 0xcf8) && (bytes == 4) )
+ return 0;
+
return ioports_access_permitted(v->domain, port, port + bytes - 1);
}
{
sub_data = pv_pit_handler(port, 0, 0);
}
- else if ( (port & 0xfffc) == 0xcf8 )
+ else if ( (port == 0xcf8) && (bytes == 4) )
{
- size = min(bytes, 4 - (port & 3));
- sub_data = v->domain->arch.pci_cf8 >> ((port & 3) * 8);
+ size = 4;
+ sub_data = v->domain->arch.pci_cf8;
}
else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )
{
{
pv_pit_handler(port, (uint8_t)data, 1);
}
- else if ( (port & 0xfffc) == 0xcf8 )
+ else if ( (port == 0xcf8) && (bytes == 4) )
{
- size = min(bytes, 4 - (port & 3));
- if ( size == 4 )
- {
- v->domain->arch.pci_cf8 = data;
- }
- else
- {
- uint32_t mask = ((1u << (size * 8)) - 1) << ((port & 3) * 8);
- v->domain->arch.pci_cf8 &= ~mask;
- v->domain->arch.pci_cf8 |= (data << ((port & 3) * 8)) & mask;
- }
+ size = 4;
+ v->domain->arch.pci_cf8 = data;
}
else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )
{