static void __init process_dom0_ioports_disable(void) { unsigned long io_from, io_to; char *t, *s = opt_dom0_ioports_disable; const char *u; if ( *s == '\0' ) return; while ( (t = strsep(&s, ",")) != NULL ) { io_from = simple_strtoul(t, &u, 16); if ( u == t ) { parse_error: printk("Invalid ioport range <%s> " "in dom0_ioports_disable, skipping\n", t); continue; } if ( *u == '\0' ) io_to = io_from; else if ( *u == '-' ) io_to = simple_strtoul(u + 1, &u, 16); else goto parse_error; if ( (*u != '\0') || (io_to < io_from) || (io_to >= 65536) ) goto parse_error; printk("Disabling dom0 access to ioport range %04lx-%04lx\n", io_from, io_to); if ( ioports_deny_access(dom0, io_from, io_to) != 0 ) BUG(); } }
int __init dom0_setup_permissions(struct domain *d) { unsigned long mfn; unsigned int i; int rc; /* The hardware domain is initially permitted full I/O capabilities. */ rc = ioports_permit_access(d, 0, 0xFFFF); rc |= iomem_permit_access(d, 0UL, (1UL << (paddr_bits - PAGE_SHIFT)) - 1); rc |= irqs_permit_access(d, 1, nr_irqs_gsi - 1); /* Modify I/O port access permissions. */ /* Master Interrupt Controller (PIC). */ rc |= ioports_deny_access(d, 0x20, 0x21); /* Slave Interrupt Controller (PIC). */ rc |= ioports_deny_access(d, 0xA0, 0xA1); /* Interval Timer (PIT). */ rc |= ioports_deny_access(d, 0x40, 0x43); /* PIT Channel 2 / PC Speaker Control. */ rc |= ioports_deny_access(d, 0x61, 0x61); /* ACPI PM Timer. */ if ( pmtmr_ioport ) rc |= ioports_deny_access(d, pmtmr_ioport, pmtmr_ioport + 3); /* PCI configuration space (NB. 0xcf8 has special treatment). */ rc |= ioports_deny_access(d, 0xcfc, 0xcff); /* Command-line I/O ranges. */ process_dom0_ioports_disable(d); /* Modify I/O memory access permissions. */ /* Local APIC. */ if ( mp_lapic_addr != 0 ) { mfn = paddr_to_pfn(mp_lapic_addr); rc |= iomem_deny_access(d, mfn, mfn); } /* I/O APICs. */ for ( i = 0; i < nr_ioapics; i++ ) { mfn = paddr_to_pfn(mp_ioapics[i].mpc_apicaddr); if ( !rangeset_contains_singleton(mmio_ro_ranges, mfn) ) rc |= iomem_deny_access(d, mfn, mfn); } /* MSI range. */ rc |= iomem_deny_access(d, paddr_to_pfn(MSI_ADDR_BASE_LO), paddr_to_pfn(MSI_ADDR_BASE_LO + MSI_ADDR_DEST_ID_MASK)); /* HyperTransport range. */ if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) rc |= iomem_deny_access(d, paddr_to_pfn(0xfdULL << 32), paddr_to_pfn((1ULL << 40) - 1)); /* Remove access to E820_UNUSABLE I/O regions above 1MB. */ for ( i = 0; i < e820.nr_map; i++ ) { unsigned long sfn, efn; sfn = max_t(unsigned long, paddr_to_pfn(e820.map[i].addr), 0x100ul); efn = paddr_to_pfn(e820.map[i].addr + e820.map[i].size - 1); if ( (e820.map[i].type == E820_UNUSABLE) && (e820.map[i].size != 0) && (sfn <= efn) ) rc |= iomem_deny_access(d, sfn, efn); } /* Prevent access to HPET */ if ( hpet_address ) { u8 prot_flags = hpet_flags & ACPI_HPET_PAGE_PROTECT_MASK; mfn = paddr_to_pfn(hpet_address); if ( prot_flags == ACPI_HPET_PAGE_PROTECT4 ) rc |= iomem_deny_access(d, mfn, mfn); else if ( prot_flags == ACPI_HPET_PAGE_PROTECT64 ) rc |= iomem_deny_access(d, mfn, mfn + 15); else if ( ro_hpet ) rc |= rangeset_add_singleton(mmio_ro_ranges, mfn); } return rc; }