Commit c9159e5321628a29bcc26216f0166e9cdd7e4b26
1 parent
8c9b861e
added IDE mult support - reduced irq latency (IDE should have good performances now)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@295 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
77 additions
and
31 deletions
vl.c
| @@ -54,6 +54,7 @@ | @@ -54,6 +54,7 @@ | ||
| 54 | #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" | 54 | #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" |
| 55 | 55 | ||
| 56 | //#define DEBUG_UNUSED_IOPORT | 56 | //#define DEBUG_UNUSED_IOPORT |
| 57 | +//#define DEBUG_IRQ_LATENCY | ||
| 57 | 58 | ||
| 58 | #define PHYS_RAM_BASE 0xa8000000 | 59 | #define PHYS_RAM_BASE 0xa8000000 |
| 59 | #define KERNEL_LOAD_ADDR 0x00100000 | 60 | #define KERNEL_LOAD_ADDR 0x00100000 |
| @@ -598,14 +599,9 @@ static int pic_get_irq(PicState *s) | @@ -598,14 +599,9 @@ static int pic_get_irq(PicState *s) | ||
| 598 | } | 599 | } |
| 599 | } | 600 | } |
| 600 | 601 | ||
| 601 | -void pic_set_irq(int irq, int level) | ||
| 602 | -{ | ||
| 603 | - pic_set_irq1(&pics[irq >> 3], irq & 7, level); | ||
| 604 | -} | ||
| 605 | - | ||
| 606 | -/* can be called at any time outside cpu_exec() to raise irqs if | ||
| 607 | - necessary */ | ||
| 608 | -void pic_handle_irq(void) | 602 | +/* raise irq to CPU if necessary. must be called every time the active |
| 603 | + irq may change */ | ||
| 604 | +static void pic_update_irq(void) | ||
| 609 | { | 605 | { |
| 610 | int irq2, irq; | 606 | int irq2, irq; |
| 611 | 607 | ||
| @@ -626,16 +622,36 @@ void pic_handle_irq(void) | @@ -626,16 +622,36 @@ void pic_handle_irq(void) | ||
| 626 | /* from master pic */ | 622 | /* from master pic */ |
| 627 | pic_irq_requested = irq; | 623 | pic_irq_requested = irq; |
| 628 | } | 624 | } |
| 629 | - global_env->hard_interrupt_request = 1; | 625 | + cpu_x86_interrupt(global_env, CPU_INTERRUPT_HARD); |
| 630 | } | 626 | } |
| 631 | } | 627 | } |
| 632 | 628 | ||
| 629 | +#ifdef DEBUG_IRQ_LATENCY | ||
| 630 | +int64_t irq_time[16]; | ||
| 631 | +int64_t cpu_get_ticks(void); | ||
| 632 | +#endif | ||
| 633 | + | ||
| 634 | +void pic_set_irq(int irq, int level) | ||
| 635 | +{ | ||
| 636 | +#ifdef DEBUG_IRQ_LATENCY | ||
| 637 | + if (level) { | ||
| 638 | + irq_time[irq] = cpu_get_ticks(); | ||
| 639 | + } | ||
| 640 | +#endif | ||
| 641 | + pic_set_irq1(&pics[irq >> 3], irq & 7, level); | ||
| 642 | + pic_update_irq(); | ||
| 643 | +} | ||
| 644 | + | ||
| 633 | int cpu_x86_get_pic_interrupt(CPUX86State *env) | 645 | int cpu_x86_get_pic_interrupt(CPUX86State *env) |
| 634 | { | 646 | { |
| 635 | int irq, irq2, intno; | 647 | int irq, irq2, intno; |
| 636 | 648 | ||
| 637 | /* signal the pic that the irq was acked by the CPU */ | 649 | /* signal the pic that the irq was acked by the CPU */ |
| 638 | irq = pic_irq_requested; | 650 | irq = pic_irq_requested; |
| 651 | +#ifdef DEBUG_IRQ_LATENCY | ||
| 652 | + printf("IRQ%d latency=%Ld\n", irq, cpu_get_ticks() - irq_time[irq]); | ||
| 653 | +#endif | ||
| 654 | + | ||
| 639 | if (irq >= 8) { | 655 | if (irq >= 8) { |
| 640 | irq2 = irq & 7; | 656 | irq2 = irq & 7; |
| 641 | pics[1].isr |= (1 << irq2); | 657 | pics[1].isr |= (1 << irq2); |
| @@ -706,6 +722,7 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -706,6 +722,7 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
| 706 | case 0: | 722 | case 0: |
| 707 | /* normal mode */ | 723 | /* normal mode */ |
| 708 | s->imr = val; | 724 | s->imr = val; |
| 725 | + pic_update_irq(); | ||
| 709 | break; | 726 | break; |
| 710 | case 1: | 727 | case 1: |
| 711 | s->irq_base = val & 0xf8; | 728 | s->irq_base = val & 0xf8; |
| @@ -1570,8 +1587,6 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -1570,8 +1587,6 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
| 1570 | s->rcnt == 0) { | 1587 | s->rcnt == 0) { |
| 1571 | s->isr |= ENISR_RDC; | 1588 | s->isr |= ENISR_RDC; |
| 1572 | ne2000_update_irq(s); | 1589 | ne2000_update_irq(s); |
| 1573 | - /* XXX: find a better solution for irqs */ | ||
| 1574 | - cpu_x86_interrupt(global_env); | ||
| 1575 | } | 1590 | } |
| 1576 | if (val & E8390_TRANS) { | 1591 | if (val & E8390_TRANS) { |
| 1577 | net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt); | 1592 | net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt); |
| @@ -1931,7 +1946,8 @@ void ne2000_init(void) | @@ -1931,7 +1946,8 @@ void ne2000_init(void) | ||
| 1931 | #define WIN_SET_MAX 0xF9 | 1946 | #define WIN_SET_MAX 0xF9 |
| 1932 | #define DISABLE_SEAGATE 0xFB | 1947 | #define DISABLE_SEAGATE 0xFB |
| 1933 | 1948 | ||
| 1934 | -#define MAX_MULT_SECTORS 16 | 1949 | +/* set to 1 set disable mult support */ |
| 1950 | +#define MAX_MULT_SECTORS 8 | ||
| 1935 | 1951 | ||
| 1936 | #define MAX_DISKS 2 | 1952 | #define MAX_DISKS 2 |
| 1937 | 1953 | ||
| @@ -1948,7 +1964,7 @@ typedef struct IDEState { | @@ -1948,7 +1964,7 @@ typedef struct IDEState { | ||
| 1948 | /* ide regs */ | 1964 | /* ide regs */ |
| 1949 | uint8_t feature; | 1965 | uint8_t feature; |
| 1950 | uint8_t error; | 1966 | uint8_t error; |
| 1951 | - uint8_t nsector; | 1967 | + uint16_t nsector; /* 0 is 256 to ease computations */ |
| 1952 | uint8_t sector; | 1968 | uint8_t sector; |
| 1953 | uint8_t lcyl; | 1969 | uint8_t lcyl; |
| 1954 | uint8_t hcyl; | 1970 | uint8_t hcyl; |
| @@ -1959,6 +1975,7 @@ typedef struct IDEState { | @@ -1959,6 +1975,7 @@ typedef struct IDEState { | ||
| 1959 | /* depends on bit 4 in select, only meaningful for drive 0 */ | 1975 | /* depends on bit 4 in select, only meaningful for drive 0 */ |
| 1960 | struct IDEState *cur_drive; | 1976 | struct IDEState *cur_drive; |
| 1961 | BlockDriverState *bs; | 1977 | BlockDriverState *bs; |
| 1978 | + int req_nb_sectors; /* number of sectors per interrupt */ | ||
| 1962 | EndTransferFunc *end_transfer_func; | 1979 | EndTransferFunc *end_transfer_func; |
| 1963 | uint8_t *data_ptr; | 1980 | uint8_t *data_ptr; |
| 1964 | uint8_t *data_end; | 1981 | uint8_t *data_end; |
| @@ -1998,7 +2015,9 @@ static void ide_identify(IDEState *s) | @@ -1998,7 +2015,9 @@ static void ide_identify(IDEState *s) | ||
| 1998 | stw(p + 21, 512); /* cache size in sectors */ | 2015 | stw(p + 21, 512); /* cache size in sectors */ |
| 1999 | stw(p + 22, 4); /* ecc bytes */ | 2016 | stw(p + 22, 4); /* ecc bytes */ |
| 2000 | padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); | 2017 | padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); |
| 2001 | - // stw(p + 47, MAX_MULT_SECTORS); | 2018 | +#if MAX_MULT_SECTORS > 1 |
| 2019 | + stw(p + 47, MAX_MULT_SECTORS); | ||
| 2020 | +#endif | ||
| 2002 | stw(p + 48, 1); /* dword I/O */ | 2021 | stw(p + 48, 1); /* dword I/O */ |
| 2003 | stw(p + 49, 1 << 9); /* LBA supported, no DMA */ | 2022 | stw(p + 49, 1 << 9); /* LBA supported, no DMA */ |
| 2004 | stw(p + 51, 0x200); /* PIO transfer cycle */ | 2023 | stw(p + 51, 0x200); /* PIO transfer cycle */ |
| @@ -2032,7 +2051,6 @@ static inline void ide_set_irq(IDEState *s) | @@ -2032,7 +2051,6 @@ static inline void ide_set_irq(IDEState *s) | ||
| 2032 | { | 2051 | { |
| 2033 | if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) { | 2052 | if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) { |
| 2034 | pic_set_irq(s->irq, 1); | 2053 | pic_set_irq(s->irq, 1); |
| 2035 | - cpu_x86_interrupt(global_env); | ||
| 2036 | } | 2054 | } |
| 2037 | } | 2055 | } |
| 2038 | 2056 | ||
| @@ -2090,51 +2108,60 @@ static void ide_set_sector(IDEState *s, int64_t sector_num) | @@ -2090,51 +2108,60 @@ static void ide_set_sector(IDEState *s, int64_t sector_num) | ||
| 2090 | static void ide_sector_read(IDEState *s) | 2108 | static void ide_sector_read(IDEState *s) |
| 2091 | { | 2109 | { |
| 2092 | int64_t sector_num; | 2110 | int64_t sector_num; |
| 2093 | - int ret; | 2111 | + int ret, n; |
| 2094 | 2112 | ||
| 2095 | s->status = READY_STAT | SEEK_STAT; | 2113 | s->status = READY_STAT | SEEK_STAT; |
| 2096 | sector_num = ide_get_sector(s); | 2114 | sector_num = ide_get_sector(s); |
| 2097 | - s->nsector--; | ||
| 2098 | - if (s->nsector == 0xff) { | 2115 | + n = s->nsector; |
| 2116 | + if (n == 0) { | ||
| 2099 | /* no more sector to read from disk */ | 2117 | /* no more sector to read from disk */ |
| 2100 | ide_transfer_stop(s); | 2118 | ide_transfer_stop(s); |
| 2101 | } else { | 2119 | } else { |
| 2102 | #if defined(DEBUG_IDE) | 2120 | #if defined(DEBUG_IDE) |
| 2103 | printf("read sector=%Ld\n", sector_num); | 2121 | printf("read sector=%Ld\n", sector_num); |
| 2104 | #endif | 2122 | #endif |
| 2105 | - ret = bdrv_read(s->bs, sector_num, s->io_buffer, 1); | ||
| 2106 | - ide_transfer_start(s, 512, ide_sector_read); | 2123 | + if (n > s->req_nb_sectors) |
| 2124 | + n = s->req_nb_sectors; | ||
| 2125 | + ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); | ||
| 2126 | + ide_transfer_start(s, 512 * n, ide_sector_read); | ||
| 2107 | ide_set_irq(s); | 2127 | ide_set_irq(s); |
| 2128 | + ide_set_sector(s, sector_num + n); | ||
| 2129 | + s->nsector -= n; | ||
| 2108 | } | 2130 | } |
| 2109 | - ide_set_sector(s, sector_num + 1); | ||
| 2110 | } | 2131 | } |
| 2111 | 2132 | ||
| 2112 | static void ide_sector_write(IDEState *s) | 2133 | static void ide_sector_write(IDEState *s) |
| 2113 | { | 2134 | { |
| 2114 | int64_t sector_num; | 2135 | int64_t sector_num; |
| 2115 | - int ret; | 2136 | + int ret, n, n1; |
| 2116 | 2137 | ||
| 2117 | s->status = READY_STAT | SEEK_STAT; | 2138 | s->status = READY_STAT | SEEK_STAT; |
| 2118 | sector_num = ide_get_sector(s); | 2139 | sector_num = ide_get_sector(s); |
| 2119 | #if defined(DEBUG_IDE) | 2140 | #if defined(DEBUG_IDE) |
| 2120 | printf("write sector=%Ld\n", sector_num); | 2141 | printf("write sector=%Ld\n", sector_num); |
| 2121 | #endif | 2142 | #endif |
| 2122 | - ret = bdrv_write(s->bs, sector_num, s->io_buffer, 1); | ||
| 2123 | - s->nsector--; | 2143 | + n = s->nsector; |
| 2144 | + if (n > s->req_nb_sectors) | ||
| 2145 | + n = s->req_nb_sectors; | ||
| 2146 | + ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); | ||
| 2147 | + s->nsector -= n; | ||
| 2124 | if (s->nsector == 0) { | 2148 | if (s->nsector == 0) { |
| 2125 | /* no more sector to write */ | 2149 | /* no more sector to write */ |
| 2126 | ide_transfer_stop(s); | 2150 | ide_transfer_stop(s); |
| 2127 | } else { | 2151 | } else { |
| 2128 | - ide_transfer_start(s, 512, ide_sector_write); | 2152 | + n1 = s->nsector; |
| 2153 | + if (n1 > s->req_nb_sectors) | ||
| 2154 | + n1 = s->req_nb_sectors; | ||
| 2155 | + ide_transfer_start(s, 512 * n1, ide_sector_write); | ||
| 2129 | } | 2156 | } |
| 2130 | - ide_set_sector(s, sector_num + 1); | 2157 | + ide_set_sector(s, sector_num + n); |
| 2131 | ide_set_irq(s); | 2158 | ide_set_irq(s); |
| 2132 | } | 2159 | } |
| 2133 | 2160 | ||
| 2134 | void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | 2161 | void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
| 2135 | { | 2162 | { |
| 2136 | IDEState *s = ide_state[0].cur_drive; | 2163 | IDEState *s = ide_state[0].cur_drive; |
| 2137 | - int unit; | 2164 | + int unit, n; |
| 2138 | 2165 | ||
| 2139 | addr &= 7; | 2166 | addr &= 7; |
| 2140 | #ifdef DEBUG_IDE | 2167 | #ifdef DEBUG_IDE |
| @@ -2147,6 +2174,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2147,6 +2174,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
| 2147 | s->feature = val; | 2174 | s->feature = val; |
| 2148 | break; | 2175 | break; |
| 2149 | case 2: | 2176 | case 2: |
| 2177 | + if (val == 0) | ||
| 2178 | + val = 256; | ||
| 2150 | s->nsector = val; | 2179 | s->nsector = val; |
| 2151 | break; | 2180 | break; |
| 2152 | case 3: | 2181 | case 3: |
| @@ -2201,14 +2230,33 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2201,14 +2230,33 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
| 2201 | break; | 2230 | break; |
| 2202 | case WIN_READ: | 2231 | case WIN_READ: |
| 2203 | case WIN_READ_ONCE: | 2232 | case WIN_READ_ONCE: |
| 2233 | + s->req_nb_sectors = 1; | ||
| 2204 | ide_sector_read(s); | 2234 | ide_sector_read(s); |
| 2205 | break; | 2235 | break; |
| 2206 | case WIN_WRITE: | 2236 | case WIN_WRITE: |
| 2207 | case WIN_WRITE_ONCE: | 2237 | case WIN_WRITE_ONCE: |
| 2208 | s->status = SEEK_STAT; | 2238 | s->status = SEEK_STAT; |
| 2239 | + s->req_nb_sectors = 1; | ||
| 2209 | ide_transfer_start(s, 512, ide_sector_write); | 2240 | ide_transfer_start(s, 512, ide_sector_write); |
| 2210 | break; | 2241 | break; |
| 2242 | + case WIN_MULTREAD: | ||
| 2243 | + if (!s->mult_sectors) | ||
| 2244 | + goto abort_cmd; | ||
| 2245 | + s->req_nb_sectors = s->mult_sectors; | ||
| 2246 | + ide_sector_read(s); | ||
| 2247 | + break; | ||
| 2248 | + case WIN_MULTWRITE: | ||
| 2249 | + if (!s->mult_sectors) | ||
| 2250 | + goto abort_cmd; | ||
| 2251 | + s->status = SEEK_STAT; | ||
| 2252 | + s->req_nb_sectors = s->mult_sectors; | ||
| 2253 | + n = s->nsector; | ||
| 2254 | + if (n > s->req_nb_sectors) | ||
| 2255 | + n = s->req_nb_sectors; | ||
| 2256 | + ide_transfer_start(s, 512 * n, ide_sector_write); | ||
| 2257 | + break; | ||
| 2211 | default: | 2258 | default: |
| 2259 | + abort_cmd: | ||
| 2212 | ide_abort_command(s); | 2260 | ide_abort_command(s); |
| 2213 | ide_set_irq(s); | 2261 | ide_set_irq(s); |
| 2214 | break; | 2262 | break; |
| @@ -2230,7 +2278,7 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) | @@ -2230,7 +2278,7 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) | ||
| 2230 | ret = s->error; | 2278 | ret = s->error; |
| 2231 | break; | 2279 | break; |
| 2232 | case 2: | 2280 | case 2: |
| 2233 | - ret = s->nsector; | 2281 | + ret = s->nsector & 0xff; |
| 2234 | break; | 2282 | break; |
| 2235 | case 3: | 2283 | case 3: |
| 2236 | ret = s->sector; | 2284 | ret = s->sector; |
| @@ -2400,7 +2448,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, | @@ -2400,7 +2448,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, | ||
| 2400 | timer_irq_count = 2; | 2448 | timer_irq_count = 2; |
| 2401 | timer_irq_count--; | 2449 | timer_irq_count--; |
| 2402 | /* just exit from the cpu to have a chance to handle timers */ | 2450 | /* just exit from the cpu to have a chance to handle timers */ |
| 2403 | - cpu_x86_interrupt(global_env); | 2451 | + cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
| 2404 | timer_irq_pending = 1; | 2452 | timer_irq_pending = 1; |
| 2405 | } | 2453 | } |
| 2406 | } | 2454 | } |
| @@ -2487,8 +2535,6 @@ void main_loop(void *opaque) | @@ -2487,8 +2535,6 @@ void main_loop(void *opaque) | ||
| 2487 | pic_set_irq(0, 0); | 2535 | pic_set_irq(0, 0); |
| 2488 | timer_irq_pending = 0; | 2536 | timer_irq_pending = 0; |
| 2489 | } | 2537 | } |
| 2490 | - | ||
| 2491 | - pic_handle_irq(); | ||
| 2492 | } | 2538 | } |
| 2493 | } | 2539 | } |
| 2494 | 2540 |