From: Ian Jackson Date: Wed, 14 May 2008 15:06:15 +0000 (+0100) Subject: Merge branch 'master' into xen X-Git-Tag: xen-3.3.0-rc1~194 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=697b2d5fee9f2470525a1ed9ae2ea8c9beb29ef0;p=qemu-xen-4.3-testing.git Merge branch 'master' into xen Conflicts: hw/ide.c hw/pc.c hw/serial.c hw/usb-hid.c loader.c sysemu.h vl.c Merge was relatively straightforward. Specific comments follow: hw/serial.c Have kept the Xen rate limiting rather than the qemu version. The Xen version does an overall rate limit but doesn't adjust according to the baud rate. The qemu version is just a maximum burst (so no overall capacity limit) but does depend on the baud rate. vl.c Several dummy functions helpfully moved into target-* directories; I put them in a new i386-dm/machine.c for now. --- 697b2d5fee9f2470525a1ed9ae2ea8c9beb29ef0 diff --cc Makefile.target index 1be2e36ee,310de1e72..557a1bdc8 --- a/Makefile.target +++ b/Makefile.target @@@ -657,11 -681,8 +681,11 @@@ LDFLAGS+=- main.o: CFLAGS+=-p endif +include hooks.mak +all: $(PROGS) + $(QEMU_PROG): $(OBJS) ../libqemu_common.a libqemu.a - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) endif # !CONFIG_USER_ONLY diff --cc hw/ide.c index 310c01222,8b86f71b8..22f6c851b --- a/hw/ide.c +++ b/hw/ide.c @@@ -202,15 -202,10 +202,16 @@@ /* set to 1 set disable mult support */ #define MAX_MULT_SECTORS 16 +#ifdef CONFIG_STUBDOM +#include - #define IDE_DMA_BUF_SIZE (BLKIF_MAX_SEGMENTS_PER_REQUEST * TARGET_PAGE_SIZE) ++#define IDE_DMA_BUF_SECTORS \ ++ ((BLKIF_MAX_SEGMENTS_PER_REQUEST * TARGET_PAGE_SIZE) / 512) +#else - #define IDE_DMA_BUF_SIZE 131072 + #define IDE_DMA_BUF_SECTORS 256 +#endif - #if (IDE_DMA_BUF_SIZE < MAX_MULT_SECTORS * 512) - #error "IDE_DMA_BUF_SIZE must be bigger or equal to MAX_MULT_SECTORS * 512" + #if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) + #error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" #endif /* ATAPI defines */ diff --cc hw/pc.c index eb4be15a7,37a1172b5..b51bbbb71 --- a/hw/pc.c +++ b/hw/pc.c @@@ -117,11 -116,17 +120,18 @@@ int cpu_get_pic_interrupt(CPUState *env static void pic_irq_request(void *opaque, int irq, int level) { - CPUState *env = opaque; - if (level && apic_accept_pic_intr(env)) - cpu_interrupt(env, CPU_INTERRUPT_HARD); + CPUState *env = first_cpu; + + if (!level) + return; + + while (env) { + if (apic_accept_pic_intr(env)) + apic_local_deliver(env, APIC_LINT0); + env = env->next_cpu; + } } +#endif /* !CONFIG_DM */ /* PC cmos mappings */ @@@ -741,13 -771,19 +798,20 @@@ static void pc_init1(ram_addr_t ram_siz if (pci_enabled) { apic_init(env); } - vmport_init(env); } + vmport_init(); + +#ifndef CONFIG_DM /* allocate RAM */ ram_addr = qemu_ram_alloc(ram_size); - cpu_register_physical_memory(0, ram_size, ram_addr); + cpu_register_physical_memory(0, below_4g_mem_size, ram_addr); + + /* above 4giga memory allocation */ + if (above_4g_mem_size > 0) { + cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size, + ram_addr + below_4g_mem_size); + } /* allocate VGA RAM */ vga_ram_addr = qemu_ram_alloc(vga_ram_size); @@@ -1051,135 -1079,5 +1117,136 @@@ QEMUMachine isapc_machine = "isapc", "ISA-only PC", pc_init_isa, + VGA_RAM_SIZE + PC_MAX_BIOS_SIZE, }; + + + + +/* + * Evil helper for non-relocatable kernels + * + * So it works out like this: + * + * 0x100000 - Xen HVM firmware lives here. Kernel wants to boot here + * + * You can't both live there and HVM firmware is needed first, thus + * our plan is + * + * 0x200000 - kernel is loaded here by QEMU + * 0x200000+kernel_size - helper code is put here by QEMU + * + * code32_switch in kernel header is set to point at out helper + * code at 0x200000+kernel_size + * + * Our helper basically does memmove(0x100000,0x200000,kernel_size) + * and then jmps to 0x1000000. + * + * So we've overwritten the HVM firmware (which was no longer + * needed) and the non-relocatable kernel can happily boot + * at its usual address. + * + * Simple, eh ? + * + * Well the assembler needed to do this is fairly short: + * + * # Load segments + * cld + * cli + * movl $0x18,%eax + * mov %ax,%ds + * mov %ax,%es + * mov %ax,%fs + * mov %ax,%gs + * mov %ax,%ss + * + * # Move the kernel into position + * xor %edx,%edx + *_doloop: + * movzbl 0x600000(%edx),%eax + * mov %al,0x100000(%edx) + * add $0x1,%edx + * cmp $0x500000,%edx + * jne _doloop + * + * # start kernel + * xorl %ebx,%ebx + * mov $0x100000,%ecx + * jmp *%ecx + * + */ +static void setup_relocator(target_phys_addr_t addr, target_phys_addr_t src, target_phys_addr_t dst, size_t len) +{ + /* Now this assembler corresponds to follow machine code, with our args from QEMU spliced in :-) */ + unsigned char buf[] = { + /* Load segments */ + 0xfc, /* cld */ + 0xfa, /* cli */ + 0xb8, 0x18, 0x00, 0x00, 0x00, /* mov $0x18,%eax */ + 0x8e, 0xd8, /* mov %eax,%ds */ + 0x8e, 0xc0, /* mov %eax,%es */ + 0x8e, 0xe0, /* mov %eax,%fs */ + 0x8e, 0xe8, /* mov %eax,%gs */ + 0x8e, 0xd0, /* mov %eax,%ss */ + 0x31, 0xd2, /* xor %edx,%edx */ + + /* Move the kernel into position */ + 0x0f, 0xb6, 0x82, (src&0xff), ((src>>8)&0xff), ((src>>16)&0xff), ((src>>24)&0xff), /* movzbl $src(%edx),%eax */ + 0x88, 0x82, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff), /* mov %al,$dst(%edx) */ + 0x83, 0xc2, 0x01, /* add $0x1,%edx */ + 0x81, 0xfa, (len&0xff), ((len>>8)&0xff), ((len>>16)&0xff), ((len>>24)&0xff), /* cmp $len,%edx */ + 0x75, 0xe8, /* jne 13 <_doloop> */ + + /* Start kernel */ + 0x31, 0xdb, /* xor %ebx,%ebx */ + 0xb9, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff), /* mov $dst,%ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + }; + cpu_physical_memory_rw(addr, buf, sizeof(buf), 1); + fprintf(stderr, "qemu: helper at 0x%x of size %d bytes, to move kernel of %d bytes from 0x%x to 0x%x\n", + (int)addr, (int)sizeof(buf), (int)len, (int)src, (int)dst); +} + + +static void xen_relocator_hook(target_phys_addr_t prot_addr, uint16_t protocol, + uint8_t header[], int kernel_size) +{ + + /* Urgh, Xen's HVM firmware lives at 0x100000, but that's also the + * address Linux wants to start life at prior to relocatable support + */ + fprintf(stderr, "checking need for relocation, header protocol: %x\n", + protocol); + + if (prot_addr != 0x10000) { /* old low kernels are OK */ + target_phys_addr_t reloc_prot_addr = 0x20000; + + if (protocol >= 0x205 && (header[0x234] & 1)) { + /* Relocatable automatically */ + stl_p(header+0x214, reloc_prot_addr); + fprintf(stderr, "qemu: kernel is relocatable\n"); + } else { + /* Setup a helper which moves kernel back to + * its expected addr after firmware has got out + * of the way. We put a helper at reloc_prot_addr+kernel_size. + * It moves kernel from reloc_prot_addr to prot_addr and + * then jumps to prot_addr. Yes this is sick. + */ + fprintf(stderr, "qemu: kernel is NOT relocatable\n"); + stl_p(header+0x214, reloc_prot_addr + kernel_size); + setup_relocator(reloc_prot_addr + kernel_size, reloc_prot_addr, prot_addr, kernel_size); + } + } + + fprintf(stderr, "qemu: loading kernel real mode (%#x bytes) at %#zx\n", + setup_size-1024, real_addr); + fprintf(stderr, "qemu: loading kernel protected mode (%#x bytes) at %#zx\n", + kernel_size, reloc_prot_addr); +} + +#ifdef CONFIG_DM + +void vmport_init(CPUX86State *env) { } +void apic_init(CPUX86State *env) { } + +#endif /* CONFIG_DM */ diff --cc hw/piix_pci.c index dec10b160,90cb3a639..7a0cfe95b --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@@ -59,12 -53,9 +59,12 @@@ static int pci_slot_get_pirq(PCIDevice int slot_addend; slot_addend = (pci_dev->devfn >> 3) - 1; return (irq_num + slot_addend) & 3; +#else /* !CONFIG_DM */ + return irq_num + ((pci_dev->devfn >> 3) << 2); +#endif /* !CONFIG_DM */ } - static uint32_t isa_page_descs[384 / 4]; + static target_phys_addr_t isa_page_descs[384 / 4]; static uint8_t smm_enabled; static int pci_irq_levels[4]; diff --cc hw/serial.c index d4defdf8f,ffd6ac9c8..2af904ded --- a/hw/serial.c +++ b/hw/serial.c @@@ -132,73 -99,11 +133,74 @@@ struct SerialState int last_break_enable; target_phys_addr_t base; int it_shift; + int baudbase; - QEMUTimer *tx_timer; - int tx_burst; + int tsr_retry; + + uint64_t last_xmit_ts; /* Time when the last byte was successfully sent out of the tsr */ + SerialFIFO recv_fifo; + SerialFIFO xmit_fifo; + + struct QEMUTimer *fifo_timeout_timer; + int timeout_ipending; /* timeout interrupt pending state */ + struct QEMUTimer *transmit_timer; + + + uint64_t char_transmit_time; /* time to transmit a char in ticks*/ + int poll_msl; + + struct QEMUTimer *modem_status_poll; }; +/* Rate limit serial requests so that e.g. grub on a serial console + doesn't kill dom0. Simple token bucket. If we get some actual + data from the user, instantly refil the bucket. */ + +/* How long it takes to generate a token, in microseconds. */ +#define TOKEN_PERIOD 1000 +/* Maximum and initial size of token bucket */ +#define TOKENS_MAX 100000 + +static int tokens_avail; + +static void fifo_clear(SerialState *s, int fifo) { + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo; + memset(f->data, 0, UART_FIFO_LENGTH); + f->count = 0; + f->head = 0; + f->tail = 0; +} + +static int fifo_put(SerialState *s, int fifo, uint8_t chr) { + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo; + + f->data[f->head++] = chr; + + if (f->head == UART_FIFO_LENGTH) + f->head = 0; + f->count++; + + tokens_avail = TOKENS_MAX; + + return 1; +} + +uint8_t fifo_get(SerialState *s, int fifo) { + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo; + uint8_t c; + + if( f->count == 0 ) + return 0; + + c = f->data[f->tail++]; + if (f->tail == UART_FIFO_LENGTH) + f->tail = 0; + f->count--; + + tokens_avail = TOKENS_MAX; + + return c; +} + static void serial_receive_byte(SerialState *s, int ch); static void serial_update_irq(SerialState *s) @@@ -257,11 -161,10 +259,12 @@@ static void serial_update_parameters(Se stop_bits = 2; else stop_bits = 1; + data_bits = (s->lcr & 0x03) + 5; + if (s->divider == 0) + return; + frame_size += data_bits + stop_bits; - - speed = 115200 / s->divider; + speed = s->baudbase / s->divider; ssp.speed = speed; ssp.parity = parity; ssp.data_bits = data_bits; @@@ -782,12 -423,12 +786,17 @@@ SerialState *serial_init(int base, qemu if (!s) return NULL; s->irq = irq; + s->baudbase = baudbase; + + s->tx_timer = qemu_new_timer(vm_clock, serial_tx_done, s); + if (!s->tx_timer) + return NULL; + s->modem_status_poll = qemu_new_timer(vm_clock, ( QEMUTimerCB *) serial_update_msl, s); + + s->fifo_timeout_timer = qemu_new_timer(vm_clock, ( QEMUTimerCB *) fifo_timeout_int, s); + s->transmit_timer = qemu_new_timer(vm_clock, ( QEMUTimerCB *) serial_xmit, s); + qemu_register_reset(serial_reset, s); serial_reset(s); diff --cc hw/usb-hid.c index be3f5bd03,068cbbfe9..76283ef41 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@@ -538,34 -529,13 +536,35 @@@ static int usb_pointer_poll(USBHIDStat if (s->buttons_state & MOUSE_EVENT_MBUTTON) b |= 0x04; - buf[0] = b; - buf[1] = s->x & 0xff; - buf[2] = s->x >> 8; - buf[3] = s->y & 0xff; - buf[4] = s->y >> 8; - buf[5] = dz; - l = 6; + switch (s->kind) { + case USB_MOUSE: - buf[0] = b; - buf[1] = dx; - buf[2] = dy; - l = 3; - if (len >= 4) { - buf[3] = dz; - l = 4; - } ++ l = 0; ++ if (len > l) ++ buf[l ++] = b; ++ if (len > l) ++ buf[l ++] = xdx; ++ if (len > l) ++ buf[l ++] = ydy; ++ if (len > l) ++ buf[l ++] = dz; + break; + + case USB_TABLET: + /* Appears we have to invert the wheel direction */ + dz = 0 - dz; + + buf[0] = b; + buf[1] = s->x & 0xff; + buf[2] = s->x >> 8; + buf[3] = s->y & 0xff; + buf[4] = s->y >> 8; + buf[5] = dz; + l = 6; + break; + + default: + abort(); + } return l; } diff --cc i386-dm/machine.c index 000000000,000000000..29a0f915b new file mode 100644 --- /dev/null +++ b/i386-dm/machine.c @@@ -1,0 -1,0 +1,8 @@@ ++void cpu_save(QEMUFile *f, void *opaque) { } ++int cpu_load(QEMUFile *f, void *opaque, int version_id) { return 0; } ++ ++static void register_machines(void) ++{ ++ qemu_register_machine(&xenfv_machine); ++ qemu_register_machine(&xenpv_machine); ++} diff --cc loader.c index 5462d2405,dcb5a6bfa..29a01d704 --- a/loader.c +++ b/loader.c @@@ -80,7 -80,26 +80,26 @@@ int fread_targphys_ok(target_phys_addr_ { return fread_targphys(dst_addr, nbytes, f) == nbytes; } - + + /* read()-like version */ + int read_targphys(int fd, target_phys_addr_t dst_addr, size_t nbytes) + { + uint8_t buf[4096]; + target_phys_addr_t dst_begin = dst_addr; + size_t want, did; + + while (nbytes) { + want = nbytes > sizeof(buf) ? sizeof(buf) : nbytes; + did = read(fd, buf, want); + if (did != want) break; + + cpu_physical_memory_write_rom(dst_addr, buf, did); + dst_addr += did; + nbytes -= did; + } + return dst_addr - dst_begin; + } + /* return the size or -1 if error */ int load_image_targphys(const char *filename, target_phys_addr_t addr, int max_sz) diff --cc sdl.c index 2911c9be5,bac60ea46..45596fa65 --- a/sdl.c +++ b/sdl.c @@@ -758,13 -634,13 +759,12 @@@ void sdl_display_init(DisplayState *ds ds->dpy_update = sdl_update; ds->dpy_resize = sdl_resize; ds->dpy_refresh = sdl_refresh; - ds->dpy_fill = sdl_fill; - ds->mouse_set = sdl_mouse_warp; - ds->cursor_define = sdl_mouse_define; + ds->dpy_colourdepth = sdl_colourdepth; + ds->dpy_setdata = sdl_setdata; - sdl_resize(ds, 640, 400); + sdl_resize(ds, 640, 400, 640 * 4); sdl_update_caption(); SDL_EnableKeyRepeat(250, 50); - SDL_EnableUNICODE(1); gui_grab = 0; sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0); diff --cc sysemu.h index ec91daf74,f666f73fa..55b3ad64f --- a/sysemu.h +++ b/sysemu.h @@@ -163,7 -160,9 +160,7 @@@ int load_uboot(const char *filename, ta int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f); int fread_targphys_ok(target_phys_addr_t dst_addr, size_t nbytes, FILE *f); - + int read_targphys(int fd, target_phys_addr_t dst_addr, size_t nbytes); -void pstrcpy_targphys(target_phys_addr_t dest, int buf_size, - const char *source); #endif #ifdef HAS_AUDIO diff --cc vl.c index 925883532,60e736134..9f7fb9803 --- a/vl.c +++ b/vl.c @@@ -2261,7 -2249,64 +2260,64 @@@ static CharDriverState *qemu_chr_open_s return chr; } + #ifdef __sun__ + /* Once Solaris has openpty(), this is going to be removed. */ + int openpty(int *amaster, int *aslave, char *name, + struct termios *termp, struct winsize *winp) + { + const char *slave; + int mfd = -1, sfd = -1; + + *amaster = *aslave = -1; + + mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY); + if (mfd < 0) + goto err; + + if (grantpt(mfd) == -1 || unlockpt(mfd) == -1) + goto err; + + if ((slave = ptsname(mfd)) == NULL) + goto err; + + if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1) + goto err; + + if (ioctl(sfd, I_PUSH, "ptem") == -1 || + (termp != NULL && tcgetattr(sfd, termp) < 0)) + goto err; + + if (amaster) + *amaster = mfd; + if (aslave) + *aslave = sfd; + if (winp) + ioctl(sfd, TIOCSWINSZ, winp); + + return 0; + + err: + if (sfd != -1) + close(sfd); + close(mfd); + return -1; + } + + void cfmakeraw (struct termios *termios_p) + { + termios_p->c_iflag &= + ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + termios_p->c_oflag &= ~OPOST; + termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + termios_p->c_cflag &= ~(CSIZE|PARENB); + termios_p->c_cflag |= CS8; + + termios_p->c_cc[VMIN] = 0; + termios_p->c_cc[VTIME] = 0; + } + #endif + -#if defined(__linux__) || defined(__sun__) +#if defined(__linux__) || defined(__sun__) || defined(__NetBSD__) || defined(__OpenBSD__) static CharDriverState *qemu_chr_open_pty(void) { struct termios tty; @@@ -8011,75 -7511,7 +7552,7 @@@ static void read_passwords(void #ifdef HAS_AUDIO struct soundhw soundhw[] = { #ifdef HAS_AUDIO_CHOICE - #if defined(TARGET_I386) && !defined(CONFIG_DM) -#if defined(TARGET_I386) || defined(TARGET_MIPS) ++#if (defined(TARGET_I386) || defined(TARGET_MIPS)) && !defined(CONFIG_DM) { "pcspk", "PC speaker", @@@ -8239,12 -7671,9 +7712,12 @@@ int main(int argc, char **argv const char *loadvm = NULL; QEMUMachine *machine; const char *cpu_model; - char usb_devices[MAX_USB_CMDLINE][128]; + const char *usb_devices[MAX_USB_CMDLINE]; int usb_devices_index; int fds[2]; +#ifndef CONFIG_STUBDOM + struct rlimit rl; +#endif const char *pid_file = NULL; VLANState *vlan; diff --cc vnc.c index 895ea4b2c,57419f1fb..cec1c97a4 --- a/vnc.c +++ b/vnc.c @@@ -2614,14 -2094,12 +2624,14 @@@ int vnc_display_open(DisplayState *ds, { struct sockaddr *addr; struct sockaddr_in iaddr; -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS struct sockaddr_un uaddr; + const char *p; #endif +#ifndef CONFIG_STUBDOM int reuse_addr, ret; +#endif socklen_t addrlen; - const char *p; VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; const char *options; int password = 0;