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
/* set to 1 set disable mult support */
#define MAX_MULT_SECTORS 16
- #define IDE_DMA_BUF_SIZE (BLKIF_MAX_SEGMENTS_PER_REQUEST * TARGET_PAGE_SIZE)
+#ifdef CONFIG_STUBDOM
+#include <xen/io/blkif.h>
- #define IDE_DMA_BUF_SIZE 131072
++#define IDE_DMA_BUF_SECTORS \
++ ((BLKIF_MAX_SEGMENTS_PER_REQUEST * TARGET_PAGE_SIZE) / 512)
+#else
+ #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 */
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 */
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);
"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 */
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];
int last_break_enable;
target_phys_addr_t base;
int it_shift;
- QEMUTimer *tx_timer;
- int tx_burst;
+ int baudbase;
+ 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)
stop_bits = 2;
else
stop_bits = 1;
+
data_bits = (s->lcr & 0x03) + 5;
-
- speed = 115200 / s->divider;
+ if (s->divider == 0)
+ return;
+ frame_size += data_bits + stop_bits;
+ speed = s->baudbase / s->divider;
ssp.speed = speed;
ssp.parity = parity;
ssp.data_bits = data_bits;
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);
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;
}
--- /dev/null
--- /dev/null
++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);
++}
{
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)
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);
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
return chr;
}
-#if defined(__linux__) || defined(__sun__)
+ #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__) || defined(__NetBSD__) || defined(__OpenBSD__)
static CharDriverState *qemu_chr_open_pty(void)
{
struct termios tty;
#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",
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;
{
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;