Bug 16155

Summary: kernel will die on some platform when switch from vga mode to framebuffer mode
Product: Drivers Reporter: Chong Qiao (qiaochong)
Component: Console/FramebuffersAssignee: James Simmons (jsimmons)
Status: RESOLVED OBSOLETE    
Severity: high CC: akpm, alan
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.27 and above Subsystem:
Regression: No Bisected commit-id:
Attachments: 0001-fix-vc-vc_origin-on-take_over_console.patch
0002-Variable-end-on-vc_do_resize-should-be-unsigned-long.patch

Description Chong Qiao 2010-06-08 00:12:38 UTC
There is a bug on framebufer and vt,kernel will die on some platform when switch from vga mode to framebuffer mode.
The reason of this bug is that bind_con_driver reset vc->vc_origin to (unsigned long)vc->vc_screenbuf.

1.The description bellow is my test on mips platform.
On this platform vga memory is at 0xb00b8000 (0xb0000000 is pci memory 0),kernel memory is from 0x80000000~0x8fffffff.

on include/asm-mips/vga.h

#define VGA_MAP_MEM(x, s)   (0xffffffffb0000000L + (unsigned long)(x))

on drivers/video/console/vgacon.c
static const char *vgacon_startup(void)
{
...
    vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
    vga_vram_end = vga_vram_base + vga_vram_size;
...
}

Here vga_vram_base will be 0xb00b8000.

