ia64/xen-unstable

changeset 16566:01c9b2b3118a

hvm stdvga: Do not emulate PIO reads inside Xen. They should be rare
(PIO write emulation is really for book-keeping to detect when we
enter/leave stdvga mode, and to work out what to do with mmio
accesses), and we may do the wrong thing depending on emulated SVGA
hardware and current mode.

This simplifies the code and means that 'stdvga=1' once again works
properly and causes the stdvga bios to be loaded by hvmloader.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sat Dec 08 16:57:13 2007 +0000 (2007-12-08)
parents c3286cb2fc59
children 1f0c6e0d74a4
files xen/arch/x86/hvm/save.c xen/arch/x86/hvm/stdvga.c xen/include/asm-x86/hvm/io.h
line diff
     1.1 --- a/xen/arch/x86/hvm/save.c	Sat Dec 08 15:47:31 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/save.c	Sat Dec 08 16:57:13 2007 +0000
     1.3 @@ -59,10 +59,8 @@ int arch_hvm_load(struct domain *d, stru
     1.4          gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") "
     1.5                 "does not match host (%#"PRIx32").\n", hdr->cpuid, eax);
     1.6  
     1.7 -#ifdef __x86_64__
     1.8      /* VGA state is not saved/restored, so we nobble the cache. */
     1.9      d->arch.hvm_domain.stdvga.cache = 0;
    1.10 -#endif
    1.11  
    1.12      return 0;
    1.13  }
     2.1 --- a/xen/arch/x86/hvm/stdvga.c	Sat Dec 08 15:47:31 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/stdvga.c	Sat Dec 08 16:57:13 2007 +0000
     2.3 @@ -65,7 +65,7 @@ const uint8_t sr_mask[8] = {
     2.4      (uint8_t)~0x00,
     2.5  };
     2.6  
     2.7 -const uint8_t gr_mask[16] = {
     2.8 +const uint8_t gr_mask[9] = {
     2.9      (uint8_t)~0xf0, /* 0x00 */
    2.10      (uint8_t)~0xf0, /* 0x01 */
    2.11      (uint8_t)~0xf0, /* 0x02 */
    2.12 @@ -96,84 +96,10 @@ static void vram_put(struct hvm_hw_stdvg
    2.13      unmap_domain_page(p);
    2.14  }
    2.15  
    2.16 -static uint64_t stdvga_inb(uint64_t addr)
    2.17 +static int stdvga_outb(uint64_t addr, uint8_t val)
    2.18  {
    2.19      struct hvm_hw_stdvga *s = &current->domain->arch.hvm_domain.stdvga;
    2.20 -    uint8_t val = 0;
    2.21 -
    2.22 -    switch ( addr )
    2.23 -    {
    2.24 -    case 0x3c4:                 /* sequencer address register */
    2.25 -        val = s->sr_index;
    2.26 -        break;
    2.27 -
    2.28 -    case 0x3c5:                 /* sequencer data register */
    2.29 -        if ( s->sr_index < sizeof(s->sr) )
    2.30 -            val = s->sr[s->sr_index];
    2.31 -        break;
    2.32 -
    2.33 -    case 0x3ce:                 /* graphics address register */
    2.34 -        val = s->gr_index;
    2.35 -        break;
    2.36 -
    2.37 -    case 0x3cf:                 /* graphics data register */
    2.38 -        val = s->gr[s->gr_index];
    2.39 -        break;
    2.40 -
    2.41 -    default:
    2.42 -        gdprintk(XENLOG_WARNING, "unexpected io addr 0x%04x\n", (int)addr);
    2.43 -    }
    2.44 -
    2.45 -    return val;
    2.46 -}
    2.47 -
    2.48 -static uint64_t stdvga_in(ioreq_t *p)
    2.49 -{
    2.50 -    /* Satisfy reads from sequence and graphics registers using local values */
    2.51 -    uint64_t data = 0;
    2.52 -
    2.53 -    switch ( p->size )
    2.54 -    {
    2.55 -    case 1:
    2.56 -        data = stdvga_inb(p->addr);
    2.57 -        break;
    2.58 -
    2.59 -    case 2:
    2.60 -        data = stdvga_inb(p->addr);
    2.61 -        data |= stdvga_inb(p->addr + 1) << 8;
    2.62 -        break;
    2.63 -
    2.64 -    case 4:
    2.65 -        data = stdvga_inb(p->addr);
    2.66 -        data |= stdvga_inb(p->addr + 1) << 8;
    2.67 -        data |= stdvga_inb(p->addr + 2) << 16;
    2.68 -        data |= stdvga_inb(p->addr + 3) << 24;
    2.69 -        break;
    2.70 -
    2.71 -    case 8:
    2.72 -        data = stdvga_inb(p->addr);
    2.73 -        data |= stdvga_inb(p->addr + 1) << 8;
    2.74 -        data |= stdvga_inb(p->addr + 2) << 16;
    2.75 -        data |= stdvga_inb(p->addr + 3) << 24;
    2.76 -        data |= stdvga_inb(p->addr + 4) << 32;
    2.77 -        data |= stdvga_inb(p->addr + 5) << 40;
    2.78 -        data |= stdvga_inb(p->addr + 6) << 48;
    2.79 -        data |= stdvga_inb(p->addr + 7) << 56;
    2.80 -        break;
    2.81 -
    2.82 -    default:
    2.83 -        gdprintk(XENLOG_WARNING, "invalid io size:%d\n", (int)p->size);
    2.84 -    }
    2.85 -
    2.86 -    return data;
    2.87 -}
    2.88 -
    2.89 -static void stdvga_outb(uint64_t addr, uint8_t val)
    2.90 -{
    2.91 -    /* Bookkeep (via snooping) the sequencer and graphics registers */
    2.92 -
    2.93 -    struct hvm_hw_stdvga *s = &current->domain->arch.hvm_domain.stdvga;
    2.94 -    int prev_stdvga = s->stdvga;
    2.95 +    int rc = 1, prev_stdvga = s->stdvga;
    2.96  
    2.97      switch ( addr )
    2.98      {
    2.99 @@ -182,20 +108,9 @@ static void stdvga_outb(uint64_t addr, u
   2.100          break;
   2.101  
   2.102      case 0x3c5:                 /* sequencer data register */
   2.103 -        switch ( s->sr_index )
   2.104 -        {
   2.105 -        case 0x00 ... 0x05:
   2.106 -        case 0x07:
   2.107 -            s->sr[s->sr_index] = val & sr_mask[s->sr_index];
   2.108 -            break;
   2.109 -        case 0x06:
   2.110 -            s->sr[s->sr_index] = ((val & 0x17) == 0x12) ? 0x12 : 0x0f;
   2.111 -            break;
   2.112 -        default:
   2.113 -            if ( s->sr_index < sizeof(s->sr) )
   2.114 -                s->sr[s->sr_index] = val;
   2.115 -            break;
   2.116 -        }
   2.117 +        rc = (s->sr_index < sizeof(s->sr));
   2.118 +        if ( rc )
   2.119 +            s->sr[s->sr_index] = val & sr_mask[s->sr_index] ;
   2.120          break;
   2.121  
   2.122      case 0x3ce:                 /* graphics address register */
   2.123 @@ -203,16 +118,20 @@ static void stdvga_outb(uint64_t addr, u
   2.124          break;
   2.125  
   2.126      case 0x3cf:                 /* graphics data register */
   2.127 -        s->gr[s->gr_index] = val;
   2.128 -        if ( s->gr_index < sizeof(gr_mask) )
   2.129 -            s->gr[s->gr_index] &= gr_mask[s->gr_index];
   2.130 +        rc = (s->gr_index < sizeof(s->gr));
   2.131 +        if ( rc )
   2.132 +            s->gr[s->gr_index] = val & gr_mask[s->gr_index];
   2.133 +        break;
   2.134 +
   2.135 +    default:
   2.136 +        rc = 0;
   2.137          break;
   2.138      }
   2.139  
   2.140      /* When in standard vga mode, emulate here all writes to the vram buffer
   2.141       * so we can immediately satisfy reads without waiting for qemu. */
   2.142      s->stdvga =
   2.143 -        (s->sr[0x07] == 0) &&  /* standard vga mode */
   2.144 +        (s->sr[7] == 0x00) &&  /* standard vga mode */
   2.145          (s->gr[6] == 0x05);    /* misc graphics register w/ MemoryMapSelect=1
   2.146                                  * 0xa0000-0xaffff (64k region), AlphaDis=1 */
   2.147  
   2.148 @@ -225,98 +144,43 @@ static void stdvga_outb(uint64_t addr, u
   2.149      {
   2.150          gdprintk(XENLOG_INFO, "leaving stdvga\n");
   2.151      }
   2.152 +
   2.153 +    return rc;
   2.154  }
   2.155  
   2.156 -static void stdvga_outv(uint64_t addr, uint64_t data, uint32_t size)
   2.157 +static int stdvga_out(ioreq_t *p)
   2.158  {
   2.159 -    switch ( size )
   2.160 +    int rc = 1;
   2.161 +
   2.162 +    switch ( p->size )
   2.163      {
   2.164      case 1:
   2.165 -        stdvga_outb(addr, data);
   2.166 +        rc &= stdvga_outb(p->addr, p->data);
   2.167          break;
   2.168  
   2.169      case 2:
   2.170 -        stdvga_outb(addr+0, data >>  0);
   2.171 -        stdvga_outb(addr+1, data >>  8);
   2.172 -        break;
   2.173 -
   2.174 -    case 4:
   2.175 -        stdvga_outb(addr+0, data >>  0);
   2.176 -        stdvga_outb(addr+1, data >>  8);
   2.177 -        stdvga_outb(addr+2, data >> 16);
   2.178 -        stdvga_outb(addr+3, data >> 24);
   2.179 -        break;
   2.180 -
   2.181 -    case 8:
   2.182 -        stdvga_outb(addr+0, data >>  0);
   2.183 -        stdvga_outb(addr+1, data >>  8);
   2.184 -        stdvga_outb(addr+2, data >> 16);
   2.185 -        stdvga_outb(addr+3, data >> 24);
   2.186 -        stdvga_outb(addr+4, data >> 32);
   2.187 -        stdvga_outb(addr+5, data >> 40);
   2.188 -        stdvga_outb(addr+6, data >> 48);
   2.189 -        stdvga_outb(addr+7, data >> 56);
   2.190 +        rc &= stdvga_outb(p->addr + 0, p->data >> 0);
   2.191 +        rc &= stdvga_outb(p->addr + 1, p->data >> 8);
   2.192          break;
   2.193  
   2.194      default:
   2.195 -        gdprintk(XENLOG_WARNING, "invalid io size:%d\n", size);
   2.196 +        rc = 0;
   2.197 +        break;
   2.198      }
   2.199 -}
   2.200  
   2.201 -static void stdvga_out(ioreq_t *p)
   2.202 -{
   2.203 -    if ( p->data_is_ptr )
   2.204 -    {
   2.205 -        int i, sign = p->df ? -1 : 1;
   2.206 -        uint64_t addr = p->addr, data = p->data, tmp;
   2.207 -        for ( i = 0; i < p->count; i++ )
   2.208 -        {
   2.209 -            hvm_copy_from_guest_phys(&tmp, data, p->size);
   2.210 -            stdvga_outv(addr, tmp, p->size);
   2.211 -            data += sign * p->size;
   2.212 -            addr += sign * p->size;
   2.213 -        }
   2.214 -    }
   2.215 -    else
   2.216 -    {
   2.217 -        stdvga_outv(p->addr, p->data, p->size);
   2.218 -    }
   2.219 +    return rc;
   2.220  }
   2.221  
   2.222  int stdvga_intercept_pio(ioreq_t *p)
   2.223  {
   2.224      struct hvm_hw_stdvga *s = &current->domain->arch.hvm_domain.stdvga;
   2.225 -    int buf = 0, rc;
   2.226 +    int rc;
   2.227  
   2.228 -    if ( p->size > 8 )
   2.229 -    {
   2.230 -        gdprintk(XENLOG_WARNING, "stdvga bad access size %d\n", (int)p->size);
   2.231 +    if ( p->data_is_ptr || (p->dir == IOREQ_READ) )
   2.232          return 0;
   2.233 -    }
   2.234  
   2.235      spin_lock(&s->lock);
   2.236 -
   2.237 -    if ( p->dir == IOREQ_READ )
   2.238 -    {
   2.239 -        if ( p->size != 1 )
   2.240 -            gdprintk(XENLOG_WARNING, "unexpected io size:%d\n", (int)p->size);
   2.241 -        if ( p->data_is_ptr )
   2.242 -            gdprintk(XENLOG_WARNING, "unexpected data_is_ptr\n");
   2.243 -        if ( !((p->addr == 0x3c5) && (s->sr_index >= sizeof(sr_mask))) &&
   2.244 -             !((p->addr == 0x3cf) && (s->gr_index >= sizeof(gr_mask))) )
   2.245 -        {
   2.246 -            p->data = stdvga_in(p);
   2.247 -            buf = 1;
   2.248 -        }
   2.249 -    }
   2.250 -    else
   2.251 -    {
   2.252 -        stdvga_out(p);
   2.253 -        buf = 1;
   2.254 -    }
   2.255 -
   2.256 -    rc = (buf && hvm_buffered_io_send(p));
   2.257 -
   2.258 +    rc = (stdvga_out(p) && hvm_buffered_io_send(p));
   2.259      spin_unlock(&s->lock);
   2.260  
   2.261      return rc;
     3.1 --- a/xen/include/asm-x86/hvm/io.h	Sat Dec 08 15:47:31 2007 +0000
     3.2 +++ b/xen/include/asm-x86/hvm/io.h	Sat Dec 08 16:57:13 2007 +0000
     3.3 @@ -164,12 +164,12 @@ extern void hvm_dpci_eoi(struct domain *
     3.4  
     3.5  struct hvm_hw_stdvga {
     3.6      uint8_t sr_index;
     3.7 -    uint8_t sr[0x18];
     3.8 +    uint8_t sr[8];
     3.9      uint8_t gr_index;
    3.10 -    uint8_t gr[256];
    3.11 +    uint8_t gr[9];
    3.12 +    bool_t stdvga;
    3.13 +    bool_t cache;
    3.14      uint32_t latch;
    3.15 -    int stdvga;
    3.16 -    int cache;
    3.17      struct page_info *vram_page[64];  /* shadow of 0xa0000-0xaffff */
    3.18      spinlock_t lock;
    3.19  };