From patchwork Mon May 23 12:15:14 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 808472 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 p4NCHA20011010 for ; Mon, 23 May 2011 12:17:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754750Ab1EWMRG (ORCPT ); Mon, 23 May 2011 08:17:06 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:52850 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754555Ab1EWMRF (ORCPT ); Mon, 23 May 2011 08:17:05 -0400 Received: by wwa36 with SMTP id 36so6130979wwa.1 for ; Mon, 23 May 2011 05:17:03 -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=B0E6BIiVEO9eEUDYHUhEnUH6q6jAP1PAdvmRkkhjda0=; b=UohIyq6+naY378bTFGO/FuzpgifiESeBrPEiNN6MnoQkZu6VDnwk3pu5b4UsR/7C3l NO0qNCT1gDbxaTb0Bnp8LjWUdTwH8iOOgS7ko8fdm/0erpRaBHPDv1rjQq12DeNY6USQ MMVh/i5euz3jQkISmoJpIzkaKkHnVR0fAAmSw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=VW+Jyzw+npmQwh+w0lUERtbhiB8GLfLQP0nVsehzOsAh1z8MTNV02X3X+N5/41gccO VqWgnpyDvq3lYOAksSwddl8boURXtnPqRAhMCWKZxxvsCeygeMOC2Ms5+3Xa2VYBJjw7 tGbunk8+O+Ns+gjXsise/K5I1zYwik4S+1fVA= Received: by 10.216.59.83 with SMTP id r61mr2171800wec.5.1306153023532; Mon, 23 May 2011 05:17:03 -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 r29sm3236685weq.45.2011.05.23.05.17.02 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 23 May 2011 05:17:03 -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 V3 1/5] kvm tools: Add BIOS INT10 handler Date: Mon, 23 May 2011 15:15:14 +0300 Message-Id: <1306152918-29944-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 12:17:10 +0000 (UTC) From: John Floren 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 [ turning code into patches and cleanup ] 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..5645cd2 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 int10_handler + + 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..1ab3a67 --- /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 int10_args { + 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 int10_putchar(struct int10_args *args) +{ + u8 al, ah; + + al = args->eax & 0xFF; + ah = (args->eax & 0xFF00) >> 8; + + outb(0x3f8, al); +} + +static void int10_vesa(struct int10_args *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 int10_handler(struct int10_args *args) +{ + u8 ah; + + ah = (args->eax & 0xff00) >> 8; + + switch (ah) { + case 0x0e: + int10_putchar(args); + break; + case 0x4f: + int10_vesa(args); + break; + } + +} +