static int vgacon_set_origin(struct vc_data *c)
{
    if (vga_is_gfx ||   /* We don't play origin tricks in graphic modes */
        (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
        return 0;

/*---------here set vc_origin,which is not releated to  vc->vc_screenbuf here. ---------*/

    c->vc_origin = c->vc_visible_origin = vga_vram_base;
    vga_set_mem_top(c);
    vga_rolled_over = 0;
    return 1;
}

Here vc_origin will be 0xb00b8000.


./drivers/char/vt.c

static void set_origin(struct vc_data *vc)
{
    WARN_CONSOLE_UNLOCKED();

    if (!CON_IS_VISIBLE(vc) ||
        !vc->vc_sw->con_set_origin ||
        !vc->vc_sw->con_set_origin(vc))
        vc->vc_origin = (unsigned long)vc->vc_screenbuf;
    vc->vc_visible_origin = vc->vc_origin;

/*---------here set vc_src_end ---------*/

    vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
    vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
}

Here vc.vc_scr_end will be 0xb00b8fa0.

So before framebuffer take over console,vc=0x81081340 vc.vc_origin=0xb00b8000,vc.vc_scr_end=0xb00b8fa0.

When kernel boot,framebuffer take over vga's console:
backtrace like this:

[<80430640>] vc_do_resize+0x2d4/0x4e4
[<80430874>] vc_resize+0x24/0x3c
[<804413ac>] fbcon_init+0x358/0x4d8
[<80430148>] visual_init+0x198/0x224
             bind_con_driver
[<80432fa4>] take_over_console+0x508/0x6e8
[<80440400>] fbcon_takeover+0x88/0xf4
[<80446bac>] fbcon_event_notify+0x46c/0x99c
[<8025f060>] notifier_call_chain+0x64/0xbc
[<8025f3f4>] __blocking_notifier_call_chain+0x5c/0x98
[<8025f444>] blocking_notifier_call_chain+0x14/0x2c
[<80439eec>] register_framebuffer+0x1e8/0x218
[<8020ff1c>] sisfb_probe+0x2140/0x224c
[<80414a00>] pci_device_probe+0x70/0xb4
[<80483874>] driver_probe_device+0x174/0x2b0
[<80483aa4>] __driver_attach+0x54/0x98
[<804824a8>] bus_for_each_dev+0x60/0xb0
[<80482df4>] bus_add_driver+0xc8/0x280
[<8048409c>] driver_register+0xb4/0x178
[<80414728>] __pci_register_driver+0x58/0xb8
[<8070e460>] sisfb_init+0x89c/0x8e4
[<80219350>] __kprobes_text_end+0x68/0x1c4
[<806f8c0c>] kernel_init+0xa8/0x134
[<8021b9e4>] kernel_thread_helper+0x1c/0x24

static int bind_con_driver(const struct consw *csw, int first, int last,
               int deflt)
{
...
/* notice that here change vc_origin to vc_screenbuf,wrong! */
 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
 visual_init(vc, i, 0);
...
}

for  vgacon in my test:
vc=0x81081340 origin=0xb00b8000,end=0xb00b8fa0
after here change to
vc=0x81081340,origin=0x810814a0,end=0xb00b8fa0
then go to see vc_do_resize,visual_init will call it.



static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
        struct vc_data *vc, unsigned int cols, unsigned int lines)
{
    unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
    unsigned int old_cols, old_rows, old_row_size, old_screen_size;
    unsigned int new_cols, new_rows, new_row_size, new_screen_size;
    unsigned int end, user;
...
        end = (old_rows > new_rows) ? old_origin +
            (old_row_size * new_rows) :
            vc->vc_scr_end;

...
/*
here for vgacon:
old_origin=810814a0,end=b00b8fa0,vc->vc_origin=810814a0
the code bellow will copy memory from 0x810814a0 to 0xb00b8fa0,
this will cover kernel code,kernel died here.
*/

    while (old_origin < end) {

        scr_memcpyw((unsigned short *) new_origin,
                (unsigned short *) old_origin, rlth);
        if (rrem)
            scr_memsetw((void *)(new_origin + rlth),
                    vc->vc_video_erase_char, rrem);
        old_origin += old_row_size;
        new_origin += new_row_size;
    }

...
}
the code bellow will above copy memory from 0x810814a0 to 0xb00b8fa0,this will cover kernel code,kernel died here.


The test I have done is on mips 32bit kernel.
On 64bit kernel,kernel will run well.
When I look close at the code,I found that variable end is defined as integer,but old_origin is unsigned long.
On 64bit kernel long is 64bit,int is 32bit,so old_origin is large than end,so kernel jump over the dead code.
So I say:

2.The kernel code may be not very clean,
In function vc_do_resize,old_origin, new_origin, new_scr_end is unsigned long type,but end is int type.
According include/linux/console_struct.h,they all should be unsigned long.


struct vc_data {
    unsigned short  vc_num;         /* Console number */
    unsigned int    vc_cols;        /* [#] Console size */
    unsigned int    vc_rows;
    unsigned int    vc_size_row;        /* Bytes per row */
    unsigned int    vc_scan_lines;      /* # of scan lines */
    unsigned long   vc_origin;      /* [!] Start of real screen */
    unsigned long   vc_scr_end;     /* [!] End of real screen */
    unsigned long   vc_visible_origin;  /* [!] Top of visible window */
    unsigned int    vc_top, vc_bottom;  /* Scrolling region */
    const struct consw *vc_sw;
    unsigned short  *vc_screenbuf;
...
}


That's all.


-- 

QiaoChong(Chong Qiao) qiaochong@loongson.cn
Comment 1 Chong Qiao 2010-06-08 00:14:37 UTC
Created attachment 26696 [details]
0001-fix-vc-vc_origin-on-take_over_console.patch

0001-fix-vc-vc_origin-on-take_over_console.patch
Comment 2 Chong Qiao 2010-06-08 00:16:22 UTC
Created attachment 26697 [details]
0002-Variable-end-on-vc_do_resize-should-be-unsigned-long.patch
Comment 3 Andrew Morton 2010-06-10 22:46:30 UTC
Please don't send patches via bugzilla - it causes lots of problems with
our usual patch management and review processes.

Please send this patch via email as per Documentation/SubmittingPatches. 
Suitable recipients for these patches are

Andrew Morton <akpm@linux-foundation.org>
linux-kernel@vger.kernel.org

Thanks.
Comment 4 Chong Qiao 2010-06-18 04:52:24 UTC
Thank you for your reply.

Greg KH Said:

> On Thu, Jun 17, 2010 at 06:46:56PM +0800, qiaochong wrote:
>   
>> kernel will die on some platform when switch from vga mode to framebuffer
>> mode.
>>     
>
> What platform does this die on?  With what kernel version?
>
>   
The platform is loongson 2f  cpu's  development board.
Loongson 2f is a mips64el  cpu.
The kernel version is 2.6.27.7, mipsel 32bit kernel.
The graphic  card  I use  is   sis  V2.
 
>> The reason of this bug is that bind_con_driver reset vc->vc_origin to
>> (unsigned long)vc->vc_screenbuf.
>> On vgacon vc->vc_origin is not releated to  vc->vc_screenbuf,if set
>> vc->vc_origin to vc->vc_screenbuf,kernel will die on vc_do_resize.
>>     
>
> Why does this not show up for everyone else?  Is this caused by
> something recently changed, or do all older kernels have this problem as
> well?
>
>   
After read your email,I spent half a day to test  kernel 2.6.18.1 and kernel 2.6.27.7.
2.6.18.1 is ok.
2.6.27.7 die.

The reason is vgacon_resize on two kernel return different,which cause the kernel's bug is probed on 2.6.27.7.

At Bellow is my analysis.

2.6.27.7's boot info:

Linux version 2.6.27.7-fl (root@softeam) (gcc version 3.4.6) #14 Fri Jun 18 11:15:25 CST 2010 -00287-gb03d998-dirty
busclock=66000000, cpuclock=697320000,memsize=256,highmemsize=1792
console [early0] enabled
CPU revision is: 00006303 (ICT Loongson-2)
FPU revision is: 00000501
Determined physical RAM map:
 memory: 10000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Zone PFN ranges:
  Normal   0x00000000 -> 0x00004000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00004000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16352
Kernel command line: rdinit=/sbin/init  console=ttyS0,115200 root=/dev/hda1
Primary instruction cache 64kB, VIPT, direct mapped, linesize 32 bytes.
Primary data cache 64kB, 4-way, VIPT, no aliases, linesize 32 bytes
Unified secondary cache 512kB 4-way, linesize 32 bytes.
PID hash table entries: 1024 (order: 10, 4096 bytes)
Console: colour VGA+ 80x25
Dentry cache hash table entries: 32768 (order: 3, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 2, 65536 bytes)
Memory: 251600k/262144k available (4129k kernel code, 10272k reserved, 992k data, 2080k init, 0k highmem)
Calibrating delay loop... 463.87 BogoMIPS (lpj=927744)
Security Framework initialized
SELinux:  Disabled at boot.
Mount-cache hash table entries: 2048
net_namespace: 768 bytes
NET: Registered protocol family 16
Linux Plug and Play Support v0.97 (c) Adam Belay
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
pci 0000:00:10.0: PME# supported from D1 D2 D3hot
pci 0000:00:10.0: PME# disabled
via686b fix: ISA bridge
via686b fix: ISA bridge done
via686b fix: IDE
via686b fix: IDE done
pci 0000:00:11.4: quirk: region eee0-eeef claimed by vt82c686 SMB
ac97 interrupt = 9
ac97 rev=32
Setting sub-vendor ID & device ID
sub vendor-device id=47101005
bus: 00 index 0 io port: [4000, ffff]
bus: 00 index 1 mmio: [50000000, 7fffffff]
NET: Registered protocol family 8
NET: Registered protocol family 20
NET: Registered protocol family 2
IP route cache hash table entries: 4096 (order: 0, 16384 bytes)
TCP established hash table entries: 8192 (order: 2, 65536 bytes)
TCP bind hash table entries: 8192 (order: 1, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
audit: initializing netlink socket (disabled)
type=2000 audit(1041389669.635:1): initialized
VFS: Disk quotas dquot_6.5.1
Dquot-cache hash table entries: 4096 (order 0, 16384 bytes)
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
msgmni has been set to 491
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
sisfb: Video ROM not found
sisfb: Video RAM at 0x50000000, mapped to 0xc0000000, size 65536k
sisfb: MMIO at 0x60000000, mapped to 0xc4080000, size 256k
sisfb: Memory heap starting at 64928K, size 32K
sisfb: Detected SiS301C video bridge
sisfb: CRT1 DDC probing failed
sisfb: Default mode is 800x600x8 (60Hz)
vc_do_resize:851 vc->vc_origin=b00b8000,vc->vc_scr_end=b00b8fa0
Call Trace:
[<80220250>] dump_stack+0x8/0x40
[<804337e8>] vc_do_resize+0x14c/0x514
[<80433bd4>] vc_resize+0x24/0x3c
[<80444564>] fbcon_startup+0x334/0x388
[<80435bd8>] register_con_driver+0x11c/0x230
[<80435e3c>] take_over_console+0x40/0x5ec
[<80443964>] fbcon_takeover+0x88/0xf4
[<8044a110>] fbcon_event_notify+0x46c/0x99c
[<80260594>] notifier_call_chain+0x64/0xbc
[<80260928>] __blocking_notifier_call_chain+0x5c/0x98
[<80260978>] blocking_notifier_call_chain+0x14/0x2c
[<8043d150>] register_framebuffer+0x1e8/0x218
[<80211550>] sisfb_probe+0x2140/0x224c
[<80417d84>] pci_device_probe+0x70/0xb4
[<8048dc34>] driver_probe_device+0x174/0x2b0
[<8048de64>] __driver_attach+0x54/0x98
[<8048c868>] bus_for_each_dev+0x60/0xb0
[<8048d1b4>] bus_add_driver+0xc8/0x280
[<8048e45c>] driver_register+0xb4/0x178
[<80417aac>] __pci_register_driver+0x58/0xb8
[<8071a7b4>] sisfb_init+0x89c/0x8e0
[<8021a380>] __kprobes_text_end+0x68/0x1c4
[<80704c0c>] kernel_init+0xa8/0x134
[<8021ca14>] kernel_thread_helper+0x1c/0x24

vc_do_resize:877 vc->vc_origin=b00b8000,vc->vc_scr_end=b00b8fa0
vc_do_resize:878 vc->vc_sw->con_resize=80442d54 vgacon_resize+0x0/0xbc
vc_do_resize:879 new_cols=100,new_rows=37
vc_do_resize:881 after resize_screen,error=-22
bind_con_driver:3079 old vc_origin=b00b8000,vc_screenbuf=81081420
bind_con_driver:3081 new vc_origin=81081420,vc_screenbuf=81081420,vc->vc_scr_end=b00b8fa0
vc_do_resize:851 vc->vc_origin=81081420,vc->vc_scr_end=b00b8fa0
Call Trace:
[<80220250>] dump_stack+0x8/0x40
[<804337e8>] vc_do_resize+0x14c/0x514
[<80433bd4>] vc_resize+0x24/0x3c
[<80444910>] fbcon_init+0x358/0x4d8
[<8043348c>] visual_init+0x158/0x1d0
[<8043624c>] take_over_console+0x450/0x5ec
[<80443964>] fbcon_takeover+0x88/0xf4
[<8044a110>] fbcon_event_notify+0x46c/0x99c
[<80260594>] notifier_call_chain+0x64/0xbc
[<80260928>] __blocking_notifier_call_chain+0x5c/0x98
[<80260978>] blocking_notifier_call_chain+0x14/0x2c
[<8043d150>] register_framebuffer+0x1e8/0x218
[<80211550>] sisfb_probe+0x2140/0x224c
[<80417d84>] pci_device_probe+0x70/0xb4
[<8048dc34>] driver_probe_device+0x174/0x2b0
[<8048de64>] __driver_attach+0x54/0x98
[<8048c868>] bus_for_each_dev+0x60/0xb0
[<8048d1b4>] bus_add_driver+0xc8/0x280
[<8048e45c>] driver_register+0xb4/0x178
[<80417aac>] __pci_register_driver+0x58/0xb8
[<8071a7b4>] sisfb_init+0x89c/0x8e0
[<8021a380>] __kprobes_text_end+0x68/0x1c4
[<80704c0c>] kernel_init+0xa8/0x134
[<8021ca14>] kernel_thread_helper+0x1c/0x24

vc_do_resize:877 vc->vc_origin=81081420,vc->vc_scr_end=b00b8fa0
vc_do_resize:878 vc->vc_sw->con_resize=804461a0 fbcon_resize+0x0/0x528
vc_do_resize:879 new_cols=100,new_rows=37
vc_do_resize:881 after resize_screen,error=0
vc_do_resize:897 old_origin=81081420,new_origin=8e124000,new_scr_end=8e125ce8
vc_do_resize:925 before scr_memcpyw:old_origin=81081420,end=b00b8fa0,vc->vc_scr_end=b00b8fa0

kernel die here.


Then see source code on 2.6.27.7:

./drivers/char/vt.c
 108 void prom_printf(char *fmt, ...);
 109 #define mydebug(s...) prom_printf("%s:%d ",__FUNCTION__,__LINE__); prom_printf(s)
...

 826 static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
 827         struct vc_data *vc, unsigned int cols, unsigned int lines)
 828 {

...

 846     new_cols = (cols ? cols : vc->vc_cols);
 847     new_rows = (lines ? lines : vc->vc_rows);
 848     new_row_size = new_cols << 1;
 849     new_screen_size = new_row_size * new_rows;
 850
 851     mydebug("vc->vc_origin=%08x,vc->vc_scr_end=%08x\n",vc->vc_origin,vc->vc_scr_end);
 852     if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 853         return 0;
...


 877     mydebug("vc->vc_origin=%08x,vc->vc_scr_end=%08x\n",vc->vc_origin,vc->vc_scr_end);
 878     mydebug("vc->vc_sw->con_resize=%08x %pS\n",vc->vc_sw->con_resize,vc->vc_sw->con_resize);
 879     mydebug("new_cols=%d,new_rows=%d\n",new_cols,new_rows);
 880     err = resize_screen(vc, new_cols, new_rows, user);
 881     mydebug("after resize_screen,error=%d\n",err);
 882     if (err) {
 883         kfree(newscreen);
 884         return err;
 885     }
 886
 887     vc->vc_rows = new_rows;
 888     vc->vc_cols = new_cols;
 889     vc->vc_size_row = new_row_size;
 890     vc->vc_screenbuf_size = new_screen_size;

...

 925     mydebug("before scr_memcpyw:old_origin=%08x,end=%08x,vc->vc_scr_end=%08x\n",old_origin,end,vc->vc_scr_end);
 926     while (old_origin < end) {
 927         scr_memcpyw((unsigned short *) new_origin,
 928                 (unsigned short *) old_origin, rlth);
 929         if (rrem)
 930             scr_memsetw((void *)(new_origin + rlth),
 931                     vc->vc_video_erase_char, rrem);
 932         old_origin += old_row_size;
 933         new_origin += new_row_size;
 934     }
...
}
...

3015 static int bind_con_driver(const struct consw *csw, int first, int last,
3016                int deflt)
3017 {
...
3078         vc->vc_sw->con_deinit(vc);
3079         mydebug("old vc_origin=%08x,vc_screenbuf=%08x\n",vc->vc_origin,vc->vc_screenbuf,vc->vc_scr_end);
3080         vc->vc_origin = (unsigned long)vc->vc_screenbuf;
3081         mydebug("new vc_origin=%08x,vc_screenbuf=%08x,vc->vc_scr_end=%08x\n",vc->vc_origin,vc->vc_screenbuf,vc->vc_scr_end);
3082         visual_init(vc, i, 0);
3083         set_origin(vc);
3084         mydebug("after set_origin vc_origin=%08x,vc_screenbuf=%08x,vc->vc_scr_end=%08x\n",vc->vc_origin,vc->vc_screenbuf
     ,vc->vc_scr_end);
3085         update_attr(vc);
3086
...
}

If resize_screen on line 880 return 0,then vc->vc_rows and vc->vc_cols will be set to new value.
Next time in visual_init call resize_screen will return on line 853,So will not die although old_origin=81081420,end=b00b8fa0,vc->vc_scr_end=b00b8fa0.

If resize_screen on line 880 return !0,next time in visual_init call resize_screen will die on 926,because
copying from 0x81081420 till 0xb00b8fa0  to new_origin will cover kernel area.

If I do not run line 882,883
 882     if (err) {
 883     //  kfree(newscreen);
 884     //  return err;
 885     }

Then boot is ok as bellow:

Linux version 2.6.27.7-fl (root@softeam) (gcc version 3.4.6) #15 Fri Jun 18 11:42:39 CST 2010 -00287-gb03d998-dirty
busclock=66000000, cpuclock=697340000,memsize=256,highmemsize=1792
console [early0] enabled
CPU revision is: 00006303 (ICT Loongson-2)
FPU revision is: 00000501
Determined physical RAM map:
 memory: 10000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Zone PFN ranges:
  Normal   0x00000000 -> 0x00004000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00004000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16352
Kernel command line: rdinit=/sbin/init  console=ttyS0,115200 root=/dev/hda1
Primary instruction cache 64kB, VIPT, direct mapped, linesize 32 bytes.
Primary data cache 64kB, 4-way, VIPT, no aliases, linesize 32 bytes
Unified secondary cache 512kB 4-way, linesize 32 bytes.
PID hash table entries: 1024 (order: 10, 4096 bytes)
Console: colour VGA+ 80x25
Dentry cache hash table entries: 32768 (order: 3, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 2, 65536 bytes)
Memory: 251600k/262144k available (4129k kernel code, 10272k reserved, 992k data, 2080k init, 0k highmem)
Calibrating delay loop... 463.87 BogoMIPS (lpj=927744)
Security Framework initialized
SELinux:  Disabled at boot.
Mount-cache hash table entries: 2048
net_namespace: 768 bytes
NET: Registered protocol family 16
Linux Plug and Play Support v0.97 (c) Adam Belay
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
pci 0000:00:10.0: PME# supported from D1 D2 D3hot
pci 0000:00:10.0: PME# disabled
via686b fix: ISA bridge
via686b fix: ISA bridge done
via686b fix: IDE
via686b fix: IDE done
pci 0000:00:11.4: quirk: region eee0-eeef claimed by vt82c686 SMB
ac97 interrupt = 9
ac97 rev=32
Setting sub-vendor ID & device ID
sub vendor-device id=47101005
bus: 00 index 0 io port: [4000, ffff]
bus: 00 index 1 mmio: [50000000, 7fffffff]
NET: Registered protocol family 8
NET: Registered protocol family 20
NET: Registered protocol family 2
IP route cache hash table entries: 4096 (order: 0, 16384 bytes)
TCP established hash table entries: 8192 (order: 2, 65536 bytes)
TCP bind hash table entries: 8192 (order: 1, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
audit: initializing netlink socket (disabled)
type=2000 audit(1041391376.635:1): initialized
VFS: Disk quotas dquot_6.5.1
Dquot-cache hash table entries: 4096 (order 0, 16384 bytes)
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
msgmni has been set to 491
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
sisfb: Video ROM not found
sisfb: Video RAM at 0x50000000, mapped to 0xc0000000, size 65536k
sisfb: MMIO at 0x60000000, mapped to 0xc4080000, size 256k
sisfb: Memory heap starting at 64928K, size 32K
sisfb: Detected SiS301C video bridge
sisfb: CRT1 DDC probing failed
sisfb: Default mode is 800x600x8 (60Hz)
vc_do_resize:851 vc->vc_origin=b00b8000,vc->vc_scr_end=b00b8fa0
Call Trace:
[<80220250>] dump_stack+0x8/0x40
[<804337e8>] vc_do_resize+0x14c/0x500
[<80433bc0>] vc_resize+0x24/0x3c
[<80444550>] fbcon_startup+0x334/0x388
[<80435bc4>] register_con_driver+0x11c/0x230
[<80435e28>] take_over_console+0x40/0x5ec
[<80443950>] fbcon_takeover+0x88/0xf4
[<8044a0fc>] fbcon_event_notify+0x46c/0x99c
[<80260594>] notifier_call_chain+0x64/0xbc
[<80260928>] __blocking_notifier_call_chain+0x5c/0x98
[<80260978>] blocking_notifier_call_chain+0x14/0x2c
[<8043d13c>] register_framebuffer+0x1e8/0x218
[<80211550>] sisfb_probe+0x2140/0x224c
[<80417d84>] pci_device_probe+0x70/0xb4
[<8048dc1c>] driver_probe_device+0x174/0x2b0
[<8048de4c>] __driver_attach+0x54/0x98
[<8048c850>] bus_for_each_dev+0x60/0xb0
[<8048d19c>] bus_add_driver+0xc8/0x280
[<8048e444>] driver_register+0xb4/0x178
[<80417aac>] __pci_register_driver+0x58/0xb8
[<8071a7b4>] sisfb_init+0x89c/0x8e0
[<8021a380>] __kprobes_text_end+0x68/0x1c4
[<80704c0c>] kernel_init+0xa8/0x134
[<8021ca14>] kernel_thread_helper+0x1c/0x24

vc_do_resize:877 vc->vc_origin=b00b8000,vc->vc_scr_end=b00b8fa0
vc_do_resize:878 vc->vc_sw->con_resize=80442d40 vgacon_resize+0x0/0xbc
vc_do_resize:879 new_cols=100,new_rows=37
vc_do_resize:881 after resize_screen,error=-22
vc_do_resize:897 old_origin=b00b8000,new_origin=8e124000,new_scr_end=8e125ce8
vc_do_resize:925 before scr_memcpyw:old_origin=b00b8000,end=b00b8fa0,vc->vc_scr_end=b00b8fa0
bind_con_driver:3079 old vc_origin=b00b8000,vc_screenbuf=8e124000
bind_con_driver:3081 new vc_origin=8e124000,vc_screenbuf=8e124000,vc->vc_scr_end=b00b9ce8
vc_do_resize:851 vc->vc_origin=8e124000,vc->vc_scr_end=b00b9ce8
bind_con_driver:3084 after set_origin vc_origin=8e124000,vc_screenbuf=8e124000,vc->vc_scr_end=8e125ce8
Console: switching to colour frame buffer device 100x37
sisfb: 2D acceleration is enabled, y-panning enabled (auto-max)
fb0: SiS 315PRO frame buffer device version 1.8.9
sisfb: Copyright (C) 2001-2005 Thomas Winischhofer
isapnp: Scanning for PnP cards...
isapnp: No Plug & Play device found
[drm] Initialized drm 1.1.0 20060810
Serial: 8250/16550 driver16 ports, IRQ sharing disabled
serial8250.0: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550Aconsole handover: boot [early0] -> real [ttyS0]
serial8250.0: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
brd: module loaded
Intel(R) PRO/1000 Network Driver - version 7.3.20-k3-NAPI
Copyright (c) 1999-2006 Intel Corporation.
e100: Intel(R) PRO/100 Network Driver, 3.5.23-k4-NAPI
e100: Copyright(c) 1999-2006 Intel Corporation
8139too Fast Ethernet driver 0.9.28
eth0: RealTek RTL8139 at 0xc4008000, 00:0a:eb:56:5e:01, IRQ 36
Linux video capture interface: v2.00
Uniform Multi-Platform E-IDE driver
Driver 'sd' needs updating - please use bus_type methods
mice: PS/2 mouse device common for all mice
usbcore: registered new interface driver hiddev
usbcore: registered new interface driver usbhid
usbhid: v2.6:USB HID core driver
TCP bic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
begin to find the vga mem range
find the frame buffer:start=50000000,end=5fffffff
Freeing unused kernel memory: 2080k freed
init started: BusyBox v1.11.3 (2010-03-31 20:49:53 CST)
starting pid 305, tty '': '/etc/init.d/rcS'
eth0: link up, 100Mbps, full-duplex, lpa 0x45E1

Please press Enter to activate this console.
starting pid 314, tty '': '-/bin/sh'
Loongson2@[\w]>


You can see that size is updated on first vc_do_resize:

 vc_do_resize:925 before scr_memcpyw:old_origin=b00b8000,end=b00b8fa0,vc->vc_scr_end=b00b8fa0
On visual_init call vc_do_resize return on line 853:

vc_do_resize:851 vc->vc_origin=8e124000,vc->vc_scr_end=b00b9ce8
bind_con_driver:3084 after set_origin vc_origin=8e124000,vc_screenbuf=8e124000,vc->vc_scr_end=8e125ce8

then run set_origin ,after  set_origin

bind_con_driver:3084 after set_origin vc_origin=8e124000,vc_screenbuf=8e124000,vc->vc_scr_end=8e125ce8

Then see boot info on linux 2.6.18.1:

Booting Linux kernel...
Godson 2F Evaluation Board
Linux version 2.6.18.1-gf0f74d7d-dirty (root@softeam) (gcc version 3.4.6) #8 Fri Jun 18 11:16:39 CST 2010 -gf0f74d7d-dirty
busclock=66000000, cpuclock=697340000,memsize=256,highmemsize=1792
CPU revision is: 00006303
FPU revision is: 00000501
Determined physical RAM map:
 memory: 0ff00000 @ 00100000 (usable)
Built 1 zonelists.  Total pages: 16384
Kernel command line: rdinit=/sbin/init  console=ttyS0,115200 root=/dev/hda1
Primary instruction cache 64kB, physically tagged, 4-way, linesize 32 bytes.
Primary data cache 64kB, 4-way, linesize 32 bytes.
Unified secondary cache 512kB 4-way, linesize 32 bytes.
Synthesized TLB refill handler (19 instructions).
Synthesized TLB load handler fastpath (31 instructions).
Synthesized TLB store handler fastpath (31 instructions).
Synthesized TLB modify handler fastpath (30 instructions).
init_IRQ done.
PID hash table entries: 2048 (order: 11, 8192 bytes)
Using 348.670 MHz high precision timer.
Console: colour VGA+ 80x25
Dentry cache hash table entries: 32768 (order: 3, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 2, 65536 bytes)
Memory: 251312k/261120k available (4476k kernel code, 9568k reserved, 1035k data, 2064k init, 0k highmem)
Mount-cache hash table entries: 2048
Checking for 'wait' instruction...  unavailable.
NET: Registered protocol family 16
SCSI subsystem initialized
usbcore: registered new driver usbfs
usbcore: registered new driver hub
via686b fix: ISA bridge
via686b fix: ISA bridge done
via686b fix: IDE
via686b fix: IDE done
PCI quirk: region eee0-eeef claimed by vt82c686 SMB
ac97 interrupt = 9
ac97 rev=32
Setting sub-vendor ID & device ID
sub vendor-device id=47101005
can not assign bus 0x0,dev 0x11,func 0x4
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: -1, 8192 bytes)
TCP established hash table entries: 8192 (order: 1, 32768 bytes)
TCP bind hash table entries: 4096 (order: 0, 16384 bytes)
TCP: Hash tables configured (established 8192 bind 4096)
TCP reno registered
squashfs: version 3.4 (2008/08/26) Phillip Lougher
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
fuse init (API version 7.7)
Registering unionfs 1.4
unionfs: debugging is not enabled
Initializing Cryptographic API
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
pci_hotplug: PCI Hot Plug PCI Core version: 0.5
cpcihp_generic: Generic port I/O CompactPCI Hot Plug Driver version: 0.1
cpcihp_generic: not configured, disabling.
sisfb: Video ROM not found
sisfb: Video RAM at 0x50000000, mapped to 0xc0000000, size 65536k
sisfb: MMIO at 0x60000000, mapped to 0xc4080000, size 256k
sisfb: Memory heap starting at 64928K, size 32K
sisfb: Detected SiS301C video bridge
sisfb: CRT1 DDC probing failed
sisfb: Default mode is 800x600x8 (60Hz)
Call Trace:
[<8020a208>] dump_stack+0x18/0x50
[<80465834>] vc_resize+0xe4/0x588
[<80413db0>] fbcon_startup+0x2a8/0x428
[<80467d88>] register_con_driver+0xcc/0x2d0
[<804680bc>] take_over_console+0x40/0x7e0
[<80413304>] fbcon_takeover+0x80/0xf4
[<8041a0f0>] fbcon_event_notify+0x9cc/0xebc
[<8023fd14>] notifier_call_chain+0x4c/0x8c
[<8023ff90>] blocking_notifier_call_chain+0x34/0x68
[<8040ca94>] register_framebuffer+0x11c/0x1b0
[<8042f3a8>] sisfb_probe+0x19e0/0x258c
[<80401a68>] pci_device_probe+0x98/0xc0
[<8047aa24>] driver_probe_device+0x94/0x100
[<8047aea0>] __driver_attach+0x23c/0x320
[<80479640>] bus_for_each_dev+0x60/0xb0
[<8047a130>] bus_add_driver+0xb4/0x1a4
[<80401784>] __pci_register_driver+0x48/0x9c
[<80780aa0>] sisfb_init+0x1b0/0x898
[<8020051c>] init+0xac/0x310
[<80204784>] kernel_thread_helper+0x1c/0x24

vc_resize:811 <0>vc->vc_origin=b00b8000,vc->vc_scr_end=b00b8fa0
vc_resize:814 resize_screen=80465504,new_cols=100,new_rows=37,err=0
vc_resize:831 old_origin=b00b8000,new_origin=809b4000,new_scr_end=809b5ce8
vc_resize:858 before scr_memcpyw:old_origin=b00b8000,end=b00b8fa0,vc->vc_scr_end=b00b8fa0
bind_con_driver:2776 old vc_origin=b00b8000,vc_screenbuf=809b4000,vc->vc_scr_end=b00b9ce8
bind_con_driver:2779 new vc_origin=809b4000,vc_screenbuf=809b4000,vc->vc_scr_end=b00b9ce8
bind_con_driver:2782 after set_origin vc_origin=809b4000,vc_screenbuf=809b4000,vc->vc_scr_end=809b5ce8
Console: switching to colour frame buffer device 100x37
sisfb: 2D acceleration is enabled, y-panning enabled (auto-max)
fb0: SiS 315PRO frame buffer device version 1.8.9
sisfb: Copyright (C) 2001-2005 Thomas Winischhofer
rtc: SRM (post-2000) epoch (2000) detected
Real Time Clock Driver v1.12ac
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
serial8250: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
RAMDISK driver initialized: 16 RAM disks of 40960K size 1024 blocksize
loop: loaded (max 8 devices)
Intel(R) PRO/1000 Network Driver - version 7.1.9-k4
Copyright (c) 1999-2006 Intel Corporation.
e100: Intel(R) PRO/100 Network Driver, 3.5.10-k2-NAPI
e100: Copyright(c) 1999-2005 Intel Corporation
8139too Fast Ethernet driver 0.9.27
eth0: RealTek RTL8139 at 0xc4008000, 00:0a:eb:56:5e:01, IRQ 20
dmfe: Davicom DM9xxx net driver, version 1.36.4 (2002-01-17)
winbond-840.c:v1.01-d (2.4 port) Nov-17-2001  Donald Becker <becker@scyld.com>
  http://www.scyld.com/network/drivers.html
uli526x: ULi M5261/M5263 net driver, version 0.9.3 (2005-7-29)
Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
VP_IDE: IDE controller at PCI slot 0000:00:11.1
PCI: VIA IRQ fixup for 0000:00:11.1, from 14 to 0
VP_IDE: chipset revision 16
VP_IDE: not 100% native mode: will probe irqs later
VP_IDE: VIA vt82c686a (rev 22) IDE UDMA66 controller on pci0000:00:11.1
    ide0: BM-DMA at 0x4cc0-0x4cc7, BIOS settings: hda:pio, hdb:pio
    ide1: BM-DMA at 0x4cc8-0x4ccf, BIOS settings: hdc:pio, hdd:pio
NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c $Revision: 1.41 $
INFTL: inftlcore.c $Revision: 1.19 $, inftlmount.c $Revision: 1.18 $
loongson flash driver
Found: SST 39LF040
loongson bootrom memory: Found 1 x8 devices at 0x0 in 8-bit bank
number of JEDEC chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
rfd_ftl: no RFD magic found in 'loongson bootrom memory'
ftl_cs: FTL header not found.
ftl_cs: FTL header corrupt!
block2mtd: version $Revision: 1.30 $
usbmon: debugfs is not available
USB Universal Host Controller Interface driver v3.0
uhci_hcd 0000:00:11.2: UHCI Host Controller
uhci_hcd 0000:00:11.2: new USB bus registered, assigned bus number 1
uhci_hcd 0000:00:11.2: irq 11, io base 0x00004c80
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
uhci_hcd 0000:00:11.3: UHCI Host Controller
uhci_hcd 0000:00:11.3: new USB bus registered, assigned bus number 2
uhci_hcd 0000:00:11.3: irq 10, io base 0x00004ca0
usb usb2: configuration #1 chosen from 1 choice
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...
usb 2-1: new full speed USB device using uhci_hcd and address 2
usb 2-1: configuration #1 chosen from 1 choice
scsi0 : SCSI emulation for USB Mass Storage devices
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
usbcore: registered new driver usbhid
/mnt/hda2/work/linux-2.6.18/drivers/usb/input/hid-core.c: v2.6:USB HID core driver
serio: i8042 AUX port at 0x60,0x64 irq 12
serio: i8042 KBD port at 0x60,0x64 irq 1
mice: PS/2 mouse device common for all mice
Via 686a/8233/8235 audio driver 1.9.1-ac4-2.5
ac97_codec: AC97 Audio codec, id: ALG112 (Unknown)
via82cxxx: board #1 at 0x4400, IRQ 9
Advanced Linux Sound Architecture Driver Version 1.0.12rc1 (Thu Jun 22 13:55:50 2006 UTC).
atkbd.c: keyboard reset failed on isa0060/serio1
atkbd.c: keyboard reset failed on isa0060/serio0
VIA 82xx Modem: probe of 0000:00:11.6 failed with error -13
ALSA device list:
  No soundcards found.
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
vga:start=50000000,end=5fffffff
Freeing unused kernel memory: 2064k freed
init started: BusyBox v1.11.3 (2010-03-31 20:49:53 CST)
starting pid 803, tty '': '/etc/init.d/rcS'
bonito irq startup 20
eth0: link up, 100Mbps, full-duplex, lpa 0x45E1

Please press Enter to activate this console.
starting pid 812, tty '': '-/bin/sh'
Loongson2@[\w]> 

you see
vc_resize:814 resize_screen=80465504,new_cols=100,new_rows=37,err=0
so boot ok.

Then see 2.6.27.7's vgacon_resize:

1279 static int vgacon_resize(struct vc_data *c, unsigned int width,
1280              unsigned int height, unsigned int user)
1281 {
1282     if (width % 2 || width > screen_info.orig_video_cols ||
1283         height > (screen_info.orig_video_lines * vga_default_font_height)/
1284         c->vc_font.height)
1285         /* let svgatextmode tinker with video timings and
1286            return success */
1287         return (user) ? 0 : -EINVAL;
1288
1289     if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1290         vgacon_doresize(c, width, height);
1291     return 0;
1292 }

Then see 2.6.18.1's vgacon_resize:

1266 static int vgacon_resize(struct vc_data *c, unsigned int width,
1267                 unsigned int height)
1268 {
1269     if (width % 2 || width > ORIG_VIDEO_COLS ||
1270         height > (ORIG_VIDEO_LINES * vga_default_font_height)/
1271         c->vc_font.height)
1272         /* let svgatextmode tinker with video timings */
1273         return 0;
1274
1275     if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1276         vgacon_doresize(c, width, height);
1277     return 0;
1278 }


always return 0.


My vga size's size is here on plat_mem_setup:

106 #ifdef CONFIG_VT
107 #if defined(CONFIG_VGA_CONSOLE)
108     conswitchp = &vga_con;
109
110     screen_info = (struct screen_info) {
111         0, 25,      /* orig-x, orig-y */
112             0,      /* unused */
113             0,      /* orig-video-page */
114             0,      /* orig-video-mode */
115             80,     /* orig-video-cols */
116             0, 0, 0,    /* ega_ax, ega_bx, ega_cx */
117             25,     /* orig-video-lines */
118             VIDEO_TYPE_VGAC,    /* orig-video-isVGA */
119             16      /* orig-video-points */
120     };
121 #elif defined(CONFIG_DUMMY_CONSOLE)
122     conswitchp = &dummy_con;
123 #endif
124 #endif


So My coclusion:
  vgacon_resize return !0 cause vc_do_resize is delayed until on visual_init,on there vc->vc_origin has been changed to vc->vc_screenbuf  ,but vc->vc_scr_end is not changed,and for vgacon vc->vc_scr_end is not related to vc->vc_screenbuf,which cause kernel die when copy old console data from
 vc->vc_origin till  vc->vc_scr_end   to  new vc_origin.


attachemt is  vt.c on my test for 2.6.18 and 2.6.27.


That's all,thanks!


> thanks,
>
> greg k-h
>
>