1783 |
} |
} |
1784 |
} |
} |
1785 |
|
|
1786 |
|
/* main execution loop */ |
1787 |
|
|
1788 |
|
CPUState *cpu_gdbstub_get_env(void *opaque) |
1789 |
|
{ |
1790 |
|
return global_env; |
1791 |
|
} |
1792 |
|
|
1793 |
|
void main_loop(void *opaque) |
1794 |
|
{ |
1795 |
|
struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd, *gdb_ufd; |
1796 |
|
int ret, n, timeout; |
1797 |
|
uint8_t ch; |
1798 |
|
CPUState *env = global_env; |
1799 |
|
|
1800 |
|
for(;;) { |
1801 |
|
|
1802 |
|
ret = cpu_x86_exec(env); |
1803 |
|
|
1804 |
|
/* if hlt instruction, we wait until the next IRQ */ |
1805 |
|
if (ret == EXCP_HLT) |
1806 |
|
timeout = 10; |
1807 |
|
else |
1808 |
|
timeout = 0; |
1809 |
|
/* poll any events */ |
1810 |
|
serial_ufd = NULL; |
1811 |
|
pf = ufds; |
1812 |
|
if (!(serial_ports[0].lsr & UART_LSR_DR)) { |
1813 |
|
serial_ufd = pf; |
1814 |
|
pf->fd = 0; |
1815 |
|
pf->events = POLLIN; |
1816 |
|
pf++; |
1817 |
|
} |
1818 |
|
net_ufd = NULL; |
1819 |
|
if (net_fd > 0 && ne2000_can_receive(&ne2000_state)) { |
1820 |
|
net_ufd = pf; |
1821 |
|
pf->fd = net_fd; |
1822 |
|
pf->events = POLLIN; |
1823 |
|
pf++; |
1824 |
|
} |
1825 |
|
gdb_ufd = NULL; |
1826 |
|
if (gdbstub_fd > 0) { |
1827 |
|
gdb_ufd = pf; |
1828 |
|
pf->fd = gdbstub_fd; |
1829 |
|
pf->events = POLLIN; |
1830 |
|
pf++; |
1831 |
|
} |
1832 |
|
|
1833 |
|
ret = poll(ufds, pf - ufds, timeout); |
1834 |
|
if (ret > 0) { |
1835 |
|
if (serial_ufd && (serial_ufd->revents & POLLIN)) { |
1836 |
|
n = read(0, &ch, 1); |
1837 |
|
if (n == 1) { |
1838 |
|
serial_received_byte(&serial_ports[0], ch); |
1839 |
|
} |
1840 |
|
} |
1841 |
|
if (net_ufd && (net_ufd->revents & POLLIN)) { |
1842 |
|
uint8_t buf[MAX_ETH_FRAME_SIZE]; |
1843 |
|
|
1844 |
|
n = read(net_fd, buf, MAX_ETH_FRAME_SIZE); |
1845 |
|
if (n > 0) { |
1846 |
|
if (n < 60) { |
1847 |
|
memset(buf + n, 0, 60 - n); |
1848 |
|
n = 60; |
1849 |
|
} |
1850 |
|
ne2000_receive(&ne2000_state, buf, n); |
1851 |
|
} |
1852 |
|
} |
1853 |
|
if (gdb_ufd && (gdb_ufd->revents & POLLIN)) { |
1854 |
|
uint8_t buf[1]; |
1855 |
|
/* stop emulation if requested by gdb */ |
1856 |
|
n = read(gdbstub_fd, buf, 1); |
1857 |
|
if (n == 1) |
1858 |
|
break; |
1859 |
|
} |
1860 |
|
} |
1861 |
|
|
1862 |
|
/* timer IRQ */ |
1863 |
|
if (timer_irq_pending) { |
1864 |
|
pic_set_irq(0, 1); |
1865 |
|
pic_set_irq(0, 0); |
1866 |
|
timer_irq_pending = 0; |
1867 |
|
} |
1868 |
|
|
1869 |
|
pic_handle_irq(); |
1870 |
|
} |
1871 |
|
} |
1872 |
|
|
1873 |
void help(void) |
void help(void) |
1874 |
{ |
{ |
1875 |
printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
1876 |
"usage: vl [-h] bzImage initrd [kernel parameters...]\n" |
"usage: vl [options] bzImage initrd [kernel parameters...]\n" |
1877 |
"\n" |
"\n" |
1878 |
"'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
"'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
1879 |
"to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
"to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
1880 |
"'initrd' is an initrd image\n" |
"'initrd' is an initrd image\n" |
1881 |
"-m megs set virtual RAM size to megs MB\n" |
"-m megs set virtual RAM size to megs MB\n" |
1882 |
"-n script set network init script [default=%s]\n" |
"-n script set network init script [default=%s]\n" |
1883 |
|
"-s wait gdb connection to port %d\n" |
1884 |
|
"-p port change gdb connection port\n" |
1885 |
"-d output log in /tmp/vl.log\n" |
"-d output log in /tmp/vl.log\n" |
1886 |
"\n" |
"\n" |
1887 |
"During emulation, use C-a h to get terminal commands:\n", |
"During emulation, use C-a h to get terminal commands:\n", |
1888 |
DEFAULT_NETWORK_SCRIPT); |
DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
1889 |
term_print_help(); |
term_print_help(); |
1890 |
exit(1); |
exit(1); |
1891 |
} |
} |
1892 |
|
|
1893 |
int main(int argc, char **argv) |
int main(int argc, char **argv) |
1894 |
{ |
{ |
1895 |
int c, ret, initrd_size, i; |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port; |
1896 |
struct linux_params *params; |
struct linux_params *params; |
1897 |
struct sigaction act; |
struct sigaction act; |
1898 |
struct itimerval itv; |
struct itimerval itv; |
1904 |
|
|
1905 |
phys_ram_size = 32 * 1024 * 1024; |
phys_ram_size = 32 * 1024 * 1024; |
1906 |
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
1907 |
|
use_gdbstub = 0; |
1908 |
|
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
1909 |
for(;;) { |
for(;;) { |
1910 |
c = getopt(argc, argv, "hm:dn:"); |
c = getopt(argc, argv, "hm:dn:sp:"); |
1911 |
if (c == -1) |
if (c == -1) |
1912 |
break; |
break; |
1913 |
switch(c) { |
switch(c) { |
1925 |
case 'n': |
case 'n': |
1926 |
pstrcpy(network_script, sizeof(network_script), optarg); |
pstrcpy(network_script, sizeof(network_script), optarg); |
1927 |
break; |
break; |
1928 |
|
case 's': |
1929 |
|
use_gdbstub = 1; |
1930 |
|
break; |
1931 |
|
case 'p': |
1932 |
|
gdbstub_port = atoi(optarg); |
1933 |
|
break; |
1934 |
} |
} |
1935 |
} |
} |
1936 |
if (optind + 1 >= argc) |
if (optind + 1 >= argc) |
2071 |
getitimer(ITIMER_REAL, &itv); |
getitimer(ITIMER_REAL, &itv); |
2072 |
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
2073 |
1000000; |
1000000; |
2074 |
|
|
2075 |
for(;;) { |
if (use_gdbstub) { |
2076 |
struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd; |
cpu_gdbstub(NULL, main_loop, gdbstub_port); |
2077 |
int ret, n, timeout; |
} else { |
2078 |
uint8_t ch; |
main_loop(NULL); |
|
|
|
|
ret = cpu_x86_exec(env); |
|
|
|
|
|
/* if hlt instruction, we wait until the next IRQ */ |
|
|
if (ret == EXCP_HLT) |
|
|
timeout = 10; |
|
|
else |
|
|
timeout = 0; |
|
|
/* poll any events */ |
|
|
serial_ufd = NULL; |
|
|
net_ufd = NULL; |
|
|
pf = ufds; |
|
|
if (!(serial_ports[0].lsr & UART_LSR_DR)) { |
|
|
serial_ufd = pf; |
|
|
pf->fd = 0; |
|
|
pf->events = POLLIN; |
|
|
pf++; |
|
|
} |
|
|
if (net_fd > 0 && ne2000_can_receive(&ne2000_state)) { |
|
|
net_ufd = pf; |
|
|
pf->fd = net_fd; |
|
|
pf->events = POLLIN; |
|
|
pf++; |
|
|
} |
|
|
ret = poll(ufds, pf - ufds, timeout); |
|
|
if (ret > 0) { |
|
|
if (serial_ufd && (serial_ufd->revents & POLLIN)) { |
|
|
n = read(0, &ch, 1); |
|
|
if (n == 1) { |
|
|
serial_received_byte(&serial_ports[0], ch); |
|
|
} |
|
|
} |
|
|
if (net_ufd && (net_ufd->revents & POLLIN)) { |
|
|
uint8_t buf[MAX_ETH_FRAME_SIZE]; |
|
|
|
|
|
n = read(net_fd, buf, MAX_ETH_FRAME_SIZE); |
|
|
if (n > 0) { |
|
|
if (n < 60) { |
|
|
memset(buf + n, 0, 60 - n); |
|
|
n = 60; |
|
|
} |
|
|
ne2000_receive(&ne2000_state, buf, n); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/* timer IRQ */ |
|
|
if (timer_irq_pending) { |
|
|
pic_set_irq(0, 1); |
|
|
pic_set_irq(0, 0); |
|
|
timer_irq_pending = 0; |
|
|
} |
|
|
|
|
|
pic_handle_irq(); |
|
2079 |
} |
} |
|
|
|
2080 |
return 0; |
return 0; |
2081 |
} |
} |