2013年2月3日 星期日

kernel loader issue in bochs

issue: 使用 bochs 2.6, kernel loader 無法載入 kernel

使用自動變數
u16 offset, next_cluster, cur_cluster;
在 bochs 2.6 下 kernel loader 無法載入 kernel

使用 static 變數 + gcc 4.4
static u16 offset, next_cluster, cur_cluster;
就沒問題 ,但若使用 gcc 4.7 compile, 還是一樣的問題。
很值得看看, 應該是 stack 這邊出了狀況, 看起來又不太像, 慘 ...

每一次的問題都是一次很好的學習機會。

git@github.com:descent/simple_os.git

issue:
git commit: c7229045fd1fb93edff72f2e816eedce6c408c30

fixed only under gcc 4.4
git commit: 7138421dd7c683734cdf774322821b943cc09b78


fixed under gcc 4.7

把 volatile u8 *buff 改成 u16 buff, 讓 "b"(buff)

31 __asm__ __volatile__ 
32 (
33 @@ -349,6 +354,10 @@ int __REGPARM read_sector(volatile u8 *buff, u8 sector_no, u8 track_no, u8 head_
34  :"a"(0x0200|blocks), "b"(buff), "c"(track_no << 8 | sector_no), "d"(head_no << 8 | disk_no)
35 ); 

直接吃 u16 的值, 可以修復這問題, 可是還沒找到 root cause。

git diff f78742eea8d145fcbb8b302bd1f7491d16d783b8 ff8d23e70841af5cc48b7131aca6a04d5e2233ce
 1 diff --git a/kernel_loader/kernel_loader.c b/kernel_loader/kernel_loader.c
 2 index 3a071ca..464da43 100644
 3 --- a/kernel_loader/kernel_loader.c
 4 +++ b/kernel_loader/kernel_loader.c
 5 @@ -314,7 +314,7 @@ int __REGPARM __NOINLINE get_drive_params(drive_params_t    *p, unsigned char
 6  // not 0: fail
 7  // if using the function read floppy fail, suggest reset floppy disk,
 8  // than try twice again.
 9 -int __REGPARM read_sector(volatile u8 *buff, u8 sector_no, u8 track_no, u8 head_no, u8 disk_no, u8 blocks)
10 +int __REGPARM read_sector(u16 buff, u8 sector_no, u8 track_no, u8 head_no, u8 disk_no, u8 blocks)
11  {
12    //bios_wait_key();
13  #if 0
14 @@ -333,12 +333,17 @@ int __REGPARM read_sector(volatile u8 *buff, u8 sector_no, u8 track_no, u8 head_
15  //  __asm__ __volatile__("movb $2, %ah\n"); 
16  //  __asm__ __volatile__("movb $1, %al\n"); 
17  #if 1
18 -    //BOCHS_MB
19    // read sector to %es:%bx, if %bx is more than 64k, need change %es
20    // to next 64k beginning address
21    // ref: http://dc0d32.blogspot.tw/2010/06/real-mode-in-c-with-gcc-writing.html
22    u16 num_blocks_transferred = 0;
23    u8 failed = 0;
24 +  //BOCHS_MB
25 +  //__asm__ __volatile__("xchg %bx, %bx");
26 +  __asm__ __volatile__("push %ax");
27 +  __asm__ __volatile__("push %bx");
28 +  __asm__ __volatile__("push %cx");
29 +  __asm__ __volatile__("push %dx");
30  
31    __asm__ __volatile__ 
32      (
33 @@ -349,6 +354,10 @@ int __REGPARM read_sector(volatile u8 *buff, u8 sector_no, u8 track_no, u8 head_
34        :"a"(0x0200|blocks), "b"(buff), "c"(track_no << 8 | sector_no), "d"(head_no << 8 | disk_no)
35      ); 
36  #endif
37 +  __asm__ __volatile__("pop %dx");
38 +  __asm__ __volatile__("pop %cx");
39 +  __asm__ __volatile__("pop %bx");
40 +  __asm__ __volatile__("pop %ax");
41    u8 ret_status = (num_blocks_transferred >> 8);
42    #ifdef MORE_ERR_MSG
43    NAME_VALUE(num_blocks_transferred)
44 @@ -524,7 +533,7 @@ int load_file_to_ram(int begin_cluster, int fat, u16 org_es, u16 es)
45  {
46    int r;
47    int r_sec = begin_cluster - 2 + bpb.root_dir_occupy_sector + bpb.root_dir_start_sector;
48 -  volatile u8 *buff = (u8*)LOAD_KERNEL_OFFSET;
49 +  u16 buff = LOAD_KERNEL_OFFSET;
50  
51    print_num(begin_cluster, "begin_cluster");
52    print_num(r_sec, "cluster sector no");
53 @@ -568,7 +577,7 @@ int load_file_to_ram(int begin_cluster, int fat, u16 org_es, u16 es)
54  #endif
55          if (read_sector_count == 65536/512)
56          {
57 -          buff = (u8*)LOAD_KERNEL_OFFSET;
58 +          buff = LOAD_KERNEL_OFFSET;
59  #ifdef MORE_ERR_MSG
60            print("\r\nmore than 64Kb\r\n");
61  #endif
62 @@ -664,7 +673,7 @@ void start_c()
63    head_no=0; // dh
64    disk_no=0; // dl
65  #endif
66 -  *buff = 0x1;
67 +  //*buff = 0x1;
68  
69    int r = read_sector(buff, sector_no, track_no, head_no, disk_no, 1);
70    init_bpb(buff, &bpb);

26 +  __asm__ __volatile__("push %eax");
27 +  __asm__ __volatile__("push %ebx");
28 +  __asm__ __volatile__("push %ecx");
29 +  __asm__ __volatile__("push %edx");
30  
31    __asm__ __volatile__ 
32      (
33 @@ -349,6 +354,10 @@ int __REGPARM read_sector(volatile u8 *buff, u8 sector_no, u8 track_no, u8 head_
34        :"a"(0x0200|blocks), "b"(buff), "c"(track_no << 8 | sector_no), "d"(head_no << 8 | disk_no)
35      ); 
36  #endif
37 +  __asm__ __volatile__("pop %edx");
38 +  __asm__ __volatile__("pop %ecx");
39 +  __asm__ __volatile__("pop %ebx");
40 +  __asm__ __volatile__("pop %eax");

似乎和 static 變數無關, 改成 push/pop 32 bit register 比較正常了。

git commit 03532548e7d57d660033e648c793a657ebe596de

似乎還得補上 push/pop %esi, %edi



 1 +  __asm__ __volatile__("push %esi");
 2 +  __asm__ __volatile__("push %edi");
 3    __asm__ __volatile__("push %eax");
 4    __asm__ __volatile__("push %ebx");
 5    __asm__ __volatile__("push %ecx");
 6 @@ -366,12 +369,15 @@ int __REGPARM read_sector(u16 buff, u8 sector_no, u8 track_no, u8 head_n
 7    __asm__ __volatile__("pop %ecx");
 8    __asm__ __volatile__("pop %ebx");
 9    __asm__ __volatile__("pop %eax");
10 +  __asm__ __volatile__("pop %edi");
11 +  __asm__ __volatile__("pop %esi");

git commit 38a3df774b25348aceffb479d731a5579641f595

我對在 c 語言使用 inline assembly 還不熟悉, 可能踩到什麼陷阱了。會加上 push/pop 這些暫存器只是我反組譯看到 c compiler 會用到這些暫存器, 所以加上。


沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。