aboutsummaryrefslogtreecommitdiff
path: root/xen-all.c
diff options
context:
space:
mode:
Diffstat (limited to 'xen-all.c')
-rw-r--r--xen-all.c76
1 files changed, 46 insertions, 30 deletions
diff --git a/xen-all.c b/xen-all.c
index d0142bdf60..ef430ca21e 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -683,11 +683,45 @@ static void do_outp(pio_addr_t addr,
}
}
-static void cpu_ioreq_pio(ioreq_t *req)
+/*
+ * Helper functions which read/write an object from/to physical guest
+ * memory, as part of the implementation of an ioreq.
+ *
+ * Equivalent to
+ * cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i,
+ * val, req->size, 0/1)
+ * except without the integer overflow problems.
+ */
+static void rw_phys_req_item(hwaddr addr,
+ ioreq_t *req, uint32_t i, void *val, int rw)
+{
+ /* Do everything unsigned so overflow just results in a truncated result
+ * and accesses to undesired parts of guest memory, which is up
+ * to the guest */
+ hwaddr offset = (hwaddr)req->size * i;
+ if (req->df) {
+ addr -= offset;
+ } else {
+ addr += offset;
+ }
+ cpu_physical_memory_rw(addr, val, req->size, rw);
+}
+
+static inline void read_phys_req_item(hwaddr addr,
+ ioreq_t *req, uint32_t i, void *val)
{
- int i, sign;
+ rw_phys_req_item(addr, req, i, val, 0);
+}
+static inline void write_phys_req_item(hwaddr addr,
+ ioreq_t *req, uint32_t i, void *val)
+{
+ rw_phys_req_item(addr, req, i, val, 1);
+}
- sign = req->df ? -1 : 1;
+
+static void cpu_ioreq_pio(ioreq_t *req)
+{
+ int i;
if (req->dir == IOREQ_READ) {
if (!req->data_is_ptr) {
@@ -697,9 +731,7 @@ static void cpu_ioreq_pio(ioreq_t *req)
for (i = 0; i < req->count; i++) {
tmp = do_inp(req->addr, req->size);
- cpu_physical_memory_write(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t *) &tmp, req->size);
+ write_phys_req_item(req->data, req, i, &tmp);
}
}
} else if (req->dir == IOREQ_WRITE) {
@@ -709,9 +741,7 @@ static void cpu_ioreq_pio(ioreq_t *req)
for (i = 0; i < req->count; i++) {
uint32_t tmp = 0;
- cpu_physical_memory_read(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
+ read_phys_req_item(req->data, req, i, &tmp);
do_outp(req->addr, req->size, tmp);
}
}
@@ -720,22 +750,16 @@ static void cpu_ioreq_pio(ioreq_t *req)
static void cpu_ioreq_move(ioreq_t *req)
{
- int i, sign;
-
- sign = req->df ? -1 : 1;
+ int i;
if (!req->data_is_ptr) {
if (req->dir == IOREQ_READ) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_read(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t *) &req->data, req->size);
+ read_phys_req_item(req->addr, req, i, &req->data);
}
} else if (req->dir == IOREQ_WRITE) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_write(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t *) &req->data, req->size);
+ write_phys_req_item(req->addr, req, i, &req->data);
}
}
} else {
@@ -743,21 +767,13 @@ static void cpu_ioreq_move(ioreq_t *req)
if (req->dir == IOREQ_READ) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_read(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
- cpu_physical_memory_write(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
+ read_phys_req_item(req->addr, req, i, &tmp);
+ write_phys_req_item(req->data, req, i, &tmp);
}
} else if (req->dir == IOREQ_WRITE) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_read(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
- cpu_physical_memory_write(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
+ read_phys_req_item(req->data, req, i, &tmp);
+ write_phys_req_item(req->addr, req, i, &tmp);
}
}
}