Hi,
The ahci driver has recently been changed to run completely in 32bit mode. This is a followup patch series for this, removing real mode memory access macros not needed any more and also moving data structures out of real mode address space.
cheers, Gerd
Gerd Hoffmann (3): ahci: zap real mode macros ahci: remote some parentheses ahci: alloc structs in high memory, simplify realloc
src/hw/ahci.c | 101 ++++++++++++++++++++++++---------------------------------- 1 file changed, 41 insertions(+), 60 deletions(-)
Not needed any more now that ahci runs in 32bit mode all the time. Script-based search & replace.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/ahci.c | 74 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 37 deletions(-)
diff --git a/src/hw/ahci.c b/src/hw/ahci.c index a4ef5c5..09e786d 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -27,7 +27,7 @@ static void sata_prep_simple(struct sata_cmd_fis *fis, u8 command) { memset_fl(fis, 0, sizeof(*fis)); - SET_LOWFLAT(fis->command, command); + fis->command = command; }
static void sata_prep_readwrite(struct sata_cmd_fis *fis, @@ -39,10 +39,10 @@ static void sata_prep_readwrite(struct sata_cmd_fis *fis, memset_fl(fis, 0, sizeof(*fis));
if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { - SET_LOWFLAT(fis->sector_count2, op->count >> 8); - SET_LOWFLAT(fis->lba_low2, lba >> 24); - SET_LOWFLAT(fis->lba_mid2, lba >> 32); - SET_LOWFLAT(fis->lba_high2, lba >> 40); + fis->sector_count2 = op->count >> 8; + fis->lba_low2 = lba >> 24; + fis->lba_mid2 = lba >> 32; + fis->lba_high2 = lba >> 40; lba &= 0xffffff; command = (iswrite ? ATA_CMD_WRITE_DMA_EXT : ATA_CMD_READ_DMA_EXT); @@ -50,34 +50,34 @@ static void sata_prep_readwrite(struct sata_cmd_fis *fis, command = (iswrite ? ATA_CMD_WRITE_DMA : ATA_CMD_READ_DMA); } - SET_LOWFLAT(fis->feature, 1); /* dma */ - SET_LOWFLAT(fis->command, command); - SET_LOWFLAT(fis->sector_count, op->count); - SET_LOWFLAT(fis->lba_low, lba); - SET_LOWFLAT(fis->lba_mid, lba >> 8); - SET_LOWFLAT(fis->lba_high, lba >> 16); - SET_LOWFLAT(fis->device, ((lba >> 24) & 0xf) | ATA_CB_DH_LBA); + fis->feature = 1; /* dma */ + fis->command = command; + fis->sector_count = op->count; + fis->lba_low = lba; + fis->lba_mid = lba >> 8; + fis->lba_high = lba >> 16; + fis->device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA; }
static void sata_prep_atapi(struct sata_cmd_fis *fis, u16 blocksize) { memset_fl(fis, 0, sizeof(*fis)); - SET_LOWFLAT(fis->command, ATA_CMD_PACKET); - SET_LOWFLAT(fis->feature, 1); /* dma */ - SET_LOWFLAT(fis->lba_mid, blocksize); - SET_LOWFLAT(fis->lba_high, blocksize >> 8); + fis->command = ATA_CMD_PACKET; + fis->feature = 1; /* dma */ + fis->lba_mid = blocksize; + fis->lba_high = blocksize >> 8; }
// ahci register access helpers static u32 ahci_ctrl_readl(struct ahci_ctrl_s *ctrl, u32 reg) { - u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg; + u32 addr = ctrl->iobase + reg; return readl((void*)addr); }
static void ahci_ctrl_writel(struct ahci_ctrl_s *ctrl, u32 reg, u32 val) { - u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg; + u32 addr = ctrl->iobase + reg; writel((void*)addr, val); }
@@ -106,26 +106,26 @@ static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, void *buffer, u32 bsize) { u32 val, status, success, flags, intbits, error; - struct ahci_ctrl_s *ctrl = GET_GLOBALFLAT(port_gf->ctrl); - struct ahci_cmd_s *cmd = GET_GLOBALFLAT(port_gf->cmd); - struct ahci_fis_s *fis = GET_GLOBALFLAT(port_gf->fis); - struct ahci_list_s *list = GET_GLOBALFLAT(port_gf->list); - u32 pnr = GET_GLOBALFLAT(port_gf->pnr); - - SET_LOWFLAT(cmd->fis.reg, 0x27); - SET_LOWFLAT(cmd->fis.pmp_type, (1 << 7)); /* cmd fis */ - SET_LOWFLAT(cmd->prdt[0].base, ((u32)buffer)); - SET_LOWFLAT(cmd->prdt[0].baseu, 0); - SET_LOWFLAT(cmd->prdt[0].flags, bsize-1); + struct ahci_ctrl_s *ctrl = port_gf->ctrl; + struct ahci_cmd_s *cmd = port_gf->cmd; + struct ahci_fis_s *fis = port_gf->fis; + struct ahci_list_s *list = port_gf->list; + u32 pnr = port_gf->pnr; + + cmd->fis.reg = 0x27; + cmd->fis.pmp_type = (1 << 7); /* cmd fis */ + cmd->prdt[0].base = ((u32)buffer); + cmd->prdt[0].baseu = 0; + cmd->prdt[0].flags = bsize-1;
flags = ((1 << 16) | /* one prd entry */ (iswrite ? (1 << 6) : 0) | (isatapi ? (1 << 5) : 0) | (5 << 0)); /* fis length (dwords) */ - SET_LOWFLAT(list[0].flags, flags); - SET_LOWFLAT(list[0].bytes, 0); - SET_LOWFLAT(list[0].base, ((u32)(cmd))); - SET_LOWFLAT(list[0].baseu, 0); + list[0].flags = flags; + list[0].bytes = 0; + list[0].base = ((u32)(cmd)); + list[0].baseu = 0;
dprintf(8, "AHCI/%d: send cmd ...\n", pnr); intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); @@ -220,13 +220,13 @@ int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
struct ahci_port_s *port_gf = container_of( op->drive_gf, struct ahci_port_s, drive); - struct ahci_cmd_s *cmd = GET_GLOBALFLAT(port_gf->cmd); + struct ahci_cmd_s *cmd = port_gf->cmd; u8 *atapi = cdbcmd; int i, rc;
sata_prep_atapi(&cmd->fis, blocksize); for (i = 0; i < CDROM_CDB_SIZE; i++) { - SET_LOWFLAT(cmd->atapi[i], atapi[i]); + cmd->atapi[i] = atapi[i]; } rc = ahci_command(port_gf, 0, 1, op->buf_fl, op->count * blocksize); @@ -241,7 +241,7 @@ ahci_disk_readwrite_aligned(struct disk_op_s *op, int iswrite) { struct ahci_port_s *port_gf = container_of( op->drive_gf, struct ahci_port_s, drive); - struct ahci_cmd_s *cmd = GET_GLOBALFLAT(port_gf->cmd); + struct ahci_cmd_s *cmd = port_gf->cmd; int rc;
sata_prep_readwrite(&cmd->fis, op, iswrite); @@ -265,7 +265,7 @@ ahci_disk_readwrite(struct disk_op_s *op, int iswrite) // Use a word aligned buffer for AHCI I/O int rc; struct disk_op_s localop = *op; - u8 *alignedbuf_fl = GET_GLOBAL(bounce_buf_fl); + u8 *alignedbuf_fl = bounce_buf_fl; u8 *position = op->buf_fl;
localop.buf_fl = alignedbuf_fl;
Minor cleanups.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/ahci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/hw/ahci.c b/src/hw/ahci.c index 09e786d..5984c1c 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -113,8 +113,8 @@ static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, u32 pnr = port_gf->pnr;
cmd->fis.reg = 0x27; - cmd->fis.pmp_type = (1 << 7); /* cmd fis */ - cmd->prdt[0].base = ((u32)buffer); + cmd->fis.pmp_type = 1 << 7; /* cmd fis */ + cmd->prdt[0].base = (u32)buffer; cmd->prdt[0].baseu = 0; cmd->prdt[0].flags = bsize-1;
@@ -124,7 +124,7 @@ static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, (5 << 0)); /* fis length (dwords) */ list[0].flags = flags; list[0].bytes = 0; - list[0].base = ((u32)(cmd)); + list[0].base = (u32)(cmd); list[0].baseu = 0;
dprintf(8, "AHCI/%d: send cmd ...\n", pnr);
With ahci running in 32bit mode we can also allocate the (ahci private) data structures in high memory. This reduces the real mode memory footprint and also simplifies the realloc as we only need to move struct ahci_port_s (which contains struct drive_s) from high memory to fseg in case the port probe was successful.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/ahci.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-)
diff --git a/src/hw/ahci.c b/src/hw/ahci.c index 5984c1c..5add207 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -358,9 +358,9 @@ ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr) } port->pnr = pnr; port->ctrl = ctrl; - port->list = memalign_tmp(1024, 1024); - port->fis = memalign_tmp(256, 256); - port->cmd = memalign_tmp(256, 256); + port->list = memalign_high(1024, 1024); + port->fis = memalign_high(256, 256); + port->cmd = memalign_high(256, 256); if (port->list == NULL || port->fis == NULL || port->cmd == NULL) { warn_noalloc(); return NULL; @@ -386,7 +386,6 @@ static void ahci_port_release(struct ahci_port_s *port) static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port) { struct ahci_port_s *tmp; - u32 cmd;
tmp = malloc_fseg(sizeof(*port)); if (!tmp) { @@ -396,25 +395,7 @@ static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port) } *tmp = *port; free(port); - port = tmp; - - ahci_port_reset(port->ctrl, port->pnr); - - free(port->list); - free(port->fis); - free(port->cmd); - port->list = memalign_low(1024, 1024); - port->fis = memalign_low(256, 256); - port->cmd = memalign_low(256, 256); - - ahci_port_writel(port->ctrl, port->pnr, PORT_LST_ADDR, (u32)port->list); - ahci_port_writel(port->ctrl, port->pnr, PORT_FIS_ADDR, (u32)port->fis); - - cmd = ahci_port_readl(port->ctrl, port->pnr, PORT_CMD); - cmd |= (PORT_CMD_FIS_RX|PORT_CMD_START); - ahci_port_writel(port->ctrl, port->pnr, PORT_CMD, cmd); - - return port; + return tmp; }
#define MAXMODEL 40
On Tue, Nov 26, 2013 at 02:23:41PM +0100, Gerd Hoffmann wrote:
With ahci running in 32bit mode we can also allocate the (ahci private) data structures in high memory. This reduces the real mode memory footprint and also simplifies the realloc as we only need to move struct ahci_port_s (which contains struct drive_s) from high memory to fseg in case the port probe was successful.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
src/hw/ahci.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-)
diff --git a/src/hw/ahci.c b/src/hw/ahci.c index 5984c1c..5add207 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -358,9 +358,9 @@ ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr) } port->pnr = pnr; port->ctrl = ctrl;
- port->list = memalign_tmp(1024, 1024);
- port->fis = memalign_tmp(256, 256);
- port->cmd = memalign_tmp(256, 256);
- port->list = memalign_high(1024, 1024);
- port->fis = memalign_high(256, 256);
- port->cmd = memalign_high(256, 256);
Ideally, one wouldn't allocate in "high" ram and then go on to free it. (Memory fragmentation due to malloc/free could chew up some guest ram.) So, I'm not sure this is an improvement.
Also, if this is done then it wont work for 1Meg guests. That's probably not a concern though.
Otherwise, the other patches look fine to me.
-Kevin
Hi,
Ideally, one wouldn't allocate in "high" ram and then go on to free it. (Memory fragmentation due to malloc/free could chew up some guest ram.) So, I'm not sure this is an improvement.
So, we can keep the realloc but move tmp -> high instead of tmp -> low.
cheers, Gerd
On Fri, Nov 29, 2013 at 09:29:21AM +0100, Gerd Hoffmann wrote:
Hi,
Ideally, one wouldn't allocate in "high" ram and then go on to free it. (Memory fragmentation due to malloc/free could chew up some guest ram.) So, I'm not sure this is an improvement.
So, we can keep the realloc but move tmp -> high instead of tmp -> low.
If you want. This does mean that 1Meg guests wont be able to use AHCI. Also, high ram could be used by guests while low ram (e-segment) doesn't compete for guest ram. Anyway, it's up to you.
-Kevin
On Di, 2013-11-26 at 14:23 +0100, Gerd Hoffmann wrote:
Hi,
The ahci driver has recently been changed to run completely in 32bit mode. This is a followup patch series for this, removing real mode memory access macros not needed any more and also moving data structures out of real mode address space.
Pushed, with the discussed fixup for patch #3.
cheers, Gerd