Mais conteúdo relacionado Semelhante a あるmmapの話 (20) あるmmapの話4. 動かない (´・ω・`)
NetBSD/alpha 6.1.1 Secondary Bootstrap, Revision 1.13
VMS PAL rev: 0x1000700010162
OSF PAL rev: 0x100070002015c
Switch to OSF PAL code succeeded.
Boot flags: a
10205376+201944=0x9ed480
Entering netbsd at 0xfffffc0000431230...
NetBSD does not yet support system type 38 (???).
panic: platform not supported
Stopped in pid 0.1 (system) at fffffc0000496e18: ret zero,(ra)
db>
9. mikutter 動いた。完! (`・ω・´)
pr-48148
NetBSD/alpha fails to install on AlphaStaion DS15
pr-48431
radeonfb fails to initialize on
Alpha Station DS15 and Alpha Station XP1000
pr-48492
sys/dev/wscons/wsdisplay_glyphcache.c/
glyphcache_wipe causes kernel panic.
10. パッチにミス(良くわかってない子)
========================================================================
I think that need ALPHA_PHYS_TO_K0SEG.
Because direct-mapped addresses.
diff -Naru src.orig/sys/arch/alpha/pci/pci_bwx_bus_mem_chipdep.c src/sys/arch/alpha/pci/pci_bwx_bus_mem_chipdep.c
--- src.orig/sys/arch/alpha/pci/pci_bwx_bus_mem_chipdep.c 2012-02-06 11:14:15.000000000 +0900
+++ src/sys/arch/alpha/pci/pci_bwx_bus_mem_chipdep.c 2013-12-01 21:33:43.000000000 +0900
@@ -500,7 +500,7 @@
int flags)
{
- return (alpha_btop(CHIP_MEM_SYS_START(v) + addr + off));
+ return (alpha_btop(ALPHA_PHYS_TO_K0SEG(CHIP_MEM_SYS_START(v) + addr + off)));
}
static inline void
========================================================================
11. 正解!
> > --- pci/tsp_bus_mem.c 6 Feb 2012 02:14:15 -0000 1.12
> > +++ pci/tsp_bus_mem.c 15 Jan 2014 15:18:22 -0000
:
> > -#define CHIP_MEM_SYS_START(v) (((struct tsp_config *)(v))->pc_iobase)
> > +#define CHIP_MEM_SYS_START(v)
> > + (((struct tsp_config *)(v))->pc_iobase | P_PCI_MEM)
:
> I apply this patch.
> It work fine!
Thanks. I'll commit this part soon.
> >return (alpha_btop(ALPHA_PHYS_TO_K0SEG(CHIP_MEM_SYS_START(v) + addr + off)));
> My patch is work but it is very very rare instances.
> I guess it should be MMU's magic!
I guess some higher bits (around P_PCI_MEM) are ignored in pmap_enter()
or alpha's MMU (but not sure).
14. mmap(2)
mmap() は、UNIXのシステムコールのひとつで、
ファイルやデバイスなどの
オペレーティングシステム (OS) 上のリソースの一部または
全部を連続した仮想アドレス空間にマッピングする関数である。
ファイルシステム上のリソースに対するアクセス方法として、
ストリームI/Oを行うシステムコールとの比較で、
ユーザ空間とカーネル空間の間で読み書きされるデータの
ブロック転送が多くのアーキテクチャ上では発生しないことから、好まれる場合がある。
デバイスでは、ioctl()とともにメモリマップドI/Oや
DMAなどの操作を抽象化するものとして
ドライバからファイルI/Oサービスの一部として提供されることがある。
wikipediaより
16. Device pager is 何?
※wsdisplay + wskbd がセットになった端末が ttyE*
if ((fd = open( "/dev/ttyE0", O_RDWR)) < 0) {
fprintf(stderr, "Failed to open /dev/ttyE0n") ;
return 1;
}
mode = WSDISPLAYIO_MODE_MAPPED ;
if (ioctl(STDIN_FILENO, WSDISPLAYIO_SMODE, &mode) == -1) {
fprintf(stderr, "WSDISPLAYIO_SMODE failed.n");
return 1;
}
if ((fb = mmap( NULL, line_length * vinfo.height,PROT_WRITE|PROT_READ,
MAP_SHARED, fd , (off_t)0)) == MAP_FAILED) {
fprintf(stderr, "mmap failed.n");
goto error;
}
memset(fb, 0xff, line_length * vinfo.height);
19. openした/dev/ttyE0のvnode構造体を取得
1139 KASSERT(handle != NULL);
1140 vp = (struct vnode *)handle;
1141
1142 /*
1143 * Don't allow mmap for EXEC if the file system
1144 * is mounted NOEXEC.
1145 */
file構造体、fd_getfile(9)
sys_mmap関数内
vp = fp->f_data;/* convert to vnode *
の処理も参照してください
20. キャラクタデバイスか判断
1146 if ((prot & PROT_EXEC) != 0 &&
1147 (vp->v_mount->mnt_flag & MNT_NOEXEC) != 0)
1148 return (EACCES);
1149
1150 if (vp->v_type != VCHR) {
1151 error = VOP_MMAP(vp, prot, curlwp->l_cred);
159 union {
160 struct mount *vu_mountedhere; /* v: ptr to vfs (VDIR) */
161 struct socket *vu_socket; /* v: unix ipc (VSOCK) */
162 struct specnode *vu_specnode; /* v: device (VCHR, VBLK) */
163 struct fifoinfo *vu_fifoinfo; /* v: fifo (VFIFO) */
164 struct uvm_ractx *vu_ractx; /* i: read-ahead ctx (VREG) */
165 } v_un;
vnode構造体を参照して下さい
21. デバイスだったらudv_attachを呼ぶ
1169 * XXX Some devices don't like to be mapped with
1170 * XXX PROT_EXEC or PROT_WRITE, but we don't really
1171 * XXX have a better way of handling this, right now
1172 */
1173 do {
1174 uobj = udv_attach((void *) &vp->v_rdev,
1175 (flags & MAP_SHARED) ? i :
1176 (i & ~VM_PROT_WRITE), foff, size);
1177 i--;
1178 } while ((uobj == NULL) && (i > 0));
23. /dev/ttyE0のデバイスナンバー取得
108 struct uvm_object *
109 udv_attach(void *arg, vm_prot_t accessprot,
110 voff_t off, /* used only for access check */
111 vsize_t size /* used only for access check */)
112 {
113 dev_t device = *((dev_t *)arg);
114 struct uvm_device *udv, *lcv;
デバイスナンバーやcdev_mmap、 cdevsw構造体については
BSDカーネルの設計と実装の第6章、入出力システムの概要が詳しいです
/src/sys/arch/alpha/conf/majors.alphaも参照して下さい
25. mmapされる領域が有効なフレームバッファのアドレスか判断
143 /*
144 * Check that the specified range of the device allows the
145 * desired protection.
146 *
147 * XXX assumes VM_PROT_* == PROT_*
148 * XXX clobbers off and size, but nothing else here needs them.
149 */
150
151 while (size != 0) {
152 if (cdev_mmap(device, off, accessprot) == -1) {
153 return (NULL);
154 }
155 off += PAGE_SIZE; size -= PAGE_SIZE;
156 }
cdev_mmap関数はデバイスナンバーを引数に
cdevsw構造体経由でデバイスドライバ(今回はradeonfb)のmmapを呼び出します
26. mmapされる領域が有効なフレームバッファのアドレスか判断
1245 paddr_t
1246 radeonfb_mmap(void *v, void *vs, off_t offset, int prot)
1247 {
1248 struct vcons_data *vd;
1249 struct radeonfb_display *dp;
1250 struct radeonfb_softc *sc;
1251 paddr_t pa;
…
1256
1257 /* XXX: note that we don't allow mapping of registers right now */
1258 /* XXX: this means that the XFree86 radeon driver won't work */
1259 if ((offset >= 0) && (offset < (dp->rd_virty * dp->rd_stride))) {
1260 pa = bus_space_mmap(sc->sc_memt,
1261 sc->sc_memaddr + dp->rd_offset + offset, 0,
1262 prot, BUS_SPACE_MAP_LINEAR);
1263 return pa;
1264 }
27. mmapされる領域が有効なフレームバッファのアドレスか判断
494 paddr_t
495 __C(CHIP,_mem_mmap)(
496 void *v,
497 bus_addr_t addr,
498 off_t off,
499 int prot,
500 int flags)
501 {
502
503 return (alpha_btop(CHIP_MEM_SYS_START(v) + addr + off));
504 }
src/sys/arch/alpha/pci/pci_bwx_bus_mem_chipdep.c
bus_space_mmap(9)については
bus space API
http://www.ceres.dti.ne.jp/tsutsui/netbsd/doc/bus_space2.html
が参考になります
ようやくフレームバッファの物理アドレスが出てくる!!
28. 突然の質問コ ナ
せんせ 、 CHIP_MEM_SYS_STARTがこの機種のPCIバスのベース値になる
と言いましたけど、そういう情報はどこから調べるんですか?
addrはフレームバッファのアドレスでPCIバスのベース値からのオフセット
と言いましたけど、どうやって調べるんですか?
OSの移植にはメモリマップが必要なんだ。(凄い人はいらない)
PCIバスのベース値などのハード固有の情報はメモリマップに書いて
あるんだよ。今回の場合はTru64 UNIXのヘッダファイルを参考にしたんだ。
フレームバッファのアドレスはPCIコンフィギュレーション空間を読めば
分かるんだよ。
ハードがメモリマップと違った動きをすると、
クリスマスに一人PS2キーボードを抜き差しするような事態に陥るんだ。
OpenBSD/sgi install battle
http://togetter.com/li/599343
「NetBSD移植 いまむかし」
http://www.ceres.dti.ne.jp/tsutsui/osc12eh/img00.html
も参考にしてね。
<
29. /src/sys/uvm/uvm_device.c
uvm_device構造体を初期化します
その際uvm_deviceops構造体を設定する事でuvm_objectからの操作を抽象化します
218 /* Note: both calls may allocate memory and sleep. */
219 udv = kmem_alloc(sizeof(*udv), KM_SLEEP);
220 uvm_obj_init(&udv->u_obj, &uvm_deviceops, true, 1);
221
222 mutex_enter(&udv_lock);
223
251 udv->u_flags = 0;
252 udv->u_device = device;
253 LIST_INSERT_HEAD(&udv_list, udv, u_list);
254 mutex_exit(&udv_lock);
255 return(&udv->u_obj);
フレームバッファの領域が有効だったら
74 const struct uvm_pagerops uvm_deviceops = {
75 .pgo_init = udv_init,
76 .pgo_reference = udv_reference,
77 .pgo_detach = udv_detach,
78 .pgo_fault = udv_fault,
79 };
35. 仮想アドレスと物理アドレスを紐づける
418 mdpgno = cdev_mmap(device, curr_offset, access_type);
419 if (mdpgno == -1) {
420 retval = EIO;
421 break;
422 }
423 paddr = pmap_phys_address(mdpgno);
424 mmapflags = pmap_mmap_flags(mdpgno);
425 mapprot = ufi->entry->protection;
426 UVMHIST_LOG(maphist,
427 " MAPPING: device: pm=0x%x, va=0x%x, pa=0x%lx, at=%d",
428 ufi->orig_map->pmap, curr_va, paddr, mapprot);
429 if (pmap_enter(ufi->orig_map->pmap, curr_va, paddr, mapprot,
430 PMAP_CANFAIL | mapprot | mmapflags) != 0) {
37. フレームバッファのアドレス(PA)からPTEを作成
1793 validate:
1794 /*
1795 * Build the new PTE.
1796 */
1797 npte = ((pa >> PGSHIFT) << PG_SHIFT) | pte_prot(pmap, prot) | PG_V;
アクセス権の設定
211 #define ALPHA_PTE_VALID 0x0001
212
213 #define ALPHA_PTE_FAULT_ON_READ 0x0002
214 #define ALPHA_PTE_FAULT_ON_WRITE 0x0004
215 #define ALPHA_PTE_FAULT_ON_EXECUTE 0x0008
216
217 #define ALPHA_PTE_ASM 0x0010 /* addr. space match */
218 #define ALPHA_PTE_GRANULARITY 0x0060 /* granularity hint */
219
220 #define ALPHA_PTE_PROT 0xff00
221 #define ALPHA_PTE_KR 0x0100
222 #define ALPHA_PTE_UR 0x0200
223 #define ALPHA_PTE_KW 0x1000
224 #define ALPHA_PTE_UW 0x2000
src/sys/arch/alpha/include/alpha_cpu.h
39. ALPHA_PHYS_TO_K0SEG is 何
src/sys/arch/alpha/pci/pci_bwx_bus_mem_chipdep.c(間違ったパッチ)
src/sys/arch/alpha/include/alpha_cpu.h494 paddr_t
495 __C(CHIP,_mem_mmap)(
496 void *v,
497 bus_addr_t addr,
498 off_t off,
499 int prot,
500 int flags)
501 {
502 bus_addr_t memaddr;
503
504 memaddr = CHIP_MEM_SYS_START(v) + addr + off;
505 return (alpha_btop(ALPHA_PHYS_TO_K0SEG(memaddr)));
506 }
203 #define ALPHA_K0SEG_BASE 0xfffffc0000000000 /* direct-mapped */
204 #define ALPHA_K0SEG_END 0xfffffdffffffffff
205 #define ALPHA_K1SEG_BASE 0xfffffe0000000000 /* virtual */
206 #define ALPHA_K1SEG_END 0xffffffffffffffff
207
208 #define ALPHA_K0SEG_TO_PHYS(x) ((x) & ~ALPHA_K0SEG_BASE)
209 #define ALPHA_PHYS_TO_K0SEG(x) ((x) | ALPHA_K0SEG_BASE)
( ˘⊖˘)。o(結局ksegって何なのかな?)
41. ksegの正しい使い方
#define ALPHA_K0SEG_BASE 0xfffffc0000000000
#define ALPHA_PHYS_TO_K0SEG(x) ((x) | ALPHA_K0SEG_BASE)
#define S_PAGE(phys) ((void *)ALPHA_PHYS_TO_K0SEG(phys))
pcireg_t *datap;
u_long z;
datap = S_PAGE(0x10440000000UL);
for(z = 0; z < 24967295; z++){
*(datap + z) = 0xffffff00;
}
例えば、radeonfb.cに以下のような
コードを書けば画面に色を書き込める
kseg経由でマップされたフレームバッファの物理アドレスに
カーネル内からダイレクトに黄色を書き込んでいます
(TLBミスを引き起こしたり、page tableに書き込んだりする必要が無い)
42. 44bit 物理アドレス空間
Alpha 21264は44bit 物理アドレス空間をサポート
フレームバッファは
* 41-bit Physical I/O Space Per PCI Node (8GBytes per) -- 43-bit VA mode
* ----------------------------------------------------
* 104 0000 0000 - 105 FFFF FFFF - I/O Space for PCI2
の範囲にあると思われる…(0x104.4000.0000?)
ただし、I/O空間へのアクセスのため43bit目に1を立てる必要が有る。
そこで正解パッチのように、
P_PCI_MEM 0x800.0000.0000をORする必要があった。
1001.0000.0100.0100.0000.0000.0000.0000.0000.0000.0000(44bit)
よって物理アドレス0x904.4000.0000がフレームバッファの物理アドレスになる!
ハズ…
45. 参考文献 & お世話になった方
UVMについて
The UVM Virtual Memory System - Usenix (英語の論文)
BSD magazine 13号 特集 NetBSDの設計と実装(論文を翻訳したもの)
OSの一般的な知識
BSDカーネルの設計と実装 -FreeBSD詳解-
Solarisインターナル ―カーネル構造のすべて(amazonで中古がめちゃ安くてビックり)
Alphaについて
Alpha Architecture Reference Manual Fourth Edition
Alpha 21264 Microprocessor Hardware Reference Manual
ページングについて
http://www.nminoru.jp/~nminoru/programming/arch/virtual_memory.html(仮想メモリ方式の分類)
お世話になった方&ファボって元気づけてくれた方
Izumi Tsutsui @tsutsuii
以下古いフォロワーさんから
Jun Ebihara @ebijun、hashimoto kenichi @h_kenken、oshimaya @oshimyja、Kenji Aoyama @ao_kenji
NONAKA Kimihiro @nonakap、Hiroshi Tokuda @tokudahiroshi、本尊ではないことが本件寄付の後に判明 @ioriveur
波打際のだよもんさん @daemon1995、まあぼ@cub @marbocub ※イカ先生 @impreza_gf8にはAlpha Station XP1000を譲っていただきました!
mltermという神アプリを作成された
arakiken @arakiken
OpenBSD/Sgiでお世話になったので、この場を借りて改めてお礼申し上げます!
しゅううさんにゃんぱすー @syuu1228