mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Accelerate IDE PIO on HVM/IA64 [1/3]
Add a bufferring mechanism for IDE PIO in qemu. Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
This commit is contained in:
1 parent
c516e5ec52
commit
cfb8ffa9f9
3 files changed
+150
No files matched your search
@@ -434,6 +434,121 @@ static void dma_create_thread(void)
|
||||
}
|
||||
#endif /* DMA_MULTI_THREAD */
|
||||
|
||||
#if defined(__ia64__)
|
||||
#include <xen/hvm/ioreq.h>
|
||||
|
||||
struct buffered_piopage *buffered_pio_page;
|
||||
|
||||
static inline struct pio_buffer *
|
||||
piobuf_by_addr(uint32_t addr)
|
||||
{
|
||||
if (addr == 0x1F0)
|
||||
return &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
|
||||
if (addr == 0x170)
|
||||
return &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
buffered_pio_init(void)
|
||||
{
|
||||
struct pio_buffer *p1, *p2;
|
||||
uint32_t off1, off2;
|
||||
|
||||
if (!buffered_pio_page)
|
||||
return;
|
||||
|
||||
p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
|
||||
p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
|
||||
off1 = offsetof(struct buffered_piopage, buffer);
|
||||
off2 = (off1 + TARGET_PAGE_SIZE)/2;
|
||||
|
||||
p1->buf_size = off2 - off1;
|
||||
p1->page_offset = off1;
|
||||
|
||||
p2->buf_size = TARGET_PAGE_SIZE - off2;
|
||||
p2->page_offset = off2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
buffered_pio_flush(struct pio_buffer *piobuf)
|
||||
{
|
||||
IDEState *s = piobuf->opaque;
|
||||
uint32_t pointer = piobuf->pointer;
|
||||
|
||||
if (s != NULL && pointer > 0) {
|
||||
uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset;
|
||||
memcpy(s->data_ptr, buf, pointer);
|
||||
s->data_ptr += pointer;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
buffered_pio_reset(IDEState *s)
|
||||
{
|
||||
struct pio_buffer *piobuf;
|
||||
|
||||
if ((unsigned)s->drive_serial - 1 < 2) /* 1,2 */
|
||||
piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
|
||||
else if ((unsigned)s->drive_serial - 3 < 2) /* 3,4 */
|
||||
piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
|
||||
else
|
||||
return;
|
||||
buffered_pio_flush(piobuf);
|
||||
piobuf->pointer = 0;
|
||||
piobuf->data_end = 0;
|
||||
piobuf->opaque = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
buffered_pio_write(IDEState *s, uint32_t addr, int size)
|
||||
{
|
||||
struct pio_buffer *piobuf = piobuf_by_addr(addr);
|
||||
uint32_t data_end;
|
||||
|
||||
if (!piobuf)
|
||||
return;
|
||||
buffered_pio_flush(piobuf);
|
||||
data_end = s->data_end - s->data_ptr - size;
|
||||
if (data_end <= 0)
|
||||
data_end = 0;
|
||||
else if (data_end > piobuf->buf_size)
|
||||
data_end = piobuf->buf_size;
|
||||
piobuf->pointer = 0;
|
||||
piobuf->data_end = data_end;
|
||||
piobuf->opaque = s;
|
||||
}
|
||||
|
||||
static inline void
|
||||
buffered_pio_read(IDEState *s, uint32_t addr, int size)
|
||||
{
|
||||
struct pio_buffer *piobuf = piobuf_by_addr(addr);
|
||||
uint32_t data_end;
|
||||
|
||||
if (!piobuf)
|
||||
return;
|
||||
s->data_ptr += piobuf->pointer;
|
||||
data_end = s->data_end - s->data_ptr - size;
|
||||
if (data_end <= 0) {
|
||||
data_end = 0;
|
||||
} else {
|
||||
uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset;
|
||||
if (data_end > piobuf->buf_size)
|
||||
data_end = piobuf->buf_size;
|
||||
memcpy(buf, s->data_ptr + size, data_end);
|
||||
}
|
||||
piobuf->pointer = 0;
|
||||
piobuf->data_end = data_end;
|
||||
piobuf->opaque = NULL;
|
||||
}
|
||||
|
||||
#else /* !__ia64__ */
|
||||
#define buffered_pio_init() do {} while (0)
|
||||
#define buffered_pio_reset(I) do {} while (0)
|
||||
#define buffered_pio_write(I,A,S) do {} while (0)
|
||||
#define buffered_pio_read(I,A,S) do {} while (0)
|
||||
#endif
|
||||
|
||||
static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
|
||||
|
||||
static void padstr(char *str, const char *src, int len)
|
||||
@@ -618,6 +733,7 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
|
||||
s->data_ptr = buf;
|
||||
s->data_end = buf + size;
|
||||
s->status |= DRQ_STAT;
|
||||
buffered_pio_reset(s);
|
||||
}
|
||||
|
||||
static void ide_transfer_stop(IDEState *s)
|
||||
@@ -626,6 +742,7 @@ static void ide_transfer_stop(IDEState *s)
|
||||
s->data_ptr = s->io_buffer;
|
||||
s->data_end = s->io_buffer;
|
||||
s->status &= ~DRQ_STAT;
|
||||
buffered_pio_reset(s);
|
||||
}
|
||||
|
||||
static int64_t ide_get_sector(IDEState *s)
|
||||
@@ -1562,6 +1679,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
ide_if[0].select = (val & ~0x10) | 0xa0;
|
||||
ide_if[1].select = (val | 0x10) | 0xa0;
|
||||
/* select drive */
|
||||
buffered_pio_reset(ide_if->cur_drive);
|
||||
unit = (val >> 4) & 1;
|
||||
s = ide_if + unit;
|
||||
ide_if->cur_drive = s;
|
||||
@@ -1928,6 +2046,7 @@ static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
|
||||
IDEState *s = ((IDEState *)opaque)->cur_drive;
|
||||
uint8_t *p;
|
||||
|
||||
buffered_pio_write(s, addr, 2);
|
||||
p = s->data_ptr;
|
||||
*(uint16_t *)p = le16_to_cpu(val);
|
||||
p += 2;
|
||||
@@ -1941,6 +2060,8 @@ static uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
||||
IDEState *s = ((IDEState *)opaque)->cur_drive;
|
||||
uint8_t *p;
|
||||
int ret;
|
||||
|
||||
buffered_pio_read(s, addr, 2);
|
||||
p = s->data_ptr;
|
||||
ret = cpu_to_le16(*(uint16_t *)p);
|
||||
p += 2;
|
||||
@@ -1955,6 +2076,7 @@ static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
|
||||
IDEState *s = ((IDEState *)opaque)->cur_drive;
|
||||
uint8_t *p;
|
||||
|
||||
buffered_pio_write(s, addr, 4);
|
||||
p = s->data_ptr;
|
||||
*(uint32_t *)p = le32_to_cpu(val);
|
||||
p += 4;
|
||||
@@ -1969,6 +2091,7 @@ static uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
||||
uint8_t *p;
|
||||
int ret;
|
||||
|
||||
buffered_pio_read(s, addr, 4);
|
||||
p = s->data_ptr;
|
||||
ret = cpu_to_le32(*(uint32_t *)p);
|
||||
p += 4;
|
||||
@@ -2517,6 +2640,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
|
||||
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
|
||||
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
|
||||
|
||||
buffered_pio_init();
|
||||
|
||||
register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
|
||||
|
||||
#ifdef DMA_MULTI_THREAD
|
||||
|
||||
@@ -5972,6 +5972,7 @@ int main(int argc, char **argv)
|
||||
xen_pfn_t *page_array;
|
||||
extern void *shared_page;
|
||||
extern void *buffered_io_page;
|
||||
extern void *buffered_pio_page;
|
||||
|
||||
char qemu_dm_logfilename[64];
|
||||
|
||||
@@ -6576,6 +6577,10 @@ int main(int argc, char **argv)
|
||||
PROT_READ|PROT_WRITE,
|
||||
BUFFER_IO_PAGE_START >> PAGE_SHIFT);
|
||||
|
||||
buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
|
||||
|
||||
for (i = 0; i < tmp_nr_pages; i++)
|
||||
page_array[i] = i;
|
||||
|
||||
|
||||
@@ -81,9 +81,29 @@ struct buffered_iopage {
|
||||
}; /* sizeof this structure must be in one page */
|
||||
typedef struct buffered_iopage buffered_iopage_t;
|
||||
|
||||
#if defined(__ia64__)
|
||||
struct pio_buffer {
|
||||
uint32_t page_offset;
|
||||
uint32_t pointer;
|
||||
uint32_t data_end;
|
||||
uint32_t buf_size;
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
#define PIO_BUFFER_IDE_PRIMARY 0 /* I/O port = 0x1F0 */
|
||||
#define PIO_BUFFER_IDE_SECONDARY 1 /* I/O port = 0x170 */
|
||||
#define PIO_BUFFER_ENTRY_NUM 2
|
||||
struct buffered_piopage {
|
||||
struct pio_buffer pio[PIO_BUFFER_ENTRY_NUM];
|
||||
uint8_t buffer[1];
|
||||
};
|
||||
#endif /* defined(__ia64__) */
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define ACPI_PM1A_EVT_BLK_ADDRESS 0x0000000000001f40
|
||||
#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
|
||||
#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
|
||||
#endif /* defined(__i386__) || defined(__x86_64__) */
|
||||
|
||||
#endif /* _IOREQ_H_ */
|
||||
|
||||
|
||||