x86/pvh: use a custom IO bitmap for PVH hardware domains

Since a PVH hardware domain has access to the physical hardware create a
custom more permissive IO bitmap. The permissions set on the bitmap are
populated based on the contents of the ioports rangeset.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Roger Pau Monné authored and Jan Beulich committed 2015-05-20 13:26:43 +02:00
1 parent 74d0932448
commit 8ddb99287c
7 files changed
+59 -5

No files matched your search

+22 -2
View File
@@ -77,9 +77,13 @@ integer_param("hvm_debug", opt_hvm_debug_level);
struct hvm_function_table hvm_funcs __read_mostly; struct hvm_function_table hvm_funcs __read_mostly;
/* I/O permission bitmap is globally shared by all HVM guests. */ /*
* The I/O permission bitmap is globally shared by all HVM guests except
* the hardware domain which needs a more permissive one.
*/
#define HVM_IOBITMAP_SIZE (3 * PAGE_SIZE)
unsigned long __attribute__ ((__section__ (".bss.page_aligned"))) unsigned long __attribute__ ((__section__ (".bss.page_aligned")))
hvm_io_bitmap[3*PAGE_SIZE/BYTES_PER_LONG]; hvm_io_bitmap[HVM_IOBITMAP_SIZE / BYTES_PER_LONG];
/* Xen command-line option to enable HAP */ /* Xen command-line option to enable HAP */
static bool_t __initdata opt_hap_enabled = 1; static bool_t __initdata opt_hap_enabled = 1;
@@ -1461,6 +1465,20 @@ int hvm_domain_initialise(struct domain *d)
goto fail1; goto fail1;
d->arch.hvm_domain.io_handler->num_slot = 0; d->arch.hvm_domain.io_handler->num_slot = 0;
/* Set the default IO Bitmap. */
if ( is_hardware_domain(d) )
{
d->arch.hvm_domain.io_bitmap = _xmalloc(HVM_IOBITMAP_SIZE, PAGE_SIZE);
if ( d->arch.hvm_domain.io_bitmap == NULL )
{
rc = -ENOMEM;
goto fail1;
}
memset(d->arch.hvm_domain.io_bitmap, ~0, HVM_IOBITMAP_SIZE);
}
else
d->arch.hvm_domain.io_bitmap = hvm_io_bitmap;
if ( is_pvh_domain(d) ) if ( is_pvh_domain(d) )
{ {
register_portio_handler(d, 0, 0x10003, handle_pvh_io); register_portio_handler(d, 0, 0x10003, handle_pvh_io);
@@ -1496,6 +1514,8 @@ int hvm_domain_initialise(struct domain *d)
stdvga_deinit(d); stdvga_deinit(d);
vioapic_deinit(d); vioapic_deinit(d);
fail1: fail1:
if ( is_hardware_domain(d) )
xfree(d->arch.hvm_domain.io_bitmap);
xfree(d->arch.hvm_domain.io_handler); xfree(d->arch.hvm_domain.io_handler);
xfree(d->arch.hvm_domain.params); xfree(d->arch.hvm_domain.params);
fail0: fail0:
+1 -1
View File
@@ -118,7 +118,7 @@ static int construct_vmcb(struct vcpu *v)
svm_disable_intercept_for_msr(v, MSR_AMD64_LWP_CBADDR); svm_disable_intercept_for_msr(v, MSR_AMD64_LWP_CBADDR);
vmcb->_msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm); vmcb->_msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
vmcb->_iopm_base_pa = (u64)virt_to_maddr(hvm_io_bitmap); vmcb->_iopm_base_pa = __pa(v->domain->arch.hvm_domain.io_bitmap);
/* Virtualise EFLAGS.IF and LAPIC TPR (CR8). */ /* Virtualise EFLAGS.IF and LAPIC TPR (CR8). */
vmcb->_vintr.fields.intr_masking = 1; vmcb->_vintr.fields.intr_masking = 1;
+2 -2
View File
@@ -1032,8 +1032,8 @@ static int construct_vmcs(struct vcpu *v)
} }
/* I/O access bitmap. */ /* I/O access bitmap. */
__vmwrite(IO_BITMAP_A, virt_to_maddr((char *)hvm_io_bitmap + 0)); __vmwrite(IO_BITMAP_A, __pa(d->arch.hvm_domain.io_bitmap));
__vmwrite(IO_BITMAP_B, virt_to_maddr((char *)hvm_io_bitmap + PAGE_SIZE)); __vmwrite(IO_BITMAP_B, __pa(d->arch.hvm_domain.io_bitmap) + PAGE_SIZE);
if ( cpu_has_vmx_virtual_intr_delivery ) if ( cpu_has_vmx_virtual_intr_delivery )
{ {
+28
View File
@@ -1446,6 +1446,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
dmi_end_boot(); dmi_end_boot();
setup_io_bitmap(dom0);
system_state = SYS_STATE_active; system_state = SYS_STATE_active;
domain_unpause_by_systemcontroller(dom0); domain_unpause_by_systemcontroller(dom0);
@@ -1509,6 +1511,32 @@ int __hwdom_init xen_in_range(unsigned long mfn)
return 0; return 0;
} }
static int __hwdom_init io_bitmap_cb(unsigned long s, unsigned long e,
void *ctx)
{
struct domain *d = ctx;
unsigned int i;
ASSERT(e <= INT_MAX);
for ( i = s; i <= e; i++ )
__clear_bit(i, d->arch.hvm_domain.io_bitmap);
return 0;
}
void __hwdom_init setup_io_bitmap(struct domain *d)
{
int rc;
if ( has_hvm_container_domain(d) )
{
bitmap_fill(d->arch.hvm_domain.io_bitmap, 0x10000);
rc = rangeset_report_ranges(d->arch.ioport_caps, 0, 0x10000,
io_bitmap_cb, d);
BUG_ON(rc);
}
}
/* /*
* Local variables: * Local variables:
* mode: C * mode: C
+3
View File
@@ -42,6 +42,7 @@
#include <xsm/xsm.h> #include <xsm/xsm.h>
#include <xen/trace.h> #include <xen/trace.h>
#include <xen/tmem.h> #include <xen/tmem.h>
#include <asm/setup.h>
/* Linux config option: propageted to domain0 */ /* Linux config option: propageted to domain0 */
/* xen_processor_pmbits: xen control Cx, Px, ... */ /* xen_processor_pmbits: xen control Cx, Px, ... */
@@ -219,6 +220,8 @@ static int late_hwdom_init(struct domain *d)
rangeset_swap(d->iomem_caps, dom0->iomem_caps); rangeset_swap(d->iomem_caps, dom0->iomem_caps);
#ifdef CONFIG_X86 #ifdef CONFIG_X86
rangeset_swap(d->arch.ioport_caps, dom0->arch.ioport_caps); rangeset_swap(d->arch.ioport_caps, dom0->arch.ioport_caps);
setup_io_bitmap(d);
setup_io_bitmap(dom0);
#endif #endif
rcu_unlock_domain(dom0); rcu_unlock_domain(dom0);
+2
View File
@@ -141,6 +141,8 @@ struct hvm_domain {
*/ */
uint64_t sync_tsc; uint64_t sync_tsc;
unsigned long *io_bitmap;
union { union {
struct vmx_domain vmx; struct vmx_domain vmx;
struct svm_domain svm; struct svm_domain svm;
+1
View File
@@ -32,6 +32,7 @@ int construct_dom0(
module_t *initrd, module_t *initrd,
void *(*bootstrap_map)(const module_t *), void *(*bootstrap_map)(const module_t *),
char *cmdline); char *cmdline);
void setup_io_bitmap(struct domain *d);
unsigned long initial_images_nrpages(nodeid_t node); unsigned long initial_images_nrpages(nodeid_t node);
void discard_initial_images(void); void discard_initial_images(void);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.