init.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2011 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/xen.h>
  19. #include <grub/term.h>
  20. #include <grub/misc.h>
  21. #include <grub/env.h>
  22. #include <grub/mm.h>
  23. #include <grub/kernel.h>
  24. #include <grub/offsets.h>
  25. #include <grub/memory.h>
  26. #include <grub/i386/tsc.h>
  27. #include <grub/term.h>
  28. #include <grub/loader.h>
  29. grub_addr_t grub_modbase;
  30. struct start_info *grub_xen_start_page_addr;
  31. volatile struct xencons_interface *grub_xen_xcons;
  32. volatile struct shared_info *grub_xen_shared_info;
  33. volatile struct xenstore_domain_interface *grub_xen_xenstore;
  34. volatile grant_entry_v1_t *grub_xen_grant_table;
  35. static const grub_size_t total_grants =
  36. GRUB_XEN_PAGE_SIZE / sizeof (grub_xen_grant_table[0]);
  37. grub_size_t grub_xen_n_allocated_shared_pages;
  38. static grub_xen_mfn_t
  39. grub_xen_ptr2mfn (void *ptr)
  40. {
  41. #ifdef GRUB_MACHINE_XEN
  42. grub_xen_mfn_t *mfn_list =
  43. (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list;
  44. return mfn_list[(grub_addr_t) ptr >> GRUB_XEN_LOG_PAGE_SIZE];
  45. #else
  46. return (grub_addr_t) ptr >> GRUB_XEN_LOG_PAGE_SIZE;
  47. #endif
  48. }
  49. void *
  50. grub_xen_alloc_shared_page (domid_t dom, grub_xen_grant_t * grnum)
  51. {
  52. void *ret;
  53. grub_xen_mfn_t mfn;
  54. volatile grant_entry_v1_t *entry;
  55. /* Avoid 0. */
  56. for (entry = grub_xen_grant_table;
  57. entry < grub_xen_grant_table + total_grants; entry++)
  58. if (!entry->flags)
  59. break;
  60. if (entry == grub_xen_grant_table + total_grants)
  61. {
  62. grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of grant entries");
  63. return NULL;
  64. }
  65. ret = grub_memalign (GRUB_XEN_PAGE_SIZE, GRUB_XEN_PAGE_SIZE);
  66. if (!ret)
  67. return NULL;
  68. mfn = grub_xen_ptr2mfn (ret);
  69. entry->frame = mfn;
  70. entry->domid = dom;
  71. mb ();
  72. entry->flags = GTF_permit_access;
  73. mb ();
  74. *grnum = entry - grub_xen_grant_table;
  75. grub_xen_n_allocated_shared_pages++;
  76. return ret;
  77. }
  78. void
  79. grub_xen_free_shared_page (void *ptr)
  80. {
  81. grub_xen_mfn_t mfn;
  82. volatile grant_entry_v1_t *entry;
  83. mfn = grub_xen_ptr2mfn (ptr);
  84. for (entry = grub_xen_grant_table + 1;
  85. entry < grub_xen_grant_table + total_grants; entry++)
  86. if (entry->flags && entry->frame == mfn)
  87. {
  88. mb ();
  89. entry->flags = 0;
  90. mb ();
  91. entry->frame = 0;
  92. mb ();
  93. }
  94. grub_xen_n_allocated_shared_pages--;
  95. }
  96. void
  97. grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
  98. char **path __attribute__ ((unused)))
  99. {
  100. }
  101. void
  102. grub_xen_store_send (const void *buf_, grub_size_t len)
  103. {
  104. const grub_uint8_t *buf = buf_;
  105. struct evtchn_send send;
  106. int event_sent = 0;
  107. while (len)
  108. {
  109. grub_size_t avail, inbuf;
  110. grub_size_t prod, cons;
  111. mb ();
  112. prod = grub_xen_xenstore->req_prod;
  113. cons = grub_xen_xenstore->req_cons;
  114. if (prod >= cons + sizeof (grub_xen_xenstore->req))
  115. {
  116. if (!event_sent)
  117. {
  118. send.port = grub_xen_start_page_addr->store_evtchn;
  119. grub_xen_event_channel_op (EVTCHNOP_send, &send);
  120. event_sent = 1;
  121. }
  122. grub_xen_sched_op (SCHEDOP_yield, 0);
  123. continue;
  124. }
  125. event_sent = 0;
  126. avail = cons + sizeof (grub_xen_xenstore->req) - prod;
  127. inbuf = (~prod & (sizeof (grub_xen_xenstore->req) - 1)) + 1;
  128. if (avail > inbuf)
  129. avail = inbuf;
  130. if (avail > len)
  131. avail = len;
  132. grub_memcpy ((void *) &grub_xen_xenstore->req[prod & (sizeof (grub_xen_xenstore->req) - 1)],
  133. buf, avail);
  134. buf += avail;
  135. len -= avail;
  136. mb ();
  137. grub_xen_xenstore->req_prod += avail;
  138. mb ();
  139. if (!event_sent)
  140. {
  141. send.port = grub_xen_start_page_addr->store_evtchn;
  142. grub_xen_event_channel_op (EVTCHNOP_send, &send);
  143. event_sent = 1;
  144. }
  145. grub_xen_sched_op (SCHEDOP_yield, 0);
  146. }
  147. }
  148. void
  149. grub_xen_store_recv (void *buf_, grub_size_t len)
  150. {
  151. grub_uint8_t *buf = buf_;
  152. struct evtchn_send send;
  153. int event_sent = 0;
  154. while (len)
  155. {
  156. grub_size_t avail, inbuf;
  157. grub_size_t prod, cons;
  158. mb ();
  159. prod = grub_xen_xenstore->rsp_prod;
  160. cons = grub_xen_xenstore->rsp_cons;
  161. if (prod <= cons)
  162. {
  163. if (!event_sent)
  164. {
  165. send.port = grub_xen_start_page_addr->store_evtchn;
  166. grub_xen_event_channel_op (EVTCHNOP_send, &send);
  167. event_sent = 1;
  168. }
  169. grub_xen_sched_op (SCHEDOP_yield, 0);
  170. continue;
  171. }
  172. event_sent = 0;
  173. avail = prod - cons;
  174. inbuf = (~cons & (sizeof (grub_xen_xenstore->req) - 1)) + 1;
  175. if (avail > inbuf)
  176. avail = inbuf;
  177. if (avail > len)
  178. avail = len;
  179. grub_memcpy (buf,
  180. (void *) &grub_xen_xenstore->rsp[cons & (sizeof (grub_xen_xenstore->rsp) - 1)],
  181. avail);
  182. buf += avail;
  183. len -= avail;
  184. mb ();
  185. grub_xen_xenstore->rsp_cons += avail;
  186. mb ();
  187. if (!event_sent)
  188. {
  189. send.port = grub_xen_start_page_addr->store_evtchn;
  190. grub_xen_event_channel_op(EVTCHNOP_send, &send);
  191. event_sent = 1;
  192. }
  193. grub_xen_sched_op(SCHEDOP_yield, 0);
  194. }
  195. }
  196. void *
  197. grub_xenstore_get_file (const char *dir, grub_size_t *len)
  198. {
  199. struct xsd_sockmsg msg;
  200. char *buf;
  201. grub_size_t dirlen = grub_strlen (dir) + 1;
  202. if (len)
  203. *len = 0;
  204. grub_memset (&msg, 0, sizeof (msg));
  205. msg.type = XS_READ;
  206. msg.len = dirlen;
  207. grub_xen_store_send (&msg, sizeof (msg));
  208. grub_xen_store_send (dir, dirlen);
  209. grub_xen_store_recv (&msg, sizeof (msg));
  210. buf = grub_malloc (msg.len + 1);
  211. if (!buf)
  212. return NULL;
  213. grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len);
  214. grub_xen_store_recv (buf, msg.len);
  215. buf[msg.len] = '\0';
  216. if (msg.type == XS_ERROR)
  217. {
  218. grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", dir, buf);
  219. grub_free (buf);
  220. return NULL;
  221. }
  222. if (len)
  223. *len = msg.len;
  224. return buf;
  225. }
  226. grub_err_t
  227. grub_xenstore_write_file (const char *dir, const void *buf, grub_size_t len)
  228. {
  229. struct xsd_sockmsg msg;
  230. grub_size_t dirlen = grub_strlen (dir) + 1;
  231. char *resp;
  232. grub_memset (&msg, 0, sizeof (msg));
  233. msg.type = XS_WRITE;
  234. msg.len = dirlen + len;
  235. grub_xen_store_send (&msg, sizeof (msg));
  236. grub_xen_store_send (dir, dirlen);
  237. grub_xen_store_send (buf, len);
  238. grub_xen_store_recv (&msg, sizeof (msg));
  239. resp = grub_malloc (msg.len + 1);
  240. if (!resp)
  241. return grub_errno;
  242. grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len);
  243. grub_xen_store_recv (resp, msg.len);
  244. resp[msg.len] = '\0';
  245. if (msg.type == XS_ERROR)
  246. {
  247. grub_dprintf ("xen", "error = %s\n", resp);
  248. grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s",
  249. dir, resp);
  250. grub_free (resp);
  251. return grub_errno;
  252. }
  253. grub_free (resp);
  254. return GRUB_ERR_NONE;
  255. }
  256. /* FIXME: error handling. */
  257. grub_err_t
  258. grub_xenstore_dir (const char *dir,
  259. int (*hook) (const char *dir, void *hook_data),
  260. void *hook_data)
  261. {
  262. struct xsd_sockmsg msg;
  263. char *buf;
  264. char *ptr;
  265. grub_size_t dirlen = grub_strlen (dir) + 1;
  266. grub_memset (&msg, 0, sizeof (msg));
  267. msg.type = XS_DIRECTORY;
  268. msg.len = dirlen;
  269. grub_xen_store_send (&msg, sizeof (msg));
  270. grub_xen_store_send (dir, dirlen);
  271. grub_xen_store_recv (&msg, sizeof (msg));
  272. buf = grub_malloc (msg.len + 1);
  273. if (!buf)
  274. return grub_errno;
  275. grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len);
  276. grub_xen_store_recv (buf, msg.len);
  277. buf[msg.len] = '\0';
  278. if (msg.type == XS_ERROR)
  279. {
  280. grub_err_t err;
  281. err = grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s",
  282. dir, buf);
  283. grub_free (buf);
  284. return err;
  285. }
  286. for (ptr = buf; ptr < buf + msg.len; ptr += grub_strlen (ptr) + 1)
  287. if (hook (ptr, hook_data))
  288. break;
  289. grub_free (buf);
  290. return grub_errno;
  291. }
  292. unsigned long gntframe = 0;
  293. static void
  294. grub_xen_setup_gnttab (void)
  295. {
  296. struct gnttab_set_version gnttab_setver;
  297. struct gnttab_setup_table gnttab_setup;
  298. grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver));
  299. gnttab_setver.version = 1;
  300. grub_xen_grant_table_op (GNTTABOP_set_version, &gnttab_setver, 1);
  301. grub_memset (&gnttab_setup, 0, sizeof (gnttab_setup));
  302. gnttab_setup.dom = DOMID_SELF;
  303. gnttab_setup.nr_frames = 1;
  304. gnttab_setup.frame_list.p = &gntframe;
  305. grub_xen_grant_table_op (GNTTABOP_setup_table, &gnttab_setup, 1);
  306. }
  307. #ifdef GRUB_MACHINE_XEN
  308. static grub_uint8_t window[GRUB_XEN_PAGE_SIZE]
  309. __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE)));
  310. #ifdef __x86_64__
  311. #define NUMBER_OF_LEVELS 4
  312. #else
  313. #define NUMBER_OF_LEVELS 3
  314. #endif
  315. #define LOG_POINTERS_PER_PAGE 9
  316. #define POINTERS_PER_PAGE (1 << LOG_POINTERS_PER_PAGE)
  317. #define MAX_N_UNUSABLE_PAGES 4
  318. static int
  319. grub_xen_is_page_usable (grub_xen_mfn_t mfn)
  320. {
  321. if (mfn == grub_xen_start_page_addr->console.domU.mfn)
  322. return 0;
  323. if (mfn == grub_xen_start_page_addr->shared_info)
  324. return 0;
  325. if (mfn == grub_xen_start_page_addr->store_mfn)
  326. return 0;
  327. if (mfn == gntframe)
  328. return 0;
  329. return 1;
  330. }
  331. static grub_uint64_t
  332. page2offset (grub_uint64_t page)
  333. {
  334. return page << 12;
  335. }
  336. #if defined (__x86_64__) && defined (__code_model_large__)
  337. #define MAX_TOTAL_PAGES (1LL << (64 - 12))
  338. #elif defined (__x86_64__)
  339. #define MAX_TOTAL_PAGES (1LL << (31 - 12))
  340. #else
  341. #define MAX_TOTAL_PAGES (1LL << (32 - 12))
  342. #endif
  343. static void
  344. map_all_pages (void)
  345. {
  346. grub_uint64_t total_pages = grub_xen_start_page_addr->nr_pages;
  347. grub_uint64_t i, j;
  348. grub_xen_mfn_t *mfn_list =
  349. (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list;
  350. grub_uint64_t *pg = (grub_uint64_t *) window;
  351. grub_uint64_t oldpgstart, oldpgend;
  352. grub_size_t n_unusable_pages = 0;
  353. struct mmu_update m2p_updates[2 * MAX_N_UNUSABLE_PAGES];
  354. if (total_pages > MAX_TOTAL_PAGES - 4)
  355. total_pages = MAX_TOTAL_PAGES - 4;
  356. for (j = 0; j < total_pages - n_unusable_pages; j++)
  357. while (!grub_xen_is_page_usable (mfn_list[j]))
  358. {
  359. grub_xen_mfn_t t;
  360. if (n_unusable_pages >= MAX_N_UNUSABLE_PAGES)
  361. {
  362. struct sched_shutdown arg;
  363. arg.reason = SHUTDOWN_crash;
  364. grub_xen_sched_op (SCHEDOP_shutdown, &arg);
  365. while (1);
  366. }
  367. t = mfn_list[j];
  368. mfn_list[j] = mfn_list[total_pages - n_unusable_pages - 1];
  369. mfn_list[total_pages - n_unusable_pages - 1] = t;
  370. m2p_updates[2 * n_unusable_pages].ptr
  371. = page2offset (mfn_list[j]) | MMU_MACHPHYS_UPDATE;
  372. m2p_updates[2 * n_unusable_pages].val = j;
  373. m2p_updates[2 * n_unusable_pages + 1].ptr
  374. = page2offset (mfn_list[total_pages - n_unusable_pages - 1])
  375. | MMU_MACHPHYS_UPDATE;
  376. m2p_updates[2 * n_unusable_pages + 1].val = total_pages
  377. - n_unusable_pages - 1;
  378. n_unusable_pages++;
  379. }
  380. grub_xen_mmu_update (m2p_updates, 2 * n_unusable_pages, NULL, DOMID_SELF);
  381. total_pages += 4;
  382. grub_uint64_t lx[NUMBER_OF_LEVELS], nlx;
  383. grub_uint64_t paging_start = total_pages - 4 - n_unusable_pages, curpage;
  384. for (nlx = total_pages, i = 0; i < (unsigned) NUMBER_OF_LEVELS; i++)
  385. {
  386. nlx = (nlx + POINTERS_PER_PAGE - 1) >> LOG_POINTERS_PER_PAGE;
  387. /* PAE wants all 4 root directories present. */
  388. #ifdef __i386__
  389. if (i == 1)
  390. nlx = 4;
  391. #endif
  392. lx[i] = nlx;
  393. paging_start -= nlx;
  394. }
  395. oldpgstart = grub_xen_start_page_addr->pt_base >> 12;
  396. oldpgend = oldpgstart + grub_xen_start_page_addr->nr_pt_frames;
  397. curpage = paging_start;
  398. int l;
  399. for (l = NUMBER_OF_LEVELS - 1; l >= 1; l--)
  400. {
  401. for (i = 0; i < lx[l]; i++)
  402. {
  403. grub_xen_update_va_mapping (&window,
  404. page2offset (mfn_list[curpage + i]) | 7,
  405. UVMF_INVLPG);
  406. grub_memset (&window, 0, sizeof (window));
  407. for (j = i * POINTERS_PER_PAGE;
  408. j < (i + 1) * POINTERS_PER_PAGE && j < lx[l - 1]; j++)
  409. pg[j - i * POINTERS_PER_PAGE] =
  410. page2offset (mfn_list[curpage + lx[l] + j])
  411. #ifdef __x86_64__
  412. | 4
  413. #endif
  414. | 3;
  415. }
  416. curpage += lx[l];
  417. }
  418. for (i = 0; i < lx[0]; i++)
  419. {
  420. grub_xen_update_va_mapping (&window,
  421. page2offset (mfn_list[curpage + i]) | 7,
  422. UVMF_INVLPG);
  423. grub_memset (&window, 0, sizeof (window));
  424. for (j = i * POINTERS_PER_PAGE;
  425. j < (i + 1) * POINTERS_PER_PAGE && j < total_pages; j++)
  426. if (j < paging_start && !(j >= oldpgstart && j < oldpgend))
  427. pg[j - i * POINTERS_PER_PAGE] = page2offset (mfn_list[j]) | 0x7;
  428. else if (j < grub_xen_start_page_addr->nr_pages)
  429. pg[j - i * POINTERS_PER_PAGE] = page2offset (mfn_list[j]) | 5;
  430. else if (j == grub_xen_start_page_addr->nr_pages)
  431. {
  432. pg[j - i * POINTERS_PER_PAGE] =
  433. page2offset (grub_xen_start_page_addr->console.domU.mfn) | 7;
  434. grub_xen_xcons = (void *) (grub_addr_t) page2offset (j);
  435. }
  436. else if (j == grub_xen_start_page_addr->nr_pages + 1)
  437. {
  438. pg[j - i * POINTERS_PER_PAGE] =
  439. grub_xen_start_page_addr->shared_info | 7;
  440. grub_xen_shared_info = (void *) (grub_addr_t) page2offset (j);
  441. }
  442. else if (j == grub_xen_start_page_addr->nr_pages + 2)
  443. {
  444. pg[j - i * POINTERS_PER_PAGE] =
  445. page2offset (grub_xen_start_page_addr->store_mfn) | 7;
  446. grub_xen_xenstore = (void *) (grub_addr_t) page2offset (j);
  447. }
  448. else if (j == grub_xen_start_page_addr->nr_pages + 3)
  449. {
  450. pg[j - i * POINTERS_PER_PAGE] = page2offset (gntframe) | 7;
  451. grub_xen_grant_table = (void *) (grub_addr_t) page2offset (j);
  452. }
  453. }
  454. grub_xen_update_va_mapping (&window, 0, UVMF_INVLPG);
  455. mmuext_op_t op[3];
  456. op[0].cmd = MMUEXT_PIN_L1_TABLE + (NUMBER_OF_LEVELS - 1);
  457. op[0].arg1.mfn = mfn_list[paging_start];
  458. op[1].cmd = MMUEXT_NEW_BASEPTR;
  459. op[1].arg1.mfn = mfn_list[paging_start];
  460. op[2].cmd = MMUEXT_UNPIN_TABLE;
  461. op[2].arg1.mfn = mfn_list[oldpgstart];
  462. grub_xen_mmuext_op (op, 3, NULL, DOMID_SELF);
  463. for (i = oldpgstart; i < oldpgend; i++)
  464. grub_xen_update_va_mapping ((void *) (grub_addr_t) page2offset (i),
  465. page2offset (mfn_list[i]) | 7, UVMF_INVLPG);
  466. void *new_start_page, *new_mfn_list;
  467. new_start_page = (void *) (grub_addr_t) page2offset (paging_start - 1);
  468. grub_memcpy (new_start_page, grub_xen_start_page_addr, 4096);
  469. grub_xen_start_page_addr = new_start_page;
  470. new_mfn_list = (void *) (grub_addr_t)
  471. page2offset (paging_start - 1
  472. - ((grub_xen_start_page_addr->nr_pages
  473. * sizeof (grub_uint64_t) + 4095) / 4096));
  474. grub_memcpy (new_mfn_list, mfn_list, grub_xen_start_page_addr->nr_pages
  475. * sizeof (grub_uint64_t));
  476. grub_xen_start_page_addr->pt_base = page2offset (paging_start);
  477. grub_xen_start_page_addr->mfn_list = (grub_addr_t) new_mfn_list;
  478. grub_addr_t heap_start = grub_modules_get_end ();
  479. grub_addr_t heap_end = (grub_addr_t) new_mfn_list;
  480. grub_mm_init_region ((void *) heap_start, heap_end - heap_start);
  481. }
  482. grub_err_t
  483. grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
  484. {
  485. grub_uint64_t total_pages = grub_xen_start_page_addr->nr_pages;
  486. grub_uint64_t usable_pages = grub_xen_start_page_addr->pt_base >> 12;
  487. if (hook (0, page2offset (usable_pages), GRUB_MEMORY_AVAILABLE, hook_data))
  488. return GRUB_ERR_NONE;
  489. hook (page2offset (usable_pages), page2offset (total_pages - usable_pages),
  490. GRUB_MEMORY_RESERVED, hook_data);
  491. return GRUB_ERR_NONE;
  492. }
  493. #endif
  494. extern char _end[];
  495. void
  496. grub_machine_init (void)
  497. {
  498. #ifdef GRUB_MACHINE_XEN
  499. #ifdef __i386__
  500. grub_xen_vm_assist (VMASST_CMD_enable, VMASST_TYPE_pae_extended_cr3);
  501. #endif
  502. #endif
  503. grub_modbase = ALIGN_UP ((grub_addr_t) _end
  504. + GRUB_KERNEL_MACHINE_MOD_GAP,
  505. GRUB_KERNEL_MACHINE_MOD_ALIGN);
  506. #ifdef GRUB_MACHINE_XEN_PVH
  507. grub_xen_setup_pvh ();
  508. #endif
  509. grub_xen_setup_gnttab ();
  510. #ifdef GRUB_MACHINE_XEN
  511. map_all_pages ();
  512. #endif
  513. grub_console_init ();
  514. grub_tsc_init ();
  515. grub_xendisk_init ();
  516. grub_boot_init ();
  517. }
  518. void
  519. grub_exit (void)
  520. {
  521. struct sched_shutdown arg;
  522. arg.reason = SHUTDOWN_poweroff;
  523. grub_xen_sched_op (SCHEDOP_shutdown, &arg);
  524. while (1);
  525. }
  526. void
  527. grub_machine_fini (int flags __attribute__ ((unused)))
  528. {
  529. grub_xendisk_fini ();
  530. grub_boot_fini ();
  531. }