From patchwork Mon May 23 08:44:47 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 808072 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4N8jgtk005712 for ; Mon, 23 May 2011 08:45:42 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751950Ab1EWIpj (ORCPT ); Mon, 23 May 2011 04:45:39 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:63394 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750755Ab1EWIpi (ORCPT ); Mon, 23 May 2011 04:45:38 -0400 Received: by bwz15 with SMTP id 15so4514519bwz.19 for ; Mon, 23 May 2011 01:45:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer; bh=UwbSeFrj0r7Jad9oC2K7LAJQ56XG6QQ4LT26Zlmw9rE=; b=eDQwv74HDtIq9eJQWXw3yx37EwyB/hVgPnxacLd5n167p6SXXBgVDuZ6zo0pWs4Fc8 FMxb6XIogG77MrUraff0ZGek58o3VaSIDKLI4j4vy8RvUNmzRUHP9xnOIrTEX7sLG3yM vx5WnUgCJWTuzPLTCi4uJ5dy9Us3BEiaA8YrU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=mpT10cOZYUuu3r+tlbDSFUzVwIhTgOE+jS4pEpUHaqtKr8LqCxhd/li93BWtCyB83T Wyri9igd6NbL6VYa3+D1wNaNE6zfJv/EQMkDoIpw01lc57PjGhtFEFH0eHCzZsYoPQsC VEHW1x09mCjYw+p43h7cjZaG6L1NQS0p0PFck= Received: by 10.204.23.71 with SMTP id q7mr1890141bkb.25.1306140337278; Mon, 23 May 2011 01:45:37 -0700 (PDT) Received: from localhost.localdomain (bzq-79-179-199-121.red.bezeqint.net [79.179.199.121]) by mx.google.com with ESMTPS id q18sm3742392bka.15.2011.05.23.01.45.35 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 23 May 2011 01:45:36 -0700 (PDT) From: Sasha Levin To: penberg@kernel.org Cc: john@jfloren.net, kvm@vger.kernel.org, mingo@elte.hu, asias.hejun@gmail.com, gorcunov@gmail.com, prasadjoshi124@gmail.com, Sasha Levin Subject: [PATCH 1/5] kvm tools: Add BIOS INT10 handler Date: Mon, 23 May 2011 11:44:47 +0300 Message-Id: <1306140291-17493-1-git-send-email-levinsasha928@gmail.com> X-Mailer: git-send-email 1.7.5.rc3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 23 May 2011 08:45:43 +0000 (UTC) INT10 handler is a basic implementation of BIOS video services. The handler implements a VESA interface which is initialized at the very beginning of loading the kernel. Signed-off-by: John Floren Signed-off-by: Sasha Levin --- tools/kvm/bios/bios-rom.S | 56 ++++++++-------- tools/kvm/bios/int10.c | 161 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 28 deletions(-) create mode 100644 tools/kvm/bios/int10.c diff --git a/tools/kvm/bios/bios-rom.S b/tools/kvm/bios/bios-rom.S index 8a53dcd..b636cb8 100644 --- a/tools/kvm/bios/bios-rom.S +++ b/tools/kvm/bios/bios-rom.S @@ -27,36 +27,36 @@ ENTRY_END(bios_intfake) * We ignore bx settings */ ENTRY(bios_int10) - test $0x0e, %ah - jne 1f + pushw %fs + pushl %es + pushl %edi + pushl %esi + pushl %ebp + pushl %esp + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + + movl %esp, %eax + /* this is way easier than doing it in assembly */ + /* just push all the regs and jump to a C handler */ + call int10handler + + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %esp + popl %ebp + popl %esi + popl %edi + popl %es + popw %fs -/* - * put char in AL at current cursor and - * increment cursor position - */ -putchar: - stack_swap - - push %fs - push %bx - - mov $VGA_RAM_SEG, %bx - mov %bx, %fs - mov %cs:(cursor), %bx - mov %al, %fs:(%bx) - inc %bx - test $VGA_PAGE_SIZE, %bx - jb putchar_new - xor %bx, %bx -putchar_new: - mov %bx, %fs:(cursor) - - pop %bx - pop %fs - - stack_restore -1: IRET + + /* * private IRQ data */ diff --git a/tools/kvm/bios/int10.c b/tools/kvm/bios/int10.c new file mode 100644 index 0000000..98205c3 --- /dev/null +++ b/tools/kvm/bios/int10.c @@ -0,0 +1,161 @@ +#include "kvm/segment.h" +#include "kvm/bios.h" +#include "kvm/util.h" +#include "kvm/vesa.h" +#include + +#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) + +struct int10args { + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; + u32 esp; + u32 ebp; + u32 esi; + u32 edi; + u32 es; +}; + +/* VESA General Information table */ +struct vesa_general_info { + u32 signature; /* 0 Magic number = "VESA" */ + u16 version; /* 4 */ + void *vendor_string; /* 6 */ + u32 capabilities; /* 10 */ + void *video_mode_ptr; /* 14 */ + u16 total_memory; /* 18 */ + + u8 reserved[236]; /* 20 */ +} __attribute__ ((packed)); + + +struct vminfo { + u16 mode_attr; /* 0 */ + u8 win_attr[2]; /* 2 */ + u16 win_grain; /* 4 */ + u16 win_size; /* 6 */ + u16 win_seg[2]; /* 8 */ + u32 win_scheme; /* 12 */ + u16 logical_scan; /* 16 */ + + u16 h_res; /* 18 */ + u16 v_res; /* 20 */ + u8 char_width; /* 22 */ + u8 char_height; /* 23 */ + u8 memory_planes; /* 24 */ + u8 bpp; /* 25 */ + u8 banks; /* 26 */ + u8 memory_layout; /* 27 */ + u8 bank_size; /* 28 */ + u8 image_planes; /* 29 */ + u8 page_function; /* 30 */ + + u8 rmask; /* 31 */ + u8 rpos; /* 32 */ + u8 gmask; /* 33 */ + u8 gpos; /* 34 */ + u8 bmask; /* 35 */ + u8 bpos; /* 36 */ + u8 resv_mask; /* 37 */ + u8 resv_pos; /* 38 */ + u8 dcm_info; /* 39 */ + + u32 lfb_ptr; /* 40 Linear frame buffer address */ + u32 offscreen_ptr; /* 44 Offscreen memory address */ + u16 offscreen_size; /* 48 */ + + u8 reserved[206]; /* 50 */ +}; + +char oemstring[11] = "KVM VESA"; +u16 modes[2] = { 0x0112, 0xffff }; + +static inline void outb(unsigned short port, unsigned char val) +{ + asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +/* + * It's probably much more useful to make this print to the serial + * line rather than print to a non-displayed VGA memory + */ +static inline void int10putchar(struct int10args *args) +{ + u8 al, ah; + + al = args->eax & 0xFF; + ah = (args->eax & 0xFF00) >> 8; + + outb(0x3f8, al); +} + +static void int10vesa(struct int10args *args) +{ + u8 al, ah; + struct vesa_general_info *destination; + struct vminfo *vi; + + al = args->eax; + ah = args->eax >> 8; + + switch (al) { + case 0: + /* Set controller info */ + + destination = (struct vesa_general_info *)args->edi; + *destination = (struct vesa_general_info) { + .signature = VESA_MAGIC, + .version = 0x102, + .vendor_string = oemstring, + .capabilities = 0x10, + .video_mode_ptr = modes, + .total_memory = (4*VESA_WIDTH * VESA_HEIGHT) / 0x10000, + }; + + break; + case 1: + vi = (struct vminfo *)args->edi; + *vi = (struct vminfo) { + .mode_attr = 0xd9, /* 11011011 */ + .logical_scan = VESA_WIDTH*4, + .h_res = VESA_WIDTH, + .v_res = VESA_HEIGHT, + .bpp = VESA_BPP, + .memory_layout = 6, + .memory_planes = 1, + .lfb_ptr = VESA_MEM_ADDR, + .rmask = 8, + .gmask = 8, + .bmask = 8, + .resv_mask = 8, + .resv_pos = 24, + .bpos = 16, + .gpos = 8, + }; + + break; + } + + args->eax = 0x004f; /* return success every time */ + +} + +bioscall void int10handler(struct int10args *args) +{ + u8 ah; + + ah = (args->eax & 0xff00) >> 8; + + switch (ah) { + case 0x0e: + int10putchar(args); + break; + case 0x4f: + int10vesa(args); + break; + } + +} +