From 6aef553b661b7504ff927ee5e120a69b44ba92aa Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 15 Jan 2008 14:17:22 +0000 Subject: [PATCH 1/5] blktap: factor out linux specific code Signed-off-by: Christoph Egger --- tools/blktap/drivers/Makefile | 23 +++++++++-------- tools/blktap/drivers/blk.h | 3 +++ tools/blktap/drivers/blk_linux.c | 42 +++++++++++++++++++++++++++++++ tools/blktap/drivers/block-aio.c | 25 ++++++------------ tools/blktap/drivers/block-qcow.c | 16 +++++++----- tools/blktap/drivers/block-ram.c | 30 ++++++++-------------- tools/blktap/drivers/block-sync.c | 25 ++++++------------ tools/blktap/drivers/block-vmdk.c | 6 ++++- tools/blktap/drivers/img2qcow.c | 27 +++++++------------- tools/blktap/drivers/qcow2raw.c | 22 ++++++++++------ tools/blktap/drivers/tapdisk.h | 4 +-- 11 files changed, 124 insertions(+), 99 deletions(-) create mode 100644 tools/blktap/drivers/blk.h create mode 100644 tools/blktap/drivers/blk_linux.c diff --git a/tools/blktap/drivers/Makefile b/tools/blktap/drivers/Makefile index fca48b6ced..b3c8fbaee9 100644 --- a/tools/blktap/drivers/Makefile +++ b/tools/blktap/drivers/Makefile @@ -28,28 +28,29 @@ LIBS += -L$(XEN_XENSTORE) -lxenstore AIOLIBS := $(LIBAIO_DIR)/libaio.a -BLK-OBJS := block-aio.o -BLK-OBJS += block-sync.o -BLK-OBJS += block-vmdk.o -BLK-OBJS += block-ram.o -BLK-OBJS += block-qcow.o -BLK-OBJS += aes.o -BLK-OBJS += tapaio.o +BLK-OBJS-y := block-aio.o +BLK-OBJS-y += block-sync.o +BLK-OBJS-y += block-vmdk.o +BLK-OBJS-y += block-ram.o +BLK-OBJS-y += block-qcow.o +BLK-OBJS-y += aes.o +BLK-OBJS-y += tapaio.o +BLK-OBJS-$(CONFIG_Linux) += blk_linux.c all: $(IBIN) qcow-util blktapctrl: blktapctrl.c $(CC) $(CFLAGS) -o blktapctrl $(LIBS) blktapctrl.c -tapdisk: $(BLK-OBJS) tapdisk.c - $(CC) $(CFLAGS) -o tapdisk $(BLK-OBJS) tapdisk.c \ +tapdisk: $(BLK-OBJS-y) tapdisk.c + $(CC) $(CFLAGS) -o tapdisk $(BLK-OBJS-y) tapdisk.c \ $(AIOLIBS) $(LIBS) .PHONY: qcow-util qcow-util: img2qcow qcow2raw qcow-create -img2qcow qcow2raw qcow-create: %: $(BLK-OBJS) - $(CC) $(CFLAGS) -o $* $(BLK-OBJS) $*.c $(AIOLIBS) $(LIBS) +img2qcow qcow2raw qcow-create: %: $(BLK-OBJS-y) + $(CC) $(CFLAGS) -o $* $(BLK-OBJS-y) $*.c $(AIOLIBS) $(LIBS) install: all $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(VHD_UTIL) $(DESTDIR)$(INST_DIR) diff --git a/tools/blktap/drivers/blk.h b/tools/blktap/drivers/blk.h new file mode 100644 index 0000000000..1cdc98098c --- /dev/null +++ b/tools/blktap/drivers/blk.h @@ -0,0 +1,3 @@ + +int blk_getimagesize(int fd, uint64_t *size); +int blk_getsectorsize(int fd, uint64_t *sector_size); diff --git a/tools/blktap/drivers/blk_linux.c b/tools/blktap/drivers/blk_linux.c new file mode 100644 index 0000000000..f1b14bd6e8 --- /dev/null +++ b/tools/blktap/drivers/blk_linux.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include "tapdisk.h" +#include "blk.h" + +int blk_getimagesize(int fd, uint64_t *size) +{ + int rc; + + *size = 0; + rc = ioctl(fd, BLKGETSIZE, size); + if (rc) { + DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image"); + return -EINVAL; + } + + return 0; +} + +int blk_getsectorsize(int fd, uint64_t *sector_size) +{ +#if defined(BLKSSZGET) + int rc; + + *sector_size = DEFAULT_SECTOR_SIZE; + rc = ioctl(fd, BLKSSZGET, sector_size); + if (rc) { + DPRINTF("ERR: BLKSSZGET failed. Falling back to use default sector size"); + *sector_size = DEFAULT_SECTOR_SIZE; + } + + if (*sector_size != DEFAULT_SECTOR_SIZE) + DPRINTF("Note: sector size is %"PRIu64" (not %u)\n", + *sector_size, DEFAULT_SECTOR_SIZE); +#else + *sector_size = DEFAULT_SECTOR_SIZE; +#endif + + return 0; +} + diff --git a/tools/blktap/drivers/block-aio.c b/tools/blktap/drivers/block-aio.c index 5c1ac373a7..d600899b61 100644 --- a/tools/blktap/drivers/block-aio.c +++ b/tools/blktap/drivers/block-aio.c @@ -41,12 +41,17 @@ #include #include #include -#include #include "tapdisk.h" #include "tapaio.h" +#include "blk.h" #define MAX_AIO_REQS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ) +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + struct pending_aio { td_callback_t cb; int id; @@ -87,11 +92,8 @@ static int get_image_info(struct td_state *s, int fd) if (S_ISBLK(stat.st_mode)) { /*Accessing block device directly*/ - s->size = 0; - if (ioctl(fd,BLKGETSIZE,&s->size)!=0) { - DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image"); + if (blk_getimagesize(fd, &s->size) != 0) return -EINVAL; - } DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " "sector_shift [%llu]\n", @@ -99,19 +101,8 @@ static int get_image_info(struct td_state *s, int fd) (long long unsigned)s->size); /*Get the sector size*/ -#if defined(BLKSSZGET) - { - int arg; + if (blk_getsectorsize(fd, &s->sector_size) != 0) s->sector_size = DEFAULT_SECTOR_SIZE; - ioctl(fd, BLKSSZGET, &s->sector_size); - - if (s->sector_size != DEFAULT_SECTOR_SIZE) - DPRINTF("Note: sector size is %ld (not %d)\n", - s->sector_size, DEFAULT_SECTOR_SIZE); - } -#else - s->sector_size = DEFAULT_SECTOR_SIZE; -#endif } else { /*Local file? try fstat instead*/ diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c index fe70326c1f..0bc8374fab 100644 --- a/tools/blktap/drivers/block-qcow.c +++ b/tools/blktap/drivers/block-qcow.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -39,6 +38,12 @@ #include "aes.h" #include "tapdisk.h" #include "tapaio.h" +#include "blk.h" + +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif #if 1 #define ASSERT(_p) \ @@ -284,8 +289,7 @@ static int get_filesize(char *filename, uint64_t *size, struct stat *st) fd = open(filename, O_RDONLY); if (fd < 0) return -1; - if (ioctl(fd,BLKGETSIZE,size)!=0) { - printf("Unable to get Block device size\n"); + if (blk_getimagesize(fd, size) != 0) { close(fd); return -1; } @@ -990,8 +994,8 @@ int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) if (!final_cluster) s->fd_end = s->l1_table_offset + l1_table_size; else { - s->fd_end = lseek64(fd, 0, SEEK_END); - if (s->fd_end == (off64_t)-1) + s->fd_end = lseek(fd, 0, SEEK_END); + if (s->fd_end == (off_t)-1) goto fail; } @@ -1230,7 +1234,7 @@ int qcow_create(const char *filename, uint64_t total_size, DPRINTF("Qcow_create: size %llu\n",(long long unsigned)total_size); fd = open(filename, - O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644); if (fd < 0) return -1; diff --git a/tools/blktap/drivers/block-ram.c b/tools/blktap/drivers/block-ram.c index 3b4ef7ceb5..f39d6422b2 100644 --- a/tools/blktap/drivers/block-ram.c +++ b/tools/blktap/drivers/block-ram.c @@ -33,16 +33,22 @@ #include #include #include +#include #include #include #include #include -#include #include #include "tapdisk.h" +#include "blk.h" #define MAX_DISK_SIZE 1024000 /*500MB disk limit*/ +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + char *img; long int disksector_size; long int disksize; @@ -71,11 +77,8 @@ static int get_image_info(struct td_state *s, int fd) if (S_ISBLK(stat.st_mode)) { /*Accessing block device directly*/ - s->size = 0; - if (ioctl(fd,BLKGETSIZE,&s->size)!=0) { - DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image"); + if (blk_getimagesize(fd, &s->size) != 0) return -EINVAL; - } DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " "sector_shift [%llu]\n", @@ -83,19 +86,8 @@ static int get_image_info(struct td_state *s, int fd) (long long unsigned)s->size); /*Get the sector size*/ -#if defined(BLKSSZGET) - { - int arg; + if (blk_getsectorsize(fd, &s->sector_size) != 0) s->sector_size = DEFAULT_SECTOR_SIZE; - ioctl(fd, BLKSSZGET, &s->sector_size); - - if (s->sector_size != DEFAULT_SECTOR_SIZE) - DPRINTF("Note: sector size is %ld (not %d)\n", - s->sector_size, DEFAULT_SECTOR_SIZE); - } -#else - s->sector_size = DEFAULT_SECTOR_SIZE; -#endif } else { /*Local file? try fstat instead*/ @@ -117,7 +109,7 @@ static int get_image_info(struct td_state *s, int fd) disksector_size = s->sector_size; disksize = s->size; diskinfo = s->info; - DPRINTF("Image sector_size: \n\t[%lu]\n", + DPRINTF("Image sector_size: \n\t[%"PRIu64"]\n", s->sector_size); return 0; @@ -159,7 +151,7 @@ int tdram_open (struct disk_driver *dd, const char *name, td_flag_t flags) "sector_shift [%llu]\n", (long long unsigned)(s->size << SECTOR_SHIFT), (long long unsigned)s->size); - DPRINTF("Image sector_size: \n\t[%lu]\n", + DPRINTF("Image sector_size: \n\t[%"PRIu64"]\n", s->sector_size); prv->fd = -1; diff --git a/tools/blktap/drivers/block-sync.c b/tools/blktap/drivers/block-sync.c index 74f77d6f61..8e6697c329 100644 --- a/tools/blktap/drivers/block-sync.c +++ b/tools/blktap/drivers/block-sync.c @@ -37,8 +37,13 @@ #include #include #include -#include #include "tapdisk.h" +#include "blk.h" + +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif struct tdsync_state { int fd; @@ -62,11 +67,8 @@ static int get_image_info(struct td_state *s, int fd) if (S_ISBLK(stat.st_mode)) { /*Accessing block device directly*/ - s->size = 0; - if (ioctl(fd,BLKGETSIZE,&s->size)!=0) { - DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image"); + if (blk_getimagesize(fd, &s->size) != 0) return -EINVAL; - } DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " "sector_shift [%llu]\n", @@ -74,19 +76,8 @@ static int get_image_info(struct td_state *s, int fd) (long long unsigned)s->size); /*Get the sector size*/ -#if defined(BLKSSZGET) - { - int arg; + if (blk_getsectorsize(fd, &s->sector_size) != 0) s->sector_size = DEFAULT_SECTOR_SIZE; - ioctl(fd, BLKSSZGET, &s->sector_size); - - if (s->sector_size != DEFAULT_SECTOR_SIZE) - DPRINTF("Note: sector size is %ld (not %d)\n", - s->sector_size, DEFAULT_SECTOR_SIZE); - } -#else - s->sector_size = DEFAULT_SECTOR_SIZE; -#endif } else { /*Local file? try fstat instead*/ diff --git a/tools/blktap/drivers/block-vmdk.c b/tools/blktap/drivers/block-vmdk.c index f6b720e1e0..4d16965213 100644 --- a/tools/blktap/drivers/block-vmdk.c +++ b/tools/blktap/drivers/block-vmdk.c @@ -42,11 +42,15 @@ #include #include #include -#include #include #include "tapdisk.h" #include "bswap.h" +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + #define safer_free(_x) \ do { \ if (NULL != _x) { \ diff --git a/tools/blktap/drivers/img2qcow.c b/tools/blktap/drivers/img2qcow.c index 926cf2742e..61a30087ec 100644 --- a/tools/blktap/drivers/img2qcow.c +++ b/tools/blktap/drivers/img2qcow.c @@ -37,9 +37,9 @@ #include #include #include -#include #include #include "tapdisk.h" +#include "blk.h" #if 1 #define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a ) @@ -47,6 +47,12 @@ #define DFPRINTF(_f, _a...) ((void)0) #endif +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + + #define TAPDISK 1 #define BLOCK_PROCESSSZ 4096 @@ -109,12 +115,8 @@ static int get_image_info(struct td_state *s, int fd) if (S_ISBLK(stat.st_mode)) { /*Accessing block device directly*/ - s->size = 0; - if (ioctl(fd,BLKGETSIZE,&s->size)!=0) { - DFPRINTF("ERR: BLKGETSIZE failed, " - "couldn't stat image"); + if (blk_getimagesize(fd, &s->size) != 0) return -EINVAL; - } DFPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " "sector_shift [%llu]\n", @@ -122,19 +124,8 @@ static int get_image_info(struct td_state *s, int fd) (long long unsigned)s->size); /*Get the sector size*/ -#if defined(BLKSSZGET) - { - int arg; + if (blk_getsectorsize(fd, &s->sector_size) != 0) s->sector_size = DEFAULT_SECTOR_SIZE; - ioctl(fd, BLKSSZGET, &s->sector_size); - - if (s->sector_size != DEFAULT_SECTOR_SIZE) - DFPRINTF("Note: sector size is %ld (not %d)\n", - s->sector_size, DEFAULT_SECTOR_SIZE); - } -#else - s->sector_size = DEFAULT_SECTOR_SIZE; -#endif } else { /*Local file? try fstat instead*/ diff --git a/tools/blktap/drivers/qcow2raw.c b/tools/blktap/drivers/qcow2raw.c index cbfe55b8e3..d553dbcdbf 100644 --- a/tools/blktap/drivers/qcow2raw.c +++ b/tools/blktap/drivers/qcow2raw.c @@ -33,13 +33,14 @@ #include #include #include +#include #include #include #include #include -#include #include #include "tapdisk.h" +#include "blk.h" #if 1 #define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a ) @@ -47,6 +48,12 @@ #define DFPRINTF(_f, _a...) ((void)0) #endif + +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + #define TAPDISK 1 #define BLOCK_PROCESSSZ 4096 @@ -142,7 +149,7 @@ static int send_read_responses(struct disk_driver *dd, int res, uint64_t sec, int main(int argc, char *argv[]) { int ret = -1, fd, len,input; - long int size; + uint64_t size; fd_set readfds; struct timeval timeout; uint64_t i; @@ -227,16 +234,15 @@ int main(int argc, char *argv[]) } if (S_ISBLK(finfo.st_mode)) { - if(ioctl(fd,BLKGETSIZE,&size)!=0) { - DFPRINTF("ERROR: BLKGETSIZE failed, " - "couldn't stat image [%s]\n", - argv[1]); + if (blk_getimagesize(fd, &size) != 0) { close(fd); - exit(-1); + return -1; } + if (size < ddqcow.td_state->size<<9) { DFPRINTF("ERROR: Not enough space on device " - "%s (%lu bytes available, %llu bytes required\n", + "%s (%"PRIu64" bytes available, " + "%llu bytes required\n", argv[1], size, (long long unsigned)ddqcow.td_state->size<<9); close(fd); diff --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h index 5c68a5e9c8..025df95407 100644 --- a/tools/blktap/drivers/tapdisk.h +++ b/tools/blktap/drivers/tapdisk.h @@ -108,8 +108,8 @@ struct td_state { void *image; void *ring_info; void *fd_entry; - unsigned long sector_size; - unsigned long long size; + uint64_t sector_size; + uint64_t size; unsigned int info; }; From 136beff1783158d3a05f94aef6ccc4339263a2a8 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 15 Jan 2008 14:22:50 +0000 Subject: [PATCH 2/5] hvm, x86: Add QEMU BIOS menu for choosing boot device. The attached patch implements a mini BIOS menu for choosing a non-default boot device. When a guest starts it'll display 'Press F10 to select boot device' And wait 3 seconds, before continuing with the normal boot device. If they press the F10 key, a menu is shown allowing a choice between floppy, harddisk, cdrom and network (PXE). I can't take credit for this originally - Jeremy Katz wrote it for KVM, I merely re-diffed the patch to work against Xen's QEMU/BIOS code tree. It has been tested in Fedora successfully against 3.1.x and 3.2.x Signed-off-by: Daniel P. Berrange CC: Jeremy Katz If more than one boot device has been selected, the currently selected number displayed in the menu is wrong. Signed-off-by: Stefano Stabellini --- tools/firmware/rombios/rombios.c | 227 ++++++++++++++++++++++++++++++- 1 file changed, 226 insertions(+), 1 deletion(-) diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c index 287840727d..a37879bd95 100644 --- a/tools/firmware/rombios/rombios.c +++ b/tools/firmware/rombios/rombios.c @@ -2031,6 +2031,229 @@ print_cdromboot_failure( code ) return; } +#define WAIT_HZ 18 +/** + * Check for keystroke. + * @returns True if keystroke available, False if not. + */ +Bit8u check_for_keystroke() +{ +ASM_START + mov ax, #0x100 + int #0x16 + jz no_key + mov al, #1 + jmp done +no_key: + xor al, al +done: +ASM_END +} + +/** + * Get keystroke. + * @returns BIOS scan code. + */ +Bit8u get_keystroke() +{ +ASM_START + mov ax, #0x0 + int #0x16 + xchg ah, al +ASM_END +} + +/** + * Waits (sleeps) for the given number of ticks. + * Checks for keystroke. + * + * @returns BIOS scan code if available, 0 if not. + * @param ticks Number of ticks to sleep. + * @param stop_on_key Whether to stop immediately upon keypress. + */ +Bit8u wait(ticks, stop_on_key) + Bit16u ticks; + Bit8u stop_on_key; +{ + long ticks_to_wait, delta; + Bit32u prev_ticks, t; + Bit8u scan_code = 0; + + /* + * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. + * We also have to be careful about interrupt storms. + */ + ticks_to_wait = ticks; + prev_ticks = read_dword(0x0, 0x46c); + do + { + t = read_dword(0x0, 0x46c); + if (t > prev_ticks) + { + delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ + ticks_to_wait -= delta; + } + else if (t < prev_ticks) + ticks_to_wait -= t; /* wrapped */ + prev_ticks = t; + + if (check_for_keystroke()) + { + scan_code = get_keystroke(); + bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code); + if (stop_on_key) + return scan_code; + } + } while (ticks_to_wait > 0); + return scan_code; +} + +static void clearscreen() { + /* Hide cursor, clear screen and move cursor to starting position */ +ASM_START + push bx + push cx + push dx + + mov ax, #0x100 + mov cx, #0x1000 + int #0x10 + + mov ax, #0x700 + mov bh, #7 + xor cx, cx + mov dx, #0x184f + int #0x10 + + mov ax, #0x200 + xor bx, bx + xor dx, dx + int #0x10 + + pop dx + pop cx + pop bx +ASM_END +} + +int bootmenu(selected) + int selected; +{ + Bit8u scode; + int max; + + /* get the number of boot devices */ + max = read_word(IPL_SEG, IPL_COUNT_OFFSET); + + for(;;) { + if (selected > max || selected < 1) selected = 1; + clearscreen(); + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n"); + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " Select boot device\n\n"); + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 1. Floppy\n"); + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 2. Hard drive\n"); + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 3. CD-ROM\n"); + if (max == 4) + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 4. Network\n"); + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n Currently selected: %d\n", selected); + + do { + scode = wait(WAIT_HZ, 1); + } while (scode == 0); + switch(scode) { + case 0x02: + case 0x03: + case 0x04: + selected = scode - 1; + break; + case 0x05: + if (max == 4) + selected = scode -1 ; + else + scode = 0; + break; + case 0x48: + selected -= 1; + if (selected < 1) + selected = 1; + scode = 0; + break; + case 0x50: + selected += 1; + if (selected > max) + selected = max; + scode = 0; + break; + case 0x1c: + break; + default: + scode = 0; + break; + } + if (scode != 0) + break; + } + + switch (selected) { + case 1: + return 0x3D; + case 2: + return 0x3E; + case 3: + return 0x3F; + case 4: + return 0x58; + default: + return 0; + } +} + +void interactive_bootkey() +{ + Bit16u i; + Bit8u scan = 0; + + bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\nPress F10 to select boot device.\n"); + for (i = 3; i > 0; i--) + { + scan = wait(WAIT_HZ, 0); + switch (scan) { + case 0x3D: + case 0x3E: + case 0x3F: + case 0x58: + break; + case 0x44: + scan = bootmenu(inb_cmos(0x3d) & 0x0f); + break; + default: + scan = 0; + break; + } + if (scan != 0) + break; + } + + /* set the default based on the keypress or menu */ + switch(scan) { + case 0x3D: + outb_cmos(0x3d, 0x01); + break; + case 0x3E: + outb_cmos(0x3d, 0x02); + break; + case 0x3F: + outb_cmos(0x3d, 0x03); + break; + case 0x58: + outb_cmos(0x3d, 0x04); + break; + default: + break; + } +} + + void nmi_handler_msg() { @@ -9825,7 +10048,9 @@ post_default_ints: call _cdemu_init ;; #endif // BX_ELTORITO_BOOT - + + call _interactive_bootkey + #if BX_TCGBIOS call _tcpa_calling_int19h /* specs: 8.2.3 step 1 */ call _tcpa_add_event_separators /* specs: 8.2.3 step 2 */ From 49c14d4312ee3fe7d0bc30a5a68fb8ad610722c1 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 15 Jan 2008 14:24:05 +0000 Subject: [PATCH 3/5] xend: Remove hardcoded (and apparently unused) xend version. Signed-off-by: Jim Fehlig --- tools/python/xen/xend/XendNode.py | 8 +------- tools/python/xen/xend/server/SrvDaemon.py | 6 ------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 841403f71d..b0e3963232 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -377,13 +377,7 @@ class XendNode: def xen_version(self): info = self.xc.xeninfo() - try: - from xen import VERSION - info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info, - 'Xend': VERSION} - except (ImportError, AttributeError): - info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info, - 'Xend': '3.0.3'} + info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info} # Add xend_config_format info.update(self.xendinfo_dict()) diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index a265aef906..225b901168 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -335,12 +335,6 @@ class Daemon: log.info("Xend changeset: %s.", xinfo['xen_changeset']) del xc - try: - from xen import VERSION - log.info("Xend version: %s", VERSION) - except ImportError: - log.info("Xend version: Unknown.") - relocate.listenRelocation() servers = SrvServer.create() servers.start(status) From 2bdb8485df02745a98ec4922e8a88d073af653b6 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 15 Jan 2008 14:27:15 +0000 Subject: [PATCH 4/5] Update version to 3.3-unstable. --- xen/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/Makefile b/xen/Makefile index 150177e700..60b578c051 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -1,8 +1,8 @@ # This is the correct place to edit the build version. # All other places this is stored (eg. compile.h) should be autogenerated. export XEN_VERSION = 3 -export XEN_SUBVERSION = 2 -export XEN_EXTRAVERSION ?= .0-rc6$(XEN_VENDORVERSION) +export XEN_SUBVERSION = 3 +export XEN_EXTRAVERSION ?= -unstable$(XEN_VENDORVERSION) export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) -include xen-version From 2a34bc2edd40f84a9ac47568c984341832ab6370 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 15 Jan 2008 14:32:15 +0000 Subject: [PATCH 5/5] x86: Allow batched mmu updates which preserve accessed/dirty pte bits. Signed-off-by: Bruce Rogers Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 110 +++++++++++++++++++++++++-------------- xen/include/public/xen.h | 9 +++- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 5303102ecd..baea82118b 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1342,21 +1342,30 @@ static inline int update_intpte(intpte_t *p, intpte_t old, intpte_t new, unsigned long mfn, - struct vcpu *v) + struct vcpu *v, + int preserve_ad) { int rv = 1; #ifndef PTE_UPDATE_WITH_CMPXCHG - rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); -#else + if ( !preserve_ad ) + { + rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); + } + else +#endif { intpte_t t = old; for ( ; ; ) { - rv = paging_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); + intpte_t _new = new; + if ( preserve_ad ) + _new |= old & (_PAGE_ACCESSED | _PAGE_DIRTY); + + rv = paging_cmpxchg_guest_entry(v, p, &t, _new, _mfn(mfn)); if ( unlikely(rv == 0) ) { MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte - ": saw %" PRIpte, old, new, t); + ": saw %" PRIpte, old, _new, t); break; } @@ -1369,20 +1378,19 @@ static inline int update_intpte(intpte_t *p, old = t; } } -#endif return rv; } /* Macro that wraps the appropriate type-changes around update_intpte(). * Arguments are: type, ptr, old, new, mfn, vcpu */ -#define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v) \ +#define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v,_ad) \ update_intpte(&_t ## e_get_intpte(*(_p)), \ _t ## e_get_intpte(_o), _t ## e_get_intpte(_n), \ - (_m), (_v)) + (_m), (_v), (_ad)) /* Update the L1 entry at pl1e to new value nl1e. */ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, - unsigned long gl1mfn) + unsigned long gl1mfn, int preserve_ad) { l1_pgentry_t ol1e; struct vcpu *curr = current; @@ -1393,7 +1401,7 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, return 0; if ( unlikely(paging_mode_refcounts(d)) ) - return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr); + return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, preserve_ad); if ( l1e_get_flags(nl1e) & _PAGE_PRESENT ) { @@ -1415,12 +1423,14 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, /* Fast path for identical mapping, r/w and presence. */ if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) ) - return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr); + return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, + preserve_ad); if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, + preserve_ad)) ) { put_page_from_l1e(nl1e, d); return 0; @@ -1428,7 +1438,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, } else { - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, curr, + preserve_ad)) ) return 0; } @@ -1441,7 +1452,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, static int mod_l2_entry(l2_pgentry_t *pl2e, l2_pgentry_t nl2e, unsigned long pfn, - unsigned long type) + unsigned long type, + int preserve_ad) { l2_pgentry_t ol2e; struct vcpu *curr = current; @@ -1469,18 +1481,20 @@ static int mod_l2_entry(l2_pgentry_t *pl2e, /* Fast path for identical mapping and presence. */ if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT)) - return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr); + return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, preserve_ad); if ( unlikely(!get_page_from_l2e(nl2e, pfn, d)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, + preserve_ad)) ) { put_page_from_l2e(nl2e, pfn); return 0; } } - else if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr)) ) + else if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, curr, + preserve_ad)) ) { return 0; } @@ -1494,7 +1508,8 @@ static int mod_l2_entry(l2_pgentry_t *pl2e, /* Update the L3 entry at pl3e to new value nl3e. pl3e is within frame pfn. */ static int mod_l3_entry(l3_pgentry_t *pl3e, l3_pgentry_t nl3e, - unsigned long pfn) + unsigned long pfn, + int preserve_ad) { l3_pgentry_t ol3e; struct vcpu *curr = current; @@ -1532,18 +1547,20 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, /* Fast path for identical mapping and presence. */ if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT)) - return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr); + return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, preserve_ad); if ( unlikely(!get_page_from_l3e(nl3e, pfn, d)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, + preserve_ad)) ) { put_page_from_l3e(nl3e, pfn); return 0; } } - else if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr)) ) + else if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, curr, + preserve_ad)) ) { return 0; } @@ -1564,7 +1581,8 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, /* Update the L4 entry at pl4e to new value nl4e. pl4e is within frame pfn. */ static int mod_l4_entry(l4_pgentry_t *pl4e, l4_pgentry_t nl4e, - unsigned long pfn) + unsigned long pfn, + int preserve_ad) { struct vcpu *curr = current; struct domain *d = curr->domain; @@ -1592,18 +1610,20 @@ static int mod_l4_entry(l4_pgentry_t *pl4e, /* Fast path for identical mapping and presence. */ if (!l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT)) - return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr); + return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, preserve_ad); if ( unlikely(!get_page_from_l4e(nl4e, pfn, d)) ) return 0; - if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, + preserve_ad)) ) { put_page_from_l4e(nl4e, pfn); return 0; } } - else if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr)) ) + else if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, curr, + preserve_ad)) ) { return 0; } @@ -1946,7 +1966,7 @@ int new_guest_cr3(unsigned long mfn) l4e_from_pfn( mfn, (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)), - pagetable_get_pfn(v->arch.guest_table)); + pagetable_get_pfn(v->arch.guest_table), 0); if ( unlikely(!okay) ) { MEM_LOG("Error while installing new compat baseptr %lx", mfn); @@ -2458,13 +2478,16 @@ int do_mmu_update( { /* * MMU_NORMAL_PT_UPDATE: Normal update to any level of page table. + * MMU_UPDATE_PT_PRESERVE_AD: As above but also preserve (OR) + * current A/D bits. */ case MMU_NORMAL_PT_UPDATE: - + case MMU_PT_UPDATE_PRESERVE_AD: rc = xsm_mmu_normal_update(d, req.val); if ( rc ) break; + req.ptr -= cmd; gmfn = req.ptr >> PAGE_SHIFT; mfn = gmfn_to_mfn(d, gmfn); @@ -2501,20 +2524,23 @@ int do_mmu_update( case PGT_l1_page_table: { l1_pgentry_t l1e = l1e_from_intpte(req.val); - okay = mod_l1_entry(va, l1e, mfn); + okay = mod_l1_entry(va, l1e, mfn, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; case PGT_l2_page_table: { l2_pgentry_t l2e = l2e_from_intpte(req.val); - okay = mod_l2_entry(va, l2e, mfn, type_info); + okay = mod_l2_entry(va, l2e, mfn, type_info, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; #if CONFIG_PAGING_LEVELS >= 3 case PGT_l3_page_table: { l3_pgentry_t l3e = l3e_from_intpte(req.val); - okay = mod_l3_entry(va, l3e, mfn); + okay = mod_l3_entry(va, l3e, mfn, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; #endif @@ -2522,7 +2548,8 @@ int do_mmu_update( case PGT_l4_page_table: { l4_pgentry_t l4e = l4e_from_intpte(req.val); - okay = mod_l4_entry(va, l4e, mfn); + okay = mod_l4_entry(va, l4e, mfn, + cmd == MMU_PT_UPDATE_PRESERVE_AD); } break; #endif @@ -2652,7 +2679,7 @@ static int create_grant_pte_mapping( } ol1e = *(l1_pgentry_t *)va; - if ( !UPDATE_ENTRY(l1, (l1_pgentry_t *)va, ol1e, nl1e, mfn, v) ) + if ( !UPDATE_ENTRY(l1, (l1_pgentry_t *)va, ol1e, nl1e, mfn, v, 0) ) { put_page_type(page); rc = GNTST_general_error; @@ -2720,9 +2747,11 @@ static int destroy_grant_pte_mapping( } /* Delete pagetable entry. */ - if ( unlikely(!UPDATE_ENTRY(l1, - (l1_pgentry_t *)va, ol1e, l1e_empty(), mfn, - d->vcpu[0] /* Change if we go to per-vcpu shadows. */)) ) + if ( unlikely(!UPDATE_ENTRY + (l1, + (l1_pgentry_t *)va, ol1e, l1e_empty(), mfn, + d->vcpu[0] /* Change if we go to per-vcpu shadows. */, + 0)) ) { MEM_LOG("Cannot delete PTE entry at %p", va); put_page_type(page); @@ -2758,7 +2787,7 @@ static int create_grant_va_mapping( return GNTST_general_error; } ol1e = *pl1e; - okay = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v); + okay = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0); guest_unmap_l1e(v, pl1e); pl1e = NULL; @@ -2796,7 +2825,7 @@ static int replace_grant_va_mapping( } /* Delete pagetable entry. */ - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) ) { MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); rc = GNTST_general_error; @@ -2860,7 +2889,8 @@ int replace_grant_host_mapping( } ol1e = *pl1e; - if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), gl1mfn, curr)) ) + if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, l1e_empty(), + gl1mfn, curr, 0)) ) { MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); guest_unmap_l1e(curr, pl1e); @@ -2948,7 +2978,7 @@ int do_update_va_mapping(unsigned long va, u64 val64, pl1e = guest_map_l1e(v, va, &gl1mfn); - if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn)) ) + if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn, 0)) ) rc = -EINVAL; if ( pl1e ) @@ -3517,7 +3547,7 @@ static int ptwr_emulated_update( else { ol1e = *pl1e; - if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) ) + if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v, 0) ) BUG(); } diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index fb4ae8d754..10f23c7704 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -168,9 +168,14 @@ * ptr[:2] -- Machine address within the frame whose mapping to modify. * The frame must belong to the FD, if one is specified. * val -- Value to write into the mapping entry. + * + * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD: + * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed + * with those in @val. */ -#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ -#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ +#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ +#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ +#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ /* * MMU EXTENDED OPERATIONS