From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58754) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xy0GK-0004qe-GR for qemu-devel@nongnu.org; Mon, 08 Dec 2014 10:30:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xy0GI-00055T-4D for qemu-devel@nongnu.org; Mon, 08 Dec 2014 10:30:12 -0500 Received: from mail-wi0-x22d.google.com ([2a00:1450:400c:c05::22d]:52744) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xy0GH-00051i-Mk for qemu-devel@nongnu.org; Mon, 08 Dec 2014 10:30:10 -0500 Received: by mail-wi0-f173.google.com with SMTP id r20so5046653wiv.0 for ; Mon, 08 Dec 2014 07:30:08 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <547B7B1B.20100@gmail.com> References: <547B7B1B.20100@gmail.com> Date: Mon, 8 Dec 2014 13:30:08 -0200 Message-ID: From: =?UTF-8?Q?Jo=C3=A3o_Henrique_Freitas?= Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] dtb support on x86 machines List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "qemu-devel@nongnu.org" Hi, Any thoughts? Thanks. On Sun, Nov 30, 2014 at 6:16 PM, Jo=C3=A3o Henrique Ferreira de Freitas wrote: > Hi, > > > I would like to share my work-in-progress about device-tree on qemux x86 > machine. The patch is not fully functional but works as a proof of concep= t. > It is based on qemu stable-2.1 and when I solve my questions I will do us= ing > master branch. > > Besides that device-tree on x86 machines is not widespread used but works= . > The bootloader syslinux has support to it and I am doing the similar patc= hes > to kexec too. So I deciced to do the some with qemu. ;) > > The patch uses setup_data field of linux boot protocol > (https://www.kernel.org/doc/Documentation/x86/boot.txt) which is a linked > list of 'struct setup_data'. Usually setup_data is used to extend boot > parameters. I am using it to put a loaded dtb there. > > Until now you can see the patch at > https://github.com/joaohf/qemu/commit/941d68e6126b4e0908fdd8a90fa7d3f2809= 8a49f. > I will send it to qemu-devel list when I solve my biggest question that I= am > going to explain later. > > ------ begin ---- > > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > index ef9fad8..94467ba 100644 > --- a/hw/i386/pc.c > +++ b/hw/i386/pc.c > @@ -51,6 +51,7 @@ > #include "exec/address-spaces.h" > #include "sysemu/arch_init.h" > #include "qemu/bitmap.h" > +#include "sysemu/device_tree.h" > #include "qemu/config-file.h" > #include "hw/acpi/acpi.h" > #include "hw/acpi/cpu_hotplug.h" > @@ -75,7 +76,7 @@ > /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables > * (128K) and other BIOS datastructures (less than 4K reported to be use= d > at > * the moment, 32K should be enough for a while). */ > -unsigned acpi_data_size =3D 0x20000 + 0x8000; > +unsigned acpi_data_size =3D 0x20000 + 0x80000; > void pc_set_legacy_acpi_data_size(void) > { > acpi_data_size =3D 0x10000; > @@ -741,17 +742,77 @@ static long get_file_size(FILE *f) > return size; > } > > +static int load_dtb(FWCfgState *fw_cfg, > + const char *dtb_filename, > + void **dtb_addr, > + int *dtb_size) > +{ > + void *fdt =3D NULL; > + > + fdt =3D load_device_tree(dtb_filename, dtb_size); > + if (!fdt) { > + fprintf(stderr, "Couldn't open dtb file %s\n", dtb_filename); > + return -1; > + } > + > + qemu_fdt_dumpdtb(fdt, *dtb_size); > + > + *dtb_addr =3D fdt; > + > + return 0; > +} > + > +struct setup_data { > + uint64_t next; > + uint32_t type; > +#define SETUP_NONE 0 > +#define SETUP_E820_EXT 1 > +#define SETUP_DTB 2 > +#define SETUP_PCI 3 > +#define SETUP_EFI 4 > + uint32_t len; > + uint8_t data[0]; > +} __attribute__((packed)); > + > +static int setup_dtb_data(FWCfgState *fw_cfg, > + void **setup_data_addr, int *setup_data_size, > + void *dtb_addr, off_t dtb_size) > +{ > + struct setup_data *sd; > + int sdsize; > + > + sd =3D g_malloc(sizeof(struct setup_data) + dtb_size); > + if (!sd) { > + return -1; > + } > + > + memset(sd, 0, sizeof(struct setup_data) + dtb_size); > + sd->next =3D 0; > + sd->type =3D SETUP_DTB; > + sd->len =3D dtb_size; > + memcpy(sd->data, dtb_addr, dtb_size); > + > + sdsize =3D sd->len + sizeof(struct setup_data); > + > + *setup_data_addr =3D (void *) sd; > + *setup_data_size =3D sdsize; > + > + return 0; > +} > + > static void load_linux(FWCfgState *fw_cfg, > const char *kernel_filename, > const char *initrd_filename, > + const char *dtb_filename, > const char *kernel_cmdline, > hwaddr max_ram_size) > { > uint16_t protocol; > - int setup_size, kernel_size, initrd_size =3D 0, cmdline_size; > + int setup_size, kernel_size, initrd_size =3D 0, cmdline_size, dtb_si= ze =3D > 0, setup_data_size =3D 0;; > uint32_t initrd_max; > uint8_t header[8192], *setup, *kernel, *initrd_data; > - hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr =3D 0; > + hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr =3D 0, > setup_data_addr =3D 0; > + void *dtb_addr, *setup_data; > FILE *f; > char *vmode; > > @@ -891,6 +952,53 @@ static void load_linux(FWCfgState *fw_cfg, > stl_p(header+0x21c, initrd_size); > } > > + /* load dtb */ > + if (dtb_filename) { > + int retval; > + retval =3D load_dtb(fw_cfg, dtb_filename, &dtb_addr, &dtb_size); > + if (retval < 0) { > + fprintf(stderr, "qemu: error loading dtb %s: %s\n", > + dtb_filename, strerror(errno)); > + exit(1); > + } > + > + retval =3D setup_dtb_data(fw_cfg, &setup_data, &setup_data_size, > + dtb_addr, dtb_size); > + if (retval < 0) { > + fprintf(stderr, "qemu: error no memory to setup_data\n"); > + exit(1); > + } > + > +// if (!initrd_addr) { > +// setup_data_addr =3D (initrd_max-initrd_size-setup_data_siz= e) & > ~4095; > +// } else { > + setup_data_addr =3D > QEMU_ALIGN_UP(initrd_max-initrd_size-setup_data_size, 4096); > +// } > + > + stq_p(header+0x250, setup_data_addr); > + > + cpu_physical_memory_write(setup_data_addr, setup_data, > setup_data_size); > + > > ---------- > > Above you can see how a dtb are loaded and how setup_data is filled. I am > put setup_data_addr at header[0x250] and tells to qemu to write > setup_data_addr to guest memory. > > This approach works and I can see my device-tree at guest > '/proc/device-tree'. > > ---------- > +#if 1 > + fprintf(stderr, > + "qemu: initrd_max =3D %d\n" > + "qemu: dtb addr =3D 0x%p\n" > + "qemu: dtb size =3D %d\n" > + "qemu: setup_data size =3D %d\n" > + "qemu: setup_data addr =3D 0x%p\n" > + "qemu: setup_data_addr =3D 0x" TARGET_FMT_plx "\n" > + "qemu: header[0x250] =3D " TARGET_FMT_plx "\n", > + initrd_max, > + dtb_addr, > + dtb_size, > + setup_data_size, > + setup_data, > + setup_data_addr, > + ldq_p(header+0x250)); > +#endif > + > + } > + > /* load kernel and setup */ > setup_size =3D header[0x1f1]; > if (setup_size =3D=3D 0) { > @@ -911,6 +1019,11 @@ static void load_linux(FWCfgState *fw_cfg, > exit(1); > } > fclose(f); > + > + fprintf(stderr, > + "qemu: setup_size =3D %d\n", > + setup_size); > + > memcpy(setup, header, MIN(sizeof(header), setup_size)); > > fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); > @@ -1298,7 +1411,7 @@ FWCfgState *pc_memory_init(MachineState *machine, > > if (linux_boot) { > load_linux(fw_cfg, machine->kernel_filename, > machine->initrd_filename, > - machine->kernel_cmdline, below_4g_mem_size); > + machine->dtb_filename, machine->kernel_cmdline, > below_4g_mem_size); > } > > for (i =3D 0; i < nb_option_roms; i++) { > > ------------ end ------------- > > So, running a qemu instance gives the following. Pay attention I am using > the '-dtb' parameter to load device-tree. > > Running qemu-system-i386... > /srv/yocto/build/dizzy/tmp/sysroots/x86_64-linux/usr/bin/qemu-system-i386 > -kernel bzImage > -net nic,vlan=3D0 -net tap,vlan=3D0,ifname=3Dtap0,script=3Dno,downscript= =3Dno -cpu > qemu32 -hda image-lsb-qemux86.ext3 > -show-cursor -usb -usbdevice wacom-tablet -vga vmware -no-reboot -dtb > device_tree_lc.dtb > -m 256 --append "vga=3D0 uvesafb.mode_option=3D640x480-32 root=3D/dev/hda= rw > mem=3D256M > ip=3D192.168.7.2::192.168.7.1:255.255.255.0 oprofile.timer=3D1 " > qemu: initrd_max =3D 267780095 > qemu: dtb addr =3D 0x0x7f0d80beb010 > qemu: dtb size =3D 134848 > qemu: setup_data size =3D 134864 > qemu: setup_data addr =3D 0x0x7f0d80a74010 > qemu: setup_data_addr =3D 0x000000000ff40000 > qemu: header[0x250] =3D 000000000ff40000 > qemu: setup_size =3D 15360 > > > [ 0.000000] Initializing cgroup subsys cpuset > [ 0.000000] Initializing cgroup subsys cpu > [ 0.000000] Initializing cgroup subsys cpuacct > [ 0.000000] Linux version 3.10.55-ltsi-yocto-standard (joaohf@azedo) (= gcc > version 4.8.2 (GCC) ) #1 SMP PREEMPT Fri Oct 31 19:23:26 BRST 2014 > [ 0.000000] e820: BIOS-provided physical RAM map: > [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usa= ble > [ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] > reserved > [ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] > reserved > [ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000000ffdffff] usa= ble > [ 0.000000] BIOS-e820: [mem 0x000000000ffe0000-0x000000000fffffff] > reserved > [ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] > reserved > [ 0.000000] e820: update [mem 0x0ff40000-0x0ff60ecf] usable =3D=3D> us= able > [ 0.000000] extended physical RAM map: > [ 0.000000] reserve setup_data: [mem > 0x0000000000000000-0x000000000009fbff] usable > [ 0.000000] reserve setup_data: [mem > 0x000000000009fc00-0x000000000009ffff] reserved > [ 0.000000] reserve setup_data: [mem > 0x00000000000f0000-0x00000000000fffff] reserved > [ 0.000000] reserve setup_data: [mem > 0x0000000000100000-0x000000000ff3ffff] usable > [ 0.000000] reserve setup_data: [mem > 0x000000000ff40000-0x000000000ff60ecf] usable > [ 0.000000] reserve setup_data: [mem > 0x000000000ff60ed0-0x000000000ffdffff] usable > [ 0.000000] reserve setup_data: [mem > 0x000000000ffe0000-0x000000000fffffff] reserved > [ 0.000000] reserve setup_data: [mem > 0x00000000fffc0000-0x00000000ffffffff] reserved > [ 0.000000] e820: remove [mem 0x10000000-0xfffffffffffffffe] usable > [ 0.000000] Notice: NX (Execute Disable) protection missing in CPU! > [ 0.000000] e820: user-defined physical RAM map: > [ 0.000000] user: [mem 0x0000000000000000-0x000000000009fbff] usable > [ 0.000000] user: [mem 0x000000000009fc00-0x000000000009ffff] reserved > [ 0.000000] user: [mem 0x00000000000f0000-0x00000000000fffff] reserved > [ 0.000000] user: [mem 0x0000000000100000-0x000000000ff3ffff] usable > [ 0.000000] user: [mem 0x000000000ff40000-0x000000000ff60ecf] usable > [ 0.000000] user: [mem 0x000000000ff60ed0-0x000000000ffdffff] usable > [ 0.000000] user: [mem 0x000000000ffe0000-0x000000000fffffff] reserved > [ 0.000000] user: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved > > > Then I conclude that 'setup_data_addr =3D 0x000000000ff40000' is the gues= t > address that qemu put the setup_data (with dtb). In the begin of dmesg we > can see: > > [ 0.000000] reserve setup_data: [mem > 0x000000000ff40000-0x000000000ff60ecf] usable > .... > [ 0.000000] user: [mem 0x000000000ff40000-0x000000000ff60ecf] usable > > The size of this memory range is the same of setup_data size (134864). > > > So, the linux claim about 'ioremap on RAM pfn 0xff40' > > > [......] > > [ 0.685545] ------------[ cut here ]------------ > [ 0.685758] WARNING: at > /srv/yocto/build/daisy-padtec-otns/tmp/work/qemux86-padtec-linux/linux-yo= cto/3.10.55+gitAUTOINC+f79a00265e_8e055f3b66-r0/linux/arch/x86/mm/ioremap.c= :63 > __ioremap_check_ram+0x85/0x90() > [ 0.685912] ioremap on RAM pfn 0xff40 > [ 0.686064] Modules linked in: > [ 0.686322] CPU: 0 PID: 1 Comm: swapper/0 Not tainted > 3.10.55-ltsi-yocto-standard #1 > [ 0.686413] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIO= S > rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014 > [ 0.686613] cf895c4c cf895c4c cf895c14 c16e3eaa cf895c3c c103650e > c189f938 cf895c68 > [ 0.686841] 0000003f c102e0e5 c102e0e5 cff3e820 0000ffe0 00000400 > cf895c54 c1036563 > [ 0.687134] 00000009 cf895c4c c189f938 cf895c68 cf895c78 c102e0e5 > c18a9358 0000003f > [ 0.687349] Call Trace: > [ 0.687627] [] dump_stack+0x16/0x18 > [ 0.687715] [] warn_slowpath_common+0x5e/0x80 > [ 0.687804] [] ? __ioremap_check_ram+0x85/0x90 > [ 0.687880] [] ? __ioremap_check_ram+0x85/0x90 > [ 0.688044] [] warn_slowpath_fmt+0x33/0x40 > [ 0.688115] [] __ioremap_check_ram+0x85/0x90 > [ 0.688187] [] walk_system_ram_range+0xe0/0x100 > [ 0.688267] [] __ioremap_caller+0x6f/0x280 > [ 0.688335] [] ? ioremap_prot+0x20/0x20 > [ 0.688403] [] ? pci_bus_read_config_word+0x74/0x80 > [ 0.688477] [] ? __pci_bus_find_cap_start+0x1e/0x50 > [ 0.688550] [] ioremap_nocache+0x1b/0x20 > [ 0.688618] [] ? pcibios_add_device+0x3a/0xb0 > [ 0.688687] [] pcibios_add_device+0x3a/0xb0 > [ 0.688756] [] pci_device_add+0xd0/0x120 > [ 0.688826] [] pci_scan_single_device+0x81/0xa0 > [ 0.688897] [] pci_scan_slot+0x48/0x140 > [ 0.689042] [] pci_scan_child_bus+0x24/0xa0 > [ 0.689114] [] pci_acpi_scan_root+0x2e1/0x420 > [ 0.689188] [] acpi_pci_root_add+0x185/0x392 > [ 0.689260] [] ? acpi_scan_match_handler+0x32/0x57 > [ 0.689332] [] acpi_bus_device_attach+0x6c/0xb3 > [ 0.689405] [] acpi_ns_walk_namespace+0xb9/0x16b > [ 0.689479] [] acpi_walk_namespace+0x79/0xa0 > [ 0.689548] [] ? acpi_bus_type_and_status+0x88/0x88 > [ 0.689622] [] acpi_bus_scan+0x95/0xa5 > [ 0.689688] [] ? acpi_bus_type_and_status+0x88/0x88 > [ 0.689762] [] acpi_scan_init+0x47/0x13a > [ 0.689830] [] acpi_init+0x233/0x276 > [ 0.689900] [] ? acpi_sleep_init+0xd2/0xd2 > [ 0.690041] [] do_one_initcall+0xda/0x130 > [ 0.690117] [] ? buffer_init+0x46/0x46 > [ 0.690187] [] kernel_init_freeable+0x130/0x1f7 > [ 0.690258] [] ? do_early_param+0x78/0x78 > [ 0.690329] [] ? _raw_spin_unlock_irq+0xd/0x40 > [ 0.690399] [] ? _raw_spin_unlock_irq+0x1b/0x40 > [ 0.690470] [] ? finish_task_switch+0x45/0xa0 > [ 0.690541] [] kernel_init+0x10/0x140 > [ 0.690610] [] ret_from_kernel_thread+0x1b/0x28 > [ 0.690680] [] ? rest_init+0x80/0x80 > [ 0.692118] ---[ end trace c548593bf4ae83de ]--- > > > I can't figure out why linux kernel is claims about: > > [ 0.685912] ioremap on RAM pfn 0xff40 > > > May I need to map setup_data allocation using a different approach? > > How I can reserve the right pointer address and pass it to guest? > > > You can see the full dmesg output at > https://gist.github.com/joaohf/c4132c767373cf85633c > > > Any help with qemu memory will be lovely. > > > Thanks. > > -- > Jo=C3=A3o Henrique Ferreira de Freitas - joaohf_at_gmail.com > Campinas-SP-Brasil > --=20 Jo=C3=A3o Henrique Ferreira de Freitas - joaohf_at_gmail.com Campinas-SP-Brasil