-
Notifications
You must be signed in to change notification settings - Fork 102
/
devmgr.txt
288 lines (226 loc) · 10.7 KB
/
devmgr.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
devmgr_config.txt:
正常:
devhost.asan.strict=false
devmgr.require-system=true
zircon.system.pkgfs.cmd=bin/pkgsvr+ce05542b18c4bd7034ca0a7ac6cb11c35168fea4c023d8e58f2ea0a40ecd64e9
zircon.system.pkgfs.file.bin/pkgsvr=d169a9cc0ec4148ed01dce26fc1c1031e04209f3fa4c2839e42b06903c730fbe
zircon.system.pkgfs.file.lib/ld.so.1=43eee99e8bd1432596496ef8873bac37044acd4085044639d87e4160d6c1c534
zircon.system.pkgfs.file.lib/libfdio.so=c509bb1487709386a83929ecd9e0f7afe854a17851236ab21aea4fa41c8f7e72
zedboot:
netsvc.netboot=true
virtcon.font=18x32
进程和通道handle的关系
devmgr:appmgr_req_cli <--> appmgr:appmgr_req_srv
devmgr:svchost_outgoing <--> svchost:dir_request
devmgr:fs_root <--> fshost:handles[0]
svchost:appmgr_svc <--> appmgr:appmgr_svc_req
devmgr.c: main()
先把从userboot传过来的loader service handle关掉
devmgr_io_init();
zx_log_create(0, &h)
logger = fdio_logger_create(h)
fdio_bind_to_fd(logger, 1, 0);
fdio_fdtab[fd] = io;
root_resource_handle = zx_get_startup_handle(PA_HND(PA_RESOURCE, 0));
这个要追溯到zircon/kernel/lib/userboot/userboot.cpp:
get_resource_handle(&handles[BOOTSTRAP_RESOURCE_ROOT]);
ResourceDispatcher::Create(&root, &rights, ZX_RSRC_KIND_ROOT, 0, 0);
这个root resource handle好像只是在关机时校验一下
devfs_init(root_job_handler)
zx_channel_create(0, &h0, &h1)
iostate_create(&root_devnode, h0)
devfs_root = h1;
devfs_root是channel的一端,可以向另一端dc_rio_handler事件处理循环发消息
zx_channel_create(0, &appmgr_req_cli, &appmgr_req_srv);
建立跟appmgr的通信通道, appmgr_req_srv会发送给appmgr
zx_event_create(0, &fshost_event);
fs_host准备好的事件
devmgr_svc_init()
svchost_start()
zx_channel_create(0, &dir_request, &svchost_outgoing)
zx_channel_create(0, &appmgr_svc_req, &appmgr_svc)
fdio_service_connect_at(appmgr_req_cli, "svc", appmgr_svc_req)
zxrio_connect(dir, h, ZXRIO_OPEN, ZX_FS_RIGHT_READABLE |
ZX_FS_RIGHT_WRITABLE, 0755, path)
把appmgr_svc_req发送给appmgr_req_cli的另一端appmgr_req_srv
appmgr_svc后面会发给svchost,相当于建立了appmgr和svchost之间的通信通道
launchpad_add_handle(lp, dir_request, PA_DIRECTORY_REQUEST);
svchost_outgoing通向svchost进程,后面fs_clone("svc")会用到
launchpad_add_handle(lp, appmgr_svc, PA_HND(PA_USER0, 0));
launchpad_go(lp, &process, &errmsg)
启动svchost进程
devmgr_vfs_init()
fshost_start()
zx_channel_create(0, &fs_root, &handles[0])
fs_root通道通往fshost的/
handles[n] = devfs_root_clone()
fdio_service_clone(devfs_root)
zx_channel_create(0, &cli, &srv)
zxrio_connect(svc, srv, ZXRIO_CLONE, ZX_FS_RIGHT_READABLE |
ZX_FS_RIGHT_WRITABLE, 0755, "")
把srv发送给devfs_root的另一端,也就是dc_rio_handler事件处理循环
对ZXRIO_CLONE的处理是devfs_open(h) 设备节点是root
把这个handle又挂在了dc_rio_handler事件处理循环上,挂在dc_port上
return cli
也就是建立了fshost与devfs的通信通道
handles[n] = fs_clone("svc")
zx_channel_create(0, &h0, &h1)
fs = svchost_outgoing
fdio_open_at(fs, path, flags, h1)
zxrio_connect(dir, h, ZXRIO_OPEN, flags, 0755, path)
把h1发送给svchost
return h0
建立fshost与svchost的通信通道
zx_channel_create(0, &ldsvc, &handles[n])
让ldsvc通往fshost,看来fshost要承担elf加载的任务?
zx_handle_duplicate(bootfs.vmo, ZX_RIGHT_SAME_RIGHTS, &handles[n])
让fshost能够访问boot fs的vmo
zx_handle_duplicate(fshost_event, ZX_RIGHT_SAME_RIGHTS, &handles[n])
让fshost完事之后通过fshost_event通知devmgr
handles[n] = zx_get_startup_handle(PA_HND(PA_VMO_BOOTDATA, m))
让fshost能访问bootdata. bootdata包含压缩的boot fs
把vdso vmo给fshost
devmgr_launch(svcs_job_handle, "fshost", argc, argv,
envp, -1, handles, types, n, NULL, 0);
启动fshost
fdio_ns_create(&ns)
fdio_ns_bind(ns, "/system", fs_clone("system"))
zx_channel_create(0, &h0, &h1)
fdio_open_at(fs, path, flags, h1)
fs通向fshost
zxrio_connect(dir, h, ZXRIO_OPEN, flags, 0755, path)
return h0
thrd_create_with_name(&t, service_starter, NULL, "service-starter")
service_starter(void* arg)
thrd_create_with_name(&t, fuchsia_starter, NULL, "fuchsia-starter")
fuchsia_starter(void* arg)
zx_object_wait_one(fshost_event, FSHOST_SIGNAL_READY, deadline, NULL)
zx_object_signal(fshost_event, FSHOST_SIGNAL_READY, 0)
再signal一次,目前没有人等待这个信号
把appmgr_req_srv发送给appmgr,建立devmgr和appmgr之间的通道
devmgr_launch(fuchsia_job_handle, "appmgr", countof(argv_appmgr),
argv_appmgr, NULL, -1, appmgr_hnds, appmgr_ids,
appmgr_hnd_count, NULL, FS_FOR_APPMGR)
会把FSTAB里除了FS_HUB(因为是appmgr自己)对应的fs_clone出来的handle都给appmgr发过去
包括devfs, fshost, svchost
\end{verbatim}
有一个中心服务devmgr coordinator. 它会扫描驱动,为每个驱动launch一个devhost进程。launch完了之后会发送
create device, bind driver这2个rpc给devhost. devhost会处理这2个rpc. 对于root device,不会处理,
因为libname=""
文档推荐在bind driver里调用add device。驱动本身是在devhost里运行的。devhost会rpc调用dev coordinator
的add device方法。这个方法主要是创建dc里对设备的代表,发布到devfs里。
寻找驱动的过程:
初始入口是arm64: platform, x86: acpi
dc进程:
\begin{verbatim}
coordinator()
find_loadable_drivers()
libname包含完整路径
di_read_driver_info(fd, libname, found_driver)
context ctx = {
.cookie = cookie,
.func = func,
};
for_each_note(&fd, di_pread,
ZIRCON_NOTE_NAME, ZIRCON_NOTE_DRIVER,
data, sizeof(data), callback, &ctx);
diread(obj, &eh, sizeof(eh), 0)
读elf header里的信息
找到elf里存的driver note信息
调用ctx->func(&dn->payload, binding, ctx->cookie)
也就是
found_driver()
dc_driver_added()
if dc_running then queue WORK_DRIVER_ADDED 实际上dc_running == false
list_add_tail(&list_drivers, &drv->node);
把driver加到链表里
process_work()
WORK_DRIVER_ADDED:
dc_handle_new_driver()
dc_bind_driver()
dc_attempt_bind()
dc_prepare_proxy()
dc_create_proxy() 为父设备创建一个代理设备
创建h0, h1
dc_new_devhost() proxy->devhost会与devhost进程有channel连接
dh_create_device() 向devhost进程发送DC_OP_CREATE_DEVICE消息,
创建新的channel. 一头设置给proxy dev,在dc里监听起来。
另一头作为handle[0]传给devhost(存放在devhost里proxy device里面,
作为其他设备的parent). 从而dc和dh里面的proxy device之间
建立了rpc通道。
h1作为handle[2]传过去,这个目前似乎只有pci_rpc_request用于
发布出去的rpcch,
跟别的关系不大。
dh_connect_proxy() 把h0作为DC_OP_CONNECT_PROXY传过去
dh_bind_driver() 向dh进程发送DC_OP_BIND_DRIVER消息。
DC_OP_ADD_DEVICE: 这个OP是由devhost需要添加child device的时候发起的
dc_add_device()
创建子device, 把发来的hrpc设置好。监听。
添加WORK_DEVICE_ADDED
WORK_DEVICE_ADDED:
dc_handle_new_device()
寻找匹配驱动
dc_attempt_bind()
dh进程:
DC_OP_CREATE_DEVICE:
dh_find_driver()
driver->ops->create(hin[2])
device_add()
device_add_from_driver()
devhost_device_create()
devhost_device_add()
proxy device case: 把rpc记录到dev里面,返回
监听hin[0], 至此proxydev和 devhost之间建立了rpc通道。
DC_OP_CONNECT_PROXY:
proxy_ios_create() 在devhost进程里监听传来的h0
DC_OP_BIND_DRIVER:
调用driver的bind()
driver's bind op:
device_add()
device_add_from_driver()
devhost_device_add()
devhost_add()
创建hrpc, hsend
给dc发送DC_OP_ADD_DEVICE消息,把hsend发回去,监听hrpc.
coordinator()
首先创建sys, test二个devhost进程。
在遍历驱动的时候,创建root, misc(console)二个devhost 进程
dc prepare proxy引起的devhost的驱动的create方法
第一次调用add device只会把hrpc加入
devhost端的proxy设备里。之后的驱动的create方法中的add device才会
引起dc端的消息。
在dc里,设备都是创建在proxy device下面的。
dmctl可以动态添加driver.
例子:
dc: create device "platform"
dh: add device platform
dc: 匹配到qemu-bus 驱动,让dh那边加载这个驱动
dh: 调用了qemu-bus驱动,里面又有Add device, 回到dc
dc: 创建pci, pl031设备
qemu_bus_bind()
device_get_protocol(parent)
dev->ops->get_protocol(dev->ctx == dev)
platform_bus_get_protocol()
protocol->ctx= bus = ctx 就是dev
\end{verbatim}
devmgr最后会创建一个新的线程启动\verb|service_starter()|
\begin{verbatim}
service_start()
thrd_create_with_name(&t, analyzer_starter, NULL, "analyzer-starter")
如果没有禁止netsvc, devmgr_launch("/boot/bin/netsvc")
如果没有禁止virtcon, devmgr_launch("/boot/bin/virtual-console")
至此,zircon layer里的活应该干完了。
thrd_create_with_name(&t, fuchsia_starter, NULL, "fuchsia-starter")
\end{verbatim}
\begin{verbatim}
fuchsia_start()
wait for fshost to start
load_system_drivers()
find_loadable_drivers("/system/driver");
find_loadable_drivers("/system/lib/driver");
devmgr_launch(fuchsia_job_handle, "appmgr", countof(argv_appmgr),
argv_appmgr, NULL, -1, appmgr_hnds, appmgr_ids,
appmgr_hnd_count, NULL, FS_FOR_APPMGR);
\end{verbatim}
应用打开设备:发送一个channel handle给devfs, devmgr将handle转发给devhost,
devhost将handle挂在自己的port上。