Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
723c808621 | |
![]() |
b238448f61 | |
![]() |
f5e3ea3d43 | |
![]() |
64b1ce9b07 | |
![]() |
b368e01771 | |
![]() |
235e2ca5f5 | |
![]() |
8645ae06c1 |
|
@ -0,0 +1,561 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 4.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
#AfterExternBlock: false # Unknown to clang-format-5.0
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
#SplitEmptyFunction: true # Unknown to clang-format-4.0
|
||||
#SplitEmptyRecord: true # Unknown to clang-format-4.0
|
||||
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
#CompactNamespaces: false # Unknown to clang-format-4.0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | sort | uniq
|
||||
ForEachMacros:
|
||||
- 'apei_estatus_for_each_section'
|
||||
- 'ata_for_each_dev'
|
||||
- 'ata_for_each_link'
|
||||
- '__ata_qc_for_each'
|
||||
- 'ata_qc_for_each'
|
||||
- 'ata_qc_for_each_raw'
|
||||
- 'ata_qc_for_each_with_internal'
|
||||
- 'ax25_for_each'
|
||||
- 'ax25_uid_for_each'
|
||||
- '__bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec_all'
|
||||
- 'bio_for_each_integrity_vec'
|
||||
- '__bio_for_each_segment'
|
||||
- 'bio_for_each_segment'
|
||||
- 'bio_for_each_segment_all'
|
||||
- 'bio_list_for_each'
|
||||
- 'bip_for_each_vec'
|
||||
- 'bitmap_for_each_clear_region'
|
||||
- 'bitmap_for_each_set_region'
|
||||
- 'blkg_for_each_descendant_post'
|
||||
- 'blkg_for_each_descendant_pre'
|
||||
- 'blk_queue_for_each_rl'
|
||||
- 'bond_for_each_slave'
|
||||
- 'bond_for_each_slave_rcu'
|
||||
- 'bpf_for_each_spilled_reg'
|
||||
- 'btree_for_each_safe128'
|
||||
- 'btree_for_each_safe32'
|
||||
- 'btree_for_each_safe64'
|
||||
- 'btree_for_each_safel'
|
||||
- 'card_for_each_dev'
|
||||
- 'cgroup_taskset_for_each'
|
||||
- 'cgroup_taskset_for_each_leader'
|
||||
- 'cpufreq_for_each_entry'
|
||||
- 'cpufreq_for_each_entry_idx'
|
||||
- 'cpufreq_for_each_valid_entry'
|
||||
- 'cpufreq_for_each_valid_entry_idx'
|
||||
- 'css_for_each_child'
|
||||
- 'css_for_each_descendant_post'
|
||||
- 'css_for_each_descendant_pre'
|
||||
- 'device_for_each_child_node'
|
||||
- 'displayid_iter_for_each'
|
||||
- 'dma_fence_chain_for_each'
|
||||
- 'do_for_each_ftrace_op'
|
||||
- 'drm_atomic_crtc_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane_state'
|
||||
- 'drm_atomic_for_each_plane_damage'
|
||||
- 'drm_client_for_each_connector_iter'
|
||||
- 'drm_client_for_each_modeset'
|
||||
- 'drm_connector_for_each_possible_encoder'
|
||||
- 'drm_for_each_bridge_in_chain'
|
||||
- 'drm_for_each_connector_iter'
|
||||
- 'drm_for_each_crtc'
|
||||
- 'drm_for_each_crtc_reverse'
|
||||
- 'drm_for_each_encoder'
|
||||
- 'drm_for_each_encoder_mask'
|
||||
- 'drm_for_each_fb'
|
||||
- 'drm_for_each_legacy_plane'
|
||||
- 'drm_for_each_plane'
|
||||
- 'drm_for_each_plane_mask'
|
||||
- 'drm_for_each_privobj'
|
||||
- 'drm_mm_for_each_hole'
|
||||
- 'drm_mm_for_each_node'
|
||||
- 'drm_mm_for_each_node_in_range'
|
||||
- 'drm_mm_for_each_node_safe'
|
||||
- 'flow_action_for_each'
|
||||
- 'for_each_acpi_dev_match'
|
||||
- 'for_each_active_dev_scope'
|
||||
- 'for_each_active_drhd_unit'
|
||||
- 'for_each_active_iommu'
|
||||
- 'for_each_aggr_pgid'
|
||||
- 'for_each_available_child_of_node'
|
||||
- 'for_each_bio'
|
||||
- 'for_each_board_func_rsrc'
|
||||
- 'for_each_bvec'
|
||||
- 'for_each_card_auxs'
|
||||
- 'for_each_card_auxs_safe'
|
||||
- 'for_each_card_components'
|
||||
- 'for_each_card_dapms'
|
||||
- 'for_each_card_pre_auxs'
|
||||
- 'for_each_card_prelinks'
|
||||
- 'for_each_card_rtds'
|
||||
- 'for_each_card_rtds_safe'
|
||||
- 'for_each_card_widgets'
|
||||
- 'for_each_card_widgets_safe'
|
||||
- 'for_each_cgroup_storage_type'
|
||||
- 'for_each_child_of_node'
|
||||
- 'for_each_clear_bit'
|
||||
- 'for_each_clear_bit_from'
|
||||
- 'for_each_cmsghdr'
|
||||
- 'for_each_compatible_node'
|
||||
- 'for_each_component_dais'
|
||||
- 'for_each_component_dais_safe'
|
||||
- 'for_each_comp_order'
|
||||
- 'for_each_console'
|
||||
- 'for_each_cpu'
|
||||
- 'for_each_cpu_and'
|
||||
- 'for_each_cpu_not'
|
||||
- 'for_each_cpu_wrap'
|
||||
- 'for_each_dapm_widgets'
|
||||
- 'for_each_dev_addr'
|
||||
- 'for_each_dev_scope'
|
||||
- 'for_each_dma_cap_mask'
|
||||
- 'for_each_dpcm_be'
|
||||
- 'for_each_dpcm_be_rollback'
|
||||
- 'for_each_dpcm_be_safe'
|
||||
- 'for_each_dpcm_fe'
|
||||
- 'for_each_drhd_unit'
|
||||
- 'for_each_dss_dev'
|
||||
- 'for_each_dtpm_table'
|
||||
- 'for_each_efi_memory_desc'
|
||||
- 'for_each_efi_memory_desc_in_map'
|
||||
- 'for_each_element'
|
||||
- 'for_each_element_extid'
|
||||
- 'for_each_element_id'
|
||||
- 'for_each_endpoint_of_node'
|
||||
- 'for_each_evictable_lru'
|
||||
- 'for_each_fib6_node_rt_rcu'
|
||||
- 'for_each_fib6_walker_rt'
|
||||
- 'for_each_free_mem_pfn_range_in_zone'
|
||||
- 'for_each_free_mem_pfn_range_in_zone_from'
|
||||
- 'for_each_free_mem_range'
|
||||
- 'for_each_free_mem_range_reverse'
|
||||
- 'for_each_func_rsrc'
|
||||
- 'for_each_hstate'
|
||||
- 'for_each_if'
|
||||
- 'for_each_iommu'
|
||||
- 'for_each_ip_tunnel_rcu'
|
||||
- 'for_each_irq_nr'
|
||||
- 'for_each_link_codecs'
|
||||
- 'for_each_link_cpus'
|
||||
- 'for_each_link_platforms'
|
||||
- 'for_each_lru'
|
||||
- 'for_each_matching_node'
|
||||
- 'for_each_matching_node_and_match'
|
||||
- 'for_each_member'
|
||||
- 'for_each_memcg_cache_index'
|
||||
- 'for_each_mem_pfn_range'
|
||||
- '__for_each_mem_range'
|
||||
- 'for_each_mem_range'
|
||||
- '__for_each_mem_range_rev'
|
||||
- 'for_each_mem_range_rev'
|
||||
- 'for_each_mem_region'
|
||||
- 'for_each_migratetype_order'
|
||||
- 'for_each_msi_entry'
|
||||
- 'for_each_msi_entry_safe'
|
||||
- 'for_each_msi_vector'
|
||||
- 'for_each_net'
|
||||
- 'for_each_net_continue_reverse'
|
||||
- 'for_each_netdev'
|
||||
- 'for_each_netdev_continue'
|
||||
- 'for_each_netdev_continue_rcu'
|
||||
- 'for_each_netdev_continue_reverse'
|
||||
- 'for_each_netdev_feature'
|
||||
- 'for_each_netdev_in_bond_rcu'
|
||||
- 'for_each_netdev_rcu'
|
||||
- 'for_each_netdev_reverse'
|
||||
- 'for_each_netdev_safe'
|
||||
- 'for_each_net_rcu'
|
||||
- 'for_each_new_connector_in_state'
|
||||
- 'for_each_new_crtc_in_state'
|
||||
- 'for_each_new_mst_mgr_in_state'
|
||||
- 'for_each_new_plane_in_state'
|
||||
- 'for_each_new_private_obj_in_state'
|
||||
- 'for_each_node'
|
||||
- 'for_each_node_by_name'
|
||||
- 'for_each_node_by_type'
|
||||
- 'for_each_node_mask'
|
||||
- 'for_each_node_state'
|
||||
- 'for_each_node_with_cpus'
|
||||
- 'for_each_node_with_property'
|
||||
- 'for_each_nonreserved_multicast_dest_pgid'
|
||||
- 'for_each_of_allnodes'
|
||||
- 'for_each_of_allnodes_from'
|
||||
- 'for_each_of_cpu_node'
|
||||
- 'for_each_of_pci_range'
|
||||
- 'for_each_old_connector_in_state'
|
||||
- 'for_each_old_crtc_in_state'
|
||||
- 'for_each_old_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_connector_in_state'
|
||||
- 'for_each_oldnew_crtc_in_state'
|
||||
- 'for_each_oldnew_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_plane_in_state'
|
||||
- 'for_each_oldnew_plane_in_state_reverse'
|
||||
- 'for_each_oldnew_private_obj_in_state'
|
||||
- 'for_each_old_plane_in_state'
|
||||
- 'for_each_old_private_obj_in_state'
|
||||
- 'for_each_online_cpu'
|
||||
- 'for_each_online_node'
|
||||
- 'for_each_online_pgdat'
|
||||
- 'for_each_pci_bridge'
|
||||
- 'for_each_pci_dev'
|
||||
- 'for_each_pci_msi_entry'
|
||||
- 'for_each_pcm_streams'
|
||||
- 'for_each_physmem_range'
|
||||
- 'for_each_populated_zone'
|
||||
- 'for_each_possible_cpu'
|
||||
- 'for_each_present_cpu'
|
||||
- 'for_each_prime_number'
|
||||
- 'for_each_prime_number_from'
|
||||
- 'for_each_process'
|
||||
- 'for_each_process_thread'
|
||||
- 'for_each_prop_codec_conf'
|
||||
- 'for_each_prop_dai_codec'
|
||||
- 'for_each_prop_dai_cpu'
|
||||
- 'for_each_prop_dlc_codecs'
|
||||
- 'for_each_prop_dlc_cpus'
|
||||
- 'for_each_prop_dlc_platforms'
|
||||
- 'for_each_property_of_node'
|
||||
- 'for_each_registered_fb'
|
||||
- 'for_each_requested_gpio'
|
||||
- 'for_each_requested_gpio_in_range'
|
||||
- 'for_each_reserved_mem_range'
|
||||
- 'for_each_reserved_mem_region'
|
||||
- 'for_each_rtd_codec_dais'
|
||||
- 'for_each_rtd_components'
|
||||
- 'for_each_rtd_cpu_dais'
|
||||
- 'for_each_rtd_dais'
|
||||
- 'for_each_set_bit'
|
||||
- 'for_each_set_bit_from'
|
||||
- 'for_each_set_clump8'
|
||||
- 'for_each_sg'
|
||||
- 'for_each_sg_dma_page'
|
||||
- 'for_each_sg_page'
|
||||
- 'for_each_sgtable_dma_page'
|
||||
- 'for_each_sgtable_dma_sg'
|
||||
- 'for_each_sgtable_page'
|
||||
- 'for_each_sgtable_sg'
|
||||
- 'for_each_sibling_event'
|
||||
- 'for_each_subelement'
|
||||
- 'for_each_subelement_extid'
|
||||
- 'for_each_subelement_id'
|
||||
- '__for_each_thread'
|
||||
- 'for_each_thread'
|
||||
- 'for_each_unicast_dest_pgid'
|
||||
- 'for_each_vsi'
|
||||
- 'for_each_wakeup_source'
|
||||
- 'for_each_zone'
|
||||
- 'for_each_zone_zonelist'
|
||||
- 'for_each_zone_zonelist_nodemask'
|
||||
- 'fwnode_for_each_available_child_node'
|
||||
- 'fwnode_for_each_child_node'
|
||||
- 'fwnode_graph_for_each_endpoint'
|
||||
- 'gadget_for_each_ep'
|
||||
- 'genradix_for_each'
|
||||
- 'genradix_for_each_from'
|
||||
- 'hash_for_each'
|
||||
- 'hash_for_each_possible'
|
||||
- 'hash_for_each_possible_rcu'
|
||||
- 'hash_for_each_possible_rcu_notrace'
|
||||
- 'hash_for_each_possible_safe'
|
||||
- 'hash_for_each_rcu'
|
||||
- 'hash_for_each_safe'
|
||||
- 'hctx_for_each_ctx'
|
||||
- 'hlist_bl_for_each_entry'
|
||||
- 'hlist_bl_for_each_entry_rcu'
|
||||
- 'hlist_bl_for_each_entry_safe'
|
||||
- 'hlist_for_each'
|
||||
- 'hlist_for_each_entry'
|
||||
- 'hlist_for_each_entry_continue'
|
||||
- 'hlist_for_each_entry_continue_rcu'
|
||||
- 'hlist_for_each_entry_continue_rcu_bh'
|
||||
- 'hlist_for_each_entry_from'
|
||||
- 'hlist_for_each_entry_from_rcu'
|
||||
- 'hlist_for_each_entry_rcu'
|
||||
- 'hlist_for_each_entry_rcu_bh'
|
||||
- 'hlist_for_each_entry_rcu_notrace'
|
||||
- 'hlist_for_each_entry_safe'
|
||||
- 'hlist_for_each_entry_srcu'
|
||||
- '__hlist_for_each_rcu'
|
||||
- 'hlist_for_each_safe'
|
||||
- 'hlist_nulls_for_each_entry'
|
||||
- 'hlist_nulls_for_each_entry_from'
|
||||
- 'hlist_nulls_for_each_entry_rcu'
|
||||
- 'hlist_nulls_for_each_entry_safe'
|
||||
- 'i3c_bus_for_each_i2cdev'
|
||||
- 'i3c_bus_for_each_i3cdev'
|
||||
- 'ide_host_for_each_port'
|
||||
- 'ide_port_for_each_dev'
|
||||
- 'ide_port_for_each_present_dev'
|
||||
- 'idr_for_each_entry'
|
||||
- 'idr_for_each_entry_continue'
|
||||
- 'idr_for_each_entry_continue_ul'
|
||||
- 'idr_for_each_entry_ul'
|
||||
- 'in_dev_for_each_ifa_rcu'
|
||||
- 'in_dev_for_each_ifa_rtnl'
|
||||
- 'inet_bind_bucket_for_each'
|
||||
- 'inet_lhash2_for_each_icsk_rcu'
|
||||
- 'key_for_each'
|
||||
- 'key_for_each_safe'
|
||||
- 'klp_for_each_func'
|
||||
- 'klp_for_each_func_safe'
|
||||
- 'klp_for_each_func_static'
|
||||
- 'klp_for_each_object'
|
||||
- 'klp_for_each_object_safe'
|
||||
- 'klp_for_each_object_static'
|
||||
- 'kunit_suite_for_each_test_case'
|
||||
- 'kvm_for_each_memslot'
|
||||
- 'kvm_for_each_vcpu'
|
||||
- 'list_for_each'
|
||||
- 'list_for_each_codec'
|
||||
- 'list_for_each_codec_safe'
|
||||
- 'list_for_each_continue'
|
||||
- 'list_for_each_entry'
|
||||
- 'list_for_each_entry_continue'
|
||||
- 'list_for_each_entry_continue_rcu'
|
||||
- 'list_for_each_entry_continue_reverse'
|
||||
- 'list_for_each_entry_from'
|
||||
- 'list_for_each_entry_from_rcu'
|
||||
- 'list_for_each_entry_from_reverse'
|
||||
- 'list_for_each_entry_lockless'
|
||||
- 'list_for_each_entry_rcu'
|
||||
- 'list_for_each_entry_reverse'
|
||||
- 'list_for_each_entry_safe'
|
||||
- 'list_for_each_entry_safe_continue'
|
||||
- 'list_for_each_entry_safe_from'
|
||||
- 'list_for_each_entry_safe_reverse'
|
||||
- 'list_for_each_entry_srcu'
|
||||
- 'list_for_each_prev'
|
||||
- 'list_for_each_prev_safe'
|
||||
- 'list_for_each_safe'
|
||||
- 'llist_for_each'
|
||||
- 'llist_for_each_entry'
|
||||
- 'llist_for_each_entry_safe'
|
||||
- 'llist_for_each_safe'
|
||||
- 'mci_for_each_dimm'
|
||||
- 'media_device_for_each_entity'
|
||||
- 'media_device_for_each_intf'
|
||||
- 'media_device_for_each_link'
|
||||
- 'media_device_for_each_pad'
|
||||
- 'nanddev_io_for_each_page'
|
||||
- 'netdev_for_each_lower_dev'
|
||||
- 'netdev_for_each_lower_private'
|
||||
- 'netdev_for_each_lower_private_rcu'
|
||||
- 'netdev_for_each_mc_addr'
|
||||
- 'netdev_for_each_uc_addr'
|
||||
- 'netdev_for_each_upper_dev_rcu'
|
||||
- 'netdev_hw_addr_list_for_each'
|
||||
- 'nft_rule_for_each_expr'
|
||||
- 'nla_for_each_attr'
|
||||
- 'nla_for_each_nested'
|
||||
- 'nlmsg_for_each_attr'
|
||||
- 'nlmsg_for_each_msg'
|
||||
- 'nr_neigh_for_each'
|
||||
- 'nr_neigh_for_each_safe'
|
||||
- 'nr_node_for_each'
|
||||
- 'nr_node_for_each_safe'
|
||||
- 'of_for_each_phandle'
|
||||
- 'of_property_for_each_string'
|
||||
- 'of_property_for_each_u32'
|
||||
- 'pci_bus_for_each_resource'
|
||||
- 'pcl_for_each_chunk'
|
||||
- 'pcl_for_each_segment'
|
||||
- 'pcm_for_each_format'
|
||||
- 'ping_portaddr_for_each_entry'
|
||||
- 'plist_for_each'
|
||||
- 'plist_for_each_continue'
|
||||
- 'plist_for_each_entry'
|
||||
- 'plist_for_each_entry_continue'
|
||||
- 'plist_for_each_entry_safe'
|
||||
- 'plist_for_each_safe'
|
||||
- 'pnp_for_each_card'
|
||||
- 'pnp_for_each_dev'
|
||||
- 'protocol_for_each_card'
|
||||
- 'protocol_for_each_dev'
|
||||
- 'queue_for_each_hw_ctx'
|
||||
- 'radix_tree_for_each_slot'
|
||||
- 'radix_tree_for_each_tagged'
|
||||
- 'rb_for_each'
|
||||
- 'rbtree_postorder_for_each_entry_safe'
|
||||
- 'rdma_for_each_block'
|
||||
- 'rdma_for_each_port'
|
||||
- 'rdma_umem_for_each_dma_block'
|
||||
- 'resource_list_for_each_entry'
|
||||
- 'resource_list_for_each_entry_safe'
|
||||
- 'rhl_for_each_entry_rcu'
|
||||
- 'rhl_for_each_rcu'
|
||||
- 'rht_for_each'
|
||||
- 'rht_for_each_entry'
|
||||
- 'rht_for_each_entry_from'
|
||||
- 'rht_for_each_entry_rcu'
|
||||
- 'rht_for_each_entry_rcu_from'
|
||||
- 'rht_for_each_entry_safe'
|
||||
- 'rht_for_each_from'
|
||||
- 'rht_for_each_rcu'
|
||||
- 'rht_for_each_rcu_from'
|
||||
- '__rq_for_each_bio'
|
||||
- 'rq_for_each_bvec'
|
||||
- 'rq_for_each_segment'
|
||||
- 'scsi_for_each_prot_sg'
|
||||
- 'scsi_for_each_sg'
|
||||
- 'sctp_for_each_hentry'
|
||||
- 'sctp_skb_for_each'
|
||||
- 'shdma_for_each_chan'
|
||||
- '__shost_for_each_device'
|
||||
- 'shost_for_each_device'
|
||||
- 'sk_for_each'
|
||||
- 'sk_for_each_bound'
|
||||
- 'sk_for_each_entry_offset_rcu'
|
||||
- 'sk_for_each_from'
|
||||
- 'sk_for_each_rcu'
|
||||
- 'sk_for_each_safe'
|
||||
- 'sk_nulls_for_each'
|
||||
- 'sk_nulls_for_each_from'
|
||||
- 'sk_nulls_for_each_rcu'
|
||||
- 'snd_array_for_each'
|
||||
- 'snd_pcm_group_for_each_entry'
|
||||
- 'snd_soc_dapm_widget_for_each_path'
|
||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
||||
- 'tb_property_for_each'
|
||||
- 'tcf_exts_for_each_action'
|
||||
- 'udp_portaddr_for_each_entry'
|
||||
- 'udp_portaddr_for_each_entry_rcu'
|
||||
- 'usb_hub_for_each_child'
|
||||
- 'v4l2_device_for_each_subdev'
|
||||
- 'v4l2_m2m_for_each_dst_buf'
|
||||
- 'v4l2_m2m_for_each_dst_buf_safe'
|
||||
- 'v4l2_m2m_for_each_src_buf'
|
||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
||||
- 'virtio_device_for_each_vq'
|
||||
- 'while_for_each_ftrace_op'
|
||||
- 'xa_for_each'
|
||||
- 'xa_for_each_marked'
|
||||
- 'xa_for_each_range'
|
||||
- 'xa_for_each_start'
|
||||
- 'xas_for_each'
|
||||
- 'xas_for_each_conflict'
|
||||
- 'xas_for_each_marked'
|
||||
- 'xbc_array_for_each_value'
|
||||
- 'xbc_for_each_key_value'
|
||||
- 'xbc_node_for_each_array_value'
|
||||
- 'xbc_node_for_each_child'
|
||||
- 'xbc_node_for_each_key_value'
|
||||
- 'zorro_for_each_dev'
|
||||
|
||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
#IndentPPDirectives: None # Unknown to clang-format-5.0
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
#SortUsingDeclarations: false # Unknown to clang-format-4.0
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
||||
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
||||
SpaceBeforeParens: ControlStatements
|
||||
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
||||
...
|
|
@ -0,0 +1,7 @@
|
|||
set confirm off
|
||||
set architecture riscv:rv64
|
||||
target remote 127.0.0.1:15234
|
||||
symbol-file build/kernel
|
||||
display/12i $pc-8
|
||||
set riscv use-compressed-breakpoints yes
|
||||
break *0x1000
|
|
@ -0,0 +1,22 @@
|
|||
name: Mirror and run GitLab CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'ch[0-9]'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Mirror + trigger CI
|
||||
uses: Gallium70/gitlab-mirror-and-ci-action@master
|
||||
with:
|
||||
args: "https://git.tsinghua.edu.cn/os-lab/2023s/public/ucore-tutorial-code-2023s"
|
||||
env:
|
||||
GITLAB_HOSTNAME: "git.tsinghua.edu.cn"
|
||||
GITLAB_PROJECT_ID: "20789"
|
||||
GITLAB_PROJECT_NAME: "ucore-tutorial-code-2023s"
|
||||
GITLAB_PROJECT_TOKEN: ${{secrets.GITLAB_PROJECT_TOKEN}}
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
|
@ -0,0 +1,12 @@
|
|||
.DS_Store
|
||||
.vscode
|
||||
.idea
|
||||
build
|
||||
target
|
||||
/user
|
||||
link_app.S
|
||||
kernel_app.ld
|
||||
*.o
|
||||
*.d
|
||||
*.asm
|
||||
*.sym
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
image: duskmoon/dev-env:ucore-ci
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
||||
test-code-job:
|
||||
stage: test
|
||||
script:
|
||||
- git clone https://token:${UCORE_CHECKER_REPO_READ_TOKEN_2023S}@git.tsinghua.edu.cn/os-lab/2023s/ta/ucore-tutorial-checker-2023s.git ucore-tutorial-ci
|
||||
- git clone https://token:${UCORE_TEST_REPO_READ_TOKEN_2023S}@git.tsinghua.edu.cn/os-lab/2023s/public/ucore-tutorial-test-2023s.git ucore-tutorial-ci/workplace/user
|
||||
- cd ucore-tutorial-ci && make test CHAPTER=`echo $CI_COMMIT_REF_NAME | grep -oP 'ch\K[0-9]'`
|
|
@ -0,0 +1,125 @@
|
|||
.PHONY: clean build user
|
||||
all: build_kernel
|
||||
|
||||
LOG ?= error
|
||||
|
||||
K = os
|
||||
U = user
|
||||
|
||||
TOOLPREFIX = riscv64-unknown-elf-
|
||||
CC = $(TOOLPREFIX)gcc
|
||||
AS = $(TOOLPREFIX)gcc
|
||||
LD = $(TOOLPREFIX)ld
|
||||
OBJCOPY = $(TOOLPREFIX)objcopy
|
||||
OBJDUMP = $(TOOLPREFIX)objdump
|
||||
PY = python3
|
||||
GDB = $(TOOLPREFIX)gdb
|
||||
CP = cp
|
||||
BUILDDIR = build
|
||||
C_SRCS = $(wildcard $K/*.c)
|
||||
AS_SRCS = $(wildcard $K/*.S)
|
||||
C_OBJS = $(addprefix $(BUILDDIR)/, $(addsuffix .o, $(basename $(C_SRCS))))
|
||||
AS_OBJS = $(addprefix $(BUILDDIR)/, $(addsuffix .o, $(basename $(AS_SRCS))))
|
||||
OBJS = $(C_OBJS) $(AS_OBJS)
|
||||
|
||||
HEADER_DEP = $(addsuffix .d, $(basename $(C_OBJS)))
|
||||
|
||||
ifeq (,$(findstring link_app.o,$(OBJS)))
|
||||
AS_OBJS += $(BUILDDIR)/$K/link_app.o
|
||||
endif
|
||||
|
||||
-include $(HEADER_DEP)
|
||||
|
||||
CFLAGS = -Wall -Werror -O -fno-omit-frame-pointer -ggdb
|
||||
CFLAGS += -MD
|
||||
CFLAGS += -mcmodel=medany
|
||||
CFLAGS += -ffreestanding -fno-common -nostdlib -mno-relax
|
||||
CFLAGS += -I$K
|
||||
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
|
||||
|
||||
ifeq ($(LOG), error)
|
||||
CFLAGS += -D LOG_LEVEL_ERROR
|
||||
else ifeq ($(LOG), warn)
|
||||
CFLAGS += -D LOG_LEVEL_WARN
|
||||
else ifeq ($(LOG), info)
|
||||
CFLAGS += -D LOG_LEVEL_INFO
|
||||
else ifeq ($(LOG), debug)
|
||||
CFLAGS += -D LOG_LEVEL_DEBUG
|
||||
else ifeq ($(LOG), trace)
|
||||
CFLAGS += -D LOG_LEVEL_TRACE
|
||||
endif
|
||||
|
||||
# Disable PIE when possible (for Ubuntu 16.10 toolchain)
|
||||
ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
|
||||
CFLAGS += -fno-pie -no-pie
|
||||
endif
|
||||
ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),)
|
||||
CFLAGS += -fno-pie -nopie
|
||||
endif
|
||||
|
||||
LDFLAGS = -z max-page-size=4096
|
||||
|
||||
$(AS_OBJS): $(BUILDDIR)/$K/%.o : $K/%.S
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(C_OBJS): $(BUILDDIR)/$K/%.o : $K/%.c $(BUILDDIR)/$K/%.d
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(HEADER_DEP): $(BUILDDIR)/$K/%.d : $K/%.c
|
||||
@mkdir -p $(@D)
|
||||
@set -e; rm -f $@; $(CC) -MM $< $(INCLUDEFLAGS) > $@.$$$$; \
|
||||
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
|
||||
rm -f $@.$$$$
|
||||
|
||||
os/link_app.o: $K/link_app.S
|
||||
os/link_app.S: scripts/pack.py
|
||||
@$(PY) scripts/pack.py
|
||||
os/kernel_app.ld: scripts/kernelld.py
|
||||
@$(PY) scripts/kernelld.py
|
||||
|
||||
build: build/kernel
|
||||
|
||||
build/kernel: $(OBJS) os/kernel_app.ld
|
||||
$(LD) $(LDFLAGS) -T os/kernel_app.ld -o $(BUILDDIR)/kernel $(OBJS)
|
||||
$(OBJDUMP) -S $(BUILDDIR)/kernel > $(BUILDDIR)/kernel.asm
|
||||
$(OBJDUMP) -t $(BUILDDIR)/kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(BUILDDIR)/kernel.sym
|
||||
@echo 'Build kernel done'
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR) os/kernel_app.ld os/link_app.S
|
||||
make -C $(U) clean
|
||||
|
||||
# BOARD
|
||||
BOARD ?= qemu
|
||||
SBI ?= rustsbi
|
||||
BOOTLOADER := ./bootloader/rustsbi-qemu.bin
|
||||
|
||||
QEMU = qemu-system-riscv64
|
||||
QEMUOPTS = \
|
||||
-nographic \
|
||||
-machine virt \
|
||||
-bios $(BOOTLOADER) \
|
||||
-kernel build/kernel \
|
||||
|
||||
run: build/kernel
|
||||
$(QEMU) $(QEMUOPTS)
|
||||
|
||||
# QEMU's gdb stub command line changed in 0.11
|
||||
QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
|
||||
then echo "-gdb tcp::15234"; \
|
||||
else echo "-s -p 15234"; fi)
|
||||
|
||||
debug: build/kernel .gdbinit
|
||||
$(QEMU) $(QEMUOPTS) -S $(QEMUGDB) &
|
||||
sleep 1
|
||||
$(GDB)
|
||||
|
||||
CHAPTER ?= $(shell git rev-parse --abbrev-ref HEAD | grep -oP 'ch\K[0-9]')
|
||||
|
||||
user:
|
||||
make -C $(U) CHAPTER=$(CHAPTER) BASE=$(BASE)
|
||||
|
||||
test: user run
|
||||
|
17
README.md
17
README.md
|
@ -9,3 +9,20 @@ Course project for THU-OS.
|
|||
实验 lab1-lab5 基准代码分别位于 ch3-ch8 分支下。
|
||||
|
||||
注:为了兼容清华 Git 的需求、避免同学在主分支写代码、明确主分支的功能性,特意单独建了仅包含 README 与 LICENSE 的 master 分支,完成课程实验时请在 clone 仓库后先 push master 分支到清华 Git,然后切到自己开发所需的分支进行后续操作。
|
||||
|
||||
## 本地开发测试
|
||||
|
||||
在本地开发并测试时,需要拉取 uCore-Tutorial-Test-2022A 到 `user` 文件夹。你可以根据网络情况和个人偏好选择下列一项执行:
|
||||
|
||||
```bash
|
||||
# 清华 git 使用 https
|
||||
git clone https://git.tsinghua.edu.cn/os-lab/public/ucore-tutorial-test-2022a.git user
|
||||
# 清华 git 使用 ssh
|
||||
git clone git@git.tsinghua.edu.cn:os-lab/public/ucore-tutorial-test-2022a.git user
|
||||
# GitHub 使用 https
|
||||
git clone https://github.com/LearningOS/uCore-Tutorial-Test-2022A.git user
|
||||
# GitHub 使用 ssh
|
||||
git clone git@github.com:LearningOS/uCore-Tutorial-Test-2022A.git user
|
||||
```
|
||||
|
||||
注意:`user` 已添加至 `.gitignore`,你无需将其提交,ci 也不会使用它
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
#include "console.h"
|
||||
#include "sbi.h"
|
||||
|
||||
void consputc(int c)
|
||||
{
|
||||
console_putchar(c);
|
||||
}
|
||||
|
||||
void console_init()
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
void consputc(int);
|
||||
void console_init();
|
||||
|
||||
#endif // CONSOLE_H
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef CONST_H
|
||||
#define CONST_H
|
||||
|
||||
#define PAGE_SIZE (0x1000)
|
||||
|
||||
enum {
|
||||
STDIN = 0,
|
||||
STDOUT = 1,
|
||||
STDERR = 2,
|
||||
};
|
||||
|
||||
#endif // CONST_H
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef DEFS_H
|
||||
#define DEFS_H
|
||||
|
||||
#include "const.h"
|
||||
#include "log.h"
|
||||
#include "printf.h"
|
||||
#include "riscv.h"
|
||||
#include "sbi.h"
|
||||
#include "string.h"
|
||||
#include "types.h"
|
||||
|
||||
// number of elements in fixed-size array
|
||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
|
||||
#endif // DEF_H
|
|
@ -0,0 +1,12 @@
|
|||
.section .text.entry
|
||||
.globl _entry
|
||||
_entry:
|
||||
la sp, boot_stack_top
|
||||
call main
|
||||
|
||||
.section .bss.stack
|
||||
.globl boot_stack
|
||||
boot_stack:
|
||||
.space 4096 * 16
|
||||
.globl boot_stack_top
|
||||
boot_stack_top:
|
|
@ -0,0 +1,51 @@
|
|||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_entry)
|
||||
BASE_ADDRESS = 0x80200000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BASE_ADDRESS;
|
||||
skernel = .;
|
||||
|
||||
s_text = .;
|
||||
.text : {
|
||||
*(.text.entry)
|
||||
*(.text .text.*)
|
||||
. = ALIGN(0x1000);
|
||||
*(trampsec)
|
||||
. = ALIGN(0x1000);
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_text = .;
|
||||
s_rodata = .;
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_rodata = .;
|
||||
s_data = .;
|
||||
.data : {
|
||||
*(.data.apps)
|
||||
*(.data .data.*)
|
||||
*(.sdata .sdata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_data = .;
|
||||
.bss : {
|
||||
*(.bss.stack)
|
||||
s_bss = .;
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_bss = .;
|
||||
ekernel = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import os
|
||||
|
||||
TARGET_DIR = "../user/target/"
|
||||
|
||||
if __name__ == '__main__':
|
||||
f = open("kernel_app.ld", mode="w")
|
||||
apps = os.listdir(TARGET_DIR)
|
||||
f.write(
|
||||
'''OUTPUT_ARCH(riscv)
|
||||
ENTRY(_entry)
|
||||
BASE_ADDRESS = 0x80200000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BASE_ADDRESS;
|
||||
skernel = .;
|
||||
|
||||
s_text = .;
|
||||
.text : {
|
||||
*(.text.entry)
|
||||
*(.text .text.*)
|
||||
. = ALIGN(0x1000);
|
||||
*(trampsec)
|
||||
. = ALIGN(0x1000);
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_text = .;
|
||||
s_rodata = .;
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_rodata = .;
|
||||
s_data = .;
|
||||
.data : {
|
||||
*(.data)
|
||||
''')
|
||||
for (idx, _) in enumerate(apps):
|
||||
f.write(' . = ALIGN(0x1000);\n')
|
||||
f.write(' *(.data.app{})\n'.format(idx))
|
||||
f.write(
|
||||
'''
|
||||
*(.data.*)
|
||||
*(.sdata .sdata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_data = .;
|
||||
.bss : {
|
||||
*(.bss.stack)
|
||||
s_bss = .;
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_bss = .;
|
||||
ekernel = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
||||
''')
|
||||
f.close()
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include "loader.h"
|
||||
#include "defs.h"
|
||||
#include "trap.h"
|
||||
|
||||
static int app_cur, app_num;
|
||||
static uint64 *app_info_ptr;
|
||||
extern char _app_num[], userret[], boot_stack_top[], ekernel[];
|
||||
|
||||
void loader_init()
|
||||
{
|
||||
if ((uint64)ekernel >= BASE_ADDRESS) {
|
||||
panic("kernel too large...\n");
|
||||
}
|
||||
app_info_ptr = (uint64 *)_app_num;
|
||||
app_cur = -1;
|
||||
app_num = *app_info_ptr;
|
||||
}
|
||||
|
||||
__attribute__((aligned(4096))) char user_stack[USER_STACK_SIZE];
|
||||
__attribute__((aligned(4096))) char trap_page[TRAP_PAGE_SIZE];
|
||||
|
||||
int load_app(uint64 *info)
|
||||
{
|
||||
uint64 start = info[0], end = info[1], length = end - start;
|
||||
memset((void *)BASE_ADDRESS, 0, MAX_APP_SIZE);
|
||||
memmove((void *)BASE_ADDRESS, (void *)start, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
int run_next_app()
|
||||
{
|
||||
struct trapframe *trapframe = (struct trapframe *)trap_page;
|
||||
app_cur++;
|
||||
app_info_ptr++;
|
||||
if (app_cur >= app_num) {
|
||||
return -1;
|
||||
}
|
||||
infof("load and run app %d", app_cur);
|
||||
uint64 length = load_app(app_info_ptr);
|
||||
debugf("bin range = [%p, %p)", *app_info_ptr, *app_info_ptr + length);
|
||||
memset(trapframe, 0, 4096);
|
||||
trapframe->epc = BASE_ADDRESS;
|
||||
trapframe->sp = (uint64)user_stack + USER_STACK_SIZE;
|
||||
usertrapret(trapframe, (uint64)boot_stack_top);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef BATCH_H
|
||||
#define BATCH_H
|
||||
|
||||
#include "const.h"
|
||||
#include "types.h"
|
||||
|
||||
void loader_init();
|
||||
int run_next_app();
|
||||
|
||||
#define BASE_ADDRESS (0x80400000)
|
||||
#define MAX_APP_SIZE (0x20000)
|
||||
#define USER_STACK_SIZE PAGE_SIZE
|
||||
#define TRAP_PAGE_SIZE PAGE_SIZE
|
||||
|
||||
#endif // BATCH_H
|
|
@ -0,0 +1,118 @@
|
|||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
extern void printf(char *, ...);
|
||||
extern int threadid();
|
||||
extern void dummy(int, ...);
|
||||
|
||||
#if defined(LOG_LEVEL_ERROR)
|
||||
|
||||
#define USE_LOG_ERROR
|
||||
|
||||
#endif // LOG_LEVEL_ERROR
|
||||
|
||||
#if defined(LOG_LEVEL_WARN)
|
||||
|
||||
#define USE_LOG_ERROR
|
||||
#define USE_LOG_WARN
|
||||
|
||||
#endif // LOG_LEVEL_ERROR
|
||||
|
||||
#if defined(LOG_LEVEL_INFO)
|
||||
|
||||
#define USE_LOG_ERROR
|
||||
#define USE_LOG_WARN
|
||||
#define USE_LOG_INFO
|
||||
|
||||
#endif // LOG_LEVEL_INFO
|
||||
|
||||
#if defined(LOG_LEVEL_DEBUG)
|
||||
|
||||
#define USE_LOG_ERROR
|
||||
#define USE_LOG_WARN
|
||||
#define USE_LOG_INFO
|
||||
#define USE_LOG_DEBUG
|
||||
|
||||
#endif // LOG_LEVEL_DEBUG
|
||||
|
||||
#if defined(LOG_LEVEL_TRACE)
|
||||
|
||||
#define USE_LOG_ERROR
|
||||
#define USE_LOG_WARN
|
||||
#define USE_LOG_INFO
|
||||
#define USE_LOG_DEBUG
|
||||
#define USE_LOG_TRACE
|
||||
|
||||
#endif // LOG_LEVEL_TRACE
|
||||
|
||||
enum LOG_COLOR {
|
||||
RED = 31,
|
||||
GREEN = 32,
|
||||
BLUE = 34,
|
||||
GRAY = 90,
|
||||
YELLOW = 93,
|
||||
};
|
||||
|
||||
#if defined(USE_LOG_ERROR)
|
||||
#define errorf(fmt, ...) \
|
||||
do { \
|
||||
int tid = threadid(); \
|
||||
printf("\x1b[%dm[%s %d]" fmt "\x1b[0m\n", RED, "ERROR", tid, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define errorf(fmt, ...) dummy(0, ##__VA_ARGS__)
|
||||
#endif // USE_LOG_ERROR
|
||||
|
||||
#if defined(USE_LOG_WARN)
|
||||
#define warnf(fmt, ...) \
|
||||
do { \
|
||||
int tid = threadid(); \
|
||||
printf("\x1b[%dm[%s %d]" fmt "\x1b[0m\n", YELLOW, "WARN", tid, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define warnf(fmt, ...) dummy(0, ##__VA_ARGS__)
|
||||
#endif // USE_LOG_WARN
|
||||
|
||||
#if defined(USE_LOG_INFO)
|
||||
#define infof(fmt, ...) \
|
||||
do { \
|
||||
int tid = threadid(); \
|
||||
printf("\x1b[%dm[%s %d]" fmt "\x1b[0m\n", BLUE, "INFO", tid, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define infof(fmt, ...) dummy(0, ##__VA_ARGS__)
|
||||
#endif // USE_LOG_INFO
|
||||
|
||||
#if defined(USE_LOG_DEBUG)
|
||||
#define debugf(fmt, ...) \
|
||||
do { \
|
||||
int tid = threadid(); \
|
||||
printf("\x1b[%dm[%s %d]" fmt "\x1b[0m\n", GREEN, "DEBUG", tid, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define debugf(fmt, ...) dummy(0, ##__VA_ARGS__)
|
||||
#endif // USE_LOG_DEBUG
|
||||
|
||||
#if defined(USE_LOG_TRACE)
|
||||
#define tracef(fmt, ...) \
|
||||
do { \
|
||||
int tid = threadid(); \
|
||||
printf("\x1b[%dm[%s %d]" fmt "\x1b[0m\n", GRAY, "TRACE", tid, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define tracef(fmt, ...) dummy(0, ##__VA_ARGS__)
|
||||
#endif // USE_LOG_TRACE
|
||||
|
||||
#define panic(fmt, ...) \
|
||||
do { \
|
||||
int tid = threadid(); \
|
||||
printf("\x1b[%dm[%s %d] %s:%d: " fmt "\x1b[0m\n", RED, \
|
||||
"PANIC", tid, __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif //! LOG_H
|
|
@ -0,0 +1,25 @@
|
|||
#include "console.h"
|
||||
#include "defs.h"
|
||||
#include "loader.h"
|
||||
#include "trap.h"
|
||||
|
||||
int threadid()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clean_bss()
|
||||
{
|
||||
extern char s_bss[];
|
||||
extern char e_bss[];
|
||||
memset(s_bss, 0, e_bss - s_bss);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
clean_bss();
|
||||
printf("hello wrold!\n");
|
||||
trap_init();
|
||||
loader_init();
|
||||
run_next_app();
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import os
|
||||
|
||||
TARGET_DIR = "../user/target"
|
||||
|
||||
if __name__ == '__main__':
|
||||
f = open("link_app.S", mode="w")
|
||||
apps = os.listdir(TARGET_DIR)
|
||||
apps.sort()
|
||||
f.write(
|
||||
''' .align 4
|
||||
.section .data
|
||||
.global _app_num
|
||||
_app_num:
|
||||
.quad {}
|
||||
'''.format(len(apps))
|
||||
)
|
||||
|
||||
for (idx, _) in enumerate(apps):
|
||||
f.write(' .quad app_{}_start\n'.format(idx))
|
||||
f.write(' .quad app_{}_end\n'.format(len(apps) - 1))
|
||||
|
||||
f.write(
|
||||
'''
|
||||
.global _app_names
|
||||
_app_names:
|
||||
''');
|
||||
|
||||
for app in apps:
|
||||
app = app[:app.find('.')]
|
||||
f.write(" .string \"" + app + "\"\n")
|
||||
|
||||
for (idx, app) in enumerate(apps):
|
||||
f.write(
|
||||
'''
|
||||
.section .data.app{0}
|
||||
.global app_{0}_start
|
||||
app_{0}_start:
|
||||
.incbin "{1}"
|
||||
'''.format(idx, TARGET_DIR + app)
|
||||
)
|
||||
f.write('app_{}_end:\n\n'.format(len(apps) - 1))
|
||||
f.close()
|
|
@ -0,0 +1,83 @@
|
|||
#include <stdarg.h>
|
||||
#include "console.h"
|
||||
#include "defs.h"
|
||||
static char digits[] = "0123456789abcdef";
|
||||
|
||||
static void printint(int xx, int base, int sign)
|
||||
{
|
||||
char buf[16];
|
||||
int i;
|
||||
uint x;
|
||||
|
||||
if (sign && (sign = xx < 0))
|
||||
x = -xx;
|
||||
else
|
||||
x = xx;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
buf[i++] = digits[x % base];
|
||||
} while ((x /= base) != 0);
|
||||
|
||||
if (sign)
|
||||
buf[i++] = '-';
|
||||
|
||||
while (--i >= 0)
|
||||
consputc(buf[i]);
|
||||
}
|
||||
|
||||
static void printptr(uint64 x)
|
||||
{
|
||||
int i;
|
||||
consputc('0');
|
||||
consputc('x');
|
||||
for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4)
|
||||
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
|
||||
}
|
||||
|
||||
// Print to the console. only understands %d, %x, %p, %s.
|
||||
void printf(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, c;
|
||||
char *s;
|
||||
|
||||
if (fmt == 0)
|
||||
panic("null fmt");
|
||||
|
||||
va_start(ap, fmt);
|
||||
for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
|
||||
if (c != '%') {
|
||||
consputc(c);
|
||||
continue;
|
||||
}
|
||||
c = fmt[++i] & 0xff;
|
||||
if (c == 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'd':
|
||||
printint(va_arg(ap, int), 10, 1);
|
||||
break;
|
||||
case 'x':
|
||||
printint(va_arg(ap, int), 16, 1);
|
||||
break;
|
||||
case 'p':
|
||||
printptr(va_arg(ap, uint64));
|
||||
break;
|
||||
case 's':
|
||||
if ((s = va_arg(ap, char *)) == 0)
|
||||
s = "(null)";
|
||||
for (; *s; s++)
|
||||
consputc(*s);
|
||||
break;
|
||||
case '%':
|
||||
consputc('%');
|
||||
break;
|
||||
default:
|
||||
// Print unknown % sequence to draw attention.
|
||||
consputc('%');
|
||||
consputc(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef PRINTF_H
|
||||
#define PRINTF_H
|
||||
|
||||
void printf(char *, ...);
|
||||
|
||||
#endif // PRINTF_H
|
|
@ -0,0 +1,322 @@
|
|||
#ifndef RISCV_H
|
||||
#define RISCV_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
// which hart (core) is this?
|
||||
static inline uint64 r_mhartid()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, mhartid" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine Status Register, mstatus
|
||||
|
||||
#define MSTATUS_MPP_MASK (3L << 11) // previous mode.
|
||||
#define MSTATUS_MPP_M (3L << 11)
|
||||
#define MSTATUS_MPP_S (1L << 11)
|
||||
#define MSTATUS_MPP_U (0L << 11)
|
||||
#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable.
|
||||
|
||||
static inline uint64 r_mstatus()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, mstatus" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_mstatus(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mstatus, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// machine exception program counter, holds the
|
||||
// instruction address to which a return from
|
||||
// exception will go.
|
||||
static inline void w_mepc(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mepc, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Supervisor Status Register, sstatus
|
||||
|
||||
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
|
||||
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
|
||||
#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
|
||||
#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable
|
||||
#define SSTATUS_UIE (1L << 0) // User Interrupt Enable
|
||||
|
||||
static inline uint64 r_sstatus()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, sstatus" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_sstatus(uint64 x)
|
||||
{
|
||||
asm volatile("csrw sstatus, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Supervisor Interrupt Pending
|
||||
static inline uint64 r_sip()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, sip" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_sip(uint64 x)
|
||||
{
|
||||
asm volatile("csrw sip, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Supervisor Interrupt Enable
|
||||
#define SIE_SEIE (1L << 9) // external
|
||||
#define SIE_STIE (1L << 5) // timer
|
||||
#define SIE_SSIE (1L << 1) // software
|
||||
static inline uint64 r_sie()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, sie" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_sie(uint64 x)
|
||||
{
|
||||
asm volatile("csrw sie, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Machine-mode Interrupt Enable
|
||||
#define MIE_MEIE (1L << 11) // external
|
||||
#define MIE_MTIE (1L << 7) // timer
|
||||
#define MIE_MSIE (1L << 3) // software
|
||||
static inline uint64 r_mie()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, mie" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_mie(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mie, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// machine exception program counter, holds the
|
||||
// instruction address to which a return from
|
||||
// exception will go.
|
||||
static inline void w_sepc(uint64 x)
|
||||
{
|
||||
asm volatile("csrw sepc, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64 r_sepc()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, sepc" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine Exception Delegation
|
||||
static inline uint64 r_medeleg()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, medeleg" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_medeleg(uint64 x)
|
||||
{
|
||||
asm volatile("csrw medeleg, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Machine Interrupt Delegation
|
||||
static inline uint64 r_mideleg()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, mideleg" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_mideleg(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mideleg, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Supervisor Trap-Vector Base Address
|
||||
// low two bits are mode.
|
||||
static inline void w_stvec(uint64 x)
|
||||
{
|
||||
asm volatile("csrw stvec, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64 r_stvec()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, stvec" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine-mode interrupt vector
|
||||
static inline void w_mtvec(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mtvec, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// use riscv's sv39 page table scheme.
|
||||
#define SATP_SV39 (8L << 60)
|
||||
|
||||
#define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))
|
||||
|
||||
// supervisor address translation and protection;
|
||||
// holds the address of the page table.
|
||||
static inline void w_satp(uint64 x)
|
||||
{
|
||||
asm volatile("csrw satp, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64 r_satp()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, satp" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Supervisor Scratch register, for early trap handler in trampoline.S.
|
||||
static inline void w_sscratch(uint64 x)
|
||||
{
|
||||
asm volatile("csrw sscratch, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline void w_mscratch(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mscratch, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
// Supervisor Trap Cause
|
||||
static inline uint64 r_scause()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, scause" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Supervisor Trap Value
|
||||
static inline uint64 r_stval()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, stval" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine-mode Counter-Enable
|
||||
static inline void w_mcounteren(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mcounteren, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64 r_mcounteren()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, mcounteren" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// machine-mode cycle counter
|
||||
static inline uint64 r_time()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("csrr %0, time" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// enable device interrupts
|
||||
static inline void intr_on()
|
||||
{
|
||||
w_sstatus(r_sstatus() | SSTATUS_SIE);
|
||||
}
|
||||
|
||||
// disable device interrupts
|
||||
static inline void intr_off()
|
||||
{
|
||||
w_sstatus(r_sstatus() & ~SSTATUS_SIE);
|
||||
}
|
||||
|
||||
// are device interrupts enabled?
|
||||
static inline int intr_get()
|
||||
{
|
||||
uint64 x = r_sstatus();
|
||||
return (x & SSTATUS_SIE) != 0;
|
||||
}
|
||||
|
||||
static inline uint64 r_sp()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("mv %0, sp" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// read and write tp, the thread pointer, which holds
|
||||
// this core's hartid (core number), the index into cpus[].
|
||||
static inline uint64 r_tp()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("mv %0, tp" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void w_tp(uint64 x)
|
||||
{
|
||||
asm volatile("mv tp, %0" : : "r"(x));
|
||||
}
|
||||
|
||||
static inline uint64 r_ra()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("mv %0, ra" : "=r"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// flush the TLB.
|
||||
static inline void sfence_vma()
|
||||
{
|
||||
// the zero, zero means flush all TLB entries.
|
||||
asm volatile("sfence.vma zero, zero");
|
||||
}
|
||||
|
||||
#define PGSIZE 4096 // bytes per page
|
||||
#define PGSHIFT 12 // bits of offset within a page
|
||||
|
||||
#define PGROUNDUP(sz) (((sz) + PGSIZE - 1) & ~(PGSIZE - 1))
|
||||
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE - 1))
|
||||
|
||||
#define PTE_V (1L << 0) // valid
|
||||
#define PTE_R (1L << 1)
|
||||
#define PTE_W (1L << 2)
|
||||
#define PTE_X (1L << 3)
|
||||
#define PTE_U (1L << 4) // 1 -> user can access
|
||||
|
||||
// shift a physical address to the right place for a PTE.
|
||||
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
|
||||
|
||||
#define PTE2PA(pte) (((pte) >> 10) << 12)
|
||||
|
||||
#define PTE_FLAGS(pte) ((pte)&0x3FF)
|
||||
|
||||
// extract the three 9-bit page table indices from a virtual address.
|
||||
#define PXMASK 0x1FF // 9 bits
|
||||
#define PXSHIFT(level) (PGSHIFT + (9 * (level)))
|
||||
#define PX(level, va) ((((uint64)(va)) >> PXSHIFT(level)) & PXMASK)
|
||||
|
||||
// one beyond the highest possible virtual address.
|
||||
// MAXVA is actually one bit less than the max allowed by
|
||||
// Sv39, to avoid having to sign-extend virtual addresses
|
||||
// that have the high bit set.
|
||||
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))
|
||||
|
||||
typedef uint64 pte_t;
|
||||
typedef uint64 *pagetable_t; // 512 PTEs
|
||||
|
||||
#endif // RISCV_H
|
|
@ -0,0 +1,39 @@
|
|||
#include "sbi.h"
|
||||
#include "types.h"
|
||||
const uint64 SBI_SET_TIMER = 0;
|
||||
const uint64 SBI_CONSOLE_PUTCHAR = 1;
|
||||
const uint64 SBI_CONSOLE_GETCHAR = 2;
|
||||
const uint64 SBI_CLEAR_IPI = 3;
|
||||
const uint64 SBI_SEND_IPI = 4;
|
||||
const uint64 SBI_REMOTE_FENCE_I = 5;
|
||||
const uint64 SBI_REMOTE_SFENCE_VMA = 6;
|
||||
const uint64 SBI_REMOTE_SFENCE_VMA_ASID = 7;
|
||||
const uint64 SBI_SHUTDOWN = 8;
|
||||
|
||||
int inline sbi_call(uint64 which, uint64 arg0, uint64 arg1, uint64 arg2)
|
||||
{
|
||||
register uint64 a0 asm("a0") = arg0;
|
||||
register uint64 a1 asm("a1") = arg1;
|
||||
register uint64 a2 asm("a2") = arg2;
|
||||
register uint64 a7 asm("a7") = which;
|
||||
asm volatile("ecall"
|
||||
: "=r"(a0)
|
||||
: "r"(a0), "r"(a1), "r"(a2), "r"(a7)
|
||||
: "memory");
|
||||
return a0;
|
||||
}
|
||||
|
||||
void console_putchar(int c)
|
||||
{
|
||||
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
|
||||
}
|
||||
|
||||
int console_getchar()
|
||||
{
|
||||
return sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0);
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
sbi_call(SBI_SHUTDOWN, 0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef SBI_H
|
||||
#define SBI_H
|
||||
|
||||
void console_putchar(int);
|
||||
int console_getchar();
|
||||
void shutdown();
|
||||
|
||||
#endif // SBI_H
|
|
@ -0,0 +1,100 @@
|
|||
#include "string.h"
|
||||
#include "types.h"
|
||||
|
||||
void *memset(void *dst, int c, uint n)
|
||||
{
|
||||
char *cdst = (char *)dst;
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
cdst[i] = c;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
int memcmp(const void *v1, const void *v2, uint n)
|
||||
{
|
||||
const uchar *s1, *s2;
|
||||
|
||||
s1 = v1;
|
||||
s2 = v2;
|
||||
while (n-- > 0) {
|
||||
if (*s1 != *s2)
|
||||
return *s1 - *s2;
|
||||
s1++, s2++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *memmove(void *dst, const void *src, uint n)
|
||||
{
|
||||
const char *s;
|
||||
char *d;
|
||||
|
||||
s = src;
|
||||
d = dst;
|
||||
if (s < d && s + n > d) {
|
||||
s += n;
|
||||
d += n;
|
||||
while (n-- > 0)
|
||||
*--d = *--s;
|
||||
} else
|
||||
while (n-- > 0)
|
||||
*d++ = *s++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
// memcpy exists to placate GCC. Use memmove.
|
||||
void *memcpy(void *dst, const void *src, uint n)
|
||||
{
|
||||
return memmove(dst, src, n);
|
||||
}
|
||||
|
||||
int strncmp(const char *p, const char *q, uint n)
|
||||
{
|
||||
while (n > 0 && *p && *p == *q)
|
||||
n--, p++, q++;
|
||||
if (n == 0)
|
||||
return 0;
|
||||
return (uchar)*p - (uchar)*q;
|
||||
}
|
||||
|
||||
char *strncpy(char *s, const char *t, int n)
|
||||
{
|
||||
char *os;
|
||||
|
||||
os = s;
|
||||
while (n-- > 0 && (*s++ = *t++) != 0)
|
||||
;
|
||||
while (n-- > 0)
|
||||
*s++ = 0;
|
||||
return os;
|
||||
}
|
||||
|
||||
// Like strncpy but guaranteed to NUL-terminate.
|
||||
char *safestrcpy(char *s, const char *t, int n)
|
||||
{
|
||||
char *os;
|
||||
|
||||
os = s;
|
||||
if (n <= 0)
|
||||
return os;
|
||||
while (--n > 0 && (*s++ = *t++) != 0)
|
||||
;
|
||||
*s = 0;
|
||||
return os;
|
||||
}
|
||||
|
||||
int strlen(const char *s)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; s[n]; n++)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
|
||||
void dummy(int _, ...)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
int memcmp(const void *, const void *, uint);
|
||||
void *memmove(void *, const void *, uint);
|
||||
void *memset(void *, int, uint);
|
||||
char *safestrcpy(char *, const char *, int);
|
||||
int strlen(const char *);
|
||||
int strncmp(const char *, const char *, uint);
|
||||
char *strncpy(char *, const char *, int);
|
||||
|
||||
#endif // STRING_H
|
|
@ -0,0 +1,50 @@
|
|||
#include "syscall.h"
|
||||
#include "defs.h"
|
||||
#include "loader.h"
|
||||
#include "syscall_ids.h"
|
||||
#include "trap.h"
|
||||
|
||||
uint64 sys_write(int fd, char *str, uint len)
|
||||
{
|
||||
debugf("sys_write fd = %d str = %x, len = %d", fd, str, len);
|
||||
if (fd != STDOUT)
|
||||
return -1;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
console_putchar(str[i]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void sys_exit(int code)
|
||||
{
|
||||
debugf("sysexit(%d)", code);
|
||||
run_next_app();
|
||||
printf("ALL DONE\n");
|
||||
shutdown();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
extern char trap_page[];
|
||||
|
||||
void syscall()
|
||||
{
|
||||
struct trapframe *trapframe = (struct trapframe *)trap_page;
|
||||
int id = trapframe->a7, ret;
|
||||
uint64 args[6] = { trapframe->a0, trapframe->a1, trapframe->a2,
|
||||
trapframe->a3, trapframe->a4, trapframe->a5 };
|
||||
tracef("syscall %d args = [%x, %x, %x, %x, %x, %x]", id, args[0],
|
||||
args[1], args[2], args[3], args[4], args[5]);
|
||||
switch (id) {
|
||||
case SYS_write:
|
||||
ret = sys_write(args[0], (char *)args[1], args[2]);
|
||||
break;
|
||||
case SYS_exit:
|
||||
sys_exit(args[0]);
|
||||
// __builtin_unreachable();
|
||||
default:
|
||||
ret = -1;
|
||||
errorf("unknown syscall %d", id);
|
||||
}
|
||||
trapframe->a0 = ret;
|
||||
tracef("syscall ret %d", ret);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef SYSCALL_H
|
||||
#define SYSCALL_H
|
||||
|
||||
void syscall();
|
||||
|
||||
#endif // SYSCALL_H
|
|
@ -0,0 +1,295 @@
|
|||
#define SYS_io_setup 0
|
||||
#define SYS_io_destroy 1
|
||||
#define SYS_io_submit 2
|
||||
#define SYS_io_cancel 3
|
||||
#define SYS_io_getevents 4
|
||||
#define SYS_setxattr 5
|
||||
#define SYS_lsetxattr 6
|
||||
#define SYS_fsetxattr 7
|
||||
#define SYS_getxattr 8
|
||||
#define SYS_lgetxattr 9
|
||||
#define SYS_fgetxattr 10
|
||||
#define SYS_listxattr 11
|
||||
#define SYS_llistxattr 12
|
||||
#define SYS_flistxattr 13
|
||||
#define SYS_removexattr 14
|
||||
#define SYS_lremovexattr 15
|
||||
#define SYS_fremovexattr 16
|
||||
#define SYS_getcwd 17
|
||||
#define SYS_lookup_dcookie 18
|
||||
#define SYS_eventfd2 19
|
||||
#define SYS_epoll_create1 20
|
||||
#define SYS_epoll_ctl 21
|
||||
#define SYS_epoll_pwait 22
|
||||
#define SYS_dup 23
|
||||
#define SYS_dup3 24
|
||||
#define SYS_fcntl 25
|
||||
#define SYS_inotify_init1 26
|
||||
#define SYS_inotify_add_watch 27
|
||||
#define SYS_inotify_rm_watch 28
|
||||
#define SYS_ioctl 29
|
||||
#define SYS_ioprio_set 30
|
||||
#define SYS_ioprio_get 31
|
||||
#define SYS_flock 32
|
||||
#define SYS_mknodat 33
|
||||
#define SYS_mkdirat 34
|
||||
#define SYS_unlinkat 35
|
||||
#define SYS_symlinkat 36
|
||||
#define SYS_linkat 37
|
||||
#define SYS_umount2 39
|
||||
#define SYS_mount 40
|
||||
#define SYS_pivot_root 41
|
||||
#define SYS_nfsservctl 42
|
||||
#define SYS_statfs 43
|
||||
#define SYS_fstatfs 44
|
||||
#define SYS_truncate 45
|
||||
#define SYS_ftruncate 46
|
||||
#define SYS_fallocate 47
|
||||
#define SYS_faccessat 48
|
||||
#define SYS_chdir 49
|
||||
#define SYS_fchdir 50
|
||||
#define SYS_chroot 51
|
||||
#define SYS_fchmod 52
|
||||
#define SYS_fchmodat 53
|
||||
#define SYS_fchownat 54
|
||||
#define SYS_fchown 55
|
||||
#define SYS_openat 56
|
||||
#define SYS_close 57
|
||||
#define SYS_vhangup 58
|
||||
#define SYS_pipe2 59
|
||||
#define SYS_quotactl 60
|
||||
#define SYS_getdents64 61
|
||||
#define SYS_lseek 62
|
||||
#define SYS_read 63
|
||||
#define SYS_write 64
|
||||
#define SYS_readv 65
|
||||
#define SYS_writev 66
|
||||
#define SYS_pread64 67
|
||||
#define SYS_pwrite64 68
|
||||
#define SYS_preadv 69
|
||||
#define SYS_pwritev 70
|
||||
#define SYS_sendfile 71
|
||||
#define SYS_pselect6 72
|
||||
#define SYS_ppoll 73
|
||||
#define SYS_signalfd4 74
|
||||
#define SYS_vmsplice 75
|
||||
#define SYS_splice 76
|
||||
#define SYS_tee 77
|
||||
#define SYS_readlinkat 78
|
||||
#define SYS_fstatat 79
|
||||
#define SYS_fstat 80
|
||||
#define SYS_sync 81
|
||||
#define SYS_fsync 82
|
||||
#define SYS_fdatasync 83
|
||||
#define SYS_sync_file_range 84
|
||||
#define SYS_timerfd_create 85
|
||||
#define SYS_timerfd_settime 86
|
||||
#define SYS_timerfd_gettime 87
|
||||
#define SYS_utimensat 88
|
||||
#define SYS_acct 89
|
||||
#define SYS_capget 90
|
||||
#define SYS_capset 91
|
||||
#define SYS_personality 92
|
||||
#define SYS_exit 93
|
||||
#define SYS_exit_group 94
|
||||
#define SYS_waitid 95
|
||||
#define SYS_set_tid_address 96
|
||||
#define SYS_unshare 97
|
||||
#define SYS_futex 98
|
||||
#define SYS_set_robust_list 99
|
||||
#define SYS_get_robust_list 100
|
||||
#define SYS_nanosleep 101
|
||||
#define SYS_getitimer 102
|
||||
#define SYS_setitimer 103
|
||||
#define SYS_kexec_load 104
|
||||
#define SYS_init_module 105
|
||||
#define SYS_delete_module 106
|
||||
#define SYS_timer_create 107
|
||||
#define SYS_timer_gettime 108
|
||||
#define SYS_timer_getoverrun 109
|
||||
#define SYS_timer_settime 110
|
||||
#define SYS_timer_delete 111
|
||||
#define SYS_clock_settime 112
|
||||
#define SYS_clock_gettime 113
|
||||
#define SYS_clock_getres 114
|
||||
#define SYS_clock_nanosleep 115
|
||||
#define SYS_syslog 116
|
||||
#define SYS_ptrace 117
|
||||
#define SYS_sched_setparam 118
|
||||
#define SYS_sched_setscheduler 119
|
||||
#define SYS_sched_getscheduler 120
|
||||
#define SYS_sched_getparam 121
|
||||
#define SYS_sched_setaffinity 122
|
||||
#define SYS_sched_getaffinity 123
|
||||
#define SYS_sched_yield 124
|
||||
#define SYS_sched_get_priority_max 125
|
||||
#define SYS_sched_get_priority_min 126
|
||||
#define SYS_sched_rr_get_interval 127
|
||||
#define SYS_restart_syscall 128
|
||||
#define SYS_kill 129
|
||||
#define SYS_tkill 130
|
||||
#define SYS_tgkill 131
|
||||
#define SYS_sigaltstack 132
|
||||
#define SYS_rt_sigsuspend 133
|
||||
#define SYS_rt_sigaction 134
|
||||
#define SYS_rt_sigprocmask 135
|
||||
#define SYS_rt_sigpending 136
|
||||
#define SYS_rt_sigtimedwait 137
|
||||
#define SYS_rt_sigqueueinfo 138
|
||||
#define SYS_rt_sigreturn 139
|
||||
#define SYS_setpriority 140
|
||||
#define SYS_getpriority 141
|
||||
#define SYS_reboot 142
|
||||
#define SYS_setregid 143
|
||||
#define SYS_setgid 144
|
||||
#define SYS_setreuid 145
|
||||
#define SYS_setuid 146
|
||||
#define SYS_setresuid 147
|
||||
#define SYS_getresuid 148
|
||||
#define SYS_setresgid 149
|
||||
#define SYS_getresgid 150
|
||||
#define SYS_setfsuid 151
|
||||
#define SYS_setfsgid 152
|
||||
#define SYS_times 153
|
||||
#define SYS_setpgid 154
|
||||
#define SYS_getpgid 155
|
||||
#define SYS_getsid 156
|
||||
#define SYS_setsid 157
|
||||
#define SYS_getgroups 158
|
||||
#define SYS_setgroups 159
|
||||
#define SYS_uname 160
|
||||
#define SYS_sethostname 161
|
||||
#define SYS_setdomainname 162
|
||||
#define SYS_getrlimit 163
|
||||
#define SYS_setrlimit 164
|
||||
#define SYS_getrusage 165
|
||||
#define SYS_umask 166
|
||||
#define SYS_prctl 167
|
||||
#define SYS_getcpu 168
|
||||
#define SYS_gettimeofday 169
|
||||
#define SYS_settimeofday 170
|
||||
#define SYS_adjtimex 171
|
||||
#define SYS_getpid 172
|
||||
#define SYS_getppid 173
|
||||
#define SYS_getuid 174
|
||||
#define SYS_geteuid 175
|
||||
#define SYS_getgid 176
|
||||
#define SYS_getegid 177
|
||||
#define SYS_gettid 178
|
||||
#define SYS_sysinfo 179
|
||||
#define SYS_mq_open 180
|
||||
#define SYS_mq_unlink 181
|
||||
#define SYS_mq_timedsend 182
|
||||
#define SYS_mq_timedreceive 183
|
||||
#define SYS_mq_notify 184
|
||||
#define SYS_mq_getsetattr 185
|
||||
#define SYS_msgget 186
|
||||
#define SYS_msgctl 187
|
||||
#define SYS_msgrcv 188
|
||||
#define SYS_msgsnd 189
|
||||
#define SYS_semget 190
|
||||
#define SYS_semctl 191
|
||||
#define SYS_semtimedop 192
|
||||
#define SYS_semop 193
|
||||
#define SYS_shmget 194
|
||||
#define SYS_shmctl 195
|
||||
#define SYS_shmat 196
|
||||
#define SYS_shmdt 197
|
||||
#define SYS_socket 198
|
||||
#define SYS_socketpair 199
|
||||
#define SYS_bind 200
|
||||
#define SYS_listen 201
|
||||
#define SYS_accept 202
|
||||
#define SYS_connect 203
|
||||
#define SYS_getsockname 204
|
||||
#define SYS_getpeername 205
|
||||
#define SYS_sendto 206
|
||||
#define SYS_recvfrom 207
|
||||
#define SYS_setsockopt 208
|
||||
#define SYS_getsockopt 209
|
||||
#define SYS_shutdown 210
|
||||
#define SYS_sendmsg 211
|
||||
#define SYS_recvmsg 212
|
||||
#define SYS_readahead 213
|
||||
#define SYS_brk 214
|
||||
#define SYS_munmap 215
|
||||
#define SYS_mremap 216
|
||||
#define SYS_add_key 217
|
||||
#define SYS_request_key 218
|
||||
#define SYS_keyctl 219
|
||||
#define SYS_clone 220
|
||||
#define SYS_execve 221
|
||||
#define SYS_mmap 222
|
||||
#define SYS_fadvise64 223
|
||||
#define SYS_swapon 224
|
||||
#define SYS_swapoff 225
|
||||
#define SYS_mprotect 226
|
||||
#define SYS_msync 227
|
||||
#define SYS_mlock 228
|
||||
#define SYS_munlock 229
|
||||
#define SYS_mlockall 230
|
||||
#define SYS_munlockall 231
|
||||
#define SYS_mincore 232
|
||||
#define SYS_madvise 233
|
||||
#define SYS_remap_file_pages 234
|
||||
#define SYS_mbind 235
|
||||
#define SYS_get_mempolicy 236
|
||||
#define SYS_set_mempolicy 237
|
||||
#define SYS_migrate_pages 238
|
||||
#define SYS_move_pages 239
|
||||
#define SYS_rt_tgsigqueueinfo 240
|
||||
#define SYS_perf_event_open 241
|
||||
#define SYS_accept4 242
|
||||
#define SYS_recvmmsg 243
|
||||
#define SYS_arch_specific_syscall 244
|
||||
#define SYS_wait4 260
|
||||
#define SYS_prlimit64 261
|
||||
#define SYS_fanotify_init 262
|
||||
#define SYS_fanotify_mark 263
|
||||
#define SYS_name_to_handle_at 264
|
||||
#define SYS_open_by_handle_at 265
|
||||
#define SYS_clock_adjtime 266
|
||||
#define SYS_syncfs 267
|
||||
#define SYS_setns 268
|
||||
#define SYS_sendmmsg 269
|
||||
#define SYS_process_vm_readv 270
|
||||
#define SYS_process_vm_writev 271
|
||||
#define SYS_kcmp 272
|
||||
#define SYS_finit_module 273
|
||||
#define SYS_sched_setattr 274
|
||||
#define SYS_sched_getattr 275
|
||||
#define SYS_renameat2 276
|
||||
#define SYS_seccomp 277
|
||||
#define SYS_getrandom 278
|
||||
#define SYS_memfd_create 279
|
||||
#define SYS_bpf 280
|
||||
#define SYS_execveat 281
|
||||
#define SYS_userfaultfd 282
|
||||
#define SYS_membarrier 283
|
||||
#define SYS_mlock2 284
|
||||
#define SYS_copy_file_range 285
|
||||
#define SYS_preadv2 286
|
||||
#define SYS_pwritev2 287
|
||||
#define SYS_pkey_mprotect 288
|
||||
#define SYS_pkey_alloc 289
|
||||
#define SYS_pkey_free 290
|
||||
#define SYS_statx 291
|
||||
#define SYS_io_pgetevents 292
|
||||
#define SYS_rseq 293
|
||||
#define SYS_kexec_file_load 294
|
||||
#define SYS_pidfd_send_signal 424
|
||||
#define SYS_io_uring_setup 425
|
||||
#define SYS_io_uring_enter 426
|
||||
#define SYS_io_uring_register 427
|
||||
#define SYS_open_tree 428
|
||||
#define SYS_move_mount 429
|
||||
#define SYS_fsopen 430
|
||||
#define SYS_fsconfig 431
|
||||
#define SYS_fsmount 432
|
||||
#define SYS_fspick 433
|
||||
#define SYS_pidfd_open 434
|
||||
#define SYS_clone3 435
|
||||
#define SYS_openat2 437
|
||||
#define SYS_pidfd_getfd 438
|
||||
#define SYS_faccessat2 439
|
||||
#define SYS_riscv_flush_icache 244 + 15
|
|
@ -0,0 +1,132 @@
|
|||
#
|
||||
# code to switch between user and kernel space.
|
||||
#
|
||||
# this code is mapped at the same virtual address
|
||||
# (TRAMPOLINE) in user and kernel space so that
|
||||
# it continues to work when it switches page tables.
|
||||
#
|
||||
# kernel.ld causes this to be aligned
|
||||
# to a page boundary.
|
||||
#
|
||||
.section .text
|
||||
.globl trampoline
|
||||
trampoline:
|
||||
.align 4
|
||||
.globl uservec
|
||||
uservec:
|
||||
#
|
||||
# trap.c sets stvec to point here, so
|
||||
# traps from user space start here,
|
||||
# in supervisor mode, but with a
|
||||
# user page table.
|
||||
#
|
||||
# sscratch points to where the process's p->trapframe is
|
||||
# mapped into user space, at TRAPFRAME.
|
||||
#
|
||||
|
||||
# swap a0 and sscratch
|
||||
# so that a0 is TRAPFRAME
|
||||
csrrw a0, sscratch, a0
|
||||
|
||||
# save the user registers in TRAPFRAME
|
||||
sd ra, 40(a0)
|
||||
sd sp, 48(a0)
|
||||
sd gp, 56(a0)
|
||||
sd tp, 64(a0)
|
||||
sd t0, 72(a0)
|
||||
sd t1, 80(a0)
|
||||
sd t2, 88(a0)
|
||||
sd s0, 96(a0)
|
||||
sd s1, 104(a0)
|
||||
sd a1, 120(a0)
|
||||
sd a2, 128(a0)
|
||||
sd a3, 136(a0)
|
||||
sd a4, 144(a0)
|
||||
sd a5, 152(a0)
|
||||
sd a6, 160(a0)
|
||||
sd a7, 168(a0)
|
||||
sd s2, 176(a0)
|
||||
sd s3, 184(a0)
|
||||
sd s4, 192(a0)
|
||||
sd s5, 200(a0)
|
||||
sd s6, 208(a0)
|
||||
sd s7, 216(a0)
|
||||
sd s8, 224(a0)
|
||||
sd s9, 232(a0)
|
||||
sd s10, 240(a0)
|
||||
sd s11, 248(a0)
|
||||
sd t3, 256(a0)
|
||||
sd t4, 264(a0)
|
||||
sd t5, 272(a0)
|
||||
sd t6, 280(a0)
|
||||
|
||||
# save the user a0 in p->trapframe->a0
|
||||
csrr t0, sscratch
|
||||
sd t0, 112(a0)
|
||||
|
||||
csrr t1, sepc
|
||||
sd t1, 24(a0)
|
||||
|
||||
ld sp, 8(a0)
|
||||
ld tp, 32(a0)
|
||||
ld t1, 0(a0)
|
||||
# csrw satp, t1
|
||||
# sfence.vma zero, zero
|
||||
ld t0, 16(a0)
|
||||
jr t0
|
||||
|
||||
.globl userret
|
||||
userret:
|
||||
# userret(TRAPFRAME, pagetable)
|
||||
# switch from kernel to user.
|
||||
# usertrapret() calls here.
|
||||
# a0: TRAPFRAME, in user page table.
|
||||
# a1: user page table, for satp.
|
||||
|
||||
# switch to the user page table.
|
||||
# csrw satp, a1
|
||||
# sfence.vma zero, zero
|
||||
|
||||
# put the saved user a0 in sscratch, so we
|
||||
# can swap it with our a0 (TRAPFRAME) in the last step.
|
||||
ld t0, 112(a0)
|
||||
csrw sscratch, t0
|
||||
|
||||
# restore all but a0 from TRAPFRAME
|
||||
ld ra, 40(a0)
|
||||
ld sp, 48(a0)
|
||||
ld gp, 56(a0)
|
||||
ld tp, 64(a0)
|
||||
ld t0, 72(a0)
|
||||
ld t1, 80(a0)
|
||||
ld t2, 88(a0)
|
||||
ld s0, 96(a0)
|
||||
ld s1, 104(a0)
|
||||
ld a1, 120(a0)
|
||||
ld a2, 128(a0)
|
||||
ld a3, 136(a0)
|
||||
ld a4, 144(a0)
|
||||
ld a5, 152(a0)
|
||||
ld a6, 160(a0)
|
||||
ld a7, 168(a0)
|
||||
ld s2, 176(a0)
|
||||
ld s3, 184(a0)
|
||||
ld s4, 192(a0)
|
||||
ld s5, 200(a0)
|
||||
ld s6, 208(a0)
|
||||
ld s7, 216(a0)
|
||||
ld s8, 224(a0)
|
||||
ld s9, 232(a0)
|
||||
ld s10, 240(a0)
|
||||
ld s11, 248(a0)
|
||||
ld t3, 256(a0)
|
||||
ld t4, 264(a0)
|
||||
ld t5, 272(a0)
|
||||
ld t6, 280(a0)
|
||||
|
||||
# restore user a0, and save TRAPFRAME in sscratch
|
||||
csrrw a0, sscratch, a0
|
||||
|
||||
# return to user mode and user pc.
|
||||
# usertrapret() set up sstatus and sepc.
|
||||
sret
|
|
@ -0,0 +1,79 @@
|
|||
#include "trap.h"
|
||||
#include "defs.h"
|
||||
#include "loader.h"
|
||||
#include "syscall.h"
|
||||
|
||||
extern char trampoline[], uservec[], boot_stack_top[];
|
||||
extern void *userret(uint64);
|
||||
|
||||
// set up to take exceptions and traps while in the kernel.
|
||||
void trap_init(void)
|
||||
{
|
||||
w_stvec((uint64)uservec & ~0x3);
|
||||
}
|
||||
|
||||
//
|
||||
// handle an interrupt, exception, or system call from user space.
|
||||
// called from trampoline.S
|
||||
//
|
||||
void usertrap(struct trapframe *trapframe)
|
||||
{
|
||||
if ((r_sstatus() & SSTATUS_SPP) != 0)
|
||||
panic("usertrap: not from user mode");
|
||||
|
||||
uint64 cause = r_scause();
|
||||
if (cause == UserEnvCall) {
|
||||
trapframe->epc += 4;
|
||||
syscall();
|
||||
return usertrapret(trapframe, (uint64)boot_stack_top);
|
||||
}
|
||||
switch (cause) {
|
||||
case StoreMisaligned:
|
||||
case StorePageFault:
|
||||
case LoadMisaligned:
|
||||
case LoadPageFault:
|
||||
case InstructionMisaligned:
|
||||
case InstructionPageFault:
|
||||
errorf("%d in application, bad addr = %p, bad instruction = %p, core "
|
||||
"dumped.",
|
||||
cause, r_stval(), trapframe->epc);
|
||||
break;
|
||||
case IllegalInstruction:
|
||||
errorf("IllegalInstruction in application, epc = %p, core dumped.",
|
||||
trapframe->epc);
|
||||
break;
|
||||
default:
|
||||
errorf("unknown trap: %p, stval = %p sepc = %p", r_scause(),
|
||||
r_stval(), r_sepc());
|
||||
break;
|
||||
}
|
||||
infof("switch to next app");
|
||||
run_next_app();
|
||||
printf("ALL DONE\n");
|
||||
shutdown();
|
||||
}
|
||||
|
||||
//
|
||||
// return to user space
|
||||
//
|
||||
void usertrapret(struct trapframe *trapframe, uint64 kstack)
|
||||
{
|
||||
trapframe->kernel_satp = r_satp(); // kernel page table
|
||||
trapframe->kernel_sp = kstack + PGSIZE; // process's kernel stack
|
||||
trapframe->kernel_trap = (uint64)usertrap;
|
||||
trapframe->kernel_hartid = r_tp(); // hartid for cpuid()
|
||||
|
||||
w_sepc(trapframe->epc);
|
||||
// set up the registers that trampoline.S's sret will use
|
||||
// to get to user space.
|
||||
|
||||
// set S Previous Privilege mode to User.
|
||||
uint64 x = r_sstatus();
|
||||
x &= ~SSTATUS_SPP; // clear SPP to 0 for user mode
|
||||
x |= SSTATUS_SPIE; // enable interrupts in user mode
|
||||
w_sstatus(x);
|
||||
|
||||
// tell trampoline.S the user page table to switch to.
|
||||
// uint64 satp = MAKE_SATP(p->pagetable);
|
||||
userret((uint64)trapframe);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef TRAP_H
|
||||
#define TRAP_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct trapframe {
|
||||
/* 0 */ uint64 kernel_satp; // kernel page table
|
||||
/* 8 */ uint64 kernel_sp; // top of process's kernel stack
|
||||
/* 16 */ uint64 kernel_trap; // usertrap()
|
||||
/* 24 */ uint64 epc; // saved user program counter
|
||||
/* 32 */ uint64 kernel_hartid; // saved kernel tp
|
||||
/* 40 */ uint64 ra;
|
||||
/* 48 */ uint64 sp;
|
||||
/* 56 */ uint64 gp;
|
||||
/* 64 */ uint64 tp;
|
||||
/* 72 */ uint64 t0;
|
||||
/* 80 */ uint64 t1;
|
||||
/* 88 */ uint64 t2;
|
||||
/* 96 */ uint64 s0;
|
||||
/* 104 */ uint64 s1;
|
||||
/* 112 */ uint64 a0;
|
||||
/* 120 */ uint64 a1;
|
||||
/* 128 */ uint64 a2;
|
||||
/* 136 */ uint64 a3;
|
||||
/* 144 */ uint64 a4;
|
||||
/* 152 */ uint64 a5;
|
||||
/* 160 */ uint64 a6;
|
||||
/* 168 */ uint64 a7;
|
||||
/* 176 */ uint64 s2;
|
||||
/* 184 */ uint64 s3;
|
||||
/* 192 */ uint64 s4;
|
||||
/* 200 */ uint64 s5;
|
||||
/* 208 */ uint64 s6;
|
||||
/* 216 */ uint64 s7;
|
||||
/* 224 */ uint64 s8;
|
||||
/* 232 */ uint64 s9;
|
||||
/* 240 */ uint64 s10;
|
||||
/* 248 */ uint64 s11;
|
||||
/* 256 */ uint64 t3;
|
||||
/* 264 */ uint64 t4;
|
||||
/* 272 */ uint64 t5;
|
||||
/* 280 */ uint64 t6;
|
||||
};
|
||||
|
||||
enum Exception {
|
||||
InstructionMisaligned = 0,
|
||||
InstructionAccessFault = 1,
|
||||
IllegalInstruction = 2,
|
||||
Breakpoint = 3,
|
||||
LoadMisaligned = 4,
|
||||
LoadAccessFault = 5,
|
||||
StoreMisaligned = 6,
|
||||
StoreAccessFault = 7,
|
||||
UserEnvCall = 8,
|
||||
SupervisorEnvCall = 9,
|
||||
MachineEnvCall = 11,
|
||||
InstructionPageFault = 12,
|
||||
LoadPageFault = 13,
|
||||
StorePageFault = 15,
|
||||
};
|
||||
|
||||
enum Interrupt {
|
||||
UserSoft = 0,
|
||||
SupervisorSoft,
|
||||
UserTimer = 4,
|
||||
SupervisorTimer,
|
||||
UserExternal = 8,
|
||||
SupervisorExternal,
|
||||
};
|
||||
|
||||
void trap_init();
|
||||
void usertrapret(struct trapframe *trapframe, uint64 kstack);
|
||||
|
||||
#endif // TRAP_H
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long uint64;
|
||||
|
||||
#endif // TYPES_H
|
|
@ -0,0 +1,69 @@
|
|||
import os
|
||||
|
||||
TARGET_DIR = "./user/target/bin/"
|
||||
|
||||
if __name__ == '__main__':
|
||||
f = open("os/kernel_app.ld", mode="w")
|
||||
apps = os.listdir(TARGET_DIR)
|
||||
f.write(
|
||||
'''OUTPUT_ARCH(riscv)
|
||||
ENTRY(_entry)
|
||||
BASE_ADDRESS = 0x80200000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = BASE_ADDRESS;
|
||||
skernel = .;
|
||||
|
||||
s_text = .;
|
||||
.text : {
|
||||
*(.text.entry)
|
||||
*(.text .text.*)
|
||||
. = ALIGN(0x1000);
|
||||
*(trampsec)
|
||||
. = ALIGN(0x1000);
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_text = .;
|
||||
s_rodata = .;
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_rodata = .;
|
||||
s_data = .;
|
||||
.data : {
|
||||
*(.data)
|
||||
''')
|
||||
for (idx, _) in enumerate(apps):
|
||||
f.write(' . = ALIGN(0x1000);\n')
|
||||
f.write(' *(.data.app{})\n'.format(idx))
|
||||
f.write(
|
||||
'''
|
||||
. = ALIGN(0x1000);
|
||||
*(.data.*)
|
||||
*(.sdata .sdata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_data = .;
|
||||
.bss : {
|
||||
*(.bss.stack)
|
||||
s_bss = .;
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
e_bss = .;
|
||||
ekernel = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
||||
''')
|
||||
f.close()
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import os
|
||||
|
||||
TARGET_DIR = "./user/target/bin/"
|
||||
|
||||
if __name__ == '__main__':
|
||||
f = open("os/link_app.S", mode="w")
|
||||
apps = os.listdir(TARGET_DIR)
|
||||
apps.sort()
|
||||
f.write(
|
||||
''' .align 4
|
||||
.section .data
|
||||
.global _app_num
|
||||
_app_num:
|
||||
.quad {}
|
||||
'''.format(len(apps))
|
||||
)
|
||||
|
||||
for (idx, _) in enumerate(apps):
|
||||
f.write(' .quad app_{}_start\n'.format(idx))
|
||||
f.write(' .quad app_{}_end\n'.format(len(apps) - 1))
|
||||
|
||||
f.write(
|
||||
'''
|
||||
.global _app_names
|
||||
_app_names:
|
||||
''');
|
||||
|
||||
for app in apps:
|
||||
f.write(" .string \"" + app + "\"\n")
|
||||
|
||||
for (idx, app) in enumerate(apps):
|
||||
f.write(
|
||||
'''
|
||||
.section .data.app{0}
|
||||
.global app_{0}_start
|
||||
app_{0}_start:
|
||||
.incbin "{1}"
|
||||
'''.format(idx, TARGET_DIR + app)
|
||||
)
|
||||
f.write('app_{}_end:\n\n'.format(len(apps) - 1))
|
||||
f.close()
|
Loading…
Reference in New Issue