mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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:
1 parent
74d0932448
commit
8ddb99287c
7 files changed
+59
-5
No files matched your search
+22
-2
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||