Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp4608093iob; Sun, 8 May 2022 19:03:31 -0700 (PDT) X-Google-Smtp-Source: ABdhPJywkgYB3N6XBaz3Nkn4n8vuxKd2LZFZ3EMJLV8FCxkkM4JboHHZZfU74GThWluArVlssskU X-Received: by 2002:a05:620a:2487:b0:6a0:50e7:94e3 with SMTP id i7-20020a05620a248700b006a050e794e3mr7773736qkn.429.1652061811681; Sun, 08 May 2022 19:03:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652061811; cv=none; d=google.com; s=arc-20160816; b=f+lWP6bBlgZXT+MS76Zx0zTQZ34AVg69qbE9KOZsUoo3SqqHIu0dI+En2CIJabTyb4 +jm2VjISgMxROmY5WB0QqpJqfjXkFNlOxZTlFPOcMrE1reBskDSouWVSn5DIiiZk2obN zvm2IHTL9Aj39ZfWtwX4vHA06zXGgoL2FxTLZjVkdMdW3JBnU2lNN+eLfLYVRbbjobcX nSVjv/oid2g8CEvo5ugVbZRW6zwI5uJOoMvEYG6GSHhLbUC4HoDNzFiHa70siGfNeEXX BqODQ2nyMPO60Amfrj7kHqJ2LpynLCYZEJgKCvFWqTmgzTRNFxBxNCm6eCMA4Go+g7uZ pz1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:content-language:subject:user-agent:mime-version :date:message-id:dkim-signature; bh=/nJwMxzR9TS8yHfsC2MGZztldlZkvoWJXx4ZFQO9Ot4=; b=RgGOtNIElLs0i9oWhTCDwA7UdQTmJ+DoJE2lR5PLZq1SclVZGZhc91hWZKvE8NCSXT GxaQ/pJxiHpCyxrawSb9DBR1q5m7WA+xHPErBZhTS63RAmyHDItuT2a/OllOKZx7O78o v67aLsyoTO46JRHFtuV8nFp+VmWj/REQEa2dYEOCl57N0VurgKRxCfXMguR+40McsNyM SkS7//GiAh+gTKct3nnDxPviSkfd16Fwa7S39YnswMaRCmrYP2Rg4nfe8ZKR40yKA2YX Fa/UrY4PVDlSCia7lnO24Oplq/CsU7Jgm06DtcaUJ3WKvfyOtKpTDkGnHspnj3/h599I Ermg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@xen0n.name header.s=mail header.b="PE/TUtgE"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id c12-20020a0cd60c000000b0045645b0287asi6311964qvj.496.2022.05.08.19.03.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 May 2022 19:03:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@xen0n.name header.s=mail header.b="PE/TUtgE"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9F1004B1DC; Sun, 8 May 2022 19:03:24 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1391339AbiEFLaQ (ORCPT + 99 others); Fri, 6 May 2022 07:30:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60930 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1389782AbiEFLaO (ORCPT ); Fri, 6 May 2022 07:30:14 -0400 Received: from mailbox.box.xen0n.name (mail.xen0n.name [115.28.160.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9DB4B13F7F; Fri, 6 May 2022 04:26:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=xen0n.name; s=mail; t=1651836387; bh=azHha70+GWhmg49YkWnFtTT3iKIMGLPZ6Q/jJlWPQuI=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=PE/TUtgED1vC70nqwhf+4/pi1bKNCjFm19JASheRMc2lYYis/Gq7FbfKbCJCAKqk2 jioMj/Q1zY4ITwJA2XqesgXVGpx5IEoEUYoZ19GNjXDbysOcyx8+MBFC+N8MSQY+nb LP7ylM4j2W5XZCd3j5A0I33AP35IP89CdrWvRKT4= Received: from [192.168.9.172] (unknown [101.88.28.48]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mailbox.box.xen0n.name (Postfix) with ESMTPSA id 734406068D; Fri, 6 May 2022 19:26:27 +0800 (CST) Message-ID: Date: Fri, 6 May 2022 19:26:24 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.0a1 Subject: Re: [PATCH V9 20/24] LoongArch: Add efistub booting support Content-Language: en-US To: Ard Biesheuvel , Huacai Chen Cc: Arnd Bergmann , Huacai Chen , Andy Lutomirski , Thomas Gleixner , Peter Zijlstra , Andrew Morton , David Airlie , Jonathan Corbet , Linus Torvalds , linux-arch , "open list:DOCUMENTATION" , Linux Kernel Mailing List , Xuefeng Li , Yanteng Si , Guo Ren , Xuerui Wang , Jiaxun Yang References: <20220430090518.3127980-1-chenhuacai@loongson.cn> <20220430090518.3127980-21-chenhuacai@loongson.cn> From: WANG Xuerui In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-3.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,NICE_REPLY_A,RDNS_NONE,SPF_HELO_NONE, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On 5/6/22 16:14, Ard Biesheuvel wrote: > [snip] >>>>> + >>>>> +static efi_status_t mk_mmap(struct efi_boot_memmap *map, struct boot_params *p) >>>>> +{ >>> Are you passing a different representation of the memory map to the >>> core kernel? I think it would be easier just to pass the EFI memory >>> map like other EFI arches do, and reuse all of the code that we >>> already have. >> Yes, this different representation is used by our "boot_params", the >> interface between bootloader (including efistub) and the core kernel. > So how does the core kernel consume the EFI memory map? Only through > this mechanism? > >>>>> + char checksum; >>>>> + unsigned int i; >>>>> + unsigned int nr_desc; >>>>> + unsigned int mem_type; >>>>> + unsigned long count; >>>>> + efi_memory_desc_t *mem_desc; >>>>> + struct loongsonlist_mem_map *mhp = NULL; >>>>> + >>>>> + memset(map_entry, 0, sizeof(map_entry)); >>>>> + memset(mmap_array, 0, sizeof(mmap_array)); >>>>> + >>>>> + if (!strncmp((char *)p, "BPI", 3)) { >>>>> + p->flags |= BPI_FLAGS_UEFI_SUPPORTED; >>>>> + p->systemtable = (efi_system_table_t *)efi_system_table; >>>>> + p->extlist_offset = sizeof(*p) + sizeof(unsigned long); >>>>> + mhp = (struct loongsonlist_mem_map *)((char *)p + p->extlist_offset); >>>>> + >>>>> + memcpy(&mhp->header.signature, "MEM", sizeof(unsigned long)); >>>>> + mhp->header.length = sizeof(*mhp); >>>>> + mhp->desc_version = *map->desc_ver; >>>>> + mhp->map_count = 0; >>>>> + } >>>>> + if (!(*(map->map_size)) || !(*(map->desc_size)) || !mhp) { >>>>> + efi_err("get memory info error\n"); >>>>> + return EFI_INVALID_PARAMETER; >>>>> + } >>>>> + nr_desc = *(map->map_size) / *(map->desc_size); >>>>> + >>>>> + /* >>>>> + * According to UEFI SPEC, mmap_buf is the accurate Memory Map >>>>> + * mmap_array now we can fill platform specific memory structure. >>>>> + */ >>>>> + for (i = 0; i < nr_desc; i++) { >>>>> + mem_desc = (efi_memory_desc_t *)((void *)(*map->map) + (i * (*(map->desc_size)))); >>>>> + switch (mem_desc->type) { >>>>> + case EFI_RESERVED_TYPE: >>>>> + case EFI_RUNTIME_SERVICES_CODE: >>>>> + case EFI_RUNTIME_SERVICES_DATA: >>>>> + case EFI_MEMORY_MAPPED_IO: >>>>> + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: >>>>> + case EFI_UNUSABLE_MEMORY: >>>>> + case EFI_PAL_CODE: >>>>> + mem_type = ADDRESS_TYPE_RESERVED; >>>>> + break; >>>>> + >>>>> + case EFI_ACPI_MEMORY_NVS: >>>>> + mem_type = ADDRESS_TYPE_NVS; >>>>> + break; >>>>> + >>>>> + case EFI_ACPI_RECLAIM_MEMORY: >>>>> + mem_type = ADDRESS_TYPE_ACPI; >>>>> + break; >>>>> + >>>>> + case EFI_LOADER_CODE: >>>>> + case EFI_LOADER_DATA: >>>>> + case EFI_PERSISTENT_MEMORY: >>>>> + case EFI_BOOT_SERVICES_CODE: >>>>> + case EFI_BOOT_SERVICES_DATA: >>>>> + case EFI_CONVENTIONAL_MEMORY: >>>>> + mem_type = ADDRESS_TYPE_SYSRAM; >>>>> + break; >>>>> + >>>>> + default: >>>>> + continue; >>>>> + } >>>>> + >>>>> + mmap_array[mem_type][map_entry[mem_type]].mem_type = mem_type; >>>>> + mmap_array[mem_type][map_entry[mem_type]].mem_start = >>>>> + mem_desc->phys_addr & TO_PHYS_MASK; >>>>> + mmap_array[mem_type][map_entry[mem_type]].mem_size = >>>>> + mem_desc->num_pages << EFI_PAGE_SHIFT; >>>>> + mmap_array[mem_type][map_entry[mem_type]].attribute = >>>>> + mem_desc->attribute; >>>>> + map_entry[mem_type]++; >>>>> + } >>>>> + >>>>> + count = mhp->map_count; >>>>> + /* Sort EFI memmap and add to BPI for kernel */ >>>>> + for (i = 0; i < LOONGSON3_BOOT_MEM_MAP_MAX; i++) { >>>>> + if (!map_entry[i]) >>>>> + continue; >>>>> + count = efi_memmap_sort(mhp, count, i); >>>>> + } >>>>> + >>>>> + mhp->map_count = count; >>>>> + mhp->header.checksum = 0; >>>>> + >>>>> + checksum = efi_crc8((char *)mhp, mhp->header.length); >>>>> + mhp->header.checksum = checksum; >>>>> + >>>>> + return EFI_SUCCESS; >>>>> +} >>>>> + >>>>> +static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) >>>>> +{ >>>>> + efi_status_t status; >>>>> + struct exit_boot_struct *p = priv; >>>>> + >>>>> + status = mk_mmap(map, p->bp); >>>>> + if (status != EFI_SUCCESS) { >>>>> + efi_err("Make kernel memory map failed!\n"); >>>>> + return status; >>>>> + } >>>>> + >>>>> + return EFI_SUCCESS; >>>>> +} >>>>> + >>>>> +static efi_status_t exit_boot_services(struct boot_params *boot_params, void *handle) >>>>> +{ >>>>> + unsigned int desc_version; >>>>> + unsigned int runtime_entry_count = 0; >>>>> + unsigned long map_size, key, desc_size, buff_size; >>>>> + efi_status_t status; >>>>> + efi_memory_desc_t *mem_map; >>>>> + struct efi_boot_memmap map; >>>>> + struct exit_boot_struct priv; >>>>> + >>>>> + map.map = &mem_map; >>>>> + map.map_size = &map_size; >>>>> + map.desc_size = &desc_size; >>>>> + map.desc_ver = &desc_version; >>>>> + map.key_ptr = &key; >>>>> + map.buff_size = &buff_size; >>>>> + status = efi_get_memory_map(&map); >>>>> + if (status != EFI_SUCCESS) { >>>>> + efi_err("Unable to retrieve UEFI memory map.\n"); >>>>> + return status; >>>>> + } >>>>> + >>>>> + priv.bp = boot_params; >>>>> + priv.runtime_entry_count = &runtime_entry_count; >>>>> + >>>>> + /* Might as well exit boot services now */ >>>>> + status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func); >>>>> + if (status != EFI_SUCCESS) >>>>> + return status; >>>>> + >>>>> + return EFI_SUCCESS; >>>>> +} >>>>> + >>>>> +/* >>>>> + * EFI entry point for the LoongArch EFI stub. >>>>> + */ >>>>> +efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, efi_system_table_t *sys_table) >>> Why are you not using the generic EFI stub boot flow? >> Hmmm, as I know, we define our own "boot_params", a interface between >> bootloader (including efistub) and the core kernel to pass memmap, >> cmdline and initrd information, three years ago. This method looks >> like the X86 way, while different from the generic stub (which is >> called arm stub before 5.8). In these years, many products have >> already use the "boot_params" interface (including UEFI, PMON, Grub, >> Kernel, etc., but most of them haven't be upstream). Replace >> boot_params with FDT (i.e., the generic stub way) is difficult for us, >> because it means a big broken of compatibility. >> > OK, I understand. So using the generic stub is not possible for you. > > So as long as you don't enable deprecated features such as initrd=, or > rely on special hacks like putting magic numbers at fixed offsets in > the image, I'm fine with this approach. I'd like to add some relevant background: this "struct boot_params" thingy is actually a Loongson corporate standard. It is available at [1]; only in Chinese but should be minimally recognizable given much of it is C code, and you can see this struct and its friends barely changed since 2019. The standard is in place long before inception of LoongArch (the earliest spec is dated back to 2014). Back when Loongson was still doing MIPS this is somewhat acceptable, due to fragmentation of the MIPS world, but they didn't take the chance to re-think most of this for LoongArch, instead simply porting everything over as-is. Hence the ship has more-or-less already sailed, and we indeed have to support this flow for keeping compatibility... Or is there compatibility at all? It turns out that this port is already incompatible with shipped systems, in other ways, at least since the March revision or so. For one thing, the exact definition of this "struct boot_params" is already incompatibly revised; this version [2] is the one actually compatible with existing firmware, so people already have to write shims (not started yet) or flash their firmware (not open-sourced or provided by Loongson yet) to actually compile and run this port. (You haven't read that wrong; indeed no one outside Loongson is able to run this kernel so far.) For another thing, the kernel ABI and the userland (mainly glibc) are also incompatible with the shipped systems with their pre-installed vendor systems. Things like different NSIG, sigcontext, and glibc symbol versions already ensured no binary can run in "the other world". So, in effect, this port is starting from scratch, and taking the chance to fix early mistakes and oversights all over; hence my opinion is, better do the Right Thing (tm) and give the generic codepath a chance. For the Loongson devs: at least, declare the struct boot_params flow deprecated from day one, then work to eliminate it from future products, if you really don't want to delay merging even further (it's already unlikely to land in 5.19, given the discussion happening in LKML [3]). It's not embarrassing to admit mistakes; we all make mistakes, and what's important is to learn from them so we don't collectively repeat ourselves. [1]: https://web.archive.org/web/20190713081851/http://www.loongson.cn/uploadfile/devsysmanual/loongson_devsys_firmware_kernel_interface_specification.pdf [2]: https://github.com/xen0n/linux/commit/a55739f8e748dc9164c12da504696161bb8b9911 [3]: https://lwn.net/ml/linux-kernel/87v8uk6kfa.wl-maz@kernel.org/