|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v6 04/13] vpci: restrict unhandled read/write operations for guests
From: Oleksandr Andrushchenko <oleksandr_andrushchenko@xxxxxxxx>
A guest can read and write those registers which are not emulated and
have no respective vPCI handlers, so it can access the HW directly.
In order to prevent a guest from reads and writes from/to the unhandled
registers make sure only hardware domain can access HW directly and restrict
guests from doing so.
Suggested-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@xxxxxxxx>
---
New in v6
---
xen/drivers/vpci/vpci.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c
index cb2ababa28e3..f8a93e61c08f 100644
--- a/xen/drivers/vpci/vpci.c
+++ b/xen/drivers/vpci/vpci.c
@@ -215,11 +215,15 @@ int vpci_remove_register(struct vpci *vpci, unsigned int
offset,
}
/* Wrappers for performing reads/writes to the underlying hardware. */
-static uint32_t vpci_read_hw(pci_sbdf_t sbdf, unsigned int reg,
+static uint32_t vpci_read_hw(bool is_hwdom, pci_sbdf_t sbdf, unsigned int reg,
unsigned int size)
{
uint32_t data;
+ /* Guest domains are not allowed to read real hardware. */
+ if ( !is_hwdom )
+ return ~(uint32_t)0;
+
switch ( size )
{
case 4:
@@ -260,9 +264,13 @@ static uint32_t vpci_read_hw(pci_sbdf_t sbdf, unsigned int
reg,
return data;
}
-static void vpci_write_hw(pci_sbdf_t sbdf, unsigned int reg, unsigned int size,
- uint32_t data)
+static void vpci_write_hw(bool is_hwdom, pci_sbdf_t sbdf, unsigned int reg,
+ unsigned int size, uint32_t data)
{
+ /* Guest domains are not allowed to write real hardware. */
+ if ( !is_hwdom )
+ return;
+
switch ( size )
{
case 4:
@@ -322,6 +330,7 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg,
unsigned int size)
const struct vpci_register *r;
unsigned int data_offset = 0;
uint32_t data = ~(uint32_t)0;
+ bool is_hwdom = is_hardware_domain(d);
if ( !size )
{
@@ -332,13 +341,13 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg,
unsigned int size)
/* Find the PCI dev matching the address. */
pdev = pci_get_pdev_by_domain(d, sbdf.seg, sbdf.bus, sbdf.devfn);
if ( !pdev )
- return vpci_read_hw(sbdf, reg, size);
+ return vpci_read_hw(is_hwdom, sbdf, reg, size);
spin_lock(&pdev->vpci_lock);
if ( !pdev->vpci )
{
spin_unlock(&pdev->vpci_lock);
- return vpci_read_hw(sbdf, reg, size);
+ return vpci_read_hw(is_hwdom, sbdf, reg, size);
}
/* Read from the hardware or the emulated register handlers. */
@@ -361,7 +370,7 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg,
unsigned int size)
{
/* Heading gap, read partial content from hardware. */
read_size = r->offset - emu.offset;
- val = vpci_read_hw(sbdf, emu.offset, read_size);
+ val = vpci_read_hw(is_hwdom, sbdf, emu.offset, read_size);
data = merge_result(data, val, read_size, data_offset);
data_offset += read_size;
}
@@ -387,7 +396,7 @@ uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg,
unsigned int size)
if ( data_offset < size )
{
/* Tailing gap, read the remaining. */
- uint32_t tmp_data = vpci_read_hw(sbdf, reg + data_offset,
+ uint32_t tmp_data = vpci_read_hw(is_hwdom, sbdf, reg + data_offset,
size - data_offset);
data = merge_result(data, tmp_data, size - data_offset, data_offset);
@@ -430,6 +439,7 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned
int size,
const struct vpci_register *r;
unsigned int data_offset = 0;
const unsigned long *ro_map = pci_get_ro_map(sbdf.seg);
+ bool is_hwdom = is_hardware_domain(d);
if ( !size )
{
@@ -448,7 +458,7 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned
int size,
pdev = pci_get_pdev_by_domain(d, sbdf.seg, sbdf.bus, sbdf.devfn);
if ( !pdev )
{
- vpci_write_hw(sbdf, reg, size, data);
+ vpci_write_hw(is_hwdom, sbdf, reg, size, data);
return;
}
@@ -456,7 +466,7 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned
int size,
if ( !pdev->vpci )
{
spin_unlock(&pdev->vpci_lock);
- vpci_write_hw(sbdf, reg, size, data);
+ vpci_write_hw(is_hwdom, sbdf, reg, size, data);
return;
}
@@ -479,7 +489,7 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned
int size,
if ( emu.offset < r->offset )
{
/* Heading gap, write partial content to hardware. */
- vpci_write_hw(sbdf, emu.offset, r->offset - emu.offset,
+ vpci_write_hw(is_hwdom, sbdf, emu.offset, r->offset - emu.offset,
data >> (data_offset * 8));
data_offset += r->offset - emu.offset;
}
@@ -498,7 +508,7 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned
int size,
if ( data_offset < size )
/* Tailing gap, write the remaining. */
- vpci_write_hw(sbdf, reg + data_offset, size - data_offset,
+ vpci_write_hw(is_hwdom, sbdf, reg + data_offset, size - data_offset,
data >> (data_offset * 8));
}
--
2.25.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |