1use crate::common::ChunkBuf;
7use crate::common::ImportFileRegion;
8use crate::common::ImportFileRegionError;
9use crate::common::ReadSeek;
10use crate::common::import_default_gdt;
11use crate::elf::load_static_elf;
12use crate::importer::Aarch64Register;
13use crate::importer::BootPageAcceptance;
14use crate::importer::GuestArch;
15use crate::importer::ImageLoad;
16use crate::importer::X86Register;
17use aarch64defs::Cpsr64;
18use aarch64defs::IntermPhysAddrSize;
19use aarch64defs::SctlrEl1;
20use aarch64defs::TranslationBaseEl1;
21use aarch64defs::TranslationControlEl1;
22use aarch64defs::TranslationGranule0;
23use aarch64defs::TranslationGranule1;
24use bitfield_struct::bitfield;
25use hvdef::HV_PAGE_SIZE;
26use loader_defs::linux as defs;
27use page_table::IdentityMapSize;
28use page_table::x64::IdentityMapBuilder;
29use page_table::x64::PAGE_TABLE_MAX_BYTES;
30use page_table::x64::PAGE_TABLE_MAX_COUNT;
31use page_table::x64::PageTable;
32use page_table::x64::align_up_to_large_page_size;
33use page_table::x64::align_up_to_page_size;
34use std::ffi::CString;
35use std::io::Read;
36use std::io::Seek;
37use thiserror::Error;
38use vm_topology::memory::MemoryLayout;
39use zerocopy::FromBytes;
40use zerocopy::FromZeros;
41use zerocopy::Immutable;
42use zerocopy::IntoBytes;
43use zerocopy::KnownLayout;
44
45pub fn build_zero_page(
48 mem_layout: &MemoryLayout,
49 acpi_base: u64,
50 acpi_len: usize,
51 cmdline_config: &CommandLineConfig<'_>,
52 initrd_base: u32,
53 initrd_size: u32,
54 bzimage_header: Option<&defs::setup_header>,
55) -> defs::boot_params {
56 const LOADER_TYPE_UNREGISTERED: u8 = 0xff;
60
61 let mut hdr = match bzimage_header {
64 Some(orig) => *orig,
65 None => defs::setup_header {
66 boot_flag: 0xaa55.into(),
67 header: 0x53726448.into(),
68 kernel_alignment: 0x100000.into(),
69 ..FromZeros::new_zeroed()
70 },
71 };
72
73 hdr.type_of_loader = LOADER_TYPE_UNREGISTERED;
75 hdr.cmd_line_ptr = cmdline_config.address.try_into().expect("must fit in u32");
76 hdr.cmdline_size = (cmdline_config.cmdline.as_bytes().len() as u64)
77 .try_into()
78 .expect("must fit in u32");
79 hdr.ramdisk_image = initrd_base.into();
80 hdr.ramdisk_size = initrd_size.into();
81
82 let mut p = defs::boot_params {
83 hdr,
84 ..FromZeros::new_zeroed()
85 };
86
87 let mut ram = mem_layout.ram().iter().cloned();
88 let range = ram.next().expect("at least one ram range");
89 assert_eq!(range.range.start(), 0);
90 assert!(range.range.end() >= 0x100000);
91 assert_eq!(acpi_base, 0xe0000);
93 p.e820_map[0] = defs::e820entry {
94 addr: 0.into(),
95 size: 0xe0000.into(),
96 typ: defs::E820_RAM.into(),
97 };
98 let aligned_acpi_len = (acpi_len + 0xfff) & !0xfff;
99 p.e820_map[1] = defs::e820entry {
100 addr: 0xe0000.into(),
101 size: (aligned_acpi_len as u64).into(),
102 typ: defs::E820_ACPI.into(),
103 };
104 p.e820_map[2] = defs::e820entry {
105 addr: (0xe0000 + aligned_acpi_len as u64).into(),
106 size: (range.range.end() - 0xe0000 - aligned_acpi_len as u64).into(),
107 typ: defs::E820_RAM.into(),
108 };
109 let mut n = 3;
110 for range in ram {
111 p.e820_map[n] = defs::e820entry {
112 addr: range.range.start().into(),
113 size: range.range.len().into(),
114 typ: defs::E820_RAM.into(),
115 };
116 n += 1;
117 }
118 p.e820_entries = n as u8;
119
120 p
121}
122
123#[derive(Debug, Error)]
124pub enum FlatLoaderError {
125 #[error("unsupported ELF File byte order")]
126 BigEndianElfOnLittle,
127 #[error("error reading kernel data structure")]
128 BadImageMagic,
129 #[error("big-endian kernel image is not supported")]
130 BigEndianKernelImage,
131 #[error("only images with 4K pages are supported")]
132 FourKibPageImageIsRequired,
133 #[error("the kernel is required to run in the low memory; not supported")]
134 LowMemoryKernel,
135 #[error("failed to read kernel image")]
136 ReadKernelImage,
137 #[error("failed to seek to file offset as pointed by the ELF program header")]
138 SeekKernelStart,
139 #[error("failed to seek to offset of kernel image")]
140 SeekKernelImage,
141}
142
143#[derive(Debug, Error)]
144pub enum Error {
145 #[error("elf loader error")]
146 ElfLoader(#[source] crate::elf::Error),
147 #[error("bzImage parse error")]
148 BzImage(#[source] crate::bzimage::Error),
149 #[error("flat loader error")]
150 FlatLoader(#[source] FlatLoaderError),
151 #[error("Address is not page aligned")]
152 UnalignedAddress(u64),
153 #[error("importer error")]
154 Importer(#[source] anyhow::Error),
155 #[error("failed to import initrd")]
156 ImportInitrd(#[source] ImportFileRegionError),
157 #[error("failed to import bzImage payload")]
158 ImportBzImage(#[source] ImportFileRegionError),
159 #[error("PageTableBuilder: {0}")]
160 PageTableBuilder(#[from] page_table::Error),
161}
162
163pub struct AcpiConfig<'a> {
164 pub rdsp_address: u64,
165 pub rdsp: &'a [u8],
166 pub tables_address: u64,
167 pub tables: &'a [u8],
168}
169
170pub struct ZeroPageConfig<'a> {
171 pub address: u64,
173 pub mem_layout: &'a MemoryLayout,
175 pub acpi_base_address: u64,
177 pub acpi_len: usize,
179}
180
181pub struct CommandLineConfig<'a> {
182 pub address: u64,
183 pub cmdline: &'a CString,
184}
185
186pub struct RegisterConfig {
187 pub gdt_address: u64,
188 pub page_table_address: u64,
189}
190
191#[derive(Debug, PartialEq, Eq, Clone, Copy)]
192pub enum InitrdAddressType {
193 AfterKernel,
195 Address(u64),
197}
198
199pub struct InitrdConfig<'a> {
200 pub initrd_address: InitrdAddressType,
201 pub initrd: &'a mut dyn ReadSeek,
202 pub size: u64,
203}
204
205#[derive(Debug, Default)]
207pub struct KernelInfo {
208 pub gpa: u64,
210 pub size: u64,
212 pub entrypoint: u64,
214}
215
216#[derive(Debug, Default)]
218pub struct InitrdInfo {
219 pub gpa: u64,
221 pub size: u64,
223}
224
225#[derive(Debug, Default)]
227pub struct LoadInfo {
228 pub kernel: KernelInfo,
230 pub initrd: Option<InitrdInfo>,
232 pub dtb: Option<std::ops::Range<u64>>,
234 pub bzimage_setup_header: Option<defs::setup_header>,
238}
239
240fn check_address_alignment(address: u64) -> Result<(), Error> {
242 if !address.is_multiple_of(HV_PAGE_SIZE) {
243 Err(Error::UnalignedAddress(address))
244 } else {
245 Ok(())
246 }
247}
248
249fn import_initrd<R: GuestArch>(
251 initrd: Option<InitrdConfig<'_>>,
252 next_addr: u64,
253 importer: &mut dyn ImageLoad<R>,
254) -> Result<Option<InitrdInfo>, Error> {
255 let initrd_info = match initrd {
256 Some(cfg) => {
257 let initrd_address = match cfg.initrd_address {
258 InitrdAddressType::AfterKernel => align_up_to_large_page_size(next_addr),
259 InitrdAddressType::Address(addr) => addr,
260 };
261
262 tracing::trace!(initrd_address, "loading initrd");
263 check_address_alignment(initrd_address)?;
264
265 ChunkBuf::new()
266 .import_file_region(
267 importer,
268 ImportFileRegion {
269 file: cfg.initrd,
270 file_offset: 0,
271 file_length: cfg.size,
272 gpa: initrd_address,
273 memory_length: cfg.size,
274 acceptance: BootPageAcceptance::Exclusive,
275 tag: "linux-initrd",
276 },
277 )
278 .map_err(Error::ImportInitrd)?;
279
280 Some(InitrdInfo {
281 gpa: initrd_address,
282 size: cfg.size,
283 })
284 }
285 None => None,
286 };
287 Ok(initrd_info)
288}
289
290pub fn load_kernel_and_initrd_x64<F>(
306 importer: &mut dyn ImageLoad<X86Register>,
307 kernel_image: &mut F,
308 kernel_minimum_start_address: u64,
309 initrd: Option<InitrdConfig<'_>>,
310) -> Result<LoadInfo, Error>
311where
312 F: Read + Seek,
313{
314 tracing::trace!(kernel_minimum_start_address, "loading x86_64 kernel");
315
316 if crate::bzimage::is_bzimage(kernel_image).map_err(Error::BzImage)? {
317 tracing::info!("detected bzImage format, loading via Linux boot protocol");
318 return load_bzimage(importer, kernel_image, kernel_minimum_start_address, initrd);
319 }
320
321 let elf_load_info = load_static_elf(
322 importer,
323 kernel_image,
324 kernel_minimum_start_address,
325 0,
326 false,
327 BootPageAcceptance::Exclusive,
328 "linux-kernel",
329 )
330 .map_err(Error::ElfLoader)?;
331
332 let crate::elf::LoadInfo {
333 minimum_address_used: min_addr,
334 next_available_address: next_addr,
335 entrypoint,
336 } = elf_load_info;
337 tracing::trace!(min_addr, next_addr, entrypoint, "loaded kernel");
338
339 let initrd_info = import_initrd(initrd, next_addr, importer)?;
340
341 Ok(LoadInfo {
342 kernel: KernelInfo {
343 gpa: min_addr,
344 size: next_addr - min_addr,
345 entrypoint,
346 },
347 initrd: initrd_info,
348 dtb: None,
349 bzimage_setup_header: None,
350 })
351}
352
353fn load_bzimage(
357 importer: &mut dyn ImageLoad<X86Register>,
358 kernel_image: &mut (impl Read + Seek),
359 kernel_start_address: u64,
360 initrd: Option<InitrdConfig<'_>>,
361) -> Result<LoadInfo, Error> {
362 let info = crate::bzimage::parse_bzimage(kernel_image).map_err(Error::BzImage)?;
363
364 check_address_alignment(kernel_start_address)?;
365
366 let payload_offset = (info.setup_sects as u64 + 1) * 512;
367 let payload_len = info.protected_mode_size;
368 let payload_memory_len = align_up_to_page_size(payload_len);
369 let entrypoint = kernel_start_address + info.entry_offset;
370
371 tracing::info!(
372 kernel_start_address = format_args!("{:#x}", kernel_start_address),
373 payload_offset,
374 payload_len,
375 entrypoint = format_args!("{:#x}", entrypoint),
376 "loading bzImage payload into guest memory"
377 );
378
379 ChunkBuf::new()
380 .import_file_region(
381 importer,
382 ImportFileRegion {
383 file: kernel_image,
384 file_offset: payload_offset,
385 file_length: payload_len,
386 gpa: kernel_start_address,
387 memory_length: payload_memory_len,
388 acceptance: BootPageAcceptance::Exclusive,
389 tag: "linux-kernel",
390 },
391 )
392 .map_err(Error::ImportBzImage)?;
393
394 let next_addr = kernel_start_address + payload_memory_len;
397 let pref_address: u64 = info.setup_header.pref_address.into();
398 let init_end = kernel_start_address
399 .max(pref_address)
400 .saturating_add(info.init_size as u64);
401 let next_addr = next_addr.max(init_end);
402 let initrd_info = import_initrd(initrd, next_addr, importer)?;
403
404 Ok(LoadInfo {
405 kernel: KernelInfo {
406 gpa: kernel_start_address,
407 size: payload_memory_len,
408 entrypoint,
409 },
410 initrd: initrd_info,
411 dtb: None,
412 bzimage_setup_header: Some(info.setup_header),
413 })
414}
415
416pub fn load_config(
425 importer: &mut impl ImageLoad<X86Register>,
426 load_info: &LoadInfo,
427 command_line: CommandLineConfig<'_>,
428 zero_page: ZeroPageConfig<'_>,
429 acpi: AcpiConfig<'_>,
430 registers: RegisterConfig,
431) -> Result<(), Error> {
432 tracing::trace!(command_line.address);
433 let raw_cmdline = command_line.cmdline.as_bytes_with_nul();
436 if raw_cmdline.len() > 1 {
437 check_address_alignment(command_line.address)?;
438 let cmdline_size_pages = align_up_to_page_size(raw_cmdline.len() as u64) / HV_PAGE_SIZE;
439 importer
440 .import_pages(
441 command_line.address / HV_PAGE_SIZE,
442 cmdline_size_pages,
443 "linux-commandline",
444 BootPageAcceptance::Exclusive,
445 raw_cmdline,
446 )
447 .map_err(Error::Importer)?;
448 }
449
450 check_address_alignment(registers.gdt_address)?;
451 import_default_gdt(importer, registers.gdt_address / HV_PAGE_SIZE).map_err(Error::Importer)?;
452 check_address_alignment(registers.page_table_address)?;
453 let mut page_table_work_buffer: Vec<PageTable> =
454 vec![PageTable::new_zeroed(); PAGE_TABLE_MAX_COUNT];
455 let mut page_table: Vec<u8> = vec![0; PAGE_TABLE_MAX_BYTES];
456 let page_table_builder = IdentityMapBuilder::new(
457 registers.page_table_address,
458 IdentityMapSize::Size4Gb,
459 page_table_work_buffer.as_mut_slice(),
460 page_table.as_mut_slice(),
461 )?;
462 let page_table = page_table_builder.build();
463 assert!((page_table.len() as u64).is_multiple_of(HV_PAGE_SIZE));
464 importer
465 .import_pages(
466 registers.page_table_address / HV_PAGE_SIZE,
467 page_table.len() as u64 / HV_PAGE_SIZE,
468 "linux-pagetables",
469 BootPageAcceptance::Exclusive,
470 page_table,
471 )
472 .map_err(Error::Importer)?;
473
474 check_address_alignment(acpi.rdsp_address)?;
476 check_address_alignment(acpi.tables_address)?;
477 let acpi_tables_size_pages = align_up_to_page_size(acpi.tables.len() as u64) / HV_PAGE_SIZE;
478 importer
479 .import_pages(
480 acpi.rdsp_address / HV_PAGE_SIZE,
481 1,
482 "linux-rdsp",
483 BootPageAcceptance::Exclusive,
484 acpi.rdsp,
485 )
486 .map_err(Error::Importer)?;
487 importer
488 .import_pages(
489 acpi.tables_address / HV_PAGE_SIZE,
490 acpi_tables_size_pages,
491 "linux-acpi-tables",
492 BootPageAcceptance::Exclusive,
493 acpi.tables,
494 )
495 .map_err(Error::Importer)?;
496
497 check_address_alignment(zero_page.address)?;
498 let boot_params = build_zero_page(
499 zero_page.mem_layout,
500 zero_page.acpi_base_address,
501 zero_page.acpi_len,
502 &command_line,
503 load_info.initrd.as_ref().map(|info| info.gpa).unwrap_or(0) as u32,
504 load_info.initrd.as_ref().map(|info| info.size).unwrap_or(0) as u32,
505 load_info.bzimage_setup_header.as_ref(),
506 );
507 importer
508 .import_pages(
509 zero_page.address / HV_PAGE_SIZE,
510 1,
511 "linux-zeropage",
512 BootPageAcceptance::Exclusive,
513 boot_params.as_bytes(),
514 )
515 .map_err(Error::Importer)?;
516
517 let mut import_reg = |register| {
519 importer
520 .import_vp_register(register)
521 .map_err(Error::Importer)
522 };
523
524 import_reg(X86Register::Cr0(x86defs::X64_CR0_PG | x86defs::X64_CR0_PE))?;
525 import_reg(X86Register::Cr3(registers.page_table_address))?;
526 import_reg(X86Register::Cr4(x86defs::X64_CR4_PAE))?;
527 import_reg(X86Register::Efer(
528 x86defs::X64_EFER_SCE
529 | x86defs::X64_EFER_LME
530 | x86defs::X64_EFER_LMA
531 | x86defs::X64_EFER_NXE,
532 ))?;
533 import_reg(X86Register::Pat(x86defs::X86X_MSR_DEFAULT_PAT))?;
534
535 import_reg(X86Register::Rip(load_info.kernel.entrypoint))?;
537 import_reg(X86Register::Rsi(zero_page.address))?;
538
539 import_reg(X86Register::MtrrDefType(0xc00))?;
542 import_reg(X86Register::MtrrFix64k00000(0x0606060606060606))?;
543 import_reg(X86Register::MtrrFix16k80000(0x0606060606060606))?;
544
545 Ok(())
546}
547
548pub fn load_x86<F>(
567 importer: &mut impl ImageLoad<X86Register>,
568 kernel_image: &mut F,
569 kernel_minimum_start_address: u64,
570 initrd: Option<InitrdConfig<'_>>,
571 command_line: CommandLineConfig<'_>,
572 zero_page: ZeroPageConfig<'_>,
573 acpi: AcpiConfig<'_>,
574 registers: RegisterConfig,
575) -> Result<LoadInfo, Error>
576where
577 F: Read + Seek,
578{
579 let load_info =
580 load_kernel_and_initrd_x64(importer, kernel_image, kernel_minimum_start_address, initrd)?;
581
582 load_config(
583 importer,
584 &load_info,
585 command_line,
586 zero_page,
587 acpi,
588 registers,
589 )?;
590
591 Ok(load_info)
592}
593
594open_enum::open_enum! {
595 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
596 pub enum Aarch64ImagePageSize: u64 {
597 UNSPECIFIED = 0,
598 PAGE4_K = 1,
599 PAGE16_K = 2,
600 PAGE64_K = 3,
601 }
602
603}
604
605impl Aarch64ImagePageSize {
606 const fn into_bits(self) -> u64 {
607 self.0
608 }
609
610 const fn from_bits(bits: u64) -> Self {
611 Self(bits)
612 }
613}
614
615#[bitfield(u64)]
617struct Aarch64ImageFlags {
618 #[bits(1)]
620 pub big_endian: bool,
621 #[bits(2)]
627 pub page_size: Aarch64ImagePageSize,
628 #[bits(1)]
635 pub any_start_address: bool,
636 #[bits(60)]
638 pub _padding: u64,
639}
640
641#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
644#[repr(C)]
645struct Aarch64ImageHeader {
646 _code0: u32,
648 _code1: u32,
650 text_offset: u64,
652 image_size: u64,
654 flags: u64,
656 _res2: u64,
658 _res3: u64,
660 _res4: u64,
662 magic: [u8; 4],
664 _res5: u32,
666}
667
668const AARCH64_MAGIC_NUMBER: &[u8] = b"ARM\x64";
669
670pub fn load_kernel_and_initrd_arm64<F>(
682 importer: &mut dyn ImageLoad<Aarch64Register>,
683 kernel_image: &mut F,
684 kernel_minimum_start_address: u64,
685 initrd: Option<InitrdConfig<'_>>,
686 device_tree_blob: Option<&[u8]>,
687) -> Result<LoadInfo, Error>
688where
689 F: Read + Seek,
690{
691 tracing::trace!(kernel_minimum_start_address, "loading aarch64 kernel");
692
693 assert_eq!(
694 kernel_minimum_start_address & ((1 << 21) - 1),
695 0,
696 "Start offset must be aligned on the 2MiB boundary"
697 );
698
699 kernel_image
700 .seek(std::io::SeekFrom::Start(0))
701 .map_err(|_| Error::FlatLoader(FlatLoaderError::SeekKernelStart))?;
702
703 let mut header = Aarch64ImageHeader::new_zeroed();
704 kernel_image
705 .read_exact(header.as_mut_bytes())
706 .map_err(|_| Error::FlatLoader(FlatLoaderError::ReadKernelImage))?;
707
708 tracing::debug!("aarch64 kernel header {header:x?}");
709
710 if header.magic != AARCH64_MAGIC_NUMBER {
711 return Err(Error::FlatLoader(FlatLoaderError::BadImageMagic));
712 }
713
714 let flags = Aarch64ImageFlags::from(header.flags);
715 if flags.big_endian() {
716 return Err(Error::FlatLoader(FlatLoaderError::BigEndianKernelImage));
717 }
718 if flags.page_size() != Aarch64ImagePageSize::PAGE4_K {
719 return Err(Error::FlatLoader(
720 FlatLoaderError::FourKibPageImageIsRequired,
721 ));
722 }
723 if !flags.any_start_address() {
724 return Err(Error::FlatLoader(FlatLoaderError::LowMemoryKernel));
725 }
726
727 kernel_image
731 .seek(std::io::SeekFrom::Start(0))
732 .map_err(|_| Error::FlatLoader(FlatLoaderError::SeekKernelStart))?;
733
734 let mut image = Vec::new();
735 kernel_image
736 .read_to_end(&mut image)
737 .map_err(|_| Error::FlatLoader(FlatLoaderError::ReadKernelImage))?;
738
739 let kernel_load_offset = (kernel_minimum_start_address + header.text_offset) as usize;
740 let kernel_size = if header.image_size != 0 {
741 header.image_size
742 } else {
743 image.len() as u64
744 };
745
746 let kernel_size = align_up_to_page_size(kernel_size);
747 importer
748 .import_pages(
749 kernel_load_offset as u64 / HV_PAGE_SIZE,
750 kernel_size / HV_PAGE_SIZE,
751 "linux-kernel",
752 BootPageAcceptance::Exclusive,
753 &image,
754 )
755 .map_err(Error::Importer)?;
756
757 let next_addr = kernel_load_offset as u64 + kernel_size;
758
759 let (next_addr, dtb) = if let Some(device_tree_blob) = device_tree_blob {
760 let dtb_addr = align_up_to_page_size(next_addr);
761 tracing::trace!(dtb_addr, "loading device tree blob at {dtb_addr:x?}");
762
763 check_address_alignment(dtb_addr)?;
764 let dtb_size_pages = align_up_to_page_size(device_tree_blob.len() as u64) / HV_PAGE_SIZE;
765
766 importer
767 .import_pages(
768 dtb_addr / HV_PAGE_SIZE,
769 dtb_size_pages,
770 "linux-device-tree",
771 BootPageAcceptance::Exclusive,
772 device_tree_blob,
773 )
774 .map_err(Error::Importer)?;
775
776 (
777 dtb_addr + device_tree_blob.len() as u64,
778 Some(dtb_addr..dtb_addr + device_tree_blob.len() as u64),
779 )
780 } else {
781 (next_addr, None)
782 };
783
784 let initrd_info = import_initrd(initrd, next_addr, importer)?;
785
786 Ok(LoadInfo {
787 kernel: KernelInfo {
788 gpa: kernel_minimum_start_address,
789 size: kernel_size,
790 entrypoint: kernel_load_offset as u64,
791 },
792 initrd: initrd_info,
793 dtb,
794 bzimage_setup_header: None,
795 })
796}
797
798pub fn set_direct_boot_registers_arm64(
804 importer: &mut impl ImageLoad<Aarch64Register>,
805 load_info: &LoadInfo,
806) -> Result<(), Error> {
807 let mut import_reg = |register| {
808 importer
809 .import_vp_register(register)
810 .map_err(Error::Importer)
811 };
812
813 import_reg(Aarch64Register::Pc(load_info.kernel.entrypoint))?;
814 import_reg(Aarch64Register::Cpsr(
815 Cpsr64::new()
816 .with_sp(true)
817 .with_el(1)
818 .with_f(true)
819 .with_i(true)
820 .with_a(true)
821 .with_d(true)
822 .into(),
823 ))?;
824 import_reg(Aarch64Register::SctlrEl1(
825 SctlrEl1::new()
826 .with_m(false)
830 .with_c(true)
832 .with_i(true)
834 .with_eos(true)
836 .with_tscxt(true)
837 .with_eis(true)
838 .with_span(true)
839 .with_n_tlsmd(true)
840 .with_lsmaoe(true)
841 .into(),
842 ))?;
843 import_reg(Aarch64Register::TcrEl1(
844 TranslationControlEl1::new()
845 .with_t0sz(0x11)
846 .with_irgn0(1)
847 .with_orgn0(1)
848 .with_sh0(3)
849 .with_tg0(TranslationGranule0::TG_4KB)
850 .with_epd0(1)
852 .with_epd1(1)
854 .with_tg1(TranslationGranule1::TG_4KB)
856 .with_ips(IntermPhysAddrSize::IPA_48_BITS_256_TB)
857 .into(),
858 ))?;
859 import_reg(Aarch64Register::Ttbr0El1(TranslationBaseEl1::new().into()))?;
860 import_reg(Aarch64Register::Ttbr1El1(TranslationBaseEl1::new().into()))?;
861 import_reg(Aarch64Register::VbarEl1(0))?;
862
863 if let Some(dtb) = &load_info.dtb {
864 import_reg(Aarch64Register::X0(dtb.start))?;
865 }
866
867 Ok(())
868}